Metadata-Version: 2.4
Name: MpyDeploy
Version: 3.1.0
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
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: platformdirs
Requires-Dist: pyserial
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
- ️ **Zip build and deploy** — package your project into a `.zip` for distribution, or deploy an existing zip 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]`
- ️ **Self-installing compiler** — if no `mpy-cross` executable is found, MpyDeploy offers to clone and build it.
-  **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 arguments, 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 -cz         # create a deployable zip instead of uploading directly
mpy -dz         # deploy an existing zip to the device
```

## 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_path`                 | `build/Project.zip`    | Path to the zip file used by `-cz` / `-dz`                                                                                                                                |
| `-mce` | `--mp_cross_executable_path` | platform data dir      | Path to the `mpy-cross` executable                                                                                                                                        |
| `-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                                                                                                                           |
| `-cz`  | `--create-zip`               | *(off)*                | Builds a zip archive of the deploy contents instead of uploading                                                                                                          |
| `-dz`  | `--deploy-zip`               | *(off)*                | Extracts, optionally compiles (based on the current compile setting), and uploads the contents of an existing ZIP archive                                                 |

> 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"
mp_cross_executable_path = "path/to/mpy-cross"
zip_dest_path = "build/Project.zip"
compiling_architecture = "armv7emsp"

wipe_files = false
file_cache = true
copy_packages = true
copy_sources = true
compile_packages = true
compile_sources = 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 no `mpy-cross` executable is found at the configured path, MpyDeploy asks for confirmation to clone
the official [micropython/micropython](https://github.com/micropython/micropython) repository and builds `mpy-cross` from source using `make`.
The resulting binary is cached at the configured executable path for future runs.
- 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 `-cz` — 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 `.zip` archive:

- **`-cz` / `--create-zip`** — bundles the collected files into a zip at the path set by `-zp` (default `build/Project.zip`).
Contents are always added uncompiled. Useful to create a distributable release without needing a device connected at all.
Note: `mip` packages cannot be included in a zip.
- **`-dz` / `--deploy-zip`** — copies the contents of an existing zip to the connected device,
compiling them if `compile_packages` / `compile_sources` are enabled.

When either flag is used, the file cache is disabled for that run.
Using `-cz` alone (without `-dz`) 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 then opens the serial connection 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
- `git` and a C build toolchain (`make`, etc.) only if `mpy-cross` needs to be built automatically
