Skip to content

Commit b7c2a06

Browse files
authored
Minor changes to the User Guide's Package Discovery page (#3332)
2 parents 4ad3d45 + 9e26f88 commit b7c2a06

File tree

2 files changed

+64
-43
lines changed

2 files changed

+64
-43
lines changed

changelog.d/3332.doc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed grammar/typos, modified example directory trees for src-layout and flat-layout -- by :user:`codeandfire`

docs/userguide/package_discovery.rst

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
.. _`package_discovery`:
22

33
========================================
4-
Package Discovery and Namespace Package
4+
Package Discovery and Namespace Packages
55
========================================
66

77
.. note::
8-
a full specification for the keyword supplied to ``setup.cfg`` or
8+
a full specification for the keywords supplied to ``setup.cfg`` or
99
``setup.py`` can be found at :doc:`keywords reference </references/keywords>`
1010

1111
.. note::
@@ -15,10 +15,10 @@ Package Discovery and Namespace Package
1515
new to setuptools, the :doc:`quickstart section <quickstart>` is a good
1616
place to start.
1717

18-
``Setuptools`` provide powerful tools to handle package discovery, including
19-
support for namespace package.
18+
``Setuptools`` provides powerful tools to handle package discovery, including
19+
support for namespace packages.
2020

21-
Normally, you would specify the package to be included manually in the following manner:
21+
Normally, you would specify the packages to be included manually in the following manner:
2222

2323
.. tab:: setup.cfg
2424

@@ -27,16 +27,17 @@ Normally, you would specify the package to be included manually in the following
2727
[options]
2828
#...
2929
packages =
30-
mypkg1
31-
mypkg2
30+
mypkg
31+
mypkg.subpkg1
32+
mypkg.subpkg2
3233
3334
.. tab:: setup.py
3435

3536
.. code-block:: python
3637
3738
setup(
3839
# ...
39-
packages=['mypkg1', 'mypkg2']
40+
packages=['mypkg', 'mypkg.subpkg1', 'mypkg.subpkg2']
4041
)
4142
4243
.. tab:: pyproject.toml (**EXPERIMENTAL**) [#experimental]_
@@ -45,12 +46,12 @@ Normally, you would specify the package to be included manually in the following
4546
4647
# ...
4748
[tool.setuptools]
48-
packages = ["mypkg1", "mypkg2"]
49+
packages = ["mypkg", "mypkg.subpkg1", "mypkg.subpkg2"]
4950
# ...
5051
5152
52-
If your packages are not in the root of the repository you also need to
53-
configure ``package_dir``:
53+
If your packages are not in the root of the repository or do not correspond
54+
exactly to the directory structure, you also need to configure ``package_dir``:
5455

5556
.. tab:: setup.cfg
5657

@@ -60,16 +61,16 @@ configure ``package_dir``:
6061
# ...
6162
package_dir =
6263
= src
63-
# directory containing all the packages (e.g. src/mypkg1, src/mypkg2)
64+
# directory containing all the packages (e.g. src/mypkg, src/mypkg/subpkg1, ...)
6465
# OR
6566
package_dir =
66-
mypkg1 = lib1
67-
# mypkg1.mod corresponds to lib1/mod.py
68-
# mypkg1.subpkg.mod corresponds to lib1/subpkg/mod.py
69-
mypkg2 = lib2
70-
# mypkg2.mod corresponds to lib2/mod.py
71-
mypkg2.subpkg = lib3
72-
# mypkg2.subpkg.mod corresponds to lib3/mod.py
67+
mypkg = lib
68+
# mypkg.module corresponds to lib/module.py
69+
mypkg.subpkg1 = lib1
70+
# mypkg.subpkg1.module1 corresponds to lib1/module1.py
71+
mypkg.subpkg2 = lib2
72+
# mypkg.subpkg2.module2 corresponds to lib2/module2.py
73+
# ...
7374
7475
.. tab:: setup.py
7576

@@ -78,18 +79,17 @@ configure ``package_dir``:
7879
setup(
7980
# ...
8081
package_dir = {"": "src"}
81-
# directory containing all the packages (e.g. src/mypkg1, src/mypkg2)
82+
# directory containing all the packages (e.g. src/mypkg, src/mypkg/subpkg1, ...)
8283
)
8384
8485
# OR
8586
8687
setup(
8788
# ...
8889
package_dir = {
89-
"mypkg1": "lib1", # mypkg1.mod corresponds to lib1/mod.py
90-
# mypkg1.subpkg.mod corresponds to lib1/subpkg/mod.py
91-
"mypkg2": "lib2", # mypkg2.mod corresponds to lib2/mod.py
92-
"mypkg2.subpkg": "lib3" # mypkg2.subpkg.mod corresponds to lib3/mod.py
90+
"mypkg": "lib", # mypkg.module corresponds to lib/mod.py
91+
"mypkg.subpkg1": "lib1", # mypkg.subpkg1.module1 corresponds to lib1/module1.py
92+
"mypkg.subpkg2": "lib2" # mypkg.subpkg2.module2 corresponds to lib2/module2.py
9393
# ...
9494
)
9595
@@ -105,19 +105,23 @@ configure ``package_dir``:
105105
# OR
106106
107107
[tool.setuptools.package-dir]
108-
mypkg1 = "lib1"
109-
# mypkg1.mod corresponds to lib1/mod.py
110-
# mypkg1.subpkg.mod corresponds to lib1/subpkg/mod.py
111-
mypkg2 = "lib2"
112-
# mypkg2.mod corresponds to lib2/mod.py
113-
"mypkg2.subpkg" = "lib3"
114-
# mypkg2.subpkg.mod corresponds to lib3/mod.py
108+
mypkg = "lib"
109+
# mypkg.module corresponds to lib/module.py
110+
"mypkg.subpkg1" = "lib1"
111+
# mypkg.subpkg1.module1 corresponds to lib1/module1.py
112+
"mypkg.subpkg2" = "lib2"
113+
# mypkg.subpkg2.module2 corresponds to lib2/module2.py
115114
# ...
116115
117116
This can get tiresome really quickly. To speed things up, you can rely on
118117
setuptools automatic discovery, or use the provided tools, as explained in
119118
the following sections.
120119
120+
.. important::
121+
Although ``setuptools`` allows developers to create a very complex mapping
122+
between directory names and package names, it is better to *keep it simple*
123+
and reflect the desired package hierarchy in the directory structure,
124+
preserving the same names.
121125
122126
.. _auto-discovery:
123127
@@ -161,7 +165,15 @@ directory::
161165
└── mypkg/
162166
├── __init__.py
163167
├── ...
164-
└── mymodule.py
168+
├── module.py
169+
├── subpkg1/
170+
│   ├── __init__.py
171+
│   ├── ...
172+
│   └── module1.py
173+
└── subpkg2/
174+
├── __init__.py
175+
├── ...
176+
└── module2.py
165177
166178
This layout is very handy when you wish to use automatic discovery,
167179
since you don't have to worry about other Python files or folders in your
@@ -186,11 +198,19 @@ The package folder(s) are placed directly under the project root::
186198
└── mypkg/
187199
├── __init__.py
188200
├── ...
189-
└── mymodule.py
201+
├── module.py
202+
├── subpkg1/
203+
│   ├── __init__.py
204+
│   ├── ...
205+
│   └── module1.py
206+
└── subpkg2/
207+
├── __init__.py
208+
├── ...
209+
└── module2.py
190210
191211
This layout is very practical for using the REPL, but in some situations
192212
it can be more error-prone (e.g. during tests or if you have a bunch
193-
of folders or Python files hanging around your project root)
213+
of folders or Python files hanging around your project root).
194214
195215
To avoid confusion, file and folder names that are used by popular tools (or
196216
that correspond to well-known conventions, such as distributing documentation
@@ -271,7 +291,7 @@ Finding simple packages
271291
-----------------------
272292
Let's start with the first tool. ``find:`` (``find_packages()``) takes a source
273293
directory and two lists of package name patterns to exclude and include, and
274-
then return a list of ``str`` representing the packages it could find. To use
294+
then returns a list of ``str`` representing the packages it could find. To use
275295
it, consider the following directory::
276296
277297
mypkg
@@ -281,14 +301,14 @@ it, consider the following directory::
281301
│   └── __init__.py
282302
├── pkg2
283303
│   └── __init__.py
284-
├── aditional
304+
├── additional
285305
│   └── __init__.py
286306
└── pkg
287307
└── namespace
288308
└── __init__.py
289309
290310
To have setuptools to automatically include packages found
291-
in ``src`` that starts with the name ``pkg`` and not ``additional``:
311+
in ``src`` that start with the name ``pkg`` and not ``additional``:
292312
293313
.. tab:: setup.cfg
294314
@@ -364,8 +384,8 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``:
364384
365385
Finding namespace packages
366386
--------------------------
367-
``setuptools`` provides the ``find_namespace:`` (``find_namespace_packages()``)
368-
which behaves similarly to ``find:`` but works with namespace package.
387+
``setuptools`` provides ``find_namespace:`` (``find_namespace_packages()``)
388+
which behaves similarly to ``find:`` but works with namespace packages.
369389
370390
Before diving in, it is important to have a good understanding of what
371391
:pep:`namespace packages <420>` are. Here is a quick recap.
@@ -415,7 +435,7 @@ distribution, then you will need to specify:
415435
[options.packages.find]
416436
where = src
417437
418-
``find:`` won't work because timmins doesn't contain ``__init__.py``
438+
``find:`` won't work because ``timmins`` doesn't contain ``__init__.py``
419439
directly, instead, you have to use ``find_namespace:``.
420440
421441
You can think of ``find_namespace:`` as identical to ``find:`` except it
@@ -494,15 +514,15 @@ available to your interpreter.
494514
495515
Legacy Namespace Packages
496516
=========================
497-
The fact you can create namespace package so effortlessly above is credited
498-
to `PEP 420 <https://www.python.org/dev/peps/pep-0420/>`_. It use to be more
517+
The fact you can create namespace packages so effortlessly above is credited
518+
to `PEP 420 <https://www.python.org/dev/peps/pep-0420/>`_. It used to be more
499519
cumbersome to accomplish the same result. Historically, there were two methods
500520
to create namespace packages. One is the ``pkg_resources`` style supported by
501521
``setuptools`` and the other one being ``pkgutils`` style offered by
502522
``pkgutils`` module in Python. Both are now considered deprecated despite the
503523
fact they still linger in many existing packages. These two differ in many
504524
subtle yet significant aspects and you can find out more on `Python packaging
505-
user guide <https://packaging.python.org/guides/packaging-namespace-packages/>`_
525+
user guide <https://packaging.python.org/guides/packaging-namespace-packages/>`_.
506526
507527
508528
``pkg_resource`` style namespace package

0 commit comments

Comments
 (0)