Skip to content

Commit

Permalink
Convert packaging lesson to use pyproject.toml instead (#235)
Browse files Browse the repository at this point in the history
* Convert packaging lesson to use pyproject.toml instead

* Update ch04packaging/03Packaging.ipynb.py

Co-authored-by: David Pérez-Suárez <d.perez-suarez@ucl.ac.uk>

---------

Co-authored-by: David Pérez-Suárez <d.perez-suarez@ucl.ac.uk>
  • Loading branch information
willGraham01 and dpshelio authored Nov 22, 2023
1 parent 14fa606 commit 11756dc
Showing 1 changed file with 89 additions and 49 deletions.
138 changes: 89 additions & 49 deletions ch04packaging/03Packaging.ipynb.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,38 @@
# %autoreload 2

# %% [markdown]
# ### Using setuptools
# ### Using pyproject.toml

# %% [markdown]
# Since June 2020, python's recommendation for creating a package is to specify package information in a `pyproject.toml` file.
# Older projects used a `setup.py` or `setup.cfg` file instead - and in fact the new `pyproject.toml` file in many ways mirrors this old format.
# A lot of projects and packages have not yet switched over from `setup.py` to `pyproject.toml`, so don't be surprised to see a mixture of the two formats when you're looking at other people's packages.

# %% [markdown]
# For our `greetings` package, right now we are adding only the name of the package and its version number.
# This information is included in the `project` section of our `pyproject.toml` file.
#
# But we also need to tell users how to build the package from these specifications.
# This information is specified in the `build-system` section of our `toml` file.
# In this case, we'll be using `setuptools` to build our package, so we list it in the `requires` field.
# We also need `setuptools_scm[toml]` so that `setuptools` can understand the settings we give it in our `.toml` file, and `wheel` to make the package distribution.
#
# To make python code into a package, we need to write a `setup.py` file. For now we are adding only the name of the package and its version number.
# Finally, we can set specific options for `setuptools` using additional sections in `pyproject.toml`: in this case, we will tell `setuptools` that it needs to find **and include** all of the files in our `greetings` folder.

# %%
# %%writefile greetings_repo/setup.py
# %%writefile greetings_repo/pyproject.toml

[project]
name = "Greetings"
version = "0.1.0"

[build-system]
requires = ["setuptools", "setuptools_scm[toml]>=6.2", "wheel"]

from setuptools import setup, find_packages
[tool.setuptools.packages.find]
include = ["greetings*"]

setup(
name="Greetings",
version="0.1.0",
packages=find_packages(),
)
[tool.setuptools_scm]


# %% [markdown]
Expand All @@ -109,7 +125,7 @@

# %% [markdown]
#
# And the package will be then available to use everywhere on the system. But so far this package doesn't contain anythin and there's nothing we can run! We need to add some files first.
# And the package will be then available to use everywhere on the system. But so far this package doesn't contain anything and there's nothing we can run! We need to add some files first.
#

# %% [markdown]
Expand Down Expand Up @@ -256,20 +272,25 @@ def process():
# %% [markdown]
# This allows us to create a command to execute part of our library. In this case when we execute `greet` on the terminal, we will be calling the `process` function under `greetings/command.py`.
#
# We can encode this into our package information by specifying the `project.scripts` field in our `pyproject.toml` file.

# %%
# %%writefile greetings_repo/setup.py
# %%writefile greetings_repo/pyproject.toml

from setuptools import setup, find_packages
[project]
name = "Greetings"
version = "0.1.0"

setup(
name="Greetings",
version="0.1.0",
packages=find_packages(),
entry_points={
'console_scripts': [
'greet = greetings.command:process'
]})
[project.scripts]
greet = "greetings.command:process"

[build-system]
requires = ["setuptools", "setuptools_scm[toml]>=6.2", "wheel"]

[tool.setuptools.packages.find]
include = ["greetings*"]

[tool.setuptools_scm]

# %% language="bash"
# cd greetings_repo
Expand All @@ -294,7 +315,7 @@ def process():
# ### Specify dependencies

# %% [markdown]
# Let's give some live to our output using ascii art
# Let's give some life to our output using ascii art

# %%
# %%writefile greetings_repo/greetings/command.py
Expand Down Expand Up @@ -324,23 +345,29 @@ def process():
process()

# %% [markdown]
# We use the setup.py file to specify the packages we depend on using `install_requires`:
# We use the `dependencies` field of the `project` section in our `pyproject.toml` file to specify the packages we depend on.
# We provide the names of the packages as a list of strings.

# %%
# %%writefile greetings_repo/setup.py
# %%writefile greetings_repo/pyproject.toml

[project]
name = "Greetings"
version = "0.1.0"
dependencies = [
"art",
]

from setuptools import setup, find_packages
[project.scripts]
greet = "greetings.command:process"

setup(
name="Greetings",
version="0.1.0",
packages=find_packages(),
install_requires=['art', 'pyyaml'],
entry_points={
'console_scripts': [
'greet = greetings.command:process'
]}
)
[build-system]
requires = ["setuptools", "setuptools_scm[toml]>=6.2", "wheel"]

[tool.setuptools.packages.find]
include = ["greetings*"]

[tool.setuptools_scm]

# %% [markdown]
# When installing the package now, pip will also install the dependencies automatically.
Expand Down Expand Up @@ -569,23 +596,36 @@ def test_greeter(fixture):
# pytest --doctest-modules

# %% [markdown]
# Finally, if we don't want to include the tests when we distribute our software for our users, you can include that using the `exclude` option on `find_packages` on `setup.py`.
# Finally, we typically don't want to include the tests when we distribute our software for our users.
# We can make sure they are not included using the `exclude` option on when telling `setuptools` to find packages.
#
# Additionally, we can make sure that our README and LICENSE are included in our package metadata by declaring them in the `readme` and `license` fields under the `project` section.
# If you're using a particularly common or standard license, you can even provide the name of the license, rather than the file, and your package builder will take care of the rest!

# %%
# %%writefile greetings_repo/setup.py

from setuptools import setup, find_packages

setup(
name="Greetings",
version="0.1.0",
packages=find_packages(exclude=['*.test']),
install_requires=['art', 'pyyaml'],
entry_points={
'console_scripts': [
'greet = greetings.command:process'
]}
)
# %%writefile greetings_repo/pyproject.toml

[project]
name = "Greetings"
version = "0.1.0"
readme = "README.md"
license = { file = "LICENSE.md" }
dependencies = [
"art",
"pyyaml",
]

[project.scripts]
greet = "greetings.command:process"

[build-system]
requires = ["setuptools", "setuptools_scm[toml]>=6.2", "wheel"]

[tool.setuptools.packages.find]
include = ["greetings*"]
exclude = ["tests*"]

[tool.setuptools_scm]

# %% [markdown]
# ### Developer Install
Expand Down

0 comments on commit 11756dc

Please sign in to comment.