NQRduckumentation/source/software_structure/development.md

219 lines
6 KiB
Markdown

# Development
This section describes the process of developing the NQRduck software.
## Development of NQRduck modules
Here, an exemplary workflow for the development of new NQRduck modules is given.
If one wants to develop a new module, a template is provided [here](https://github.com/nqrduck/nqrduck-module). This template can be used as a starting point for a new module.
For example, if one wants to develop a new module called *myduck*, one would first clone the repository.
The template repository has the following file structure:
```bash
nqrduck-module/
|-- .gitignore
|-- LICENCE
|-- README.md
|-- pyproject.toml
|-- src/
| |-- nqrduck_module/
| | |-- __init__.py
| | |-- controller.py
| | |-- model.py
| | |-- module.py
| | |-- resources/
| | | |-- module.ini
| | | |-- module_widget.ui
| | |-- view.py
| | |-- widget.py
```
*File structure of the NQRDuck module Git repository.*
If one would now like to create a module with the example name *myduck*, the folder and file names would be modified in the following way:
```bash
nqrduck-myduck/
|-- .gitignore
|-- LICENCE
|-- README.md
|-- pyproject.toml
|-- src/
| |-- nqrduck_myduck/
| | |-- __init__.py
| | |-- controller.py
| | |-- model.py
| | |-- myduck.py
| | |-- resources/
| | | |-- module.ini
| | | |-- myduck_widget.ui
| | |-- view.py
| | |-- widget.py
```
*File structure of the newly created *myduck* module.*
The class names inside the model, view, and controller classes should also be modified to have a more representative name (e.g., `MyDuckController`, `MyDuckView`, `MyDuckModel`). The object created in the `myduck` file should also be renamed:
```python
from nqrduck.module.module import Module
from .model import MyDuckModel
from .view import MyDuckView
from .controller import MyDuckController
MyDuck = Module(MyDuckModel, MyDuckView, MyDuckController)
```
Then the `.ini` file inside the resources folder should be modified to represent the *myduck* module.
```toml
[META]
name = nqrduck-myduck
category = MyOwnModules
toolbar_name = MyDuck
tooltip = Template for a new module
```
*Example for the modified .ini file. The category, toolbar name, and tooltip can be freely chosen.*
Additionally, the `pyproject.toml` has to be modified to represent the new module structure:
```toml
[project]
name = "nqrduck-myduck"
version = "0.0.1"
authors = [
{ name="YOUR NAME", email="your@e.mail" },
]
description = "Your description"
...
dependencies = [
"nqrduck",
"pyqt6",
...
]
[project.entry-points."nqrduck"]
"nqrduck-myduck" = "nqrduck_myduck.myduck:MyDuck"
```
Now functionality can be implemented. For example, the `myduck_widget.ui` could be modified using Qt Designer. The `widget.py` file can then be updated using `pyuic6`.
```bash
# Navigate to the repository directory
cd nqrduck-myduck
# Generate your widget.py
pyuic6 src/nqrduck_myduck/resources/myduck_widget.ui > src/nqrduck_myduck/widget.py
```
The module should be installed to test its functionality. Ideally, the module is installed with the `-e` argument of `pip` to install it in editable mode. This means changes in the source code of the project will be applied without reinstalling the module.
```bash
# Navigate to the repository directory
cd nqrduck-myduck
# Install the package and all dependencies
pip install -e .
```
## Example pyproject.toml
```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "nqrduck-module"
version = "0.0.1"
authors = [
{ name="Author Name", email="author@e.mail" },
]
description = "A template for nqrduck modules."
readme = "README.md"
license = { file="LICENSE" }
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
dependencies = [
"matplotlib",
"pyqt6",
"nqrduck",
]
[project.entry-points."nqrduck"]
"nqrduck-module" = "nqrduck_module.module:module"
```
## Style
Here the style guide for the NQRduck software is described.
### Linting
Linting is done using [ruff](https://astral.sh/ruff) with the following configuration specified in the `pyproject.toml` file:
```toml
[tool.ruff]
exclude = [
"widget.py",
"base_spectrometer_widget.py",
]
[tool.ruff.lint]
extend-select = [
"UP", # pyupgrade
"D", # pydocstyle
]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
[tool.ruff.lint.pydocstyle]
convention = "google"
```
Run `ruff check` to lint the code, ideally in a pre-commit hook.
### Formatting
Formatting is done using [black](https://black.readthedocs.io/en/stable/).
### Typing
Use type hints for all functions and classes. The type hints should be as specific as possible.
## Documentation
Documentation is implemented with [Sphinx](https://www.sphinx-doc.org/en/master/) project. The documentation is located in `NQRduckumentation` repository.
For docstrings in the code, the [Google style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) is used.
## Branching
The main branch is used for releases. Development is done on a development branch. Feature branches are created from the development branch and merged back into it. The development branch is merged into the main branch for releases. Releases are tagged with a version number starting with `v` (e.g. `v0.1.0`) and should follow [semantic versioning](https://semver.org/) (right now they don't).
## Testing
Testing is done using [pytest](https://docs.pytest.org/en/stable/). The tests are located in the `tests` directory and can be run using `pytest`.
Right now the tests are not very extensive, but they are a good starting point for further development.
## Deployment
- The software is deployed via [PyPI](https://pypi.org/). Different modules are distributed as separate packages. The Action is run on a tag push to the main branch starting with `v` (e.g. `v0.1.0`).
- For Cython modules, `aarch64` and `x86_64` wheels are built using GitHub Actions. The wheels are deployed alongside the source distribution to PyPI.