Skip to content

Commit a9fc8c1

Browse files
authored
Merge pull request #239 from ucodery/literalinclude
literalinclude directives
2 parents 7b422d4 + 9492fed commit a9fc8c1

File tree

4 files changed

+192
-83
lines changed

4 files changed

+192
-83
lines changed

CONTRIBUTING.md

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This is a community resource. We welcome contributions in the form of issues and
99
* If you find a typo, feel free to [submit a pull request](https://github.com/pyOpenSci/python-package-guide/pulls) to modify the text directly. Or, if you are less comfortable with pull requests, feel free to open an issue.
1010
* If you want to see a larger change to the content of the guide book, please submit an issue first!
1111

12-
## How this guide structured
12+
## How this guide is structured
1313

1414
Most of this repository is structured for **Sphinx**, a documentation engine built in `Python`. We are using the Sphinx Book Theme and the `myST` syntax to create each page in this book.
1515

@@ -31,18 +31,121 @@ To do so, follow these steps:
3131
1. Install `nox`
3232

3333
```
34-
pip install nox
34+
python -m pip install nox
3535
```
3636
2. Build the documentation:
3737

3838
```
39-
nox -s docs
39+
python -m nox -s docs
4040
```
4141

4242
This should create a local environment in a `.nox` folder, build the documentation (as specified in the `noxfile.py` configuration), and the output will be in `_build/html`.
43+
The site can then be viewed locally by opening the top level `index.html` in your web browser. The exact location of this file will depend on you system, but the output of the following command could be copied into an address bar
44+
45+
```
46+
echo "file://$(pwd)/_build/html/index.html"
47+
```
4348

4449
To build live documentation that updates when you update local files, run the following command:
4550

4651
```
47-
nox -s docs-live
52+
python -m nox -s docs-live
53+
```
54+
55+
When build like this, the output will tell you a localhost address where the site can be viewed, generally http://127.0.0.1:8000.
56+
57+
## Code examples
58+
59+
This guide uses the [literalinclude Sphinx directive](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-literalinclude)
60+
whenever possible to keep code and prose separate. Code for use in the documentation is kept in the `examples/` folder.
61+
62+
### Referencing code in documentation
63+
64+
If an example is present elsewhere in the documentation that you want to use, you can copy the `literalinclude`
65+
directive verbatim and the examples will stay in sync.
66+
67+
If you already see code in the examples folder that you can use for new documentation, a new `literalinclude` can be
68+
made to extract it into the site. Only a relative path to the code is required for a working `literalinclude`, but you
69+
should in almost all cases also provide a `:language:` and `:lines:`. The former makes code examples prettier, and the
70+
later can protect your example from future modifications to the code.
71+
72+
**Pro tip**: As an alternative to `:lines:` there are also the `:start-after:`, `:start-at:`, `:end-before:`, and
73+
`:end-at:` options. And if the example code is Python, `:pyobject:` can be an even more future-proof way to keep the
74+
same documentation content even through code refactors.
75+
76+
If you need example code that doesn't yet exist in `examples/` [see creating code for documentation](#creating-code-for-documentation).
77+
78+
### Creating code for documentation
79+
80+
Whenever you come across a place that could benefit from a code block, instead of writing it in-line with a code fence
81+
(`` ``` `` blocked text) you can write it as a file in its own format. Your example may even already exist; [see referencing code in documentation
82+
](#referencing-code-in-documentation).
83+
84+
If you want to add a new example that doesn't fit into any of the existing example files, you can create a new file and
85+
reference it in a `literalinclude` block. If it makes sense for that file to live within one of the existing example
86+
projects please add it there; otherwise create a new folder in the `examples` directory.
87+
88+
If an existing example is incomplete or a new example makes sense to be added to an existing file, go ahead and add it,
89+
but take care to not break the rest of the guide. Whenever possible, extend the example rather that rewrite it. So for
90+
instance, add new functions to the end of the file, new methods after all existing ones in a class.
91+
92+
Example code is checked for correctness, so adding a new example may require adding additional tests for coverage, and
93+
will require fixing any failing tests.
94+
95+
***⚠️ WARNING***: great care should be taken when modifying existing example code, especially any modification beyond
96+
appending to the end of the file. All code examples are (potentially) shared examples. This makes for more consistent
97+
examples in the guide but can mean action-at-a-distance when modifying the examples for one particular use case.
98+
If you find yourself modifying existing examples try running this command and then checking those pages in a new build.
99+
```bash
100+
grep -lr '\.\./examples/path/to/modified\.py' documentation/
101+
```
102+
103+
Example:
104+
105+
Instead of writing example code in markdown like this
106+
107+
````md
108+
Here is an example Python function:
109+
110+
```python
111+
def is_empty(x):
112+
return not bool(len(x))
113+
```
114+
````
115+
116+
The python can be extracted into a `.py` file
117+
```python
118+
def is_empty(x):
119+
return not bool(len(x))
120+
```
121+
122+
````md
123+
Here is an example Python function:
124+
125+
:::{literalinclude} ../examples/contributing_example.py
126+
:language: python
127+
:lines: 1-2
128+
````
129+
130+
As another example, if you only need to show part of a `pyproject.toml`, we already have complete project definitions,
131+
you need only to find the relevant part.
132+
133+
Instead of writing this
134+
````md
135+
Classifiers are just a list of plain strings
136+
```toml
137+
classifiers = [
138+
"Programming Language :: Python :: 3",
139+
"License :: OSI Approved :: BSD License",
140+
"Operating System :: OS Independent",
141+
]
142+
```
143+
````
144+
145+
an example could be extracted from an existing toml file
146+
```md
147+
:::{literalinclude} ../examples/pure-hatch/pyproject.toml
148+
:language: toml
149+
:start-at: classifiers = [
150+
:end-at: ]
48151
```

examples/pure-hatch/pyproject.toml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "examplePy"
7+
authors = [
8+
{name = "Some Maintainer", email = "[email protected]"},
9+
]
10+
maintainers = [
11+
{name = "All the contributors"},
12+
]
13+
description = "An example Python package used to support Python packaging tutorials"
14+
keywords = ["pyOpenSci", "python packaging"]
15+
readme = "README.md"
16+
classifiers = [
17+
"Programming Language :: Python :: 3",
18+
"License :: OSI Approved :: BSD License",
19+
"Operating System :: OS Independent",
20+
]
21+
dependencies = [
22+
"dependency-package-name-1",
23+
"dependency-package-name-2",
24+
]
25+
26+
[project.optional-dependencies]
27+
tests = [
28+
"pytest",
29+
"pytest-cov"
30+
]
31+
lint = [
32+
"black",
33+
"flake8"
34+
]
35+
docs = [
36+
"sphinx",
37+
"pydata-sphinx-theme"
38+
]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[build-system]
2+
requires = ["setuptools>=61"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "examplePy"
7+
authors = [
8+
{name = "Some Maintainer", email = "[email protected]"},
9+
]
10+
maintainers = [
11+
{name = "All the contributors"},
12+
]
13+
description = "An example Python package used to support Python packaging tutorials"
14+
keywords = ["pyOpenSci", "python packaging"]
15+
readme = "README.md"
16+
classifiers = [
17+
"Programming Language :: Python :: 3",
18+
"License :: OSI Approved :: BSD License",
19+
"Operating System :: OS Independent",
20+
]
21+
dependencies = [
22+
"dependency-package-name-1",
23+
"dependency-package-name-2",
24+
]

package-structure-code/pyproject-toml-python-package-metadata.md

Lines changed: 23 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ Below that table identifier are key/value pairs that
8888
support configuration for that particular table.
8989

9090
- Below `[build-system]` is considered a table in the toml language.
91-
- Within the build-system table below requires = is a key.
92-
- The associated value for requires is an array containing the value "hatchling".
91+
- Within the `build-system` table below `requires =` is a key.
92+
- The associated value for `requires` is an array containing the value `"hatchling"`.
9393

94-
```toml
95-
[build-system] # <- this is a table
96-
requires = ["hatchling"] # requires = is a key and "hatchling" is a value contained within an array specified by square brackets [].
97-
98-
```
94+
:::{literalinclude} ../examples/pure-hatch/pyproject.toml
95+
:language: toml
96+
:start-at: [build-system]
97+
:end-at: requires = [
98+
:::
9999

100100
### How the pyproject.toml is used when you build a package
101101

@@ -160,11 +160,11 @@ what dependencies your package requires.
160160
- **Authors:** these are the original authors of the package. Sometimes the authors are different from the maintainers. Other times they might be the same.
161161
- **Maintainers:** you can choose to populate this or not. You can populate this using a list with a sub element for each author or maintainer name, email
162162

163-
```toml
164-
authors = [
165-
{name = "A. Random Developer", email = "[email protected]" }
166-
]
167-
```
163+
:::{literalinclude} ../examples/pure-hatch/pyproject.toml
164+
:language: toml
165+
:start-at: authors = [
166+
:end-at: ]
167+
:::
168168

169169
- **dependencies:** dependencies are optional but we strongly suggest you include them in your pyproject.toml. Dependencies will be installed by pip when your project is installed creating a better user-experience.
170170

@@ -194,21 +194,10 @@ To add dependencies to your build, add a `[project.optional-dependencies]` table
194194

195195
Then specify dependency groups as follows:
196196

197-
```
198-
[project.optional-dependencies]
199-
tests = [
200-
"pytest,
201-
"pytest-cov"
202-
]
203-
lint = [
204-
"black",
205-
"flake8"
206-
]
207-
docs = [
208-
"sphinx",
209-
"pydata-sphinx-theme
210-
]
211-
```
197+
:::{literalinclude} ../examples/pure-hatch/pyproject.toml
198+
:language: toml
199+
:start-at: [project.optional-dependencies]
200+
:::
212201

213202
Following the above example, you install dependencies like this:
214203

@@ -232,32 +221,10 @@ You can also setup sets of recursive dependencies. [See this blog post for more.
232221
Below is an example build configuration for a Python project. This example
233222
package setup uses **hatchling** to build the [package's sdist and wheels](python-package-distribution-files-sdist-wheel).
234223

235-
```toml
236-
[build-system]
237-
requires = ["hatchling"]
238-
build-backend = "hatchling.build"
239-
240-
[project]
241-
name = "examplePy"
242-
authors = [
243-
{name = "Some Maintainer", email = "[email protected]"},
244-
]
245-
maintainers = [
246-
{name = "All the contributors"},
247-
]
248-
description = "An example Python package used to support Python packaging tutorials"
249-
keywords = ["pyOpenSci", "python packaging"]
250-
readme = "README.md"
251-
classifiers = [
252-
"Programming Language :: Python :: 3",
253-
"License :: OSI Approved :: BSD License",
254-
"Operating System :: OS Independent",
255-
]
256-
dependencies = [
257-
"dependency-package-name-1",
258-
"dependency-package-name-2",
259-
]
260-
```
224+
:::{literalinclude} ../examples/pure-hatch/pyproject.toml
225+
:language: toml
226+
:end-before: [project.optional-dependencies]
227+
:::
261228

262229
Notice that dependencies are specified in this file.
263230

@@ -278,32 +245,9 @@ of values. It has two keys that specify the build backend API and containing pac
278245
1. `requires =`
279246
1. `build-back-end =`
280247

281-
```
282-
[build-system]
283-
requires = ["setuptools>=61"]
284-
build-backend = "setuptools.build_meta"
285-
286-
[project]
287-
name = "examplePy"
288-
authors = [
289-
{name = "Some Maintainer", email = "[email protected]"},
290-
]
291-
maintainers = [
292-
{name = "All the contributors"},
293-
]
294-
description = "An example Python package used to support Python packaging tutorials"
295-
keywords = ["pyOpenSci", "python packaging"]
296-
readme = "README.md"
297-
classifiers = [
298-
"Programming Language :: Python :: 3",
299-
"License :: OSI Approved :: BSD License",
300-
"Operating System :: OS Independent",
301-
]
302-
dependencies = [
303-
"dependency-package-name-1",
304-
"dependency-package-name-2",
305-
]
306-
```
248+
:::{literalinclude} ../examples/pure-setuptools/pyproject.toml
249+
:language: toml
250+
:::
307251

308252
```{note}
309253
[Click here to read about our packaging build tools including PDM, setuptools, Poetry and Hatch.](/package-structure-code/python-package-build-tools)

0 commit comments

Comments
 (0)