@@ -38,8 +38,142 @@ included manually in the following manner:
38
38
packages = [' mypkg1' , ' mypkg2' ]
39
39
)
40
40
41
- This can get tiresome really quickly. To speed things up, we introduce two
42
- functions provided by setuptools:
41
+ This can get tiresome really quickly. To speed things up, you can rely on
42
+ setuptools automatic discovery, or use the provided tools, as explained in
43
+ the following sections.
44
+
45
+
46
+ Automatic discovery
47
+ ===================
48
+
49
+ By default setuptools will consider 2 popular project layouts, each one with
50
+ its own set of advantages and disadvantages [#layout1 ]_ [#layout2 ]_.
51
+
52
+ src-layout:
53
+ The project should contain a ``src `` directory under the project root and
54
+ all modules and packages meant for distribution are placed inside this
55
+ directory::
56
+
57
+ project_root_directory
58
+ ├── pyproject.toml
59
+ ├── setup.cfg # or setup.py
60
+ ├── ...
61
+ └── src/
62
+ └── mypkg/
63
+ ├── __init__.py
64
+ ├── ...
65
+ └── mymodule.py
66
+
67
+ This layout is very handy when you wish to use automatic discovery,
68
+ since you don't have to worry about other Python files or folders in your
69
+ project root being distributed by mistake. In some circumstances it can be
70
+ also less error-prone for testing or when using :pep: `420 `-style packages.
71
+ On the other hand you cannot rely on the implicit ``PYTHONPATH=. `` to fire
72
+ up the Python REPL and play with your package (you will need an
73
+ `editable install `_ to be able to do that).
74
+
75
+ flat-layout (also known as "adhoc"):
76
+ The package folder(s) are placed directly under the project root::
77
+
78
+ project_root_directory
79
+ ├── pyproject.toml
80
+ ├── setup.cfg # or setup.py
81
+ ├── ...
82
+ └── mypkg/
83
+ ├── __init__.py
84
+ ├── ...
85
+ └── mymodule.py
86
+
87
+ This layout is very practical for using the REPL, but in some situations
88
+ it can be can be more error-prone (e.g. during tests or if you have a bunch
89
+ of folders or Python files hanging around your project root)
90
+
91
+ There is also a handy variation of the *flat-layout * for utilities/libraries
92
+ that can be implemented with a single Python file:
93
+
94
+ single-module approach (or "few top-level modules"):
95
+ Standalone modules are placed directly under the project root, instead of
96
+ inside a package folder::
97
+
98
+ project_root_directory
99
+ ├── pyproject.toml
100
+ ├── setup.cfg # or setup.py
101
+ ├── ...
102
+ └── single_file_lib.py
103
+
104
+ Setuptools will automatically scan your project directory looking for these
105
+ layouts and try to guess the correct values for the :ref: `packages <declarative
106
+ config>` and :doc: `py_modules </references/keywords >` configuration.
107
+
108
+ To avoid confusion, file and folder names that are used by popular tools (or
109
+ that correspond to well-known conventions, such as distributing documentation
110
+ alongside the project code) are automatically filtered out in the case of
111
+ *flat-layouts *:
112
+
113
+ .. autoattribute :: setuptools.discovery.FlatLayoutPackageFinder.DEFAULT_EXCLUDE
114
+
115
+ .. autoattribute :: setuptools.discovery.FlatLayoutModuleFinder.DEFAULT_EXCLUDE
116
+
117
+ Also note that you can customise your project layout by explicitly setting
118
+ ``package_dir ``:
119
+
120
+ .. tab :: setup.cfg
121
+
122
+ .. code-block :: ini
123
+
124
+ [options]
125
+ # ...
126
+ package_dir =
127
+ = lib
128
+ # similar to "src-layout" but using the "lib" folder
129
+ # pkg.mod corresponds to lib/pkg/mod.py
130
+ # OR
131
+ package_dir =
132
+ pkg1 = lib1
133
+ # pkg1.mod corresponds to lib1/mod.py
134
+ # pkg1.subpkg.mod corresponds to lib1/subpkg/mod.py
135
+ pkg2 = lib2
136
+ # pkg2.mod corresponds to lib2/mod.py
137
+ pkg2.subpkg = lib3
138
+ # pkg2.subpkg.mod corresponds to lib3/mod.py
139
+
140
+ .. tab :: setup.py
141
+
142
+ .. code-block :: python
143
+
144
+ setup(
145
+ # ...
146
+ package_dir = {" " : " lib" }
147
+ # similar to "src-layout" but using the "lib" folder
148
+ # pkg.mod corresponds to lib/pkg/mod.py
149
+ )
150
+
151
+ # OR
152
+
153
+ setup(
154
+ # ...
155
+ package_dir = {
156
+ " pkg1" : " lib1" , # pkg1.mod corresponds to lib1/mod.py
157
+ # pkg1.subpkg.mod corresponds to lib1/subpkg/mod.py
158
+ " pkg2" : " lib2" , # pkg2.mod corresponds to lib2/mod.py
159
+ " pkg2.subpkg" : " lib3" # pkg2.subpkg.mod corresponds to lib3/mod.py
160
+ # ...
161
+ )
162
+
163
+ .. important:: Automatic discovery will ** only** be enabled if you don' t
164
+ provide any configuration for both `` packages`` and `` py_modules`` .
165
+ If at least one of them is explicitly set , automatic discovery will not take
166
+ place.
167
+
168
+
169
+ Custom discovery
170
+ ================
171
+
172
+ If the automatic discovery does not work for you
173
+ (e.g., you want to * include* in the distribution top- level packages with
174
+ reserved names such as `` tasks`` , `` example`` or `` docs`` , or you want to
175
+ * exclude* nested packages that would be otherwise included), you can use
176
+ the provided tools for package discovery:
43
177
44
178
.. tab:: setup.cfg
45
179
@@ -61,7 +195,7 @@ functions provided by setuptools:
61
195
62
196
63
197
Using `` find:`` or `` find_packages``
64
- ====================================
198
+ ------------------------------------
65
199
Let' s start with the first tool. ``find:`` (``find_packages``) takes a source
66
200
directory and two lists of package name patterns to exclude and include, and
67
201
then return a list of `` str `` representing the packages it could find. To use
@@ -113,7 +247,7 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``:
113
247
.. _Namespace Packages:
114
248
115
249
Using `` find_namespace:`` or `` find_namespace_packages``
116
- ========================================================
250
+ --------------------------------------------------------
117
251
`` setuptools`` provides the `` find_namespace:`` (`` find_namespace_packages`` )
118
252
which behaves similarly to `` find:`` but works with namespace package. Before
119
253
diving in , it is important to have a good understanding of what namespace
@@ -249,3 +383,9 @@ file contains the following:
249
383
__path__ = __import__ (' pkgutil' ).extend_path(__path__ , __name__ )
250
384
251
385
The project layout remains the same and `` setup.cfg`` remains the same.
386
+
387
+
388
+ .. [# layout1] https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure
389
+ .. [# layout2] https://blog.ionelmc.ro/2017/09/25/rehashing-the-src-layout/
390
+
391
+ .. _editable install: https:// pip.pypa.io/ en/ stable/ cli/ pip_install/ # editable-installs
0 commit comments