Metadata-Version: 2.4
Name: MpyDeploy
Version: 4.0.1
Summary: CLI tool to compile, cache, and deploy MicroPython projects
Author: FÜNA
License-Expression: MIT
Project-URL: Repository, https://github.com/FUNA-FA/MpyDeploy
Project-URL: Issues, https://github.com/FUNA-FA/MpyDeploy/issues
Keywords: micropython,mpy,deploy,mpy-cross,embedded
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Embedded Systems
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mpremote
Requires-Dist: mpy-cross
Requires-Dist: platformdirs
Requires-Dist: pyserial
Requires-Dist: requests
Dynamic: license-file

# MpyDeploy

**MpyDeploy** is a CLI tool that collects, compiles, caches and deploys MicroPython project files
to one or more connected MicroPython devices.

Installed CLI command: **`mpy`**

## Features

-  **Automatic COM port detection** — scans connected serial ports and identifies MicroPython devices, or use a manually specified port
-  **File upload** — deploys your project's own source folder(s) *and* any installed MicroPython packages in your `.venv`
- ️ **Cross-compilation** — compiles `.py` files to `.mpy` via `mpy-cross`, with automatic architecture detection
-  **Cached deploys** — an SHA-256 based file cache skips files that haven't changed since the last upload
-  **Device wipe** — optionally erase all files on the device before deploying
- ️ **Project build and deploy** — package your project into a `.zip` for distribution, or deploy an existing Project to a device
-  **Reboot and live output** — soft-reboots the device after deployment and streams its serial output until the REPL prompt is ready
-  **Config via `pyproject.toml`** — all settings can be set project-wide under `[tool.mpy_deploy]`
-  **mip package installation** — automatically installs configured `mip` packages after upload

## Installation

MpyDeploy requires **Python 3.14+**. Since it is a standalone tool rather than a project dependency,
it's **not recommended** to install it in your project's virtual environment.

it is **Recommended** to use [uv](https://docs.astral.sh/uv/), which creates an isolated environment with the required Python version for you:

```bash
uv tool install MpyDeploy
```

Alternatively, with `pipx`:

```bash
pipx install MpyDeploy
```

Or via `pip`, as long as the interpreter you install it with is Python 3.14+:

```bash
pip install MpyDeploy
```

After installation, the tool is available under the short command **`mpy`**.

## Usage

Run `mpy` from your project's root directory — the directory that contains your `pyproject.toml` and
(by default) a `src/` folder with your MicroPython code:

```bash
mpy
```

With no settings, this will:
1. Auto-detect the connected MicroPython device's COM port
2. Collect files from `./src` and any marked mpy packages in `.venv`
3. Compare against the local file cache and skip unchanged files
4. Compile packages to `.mpy` (sources are uploaded as `.py` by default)
5. Upload everything to the device
6. Reboot the device and stream its output until the REPL is ready

Some common examples:

```bash
mpy -p COM5     # use a specific COM port instead of auto-detecting
mpy -w          # wipe the device before deploying
mpy -cc         # clear the local file cache
mpy -cs         # also compile sources, not just packages
mpy -dcp        # skip packages, only deploy sources
mpy -nr         # deploy without rebooting afterwards
mpy -zp         # create a deployable zip using the default path
mpy -dp         # deploy an existing project archive
```

## Argument Table

| Flag   | Long form                             | Default                | Effect                                                                                                                                                                    |
|--------|---------------------------------------|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-p`   | `--port`                              | auto-detect            | COM port of the connected MicroPython device                                                                                                                              |
| `-ca`  | `--compiling_architecture`            | auto-detect            | Target architecture for compilation (`x86`, `x64`, `armv6`, `armv6m`, `armv7m`, `armv7em`, `armv7emsp`, `armv7emdp`, `xtensa`, `xtensawin`, `rv32imc`, `rv64imc`, `None`) |
| `-zp`  | `--zip-project [PATH]`                | *(off)*                | Builds a zip archive of the collected project files. Optional `PATH` to set custom destination path.                                                                      |
| `-dp`  | `--deploy-project [PATH] [PATH_PATH]` | *(off)*                | Deploys an existing project archive. Optional `PATH` is the project source path and `PATH_PATH` is to specify the folder inside of the source path.                       |
| `-nc`  | `--no_cache`                          | *(cache enabled)*      | Disables the file-hash cache for this run.                                                                                                                                |
| `-cc`  | `--clear-cache`                       | *(off)*                | Deletes the file-hash cache before running.                                                                                                                               |
| `-dcp` | `--dont_copy_packages`                | *(copy packages)*      | Skips copying packages.                                                                                                                                                   |
| `-dcs` | `--dont_copy_sources`                 | *(copy sources)*       | Skips copying sources.                                                                                                                                                    |
| `-ncp` | `--no_compile_packages`               | *(compile packages)*   | Uploads packages as `.py` instead of compiling to `.mpy`.                                                                                                                 |
| `-cs`  | `--compile_sources`                   | *(off)*                | Compile sources to `.mpy`.                                                                                                                                                |
| `-w`   | `--wipe-files`                        | *(off)*                | Deletes all files on the device before deploying.                                                                                                                         |
| `-nr`  | `--no_reboot`                         | *(reboot enabled)*     | Skips the device reboot at the end.                                                                                                                                       |
| `-npl` | `--no_print_loop`                     | *(print-loop enabled)* | Skips streaming live device output after reboot.                                                                                                                          |

> Flags with a boolean default of `None` inherit their effective default from `pyproject.toml` / the tool's internal `Settings`,
> shown in the "Default" column above.

## Configuration via `pyproject.toml`

Beyond the CLI flags, project-wide defaults can be set under `[tool.mpy_deploy]` in your `pyproject.toml`.

```toml
[tool.mpy_deploy]
com_ports = ["COM5"]                   # list of COM ports; use multiple entries for multiple devices, e.g. ["COM5", "COM6"]
source_paths = [["src", ""]]           # list of [source_path, device_dest] pairs
package_paths = []                     # extra local package folders to include
mip_packages = ["some-mip-package"]    # mip packages to install after upload
packages_search_path = ".venv/lib/python3.14/site-packages"
cache_folder_path = ".mpy_file_cache"
zip_dest_path = "build/Project.zip"
deploy_source_path = "build/Project.zip"
deploy_source_local_path = ""          # path inside the source folder
compiling_architecture = "armv7emsp"

wipe_files = false
file_cache = true
clear_file_cache = false
copy_packages = true
copy_sources = true
compile_packages = true
compile_sources = false
zip_project = false
deploy_project = false
reboot = true
print_loop = true
```

CLI arguments always take precedence over values from `pyproject.toml`.

## Compilation Feature

- Files are compiled from `.py` to `.mpy` using `mpy-cross`. Packages are compiled by default
- `main.py` and `boot.py` are **never compiled** when placed at the device root, since MicroPython needs to run them as plain Python.
- The target **architecture** is auto-detected unless overwritten with `-ca`.
- If compiling a file fails, MpyDeploy falls back to uploading the uncompiled `.py` version and continues instead of aborting.
- This does not apply to a `.zip` archive built with `-zp` — its contents are always stored uncompiled,
regardless of `compile_packages` / `compile_sources`. See [Zip Feature](#zip-feature).

## Copy Feature

MpyDeploy gathers files from two independent sources, both enabled by default:

- **Sources** — everything under your configured source path(s) (default: `./src`), mirrored to the corresponding path on the device.
- **Packages** — installed packages inside your virtualenv's `site-packages` that opt in to being deployed.
A folder is treated as a mpy package if its `__init__.py` starts with the exact first line `# mpy`.
These packages are uploaded under `lib/` on the device. The search path is auto-detected from `.venv`
(`Lib/site-packages` on Windows, `lib/python3.*/site-packages` on POSIX), or can be overridden via `packages_search_path`.

Both can be disabled individually with `-dcp` / `-dcs`.

**File caching:** every uploaded file is hashed (SHA-256) and stored in a local JSON cache (`.mpy_file_cache/` by default).
On subsequent runs, only files whose hash changed are re-uploaded — significantly speeding up iterative development.
Use `-nc` to bypass the cache for one run, or `-cc` to clear it entirely (also happens automatically before a `-w` wipe).

After the main file transfer, any packages listed under `mip_packages` in `pyproject.toml` are installed on the device
via `mpremote mip install`.

## Zip Feature

Instead of uploading directly to a device, MpyDeploy can work with a project `.zip` archive:

- **`-zp` / `--zip-project [PATH]`** — bundles the collected files into a zip. With no `PATH`,
the configured `zip_dest_path` is used (default `build/Project.zip`). The archive contents are always stored uncompiled.
Useful for creating a distributable release without needing a device connected. `mip` packages cannot be included in a zip.
- **`-dp [PATH] [PATH_PATH]` / `--deploy-project [PATH] [PATH_PATH]`** —
deploys the contents of an existing project to the connected device.
The `PATH` parameter defines the source of the project (**folder_path**, **zipfile_path**, **zip_download_url**)
The `PATH_PATH` parameter is used to specify a target directory inside the source folder.
the contents are compiled according to `compile_packages` / `compile_sources`.

#### `--deploy-project` Example with URL source:
````bash
mpy -dp https://great/repo/download path/inside/repo/to/mpy/project
````

When either project mode is used, the file cache is disabled for that run.
Using `-zp` alone skips connecting to a device and compiling entirely — no COM port or compiler architecture is required.

## Reboot and Output

After a successful deployment (unless `-nr` is used), MpyDeploy soft-reboots the device by sending a keyboard-interrupt
followed by a soft-reset over the serial connection.

If the print loop is enabled (disable with `-npl`), MpyDeploy opens the serial connection for the fist device and
streams the device's console output live to your terminal until it detects the `>>>` REPL prompt,
indicating the device has finished and is idle. The loop can be stopped early with `Ctrl+C`.

## Requirements

- Python **3.14+** to run MpyDeploy itself
