Contributing#

All command lines in code block are run from root folder pyrevsymg/

Installation#

  • You must have virtualenv

    python3.9 -m pip install virtualenv
    
  • Python virtual environment

    ./config/install_venv39-dev.sh
    

Import system#

Import system can hide some sub-sub-…-modules hierarchy.

As an example, let suppose the following file hierarchy:

.
└── src
    └── pkg_name
        ├── dir_a
        │   ├── dir_a_1
        │   │   ├── __init__.py
        │   │   └── mod_a_1_1.py
        │   └── __init__.py
        └── __init__.py

Imagine for clarity reasons we want the users import all the public code in the dir_a/dir_a_1/mod_a_1_1.py file directly from the pkg_name.dir_a namespace.

As a MWE, let suppose there is a public class ClassA11 in the file mod_a_1_1.py:

# dir_a/dir_a_1/mod_a_1_1.py

class ClassA11():
    ...

By default, to access it, a user have to code:

from pkg_name.dir_a.dir_a_1.mod_a_1_1 import ClassA11

This submodule structure was decided for developing organisation. However, the module mod_a_1_1.py is too deep, and we would prefer the users code:

from pkg_name.dir_a import ClassA11

To benefit from this behaviour, one can be a solution:

  • In the __init__.py file:

    import pkg_name.dir_a  # just import package namespace
    
  • In the dir_a/__init__.py file:

    from pkg_name.dir_a.dir_a_1 import *
    
  • In the dir_a_1/__init__.py file:

    from pkg_name.dir_a.dir_a_1.mod_a_1_1 import ClassA11
    

Note: to avoid this behaviour, one convention should be to use the same submodule hierarchy for developing as the namespace we want the users write.

For more detail about some import strategies, have a look to https://towardsdatascience.com/whats-init-for-me-d70a312da583

Testing#

Structure#

The testing folder structure should follow the way the user import.

Example (see import system example):

.
└── tests
    ├── dir_a
    │   ├── __init__.py
    │   └── test_a_1_1.py
    ├── __init__.py
    └── conftest.py

In the dir_a/test_a_1_1.py file:

from typing import Iterator
import pytest
from pkg_name.dir_a import ClassA11

@pytest.fixture
def a_1_1_fixture() -> Iterator[ClassA11]:
    ...

def test_class_a_1_1(a_1_1_fixture: ClassA11):
    ...

If one of the test module need the fixture a_1_1_fixture defined in the tests/dir_a/test_a_1_1 file, then you have to import it in the conftest.py file:

# tests/conftest.py

from tests.dir_a.test_a_1_1 import a_1_1_fixture

Tox command#

tox -e report

Coverage#

After running the tox command, code coverage results appear in HTML files:

.
└── tests
    └── coverage
        ├── html
        │   ├── index.html
        │   └── ...
        ├── .coverage
        ├── cov.lcov
        └── cov.xml

Just open coverage/html/index.hml file in an internet navigator to visualise the covered code.

Documenting#

Import object#

All paths are those that the user will write.

In the example,

```{module} pkg_name.dir_a
```
or

```{currentmodule} pkg_name.dir_a
```

```{eval-rst}
.. autoclass:: ClassA11()
   :autosummary:
   :members:
   :undoc-members:
   :inherited-members:
```

Especially in docstrings:

"""A docstring.

:class:`~pkg_name.dir_a.ClassA11`
"""

Type alias#

  • Thanks to napoleon: extract docstring

  • Thanks to autodoc: autodoc

  • But type or default constant module paths are lost

  • So use json to add manually the module path

  • That’s why must respect convention in import system example

  • Test the aliases, see testing

Tox command#

tox -e docs-html

New version#

You can use the helper script:

python3.9 config/new_release.py

It tells you to compute the following tasks:

  • Create release branch

    git checkout -b release-M.m.p develop
    
  • Change the version number in the pyproject.toml file

  • Finish to write the docs/src/changelog.md file (see Changelog section)

  • Commit changes

    git commit -a -m "Bumped version number to M.m.p"
    
  • Merge the commits

    • Tag the release and push to the main branch

      Note:

      • Suppose your main branch is called master

      git checkout master
      git merge --no-ff release-M.m.p -m "Merge release"
      git tag -a vM.m.p -m "Release vM.m.p"
      git push origin master --follow-tags
      
    • Merge to the developing branch

      git checkout develop
      git merge --no-ff release-M.m.p -m "Merge release"
      git push origin develop --follow-tags
      
    • Remove the release branch

      git branch -d release-M.m.p
      

For more information about the convention that is followed, have a look to https://nvie.com/posts/a-successful-git-branching-model/

Changelog#

Complete regularly docs/src/changelog.md:

  • [Unreleased] - yyyy-mm-dd section until new release

  • [M.m.p] - yyyy-mm-dd section when decide to release a new version (M: Major, m: minor, p: patch, yyyy: year number, mm: month number, dd: day number)

See Keep a Changelog link for more details.

  • Added for new features.

  • Changed for changes in existing functionality.

  • Deprecated for soon-to-be removed features.

  • Removed for now removed features.

  • Fixed for any bug fixes.

  • Security in case of vulnerabilities.