.. _contributing: Contributing ############ We're excited that you're interested in contributing. Whether you're new to coding or an experienced developer, this guide will walk you through everything you need to know to get started, from setting up your development environment to submitting your first contribution. Ways to Contribute ****************** There are many ways to contribute, regardless of your experience level: Reporting Issues ================ Found a bug? Have an idea for a new feature? Reporting issues is one of the most valuable ways to contribute. It helps us improve the project and ensures that we address the needs of our users. When adding new issues, try to adhere to the following principles: - Check existing issues to avoid duplicates. - Provide clear, reproducible steps for bugs. - Include relevant information (OS, Python version, etc.). - Make sure you select the right git project (HEROS, BOSS,...) You can report issues on our `GitLab issue page `_. Writing Tutorials and Improving Documentation ============================================= Help new users get started by creating tutorials and improving the documentation. This is an invaluable way to contribute, especially if you are new to the project or have limited coding experience. It's often hard for experienced contributors to capture all the pitfalls and steps that might be unclear to newcomers. If you find anything where the documentation is lacking, please consider improving it or creating an issue. Even small contributions like fixing typos or layout issues are more than welcome! There is typically also a range of documentation-related issues on our `GitLab `_. Fixing Bugs and Adding Features =============================== Community contributions in the form of new features or bug fixes are highly appreciated. For many device drivers, it is actually necessary to own the physical hardware. As the maintainers cannot own each and every device, contributing device drivers and fixing driver-related issues is an extremely important and valued task. If you are looking into fixing an issue, don't hesitate to ask for clarification if you're unsure about requirements. Keep your fixes minimal and focused without changing large parts of the codebase. Also, consider writing tests that reproduce the bug and help avoid it in the future. When implementing features, start by opening an `issue `_ with your proposal so it can be discussed by the community. Again, try to focus on one manageable feature and keep the code changes as simple as possible. Please follow the existing code patterns and conventions. The best starting point is always to look at existing code and get familiar with it. For your code to be really usable by a broad public, it needs to be lined with documentation and comprehensive tests. And most importantly, if you don't feel comfortable with a certain subtask, don't hesitate to ask for help (for example, in our `Matrix channel `_)! | Repository Structure ==================== All our repositories are set up adhering to the same structure. .. code-block:: text / ├── src/ │ └── / │ ├── __init__.py │ └── ... ├── tests/ │ └── ... ├── docs/ │ └── source/ │ └── ... ├── pyproject.toml └── ... - **src/**: Contains the main source code of the package, this is the part which gets published on PyPI in the end. - **tests/**: Contains unit test files. - **docs/**: Contains the documentation files. - **pyproject.toml**: Project configuration file. Making Changes to the Codebase ****************************** If you want to contribute directly to the codebase, either by writing documentation, fixing bugs, or contributing device drivers, this is the section for you. It assumes a basic understanding of Git and GitLab. If you are new to that, consider reading `GitLab's official guide `_. Setting Up the Development Environment ======================================= Before you begin contributing code or documentation, you'll need to set up your development environment. Here's what you'll need: - **GitLab Account**: Required to contribute code. `Sign up here `_ if you don't have one. - **uv**: Our preferred Python virtual environment manager. `Installation instructions `_. You can also use any other way to create and use virtual environments. **Fork and Clone the Repository** Create your own copy of the repository by clicking the **Fork** button on the GitLab page of the project you want to contribute, for example `herosdevices `_. This allows you to freely experiment with changes without affecting the main project. Once forked, clone your fork to your local machine by running: .. code-block:: console git clone https://gitlab.com//.git cd **Install Dependencies** Create a virtual environment in your repository folder by running: .. code-block:: console uv venv To install the necessary Python dependencies, run: .. code-block:: console uv pip install --group dev --group docs .. note:: If pip complains that the group does not exist, most likely you are in a subproject which still defines the dev dependencies as ``optional-dependencies``. In this case you have to run .. code-block:: console uv pip install -e ".[dev,docs]" This installs the package in editable mode along with all development and documentation dependencies. .. important:: The `herosdevices `_ repository uses many different vendor libraries, depending on what you want to contribute, you may have to install the corresponding packages. Refer to the documentation of the individual drivers for more details. **Create a Descriptive Branch** Start your development on a branch by running: .. code-block:: console git checkout -b Implement, Test and Document your Changes ========================================= .. important:: Before implementing, read the :ref:`contrib-code-guide` and prepare your environment accordingly. After applying your changes, run our tests by running .. code-block:: console uv run pytest If the existing tests fail, adjust your code so that they pass or start a discussion in your merge request (see below) why the tests should be changed. .. important:: If you added new feature, consider writing new tests to validate their functionality and :ref:`add documentation! ` Commit and push =============== When you're ready to contribute your changes, commit them and push them to your GitLab fork by running: .. code-block:: console git add path/to/modified/files git commit -m "Commit message describing your changes" git push --set-upstream origin Submit a merge request ====================== Finally, initiate a merge request to merge your contributions with the main repository. From the main repository gitlab page, go to the "Merge requests" page, and click the `New merge request` button, then select your fork and branch as a source. Compare your branches and write a comprehensive description of the changes you made, use one of the predefined templates (if available) to guide you through. Then submit the request and wait for the maintainers to check, comment and approve your code. | .. _contrib-branches: Working with branches ********************* We use a simple branching model to manage development: - The ``main`` branch contains production-ready code and is protected from direct pushes - All development happens in feature branches that are merged via merge requests. **Do not edit the** ``main`` **branch directly as it makes it much harder to keep your fork up to date with upstream** - Feature branches should be created from the latest ``main`` branch When creating branches, please use these naming conventions: - ``device/`` for new device drivers (e.g., ``device/siglent-sdg6xxx``) - ``feat/`` for new features (e.g., ``feat/image_viewer``) - ``fix/`` for bug fixes (e.g., ``fix/boss_starter_arg_handling``) - ``doc/`` for documentation changes (e.g., ``doc/update-install-guide``) - ``test/`` for testing improvements (e.g., ``test/add-coverage-for-camera``) To ensure you're working with the latest code, use the `Update Fork` button on the GitLab page of your fork! This helps prevent merge conflicts and keeps your development environment in sync with the main project. .. _contrib-code-guide: Coding Guidelines ***************** We recommend that you use the following tools for linting and formatting: `Pre-commit `_ tool Once you've installed this tool, integrate it as a pre-commit hook into your local repository with the following command: .. code-block:: console pre-commit install This automatically formats your code and conducts style checks before each commit. For manual checks at any time, execute: .. code-block:: console pre-commit run --all-files `Ruff `_ Installing `ruff` into the editor of your choice helps you with adhering to the style guide of this project directly while your write your code! See this `guide `_ on how to integrate `ruff` in your editor. `Ty `_ Ty helps you with getting the types right. It is run in the GitLab-CI and run with pre-commit but installing it in the editor of your choice will help you during development. See this `guide `_. .. note:: If you are no python expert, it can be hard to get the typing right. Therefore we accept also incorrectly typed code contributions, where the typing will be added by one of the maintainers, so don't worry if it fails. You can skip the pre-commit ty hook by running:: SKIP=ty git commit ... .. note:: We are currently migrating to ty, so not all repositories will include ty yet. .. _contrib-write-doc: Writing documentation ********************* Good documentation is essential for making the project accessible: We are using `Google format `_ for docstrings of all public functions and classes. We recommend reading the Google `doc style guide `_ for a tutorial on how to write good docstrings. .. card:: Herosdevices Device Driver If you added a new device driver, use the :py:func:`herosdevices.helper.mark_driver` decorator. For an example, see `the IDS camera driver `_. This decorator builds a documentation page for your driver automatically and adds it to the :ref:`hardware page `. Additional to the meta data (like required python packages and a short description) you have to specify as arguments to :py:func:`herosdevices.helper.mark_driver`, it automatically collects the following information from your driver function (here on the example of :py:class:`herosdevices.hardware.ids.peak_camera.PeakCompatibleCamera`): * Name of the vendor specified by `__vendor_name__ = "Vendor Name"` on a vendor module level (i.e. in ``hardware/ids/__init__.py``) * Long vendor docstring on the module level. This is the second part of the docstring in ``hardware/ids/__init__.py`` without the first line. * Docstrings and call signatures from the ``__init__``, ``__new__`` and ``__call__`` methods and the class itself. * Arguments necessary for instantiation by parsing the ``__init__``, ``__new__`` and ``__call__`` methods and there docstrings. It tries to infer also which arguments are required for parent classes. * In the ``Args:`` section of the docstrings, example values that are used for constructing a sample BOSS JSON string can be given by adding it to the docstring for each argument like ``Example: `` make sure to include an example how to setup the device with a `boss `_ JSON string. An example for this kind of docstring can be found in the `PvcamCamera class `_. .. _contrib-build-doc: Building Documentation Locally ============================== When making changes to the documentation, it is often necessary to visually check the result, therefore you have to build it locally. Our documentation is built using Sphinx, to build it run: .. code-block:: console uv run --directory docs/ make html View the documentation by opening ``./build/html/index.html`` in your browser. | Thank you for contributing to our project! Your efforts help make this framework better for everyone.