Contributing#
Contributions are welcome!
Development#
To install magicgui for development, first clone the repository:
git clone https://github.com/pyapp-kit/magicgui
cd magicgui
Then install the package in editable mode with the dev extra:
pip install -e .[dev]
To run the tests:
pytest
Code Quality#
magicgui attempts to adhere to strict coding rules and employs the following
static analysis tools to prevent errors from being introduced into the codebase:
To prevent continuous integration failures when contributing, please consider installing pre-commit in your environment to run all of these checks prior to checking in new code.
pre-commit install
To run the checks manually, you can use:
pre-commit run --all-files
Adding a widget#
These instructions may change in the future as the repo structures changes. If they appear outdated as you follow them, please open an issue.
To add a new widget, you will need to:
-
Create a new class in
magicgui/widgets/_concrete.pythat inherits from the base class most appropriate for your widget (e.g.ValueWidget, orCategoricalWidget).In some (complex) cases, you may need to extend one of the base classes. If so, it is likely that you will also need to extend one of the
Protocolsfound inmagicgui.widgets.protocols. This is where all of protocols that backend classes need to implement to work with a given widget type. (Don't hesitate to open an issue if you're confused). -
Most likely, you will want to decorate the class with
@backend_widget. Using this decorator implies that there is a class with the same name in any any backend modules that will support this widget type (e.g.magicgui.backends._qtpy.widgetsfor Qt support.). - Make any changes necessary to your new concrete class. For example, you may
need to change the
valueproperty and corresponding setter to handle a specific type. This part of the code should be backend agnostic. - Export the new class in
magicgui/widgets/__init__.pyso that it can be imported frommagicgui.widgets. - Implement the backend widget class (using the same class name) in the
appropriate backend module (e.g.
magicgui.backends._qtpy.widgetsfor Qt support). Usually this will mean implementing the appropriate_mgui_get/set_...methods for theProtocolof the corresponding widget base class your chose to extend. - Export the backend widget class in the
__init__.pyof the backend module (e.g.magicgui.backends._qtpy.__init__.pyfor Qt support). This is important, as that is where the@backend_widgetdecorator will look. - Add a test for your new widget.
For an example of a minimal PR adding a new widget, see #483, which added a
QuantityWidgetto be used withpint.Quantityobjects.
Associating a widget with a type#
To associate your new widget with a specific type such that it will be used when
someone annotates a parameter with that type, you will need to update code in
magicgui.type_map._type_map.
In the simplest of cases, this will mean adding a new entry to the
magicgui.type_map._type_map._SIMPLE_TYPES dict. This is a mapping from a
python type to a widget class. (Note that all subclasses of the type will also
be matched.)
For more complex cases, you can add a new conditional to the body of the
match_type function. That function should always return a tuple of widget
type, and kwargs that will be passed to the widget constructor. For example:
return widgets.MyNewWidget, {}.
Building the documentation#
To build the documentation locally, you will need to install the docs extra:
pip install -e .[docs]
Then, from the root of the repository, run:
mkdocs serve
This will start a local server at http://127.0.0.1:8000/ where you can view
the documentation as you edit it.