Skip to content

Commit fff0808

Browse files
committed
Update to pyansys-template
1 parent 822ca74 commit fff0808

File tree

1 file changed

+186
-43
lines changed

1 file changed

+186
-43
lines changed

doc/source/library_description/packaging.rst

Lines changed: 186 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,177 @@
22

33
Packaging
44
#########
5-
A Python package organizes and structures a Python library, which contains several
6-
modules and assets such as examples or binary extensions. A Python package
7-
offers an easy, reliable, and comprehensive way to distribute and install
8-
a Python library on a variety of platforms and environments.
5+
6+
A Python package organizes and structures a Python library, which contains
7+
several modules and assets such as examples or binary extensions. A Python
8+
package offers an easy, reliable, and comprehensive way to distribute and
9+
install a Python library on a variety of platforms and environments.
10+
11+
.. note::
12+
13+
If you want to create a new PyAnsys project according to the guidelines
14+
presented in the following lines, consider using the `pyansys template`_.
15+
16+
17+
Python Scripts, Modules, Sub-packages, and Packages
18+
---------------------------------------------------
19+
20+
It is important to understand the difference between Python scripts, modules,
21+
sub-packages, and packages:
22+
23+
* ``Script``: Any Python file with logic source code.
24+
* ``Module``: Any Python script hosted next to an ``__init__.py`` file.
25+
* ``Sub-package``: Any directory containing various Python modules.
26+
* ``Package``: Any directory containing Python modules and sub-packages.
27+
28+
The following structure is shown to better explain previous concepts:
29+
30+
.. code:: bash
31+
32+
.
33+
├── src
34+
│   └── package
35+
│   ├── subpackage_a
36+
│   │   ├── __init__.py
37+
│   │   └── module_c.py
38+
│   ├── __init__.py
39+
│   ├── module_a.py
40+
│   └── module_b.py
41+
├── LICENSE
42+
├── README.rst
43+
└── pyproject.toml
44+
945
1046
Namespace Packaging
1147
-------------------
12-
A PyAnsys library uses `namespace packaging`_.
13-
Namespace packages allow a user to easily split subpackages from a package into
14-
single, independent distributions.
48+
A PyAnsys library uses `namespace packaging`_. Namespace packages allow you
49+
to easily split sub-packages from a package into single, independent
50+
distributions.
51+
52+
There are different approaches available for creating a namespace package. For
53+
the ``ansys`` namespace, we use the `PEP 420`_ `native namespace packages`_
54+
approach.
55+
56+
Following previous namespace, the source directory of any `PyAnsys library`
57+
should look like this:
58+
59+
.. code:: bash
60+
61+
.
62+
└── src
63+
└── ansys
64+
└── product
65+
└── library
66+
└── __init__.py
1567
16-
There are different approaches available for creating a namespace package. For the
17-
``ansys`` namespace, we use the `PEP 420`_ `native namespace packages`_ approach.
1868
1969
Required Files
2070
--------------
2171

22-
* README.rst file: Describes the purpose of the package.
72+
* ``README.rst`` file: Describes the purpose of the package.
2373
*The format of this file must be reStructuredText.*
2474

25-
* LICENSE file: Specifies copyrights and required authorization.
75+
* ``LICENSE`` file: Specifies copyrights and required authorization.
2676

27-
* pyproject.toml file: Provides package information.
28-
This file provides the package metadata, and defines how it is built.
29-
There are different build backends available, such as `setuptools`_,
30-
`poetry`_ and `flit`_.
77+
* ``pyproject.toml`` file: Provides package metadata and defines how the package
78+
is built. There are different build backends available, such as `setuptools`_,
79+
`poetry`_, and `flit`_.
3180

81+
* ``src/ansys/product/library/__init__.py`` file: Usually contains the
82+
version of the package in a variable named ``__version__``. The value of this
83+
variable can be parsed from the ``pyproject.toml`` file so that the version
84+
is only specified in one location.
3285

33-
Project Configuration File
34-
--------------------------
86+
87+
Additional Directories
88+
----------------------
89+
90+
The following directories may be specified at the same level as the ``src/`` one:
91+
92+
* ``tests/``: Contains all unit tests for the package. It is
93+
likely that these tests take advantage of the `pytest`_ framework.
94+
95+
* ``doc/``: Contain all documentation files and examples on
96+
how to use the package.
97+
98+
99+
Project File and Build System
100+
------------------------------
35101

36102
The ``pyproject.toml`` file is the standardized build configuration file for Python
37-
projects. It needs to at least contain a ``[build-system]`` section, which determines
103+
projects. It must contain at least a ``[build-system]`` section, which determines
38104
how the project is built. Some commonly used packaging tools are `setuptools`_,
39-
`poetry`_, or `flit`_.
105+
`poetry`_, and `flit`_. All three of these packaging tools are currently supported by
106+
the `pyansys template`_.
107+
108+
109+
Flit
110+
^^^^
40111

41-
We use `poetry`_ as a default choice in the `PyAnsys template`_, for the following reasons:
42-
* it supports pinning dependency versions, which we use for testing / CI
43-
* downstream packages can still consume a loose dependency specification
44-
* it integrates with `dependabot`_ to update the pinned version
112+
Flit is a modern and lightweight build system that requires developers
113+
to manage virtual environments on their own. Developers must:
45114

46-
Feel free to use any one of the packaging tools mentioned above that best suits
47-
your needs. The advantage of `flit`_ is its simplicity, while `setuptools`_ is most useful
48-
when custom build steps need to be implemented as Python code.
115+
* Create a virtual environment and activate it.
116+
* Install the package in editable mode.
49117

50-
To use `poetry`_ as a packaging tool, the ``pyproject.toml`` should contain
118+
Flit is the default tool for creating a new project when using the
119+
`pyansys template`_.
51120

52-
.. code:: toml
121+
The ``[project]`` section specifies the project's metadata and required
122+
dependencies. For more information, see the `flit pyproject.toml
123+
guidelines`_.
53124

54-
[build-system]
55-
requires = ["poetry-core>=1.0.0"]
56-
build-backend = "poetry.core.masonry.api"
57125

58-
The ``[tool.poetry]`` section contains metadata, and defines the project's dependencies. Refer to the
59-
`poetry pyproject.toml documentation`_ for details.
126+
Poetry
127+
^^^^^^
128+
129+
Poetry is known because of its strong dependency pinning thanks to the
130+
``poetry.lock`` file. When installing a package, poetry creates a virtual
131+
environment, thus ensuring an isolated package development environment.
132+
133+
It is possible to avoid previous behavior by executing the following command:
134+
135+
.. code:: bash
136+
137+
poetry config virtualenvs.create false --local
138+
139+
Therefore, `poetry`_ may be chosen due to the following reasons:
140+
141+
* It supports pinning dependency versions via a ``poetry.lock`` file, which we
142+
use for testing / CI.
143+
* Downstream packages can still consume a loose dependency specification.
144+
* It integrates with `dependabot`_ to update the pinned version.
145+
146+
The ``[tool.poetry]`` section contains metadata, and defines the project's
147+
dependencies. Refer to the `poetry pyproject.toml documentation`_ for details.
148+
149+
150+
Setuptools
151+
^^^^^^^^^^
152+
153+
Setuptools is a very well known build system in the Python ecosystem. It is used
154+
in projects requiring a ``setup.py``. Setuptools can be used with projects using
155+
the ``pyproject.toml`` too, although not all metadata is fully supported yet.
156+
157+
The main advantage of this build system is the ability of creating custom build
158+
steps in the form of Python code.
159+
160+
161+
Specifying Package Version
162+
--------------------------
163+
164+
It is very common for packages to specify their current version in the
165+
``__version__`` variable. This variable is usually declared in the
166+
``__init__.py`` file included in the ``library`` directory.
167+
168+
However, it is also required to specify the version in the ``pyproject.toml`` or
169+
``setup.py``. This leads to a duplicate declaration of the project's version,
170+
which could lead to a potential mismatch between both.
171+
172+
Therefore, a good practice is to take advantage of the `importlib.metadata package`_,
173+
for parsing the version from package metadata. This guarantees no mismatch
174+
between both version declarations.
60175

61-
Since poetry cannot automatically determine a package's version, we instead specify it in the ``[tool.poetry]``
62-
section, and add code to ``__init__.py`` which obtains the version from the installation metadata:
63176

64177
.. code:: python
65178
@@ -71,14 +184,26 @@ section, and add code to ``__init__.py`` which obtains the version from the inst
71184
__version__ = importlib_metadata.version(__name__.replace(".", "-"))
72185
73186
74-
Where supported, we aim to put all tooling-related configuration into ``pyproject.toml``.
75-
For example, it can also be used to configure the code formatter `black`_ or the static
76-
type checker `mypy`_.
187+
Extra Tools Configuration
188+
-------------------------
189+
190+
There are plenty of tools in the Python ecosystem which enable developers to
191+
write clean code according to different coding style guidelines. Some of these
192+
tools are `black`_, `isort`_, `flake8`_, `mypy`_...
193+
194+
Some of these tools can be configured. This configuration might be specified in
195+
custom files required by the tool or in the ``pyproject.toml`` reducing thus the
196+
amount of files in the project directory.
77197

78198
.. note::
79199

80-
When using `setuptools`_ as a build backend, providing the metadata in ``pyproject.toml`` is not yet fully supported.
81-
Instead, it also requires a ``setup.cfg`` and / or ``setup.py`` file.
200+
When using `setuptools`_ as a build backend, providing the metadata in
201+
``pyproject.toml`` is not yet fully supported. Instead, it also requires a
202+
``setup.cfg`` and / or ``setup.py`` file.
203+
204+
In the `pyansys template`, all these configurations are included by default in
205+
the `.pre-commit-config.yaml`, as `pre-commit` is not able to parse the
206+
``pyproject.toml`` file neither the ``setup.py`` one.
82207

83208

84209
Generate the Package and Upload It on PyPI
@@ -94,15 +219,28 @@ Create the python package.
94219
pip install build
95220
python -m build
96221
222+
If using flit or poetry, you can also run:
223+
224+
.. code::
225+
226+
flit build
227+
poetry build
228+
97229
Verify the distribution's long description rendering with ``twine``.
98230

99231
.. code::
100232
101233
pip install twine
102234
twine check dist/*
103235
104-
Upload the package to PyPI using ``twine`` and the upload token generated for the ``ansys`` PyPI account.
105-
Contact [email protected] for the token.
236+
237+
Upload the package to PyPI using ``twine`` and the upload token generated for
238+
the ``ansys`` PyPI account. As soon as the package has been released for the
239+
first time, it is possible to create an independent token dedicated to this
240+
package. This way the token stored in the GitHub secrets and used in the
241+
release's workflow is only related to that specific package. This limits the
242+
exposure to any potential token security flaws. Contact
243+
[email protected] for the token.
106244

107245
.. code::
108246
@@ -169,12 +307,17 @@ To create a package complying with the above standards, here is the minimal cont
169307
.. _PEP 420: https://www.python.org/dev/peps/pep-0420/
170308
.. _setuptools: https://setuptools.pypa.io
171309
.. _poetry: https://python-poetry.org/docs/
310+
.. _flit pyproject.toml guidelines: https://flit.readthedocs.io/en/latest/pyproject_toml.html
172311
.. _flit: https://flit.readthedocs.io
173312
.. _dependabot: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/about-dependabot-version-updates
174-
.. _PyAnsys template: https://github.com/pyansys/template
313+
.. _pyansys template: https://github.com/pyansys/pyansys-template
175314
.. _poetry pyproject.toml documentation: https://python-poetry.org/docs/pyproject/
176315
.. _black: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file
177316
.. _mypy: https://mypy.readthedocs.io/en/stable/config_file.html#the-mypy-configuration-file
178317
.. _trunk-based development: https://trunkbaseddevelopment.com/
179318
.. _secret: https://docs.github.com/en/actions/reference/encrypted-secrets
180319
.. _setup.py: https://packaging.python.org/tutorials/packaging-projects/#configuring-metadata
320+
.. _importlib.metadata package: https://docs.python.org/3/library/importlib.metadata.html
321+
.. _isort: https://github.com/PyCQA/isort
322+
.. _flake8: https://flake8.pycqa.org/en/latest/
323+
.. _pytest: https://docs.pytest.org/en/latest/

0 commit comments

Comments
 (0)