Skip to main content

Package and project manager for MicroPython and CircuitPython

Project description

Minny

Package and project manager for MicroPython and CircuitPython

Python 3.11+ License: MIT Development Status

What is Minny?

Minny is like uv or Poetry for MicroPython and CircuitPython projects—it enables managing your project's development and runtime environment in a declarative way.

Note: Minny's main features are useful only if you keep your project in a local folder on your development machine. You don't need it when you edit files directly on the device, but keep reading—maybe you'll start liking the local-first workflow!

Declarative

Uploading your files with mpremote or installing dependencies with Circup is straightforward, but it may become tedious if you need to reproduce the same setup on another board (or on the same board after upgrading its firmware).

With Minny, you write down your dependencies and deployment rules in pyproject.toml once, and let the tool take care of setting up the device.

Here is a sample configuration for a MicroPython app:

[tool.minny.dependencies]
mip = [
    "logging",
    "github:jimmo/micropython-mlx90640",
    "-e ../pfx-330-c" # an editable local project
]

[[tool.minny.deploy.files]]
source = "src"
destination = "/flash"
include = ["**/*.py", "configuration.json"]
compile = "auto"  # compiles all .py files on the fly except main.py and boot.py

# no need to mention deploying dependencies—these will be copied over by default

Here's another example for a CircuitPython app:

[tool.minny.dependencies]
pip = [
    "adafruit-circuitpython-charlcd~=2.2.0",
    "adafruit-circuitpython-logging",
    "-e ../my-shared-circuitpython-library",
]
circup = ["multi_keypad"]


# [[tool.minny.deploy.files]] block not needed because of useful defaults,
# but we want to skip some transitive dependencies that are not required at runtime:
[[tool.minny.deploy.packages]]
exclude = ["adafruit-circuitpython-typing", "typing-extensions"] 

Note: If you are creating a MicroPython or CircuitPython package (not an app), then you may not even need tool.minny settings—Minny will pick up your package dependencies from project.dependencies or from deps in MicroPython's package.json'.

Development environment

Local copies of dependencies

When your project has dependencies, you want your IDE and type-checker to know about them so you can get full support for code completion and type checking. Minny helps by making dependencies available locally.

Once you have your dependencies declared in pyproject.toml, you would run:

> minny sync

This makes Minny download and install all dependencies into the lib subfolder of your project (just like uv sync creates or updates the .venv folder).

Now you have a folder of .py files, which you can feed to your type-checker or IDE's language server. For example, if you're using Basedpyright, you would configure it like this:

[tool.basedpyright]
...
extraPaths = ["lib"]
...

Besides code completion and type-checking, your IDE should now allow you to Ctrl-click or Command-click from a library function call to its implementation so you can investigate the source code when the documentation is lacking.

Note: If you choose to keep the lib folder under version control, you'll have solid dependency locking in place. If you don't need this, feel free to add the folder to .gitignore and let Minny create and populate it each time someone clones the project and starts working on it.

Type stubs

Type stubs are another way to support your IDE or type checker. See the documentation for more information.

Minny supports making type stubs and custom typesheds easily available for type-checkers and language servers. Here's an example pyproject.toml that makes minny sync download and install a custom typeshed to the project's "typeshed" folder and Pimoroni Pico MicroPython Stubs to the "typings" folder, and configures Basedpyright to consult these folders:

...

[dependency-groups]
typeshed = ["micropython-typeshed~=0.1.*"]
typings = ["pimoroni-pico-stubs==1.21.0"]

[tool.basedpyright]
typeshedPath = "typeshed"
stubPath = "typings" # this is actually the default value, so I could have omitted this line

...

Note: Just like with the "lib" folder, you don't need to keep the "typeshed" and "typings" folders under version control—Minny has enough information to recreate them when required.

More about type stubs

TODO: move this to documentation

These are *.pyi files containing typing information for modules lacking embedded typing annotations (for example, modules in the MicroPython and CircuitPython standard libraries).

Type stubs for MicroPython and CircuitPython are usually published at Python Package Index as pip-compatible distribution packages. See https://micropython-stubs.readthedocs.io/en/main/ and https://pypi.org/project/circuitpython-stubs/

If your type-checker or language server picks up type stubs automatically from .venv, you may want to skip Minny's support and add stub packages to the "dev" dependency group and sync your .venv with uv sync.

Editable dependencies

For local development, you often need to work with packages that are not yet published or are under active development. Minny supports editable dependencies using the same -e syntax as pip's requirements.txt files:

[tool.minny.dependencies]
pip = [
    "published-package>=1.0.0",
    "-e ../my-local-library",           # Relative path
    "-e /absolute/path/to/package"      # Absolute path
]

mip = [
    # You can specify a "public name" to your local package.
    # This allows overriding a transitive dependency with the same name.
    "-e github:mphacker75/pfx-330-c@../pfx-330-c"
]

When you run minny sync, editable dependencies are represented in lib by metadata and special marker files, which point to the location of the modules under their project directory.

Editable dependencies are particularly useful when:

  • Developing multiple related packages simultaneously
  • Contributing to open-source libraries used by your project
  • Working with experimental or unreleased versions of dependencies

Note: The current package (in case your project represents a package (not an app) always gets installed to lib in editable mode.

Runtime environment

Once you're ready to test your code, plug in a device and execute something like this:

minny --port COM4 deploy

Under the hood, this command performs the following steps:

  1. Perform a minny sync to make sure the lib folder is in sync with your project specification.
  2. Transfer all dependencies to your device's lib folder. By default, Minny compiles .py files to .mpy files on the fly.
  3. If the project represents a package, build it and transfer the files to the lib folder, just like the dependencies.
  4. Copy the main files (e.g., main.py, code.py, boot.py, and helper modules) to the device's main folder, according to the deploy rules specified in pyproject.toml.

Now you can press Ctrl-D on your device and test your program. If you're not satisfied, edit some files and invoke the same command again—this time it will be faster as only changed files need to be updated on the device.

Alternatively, you can execute following command:

minny --port COM4 run my-test.py

This would be like deploy followed by sending the contents of my-test.py to the REPL, except that main.py would not be updated on the board.

Lower-level commands

If you prefer to manage your dependencies manually, you can use Minny's lower-level commands for installing, uninstalling, and listing. Some examples:

  • minny --port COM4 mip install logging
  • minny --port /dev/ttyACM0 pip install micropython-logging
  • minny --mount G:\lib pip install adafruit-circuitpython-ssd1306
  • minny --dir my_project/dependencies circup install multi_keypad
  • minny --port COM5 pip uninstall micropython-logging micropython-oled
  • minny --port COM5 mip list --outdated

Note: Minny does not use vanilla pip, mip, or circup. See the documentation for more information.

Minny and Thonny

Minny powers MicroPython and CircuitPython support in Thonny since version 5.0, so if you click the run button while having selected a Minny back-end, Thonny will invoke minny run behind the scenes.

Project Status

Current Version: 0.1.0a1 (Alpha)

Status: Core functionality implemented, active development

Contributing

Contributions are welcome. See CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

minny-0.0.1a2.tar.gz (56.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

minny-0.0.1a2-py3-none-any.whl (64.6 kB view details)

Uploaded Python 3

File details

Details for the file minny-0.0.1a2.tar.gz.

File metadata

  • Download URL: minny-0.0.1a2.tar.gz
  • Upload date:
  • Size: 56.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for minny-0.0.1a2.tar.gz
Algorithm Hash digest
SHA256 34d9a75cf87010ab63af053f77a44f3e7bdecc24760f0086a665faa1c93f2c1d
MD5 cfbd0b8b1f17eb7d6ca978fd7c04f04c
BLAKE2b-256 9193090acf581465711220181439018ce45b3669a5df8b0f56e6bbb01691efb7

See more details on using hashes here.

File details

Details for the file minny-0.0.1a2-py3-none-any.whl.

File metadata

  • Download URL: minny-0.0.1a2-py3-none-any.whl
  • Upload date:
  • Size: 64.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for minny-0.0.1a2-py3-none-any.whl
Algorithm Hash digest
SHA256 d916418dcb3f8a25048ee14273cff6e099c580693aa90ba8f2a359eed22e6183
MD5 d7ff5e318bbbd582fbd667fa799616ae
BLAKE2b-256 451ddb7dbc60ca185af6e71a09b50051464347586fd1484502707fd4d17d7bdc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page