Skip to content

Commit 5b84536

Browse files
committed
Migrate examples to src-layout
And de-emphasize ``setup.py`` in favor of ``pyproject.toml``.
1 parent b4ffccd commit 5b84536

File tree

1 file changed

+71
-55
lines changed

1 file changed

+71
-55
lines changed

source/guides/packaging-namespace-packages.rst

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ have the following package structure:
1919
__init__.py
2020
...
2121
module_b.py
22-
setup.py
22+
pyproject.toml
2323
2424
And you use this package in your code like so::
2525

@@ -31,17 +31,19 @@ Then you can break these sub-packages into two separate distributions:
3131
.. code-block:: text
3232
3333
mynamespace-subpackage-a/
34-
setup.py
35-
mynamespace/
36-
subpackage_a/
37-
__init__.py
34+
pyproject.toml
35+
src/
36+
mynamespace/
37+
subpackage_a/
38+
__init__.py
3839
3940
mynamespace-subpackage-b/
40-
setup.py
41-
mynamespace/
42-
subpackage_b/
43-
__init__.py
44-
module_b.py
41+
pyproject.toml
42+
src/
43+
mynamespace/
44+
subpackage_b/
45+
__init__.py
46+
module_b.py
4547
4648
Each sub-package can now be separately installed, used, and versioned.
4749

@@ -73,44 +75,29 @@ Native namespace packages
7375
Python 3.3 added **implicit** namespace packages from :pep:`420`. All that is
7476
required to create a native namespace package is that you just omit
7577
:file:`__init__.py` from the namespace package directory. An example file
76-
structure:
78+
structure (following :ref:`src-layout <setuptools:src-layout>`):
7779

7880
.. code-block:: text
7981
8082
mynamespace-subpackage-a/
81-
setup.py # AND/OR pyproject.toml, setup.cfg
82-
mynamespace/ # namespace package
83-
# No __init__.py here.
84-
subpackage_a/
85-
# Sub-packages have an __init__.py.
86-
__init__.py
87-
module.py
83+
pyproject.toml # AND/OR setup.py, setup.cfg
84+
src/
85+
mynamespace/ # namespace package
86+
# No __init__.py here.
87+
subpackage_a/
88+
# Sub-packages have an __init__.py.
89+
__init__.py
90+
module.py
8891
8992
It is extremely important that every distribution that uses the namespace
9093
package omits the :file:`__init__.py` or uses a pkgutil-style
9194
:file:`__init__.py`. If any distribution does not, it will cause the namespace
9295
logic to fail and the other sub-packages will not be importable.
9396

94-
Because ``mynamespace`` doesn't contain an :file:`__init__.py`,
95-
:func:`setuptools.find_packages` won't find the sub-package. You must
96-
use :func:`setuptools.find_namespace_packages` instead or explicitly
97-
list all packages in your :file:`setup.py`. For example:
98-
99-
.. code-block:: python
100-
101-
from setuptools import setup, find_namespace_packages
102-
103-
setup(
104-
name='mynamespace-subpackage-a',
105-
...
106-
packages=find_namespace_packages(include=['mynamespace.*'])
107-
# or list a single package explicitly:
108-
# packages=['mynamespace.subpackage_a'],
109-
)
110-
111-
The same can be accomplished by replacing the :file:`setup.py` in the
112-
namespace packages' parent directory with a :file:`pyproject.toml`,
113-
with the following contents:
97+
The ``src-layout`` directory structure allows automatic discovery of packages
98+
by most :term:`build backends <Build Backend>`. If however you want to manage
99+
exclusions or inclusions of packages yourself, this is possible to be configured
100+
in the top-level :file:`pyproject.toml`:
114101

115102
.. code-block:: toml
116103
@@ -119,13 +106,38 @@ with the following contents:
119106
build-backend = "setuptools.build_meta"
120107
121108
[tool.setuptools.packages.find]
122-
where = ["."]
123-
include = ["mynamespace.*"]
109+
where = ["src/"]
110+
include = ["mynamespace.subpackage_a"]
124111
125112
[project]
126113
name = "mynamespace-subpackage-a"
127114
...
128115
116+
The same can be accomplished with a :file:`setup.cfg`:
117+
118+
.. code-block:: ini
119+
120+
[options]
121+
package_dir =
122+
=src
123+
packages = find_namespace:
124+
125+
[options.packages.find]
126+
where = src
127+
128+
Or :file:`setup.py`:
129+
130+
.. code-block:: python
131+
132+
from setuptools import setup, find_namespace_packages
133+
134+
setup(
135+
name='mynamespace-subpackage-a',
136+
...
137+
packages=find_namespace_packages(where='src/', include=['mynamespace.subpackage_a']),
138+
package_dir={"": "src"},
139+
)
140+
129141
:ref:`setuptools` will search the directory structure for implicit namespace
130142
packages by default.
131143

@@ -170,12 +182,14 @@ To create a pkgutil-style namespace package, you need to provide an
170182

171183
.. code-block:: text
172184
173-
setup.py # AND/OR pyproject.toml, setup.cfg
174-
mynamespace/
175-
__init__.py # Namespace package __init__.py
176-
subpackage_a/
177-
__init__.py # Sub-package __init__.py
178-
module.py
185+
mynamespace-subpackage-a/
186+
src/
187+
pyproject.toml # AND/OR setup.cfg, setup.py
188+
mynamespace/
189+
__init__.py # Namespace package __init__.py
190+
subpackage_a/
191+
__init__.py # Sub-package __init__.py
192+
module.py
179193
180194
The :file:`__init__.py` file for the namespace package needs to contain
181195
the following:
@@ -215,22 +229,24 @@ To create a pkg_resources-style namespace package, you need to provide an
215229

216230
.. code-block:: text
217231
218-
setup.py # AND/OR pyproject.toml, setup.cfg
219-
mynamespace/
220-
__init__.py # Namespace package __init__.py
221-
subpackage_a/
222-
__init__.py # Sub-package __init__.py
223-
module.py
232+
mynamespace-subpackage-a/
233+
src/
234+
pyproject.toml # AND/OR setup.cfg, setup.py
235+
mynamespace/
236+
__init__.py # Namespace package __init__.py
237+
subpackage_a/
238+
__init__.py # Sub-package __init__.py
239+
module.py
224240
225241
The :file:`__init__.py` file for the namespace package needs to contain
226-
**only** the following:
242+
the following:
227243

228244
.. code-block:: python
229245
230246
__import__('pkg_resources').declare_namespace(__name__)
231247
232-
**Every** distribution that uses the namespace package must include an
233-
identical :file:`__init__.py`. If any distribution does not, it will cause the
248+
**Every** distribution that uses the namespace package must include such an
249+
:file:`__init__.py`. If any distribution does not, it will cause the
234250
namespace logic to fail and the other sub-packages will not be importable. Any
235251
additional code in :file:`__init__.py` will be inaccessible.
236252

0 commit comments

Comments
 (0)