2
2
3
3
Packaging
4
4
#########
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 holding logic source code.
24
+ * ``Module ``: any Python script hosted next to an ``__init__.py `` file.
25
+ * ``Sub-package ``: any directory holding various Python modules.
26
+ * ``Package ``: any directory which contains 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
+
9
45
10
46
Namespace Packaging
11
47
-------------------
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 a user
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
15
67
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.
18
68
19
69
Required Files
20
70
--------------
21
71
22
- * README.rst file: Describes the purpose of the package.
72
+ * `` README.rst `` file: Describes the purpose of the package.
23
73
*The format of this file must be reStructuredText. *
24
74
25
- * LICENSE file: Specifies copyrights and required authorization.
75
+ * `` LICENSE `` file: Specifies copyrights and required authorization.
26
76
27
- * pyproject.toml file: Provides package information.
77
+ * `` pyproject.toml `` file: Provides package information.
28
78
This file provides the package metadata, and defines how it is built.
29
79
There are different build backends available, such as `setuptools `_,
30
80
`poetry `_ and `flit `_.
31
81
82
+ * ``src/ansys/product/library/__init__.py `` file: This file usually holds the
83
+ version of the package in a variable named ``__version__ ``. The value of this
84
+ variable can be parsed from the `pyproject.toml ` file, so it is only specified
85
+ in one location.
32
86
33
- Project Configuration File
34
- --------------------------
87
+
88
+ Additional Directories
89
+ ----------------------
90
+
91
+ The following directories may be specified at the same level of ``src/ `` one:
92
+
93
+ * ``tests/ ``: This directory holds all unitary tests of the package. It is
94
+ likely that those take advantage of the `pytest `_ framework.
95
+
96
+ * ``doc/ ``: A directory devoted to hold all documentation files and examples on
97
+ how to use the package.
98
+
99
+
100
+ Project File and Build System
101
+ ------------------------------
35
102
36
103
The ``pyproject.toml `` file is the standardized build configuration file for Python
37
104
projects. It needs to at least contain a ``[build-system] `` section, which determines
38
105
how the project is built. Some commonly used packaging tools are `setuptools `_,
39
- `poetry `_, or `flit `_.
106
+ `poetry `_, or `flit `_. All these three build systems are currently supported by
107
+ the `pyansys template `_.
108
+
109
+
110
+ Flit
111
+ ^^^^
40
112
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
113
+ It is a modern and lightweight build system. Using this tool requires
114
+ developers to manage virtual environments by their own, that is:
45
115
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.
116
+ * Creating a virtual environment and activating it.
117
+ * Installing the package in editable mode.
49
118
50
- To use `poetry `_ as a packaging tool, the ``pyproject.toml `` should contain
119
+ This tool is the default one for creating a new project when using the
120
+ `pyansys template `_.
51
121
52
- .. code :: toml
122
+ The ``[project] `` section is used for specifying project's metadata and required
123
+ dependencies. More information can be found in the `flit pyproject.toml
124
+ guidelines `_.
53
125
54
- [build-system]
55
- requires = ["poetry-core>=1.0.0"]
56
- build-backend = "poetry.core.masonry.api"
57
126
58
- The ``[tool.poetry] `` section contains metadata, and defines the project's dependencies. Refer to the
59
- `poetry pyproject.toml documentation `_ for details.
127
+ Poetry
128
+ ^^^^^^
129
+
130
+ Poetry is known because of its strong dependency pinning thanks to the
131
+ ``poetry.lock `` file. When installing a package, poetry creates a virtual
132
+ environment, thus ensuring an isolated package development environment.
133
+
134
+ It is possible to avoid previous behavior by executing the following command:
135
+
136
+ .. code :: bash
137
+
138
+ poetry config virtualenvs.create false --local
139
+
140
+ Therefore, `poetry `_ may be chosen due to the following reasons:
141
+
142
+ * It supports pinning dependency versions via a ``poetry.lock `` file, which we
143
+ use for testing / CI.
144
+ * Downstream packages can still consume a loose dependency specification.
145
+ * It integrates with `dependabot `_ to update the pinned version.
146
+
147
+ The ``[tool.poetry] `` section contains metadata, and defines the project's
148
+ dependencies. Refer to the `poetry pyproject.toml documentation `_ for details.
149
+
150
+
151
+ Setuptools
152
+ ^^^^^^^^^^
153
+
154
+ Setuptools is a very well known build system in the Python ecosystem. It is used
155
+ in projects requiring a ``setup.py ``. Setuptools can be used with projects using
156
+ the ``pyproject.toml `` too, although not all metadata is fully supported yet.
157
+
158
+ The main advantage of this build system is the ability of creating custom build
159
+ steps in the form of Python code.
160
+
161
+
162
+ Specifying Package Version
163
+ --------------------------
164
+
165
+ It is very common for packages to specify their current version in the
166
+ ``__version__ `` variable. This variable is usually declared in the
167
+ ``__init__.py `` file included in the ``library `` directory.
168
+
169
+ However, it is also required to specify the version in the ``pyproject.toml `` or
170
+ ``setup.py ``. This leads to a duplicate declaration of the project's version,
171
+ which could lead to a potential mismatch between both.
172
+
173
+ Therefore, a good practice is to take advantage of the `importlib.metadata package `_,
174
+ for parsing the version from package metadata. This guarantees no mismatch
175
+ between both version declarations.
60
176
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:
63
177
64
178
.. code :: python
65
179
@@ -71,14 +185,26 @@ section, and add code to ``__init__.py`` which obtains the version from the inst
71
185
__version__ = importlib_metadata.version(__name__ .replace(" ." , " -" ))
72
186
73
187
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 `_.
188
+ Extra Tools Configuration
189
+ -------------------------
190
+
191
+ There are plenty of tools in the Python ecosystem which enable developers to
192
+ write clean code according to different coding style guidelines. Some of these
193
+ tools are `black `_, `isort `_, `flake8 `_, `mypy `_...
194
+
195
+ Some of these tools can be configured. This configuration might be specified in
196
+ custom files required by the tool or in the ``pyproject.toml `` reducing thus the
197
+ amount of files in the project directory.
77
198
78
199
.. note ::
79
200
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.
201
+ When using `setuptools `_ as a build backend, providing the metadata in
202
+ ``pyproject.toml `` is not yet fully supported. Instead, it also requires a
203
+ ``setup.cfg `` and / or ``setup.py `` file.
204
+
205
+ In the `pyansys template `, all these configurations are included by default in
206
+ the `.pre-commit-config.yaml `, as `pre-commit ` is not able to parse the
207
+ ``pyproject.toml `` file neither the ``setup.py `` one.
82
208
83
209
84
210
Generate the Package and Upload It on PyPI
@@ -94,15 +220,28 @@ Create the python package.
94
220
pip install build
95
221
python -m build
96
222
223
+ If using flit or poetry, you can also run:
224
+
225
+ .. code ::
226
+
227
+ flit build
228
+ poetry build
229
+
97
230
Verify the distribution's long description rendering with ``twine ``.
98
231
99
232
.. code ::
100
233
101
234
pip install twine
102
235
twine check dist/*
103
236
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.
237
+
238
+ Upload the package to PyPI using ``twine `` and the upload token generated for
239
+ the ``ansys `` PyPI account. As soon as the package has been released for the
240
+ first time, it is possible to create an independent token dedicated to this
241
+ package. This way the token stored in the GitHub secrets and used in the
242
+ release's workflow is only related to that specific package. This limits the
243
+ exposure to any potential token security flaws. Contact
244
+
106
245
107
246
.. code ::
108
247
@@ -169,12 +308,17 @@ To create a package complying with the above standards, here is the minimal cont
169
308
.. _PEP 420 : https://www.python.org/dev/peps/pep-0420/
170
309
.. _setuptools : https://setuptools.pypa.io
171
310
.. _poetry : https://python-poetry.org/docs/
311
+ .. _flit pyproject.toml guidelines : https://flit.readthedocs.io/en/latest/pyproject_toml.html
172
312
.. _flit : https://flit.readthedocs.io
173
313
.. _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
314
+ .. _ pyansys template : https://github.com/pyansys/pyansys- template
175
315
.. _poetry pyproject.toml documentation : https://python-poetry.org/docs/pyproject/
176
316
.. _black : https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file
177
317
.. _mypy : https://mypy.readthedocs.io/en/stable/config_file.html#the-mypy-configuration-file
178
318
.. _trunk-based development : https://trunkbaseddevelopment.com/
179
319
.. _secret : https://docs.github.com/en/actions/reference/encrypted-secrets
180
320
.. _setup.py : https://packaging.python.org/tutorials/packaging-projects/#configuring-metadata
321
+ .. _importlib.metadata package : https://docs.python.org/3/library/importlib.metadata.html
322
+ .. _isort : https://github.com/PyCQA/isort
323
+ .. _flake8 : https://flake8.pycqa.org/en/latest/
324
+ .. _pytest : https://docs.pytest.org/en/latest/
0 commit comments