Skip to content

Commit 52643b5

Browse files
authored
Merge branch 'main' into ci
2 parents fb8519a + 4b45c5d commit 52643b5

File tree

5 files changed

+98
-59
lines changed

5 files changed

+98
-59
lines changed

package-structure-code/intro.md

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
1-
# Python package structure information
1+
# Python Package Structure
22

3-
This section provides guidance on your Python package's structure, code formats
4-
and style. It also reviews the various packaging tools that you can use to
5-
support building and publishing your package.
3+
This section provides guidance on your Python package's structure, code format,
4+
and style. It also reviews the various [packaging tools](python-package-build-tools) you can use to
5+
[build](python-package-distribution-files-sdist-wheel) and [publish](publish-python-package-pypi-conda) your Python package.
6+
7+
If you want end-to-end tutorials, check out our tutorial series that starts by introducing [what a Python package is](what-is-a-package).
68

79
If you are confused by Python packaging, you are not alone! The good news is
8-
there are some great modern packaging tools that ensure that you're following
9-
best practices. Here, we review tool features and suggest tools that might be
10-
best fitted for your workflow.
10+
that some great modern packaging tools ensure you follow
11+
best practices. Here, we review tool features and suggest tools you can use
12+
for your Python packaging workflow.
13+
14+
:::{button-link} /tutorials/intro
15+
:color: success
16+
:class: sd-rounded-pill float-left
17+
18+
Checkout our beginning-to-end create a Python package tutorials
19+
20+
:::
21+
22+
23+
:::{admonition} How this content is developed
24+
All of the content in this guide has been vetted by community members, including maintainers and developers of the core packaging tools.
25+
:::
26+
1127

1228
:::::{grid} 1 1 2 2
1329
:class-container: text-center

package-structure-code/python-package-distribution-files-sdist-wheel.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ Also note that we are not discussing conda build workflows in this section.
152152
```
153153

154154
(python-source-distribution)=
155-
## Source Distribution (sdist)
155+
## What is a source distribution (sdist)
156156

157157
**Source files** are the unbuilt files needed to build your
158158
package. These are the "raw / as-is" files that you store on GitHub or whatever
@@ -226,7 +226,7 @@ the sdist may also contain a file that stores the version.
226226
```
227227

228228
(python-wheel)=
229-
## Wheel (.whl files):
229+
## What is a Python wheel (whl):
230230

231231
A wheel file is a ZIP-format archive whose filename follows a specific format
232232
(below) and has the extension `.whl`. The `.whl` archive contains a specific

package-structure-code/python-package-structure.md

+68-48
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,41 @@
22

33
There are two different layouts that you will commonly see
44
within the Python packaging ecosystem:
5-
[src and flat layouts.](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/)
5+
src and flat layouts.
66
Both layouts have advantages for different groups of maintainers.
77

88
We strongly suggest, but do not require, that you use the **src/** layout (discussed below)
99
for creating your Python package. This layout is also recommended in the
10-
[PyPA packaging guide](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
10+
[PyPA packaging guide tutorial](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
1111

1212
```{admonition} pyOpenSci will never require a specific package structure for peer review
1313
:class: important
1414
15-
We understand that it would be tremendous effort for existing
15+
We understand that it would take significant effort for existing
1616
maintainers to move to a new layout.
1717
1818
The overview on this page presents recommendations that we think are best for
1919
someone getting started with Python packaging or someone who's package
2020
has a simple build and might be open to moving to a more fail-proof approach.
21+
22+
Other resources you can check out:
23+
* [PyPA's overview of src vs flat layouts](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/)
2124
```
2225

23-
An example of the **src/package** layout structure can be seen below.
26+
You can use tools like Hatch to quickly create a modern Python package structure. Check out our quickstart tutorial:
27+
28+
29+
:::{button-link} /tutorials/installable-code.html#step-1-set-up-the-package-directory-structure
30+
:color: success
31+
:class: sd-rounded-pill float-left
32+
33+
Want to learn how to create the structure to build your package? Click here.
34+
35+
:::
36+
37+
## What is the Python package source layout?
38+
39+
An example of the **src/package** layout structure is below.
2440

2541
```
2642
myPackageRepoName
@@ -44,8 +60,8 @@ myPackageRepoName
4460

4561
Note the location of the following directories in the example above:
4662

47-
- **docs/:** discussed in our docs chapter, this directory contains your user-facing documentation website. In a **src/** layout docs/ are normally included at the same directory level of the **src/** folder.
48-
- **tests/** this directory contains the tests for your project code. In a **src/** layout tests are normally included at the same directory level of the **src/** folder.
63+
- **docs/:** Discussed in our docs chapter, this directory contains your user-facing documentation website. In a **src/** layout docs/ are normally included at the same directory level as the **src/** folder.
64+
- **tests/** This directory contains the tests for your project code. In a **src/** layout, tests are normally included at the same directory level as the **src/** folder.
4965
- **src/package/**: this is the directory that contains the code for your Python project. "Package" is normally your project's name.
5066

5167
Also in the above example, notice that all of the core documentation files that
@@ -61,14 +77,12 @@ include:
6177
<!-- TODO: CHANGELOG is not mentioned in either documentation nor peer review -->
6278

6379
```{button-link} https://www.pyopensci.org/python-package-guide/documentation
64-
:color: primary
80+
:color: info
6581
:class: sd-rounded-pill
6682
6783
Click here to read about our packaging documentation requirements.
6884
```
6985

70-
While we recommend the **src/** layout we also review the **flat** layout here. Both are used in the Python ecosystem.
71-
7286
```{admonition} Example scientific packages that use **src/package** layout
7387
7488
* [Sourmash](https://github.com/sourmash-bio/sourmash)
@@ -81,14 +95,13 @@ While we recommend the **src/** layout we also review the **flat** layout here.
8195

8296
## The src/ layout and testing
8397

84-
The benefit of using the **src/package** layout, particularly if you
85-
are creating a new package, is that it ensures tests are run against the
98+
The benefit of using the **src/package** layout is that it ensures tests are run against the
8699
installed version of your package rather than the files in your package
87100
working directory. If you run your tests on your files rather than the
88-
installed version, you may be missing issues that users encounter when
101+
installed version of your package, you may be missing issues that users encounter when
89102
your package is installed.
90103

91-
If `tests/` are outside of the **src/package** directory, they aren't included in the package wheel. This makes your package size slightly smaller which then places places a smaller storage burden on PyPI which has over 400,000 packages to support.
104+
If `tests/` are outside the **src/package** directory, they aren't included in the package's [wheel](python-wheel). This makes your package size slightly smaller, which places a smaller storage burden on PyPI, and makes them faster to fetch.
92105

93106
- [Read more about reasons to use the **src/package** layout](https://hynek.me/articles/testing-packaging/)
94107

@@ -98,14 +111,14 @@ By default, Python adds a module in your current working directory to the front
98111
99112
This means that if you run your tests in your package's working directory, using a flat layout, `/package/module.py`, Python will discover `package/module.py` file before it discovers the installed package.
100113
101-
However, if your package lives in a src/ directory structure **src/package** then it won't be, by default, added to the Python path. This means that when you import your package, Python will be forced to search the active environment (which has your package installed).
114+
However, if your package lives in a src/ directory structure **src/package**, then it won't be added to the Python path by default. This means that when you import your package, Python will be forced to search the active environment (which has your package installed).
102115
103-
Note: Python versions 3.11 and above have a path setting that can be adjusted to ensure the priority is to use installed packages first (e.g. `PYTHONSAFEPATH`).
116+
Note: Python versions 3.11 and above have a path setting that can be adjusted to ensure the priority is to use installed packages first (e.g., `PYTHONSAFEPATH`).
104117
```
105118

106-
### Sometimes tests are needed in a distribution
119+
### Don't include tests in your package wheel
107120

108-
We do not recommend including tests as part of your package wheel by default. However, not including tests in your package distribution will make it harder for people other than yourself to test whether your package is functioning correctly on their system. If you have a small test suite (Python files + data), and think your users may want to run tests locally on their systems, you can include tests by moving the `tests/` directory into the **src/package** directory (see example below).
121+
Writing [tests](tests-intro) for your package is important; however, we do not recommend including tests as part of your [package wheel](python-wheel) by default. However, not including tests in your package distribution will make it harder for people other than yourself to test whether your package runs properly on their system. If you have a small test suite (Python files + data), and think your users may want to run tests locally on their systems, you can include tests by moving the `tests/` directory into the **src/package** directory (see example below).
109122

110123
```bash
111124
src/
@@ -114,69 +127,76 @@ src/
114127
docs/
115128
```
116129

117-
Including the **tests/** directory in your **src/package** directory ensures that tests will be included in your package's wheel.
130+
Including the **tests/** directory in your **src/package** directory ensures that tests will be included in your package's [wheel](python-wheel).
118131

119132
Be sure to read the [pytest documentation for more about including tests in your package distribution](https://docs.pytest.org/en/7.2.x/explanation/goodpractices.html#choosing-a-test-layout-import-rules).
120133

121134
```{admonition} Challenges with including tests and data in a package wheel
122135
:class: tip
123136
124-
Tests, especially when accompanied by test data can create a few small challenges including:
137+
Tests, especially when accompanied by test data, can create a few small challenges, including:
125138
126-
- Take up space in your distribution which will build up over time as storage space on PyPI
127-
- Large file sizes can also slow down package install.
139+
- Take up space in your distribution, which will build up over time as storage space on PyPI
140+
- Large file sizes can also slow down package installation.
128141
129-
However, in some cases, particularly in the scientific Python ecosystems you may need to include tests.
142+
However, in some cases, particularly in the scientific Python ecosystem, you may need to include tests.
130143
```
131144

132145
### **Don't include test suite datasets in your package**
133146

134-
If you do include your tests in your package distribution, we strongly
147+
If you include your tests in your package distribution, we strongly
135148
discourage you from including data in your test suite directory. Rather,
136149
host your test data in a repository such as Figshare or Zenodo. Use a
137150
tool such as [Pooch](https://www.fatiando.org/pooch/latest/) to access
138151
the data when you (or a user) runs tests.
139152

140-
Check out the testing section of our guide for more information about tests.
153+
For more information about Python package tests, see the [tests section of our guide](tests-intro).
141154

142155
- The **src/package** layout is semantically more clear. Code is always found in the
143156
**src/package** directory, `tests/` and `docs/`are in the root directory.
144157

145158
```{important}
146-
If your package tests require data, we suggest that you do NOT include that
147-
data within your package structure. We will discuss this in more detail in a
148-
tutorial. Include data in your package structure increases the size of your
159+
If your package tests require data, do NOT include that
160+
data within your package structure. Including data in your package structure increases the size of your
149161
distribution files. This places a maintenance toll on repositories like PyPI and
150162
Anaconda.org that have to deal with thousands of package uploads.
151163
```
152164

153-
## About the flat Python package layout
154165

155-
Currently most scientific packages use the **flat-layout** given:
166+
:::{button-link} /tutorials/installable-code.html#step-1-set-up-the-package-directory-structure
167+
:color: success
168+
:class: sd-rounded-pill float-left
156169

157-
- It's the most commonly found layout with the scientific Python ecosystem and
158-
people tend to look to other packages / maintainers that they respect for examples
159-
of how to build Python packages.
160-
- Many Python tools depend upon tools in other language and / or complex builds
161-
with compilation steps. Many developers thus appreciate / are used to features
162-
of the flat layout.
163170

164-
While we present this layout here in our guide, we suggest that those just
165-
getting started with python packaging start with the src/package layout
166-
discussed above. Numerous packages in the ecosystem [have had to move to a
167-
src/ layout](https://github.com/scikit-build/cmake-python-distributions/pull/145)
171+
Click here for a quickstart tutorial on creating your Python package.
172+
173+
:::
174+
175+
(flat-layout)=
176+
## What is the flat Python package layout?
177+
178+
Many scientific packages use the **flat-layout** given:
179+
180+
- This layout is used by many core scientific Python packages such as NumPy, SciPy, and Matplotlib.
181+
- Many Python tools depend upon tools in other languages and/or complex builds
182+
with compilation steps. Many maintainers prefer features
183+
of the flat layout for more complex builds.
184+
185+
While we suggest that you use the **src/package** layout discussed above, it's important to also
186+
understand the flat layout, especially if you plan to contribute to a package that uses this layout.
187+
168188

169189
```{admonition} Why most scientific Python packages do not use source
170190
:class: tip
171191
172-
In most cases the advantages of using the **src/package** layout for
173-
larger scientific packages that already use flat approach are not worth it.
174-
Moving from a flat layout to a **src/package** layout would come at a significant cost to
175-
maintainers.
192+
In most cases, moving to the **src/package** layout for
193+
larger scientific packages that already use a flat layout would consume significant time.
176194
177195
However, the advantages of using the **src/package** layout for a beginner are significant.
178-
As such, we recommend that if you are getting started with creating a package,
179-
that you consider using a **src/package** layout.
196+
As such, we recommend that you use the **src/package** layout if you are creating a new package.
197+
198+
Numerous packages in the ecosystem [have had to move to a
199+
**src/package** layout](https://github.com/scikit-build/cmake-python-distributions/pull/145).
180200
```
181201

182202
## What does the flat layout structure look like?
@@ -234,7 +254,7 @@ There are some benefits to the scientific community in using the flat layout.
234254
235255
It would be a significant maintenance cost and burden to move all of these
236256
packages to a different layout. The potential benefits of the source layout
237-
for these tools is not worth the maintenance investment.
257+
for these tools are not worth the maintenance investment.
238258
```
239259

240260
<!--
@@ -243,12 +263,12 @@ Not sure where to put this now ... most new users won't have multiple packages.
243263
```{admonition} Multiple packages in a src/ folder
244264
:class: tip
245265
246-
In some more advanced cases you may have more than one package in your src/ directory. See [black's GitHub repo](https://github.com/psf/black/tree/main/src) for an example of this. However, for most beginners you will likely only have one sub-directory in your **src/** folder.
266+
In some more advanced cases, you may have more than one package in your **src/** directory. See [Black's GitHub repo](https://github.com/psf/black/tree/main/src) for an example of this. However, for most beginners you will likely only have one sub-directory in your **src/** folder.
247267
``` -->
248268

249269
<!--
250270
```{admonition} A few notes about the src/ layout
251271
:class: tip
252272
253-
It is important to note here that sometimes when using the src/package structure the directory name (e.g. package name) is different from the actual project or package name. What is important to take away here is that you should store your code within a sub directory within **src/**.
273+
It is important to note here that sometimes, when using the **src/package** structure, the directory name (e.g., package name) is different from the actual project or package name. What is important to take away here is that you should store your code within a subdirectory within **src/**.
254274
``` -->

tests/index.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
(tests-intro)=
12
# Tests and data for your Python package
23

34
Tests are an important part of your Python package because they
45
provide a set of checks that ensure that your package is
56
functioning how you expect it to.
67

7-
In this section you will learn more about the importance of writing
8-
tests for your Python package and how you can setup infrastructure
8+
In this section, you will learn more about the importance of writing
9+
tests for your Python package and how you can set up infrastructure
910
to run your tests both locally and on GitHub.
1011

1112

tutorials/intro.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
(packaging-101)=
12
# Python packaging 101
23

34
_A start to finish beginner-friendly tutorial_
@@ -75,6 +76,7 @@ After reading this lesson you will:
7576

7677
:::
7778

79+
(what-is-a-package)=
7880
## What is a Python package?
7981

8082
At a high level, you can think about a Python package as a toolbox

0 commit comments

Comments
 (0)