2
2
3
3
:::{objectives}
4
4
In this episode we will create a pip-installable Python package and learn how
5
- to deploy it to PyPI. As example, we will use the star counting script which
6
- we created in the previous episode .
5
+ to deploy it to PyPI. As example, we can use one of the Python scripts from our
6
+ example repository .
7
7
:::
8
8
9
9
10
- ## Creating a Python package with the help of flit
10
+ ## Creating a Python package with the help of [ Flit ] ( https:// flit.pypa.io/ )
11
11
12
12
There are unfortunately many ways to package a Python project:
13
13
- ` setuptools ` is the most common way to package a Python project. It is very
14
14
powerful and flexible, but also can get complex.
15
- - ` flit ` is a simpler alternative to ` setuptools ` . It is less powerful , but
15
+ - ` flit ` is a simpler alternative to ` setuptools ` . It is less versatile , but
16
16
also easier to use.
17
- - ` poetry ` is a modern packaging tool which is more powerful than ` flit ` and
17
+ - ` poetry ` is a modern packaging tool which is more versatile than ` flit ` and
18
18
also easier to use than ` setuptools ` .
19
19
- ` twine ` is another tool to upload packages to PyPI.
20
20
- ...
@@ -26,33 +26,39 @@ There are unfortunately many ways to package a Python project:
26
26
> Make the easy things easy and the hard things possible is an old motto from
27
27
> the Perl community. Flit is entirely focused on the easy things part of that,
28
28
> and leaves the hard things up to other tools.
29
-
30
29
:::
31
30
32
31
33
32
## Step 1: Initialize the package metadata and try a local install
34
33
35
- 1 . Our starting point is that we have a Python script called ` countstars .py`
34
+ 1 . Our starting point is that we have a Python script called ` example .py`
36
35
which we want to package.
37
36
38
37
2 . Now we follow the [ flit quick-start usage] ( https://flit.pypa.io/en/stable/#usage ) and add a docstring to the script and a ` __version__ ` .
39
38
40
39
3 . We then run ` flit init ` to create a ` pyproject.toml ` file and answer few questions. I obtained:
41
- ``` toml
40
+ ``` {code-block} toml
41
+ ---
42
+ emphasize-lines: 6, 13
43
+ ---
42
44
[build-system]
43
45
requires = ["flit_core >=3.2,<4"]
44
46
build-backend = "flit_core.buildapi"
45
47
46
48
[project]
47
- name = " countstars "
48
- authors = [{
name =
" Radovan Bast " ,
email =
" [email protected] " }]
49
+ name = "example "
50
+ authors = [{name = "Firstname Lastname ", email = "[email protected] "}]
49
51
license = {file = "LICENSE"}
50
- classifiers = [" License :: OSI Approved :: MIT License " ]
52
+ classifiers = ["License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2) "]
51
53
dynamic = ["version", "description"]
52
54
53
55
[project.urls]
54
- Home = " https://github.com/workshop-material/countstars "
56
+ Home = "https://example.org "
55
57
```
58
+ To have a more concrete example, if we package the ` generate_data.py ` script
59
+ from the [ example
60
+ repository] ( https://github.com/workshop-material/classification-task ) , then
61
+ replace the name ` example ` with ` generate_data ` .
56
62
57
63
4 . We now add dependencies and also an entry point for the script:
58
64
``` {code-block} toml
@@ -64,22 +70,22 @@ There are unfortunately many ways to package a Python project:
64
70
build-backend = "flit_core.buildapi"
65
71
66
72
[project]
67
- name = "countstars "
68
- authors = [{name = "Radovan Bast ", email = "[email protected] "}]
73
+ name = "example "
74
+ authors = [{name = "Firstname Lastname ", email = "[email protected] "}]
69
75
license = {file = "LICENSE"}
70
- classifiers = ["License :: OSI Approved :: MIT License "]
76
+ classifiers = ["License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2) "]
71
77
dynamic = ["version", "description"]
72
78
dependencies = [
73
79
"click",
74
- "matplotlib ",
75
- "scikit-image ",
80
+ "numpy ",
81
+ "pandas ",
76
82
]
77
83
78
84
[project.urls]
79
- Home = "https://github.com/workshop-material/countstars "
85
+ Home = "https://example.org "
80
86
81
87
[project.scripts]
82
- count-stars = "countstars :main"
88
+ example = "example :main"
83
89
```
84
90
85
91
5 . Before moving on, try a local install:
@@ -99,21 +105,23 @@ There are unfortunately many ways to package a Python project:
99
105
100
106
If a local install worked, push the ` pyproject.toml ` to GitHub and try to install the package from GitHub.
101
107
102
- In a ` requirements.txt ` file, you can specify the GitHub repository and the branch:
108
+ In a ` requirements.txt ` file, you can specify the GitHub repository and the
109
+ branch (adapt the names):
103
110
```
104
- git+https://github.com/workshop-material/countstars .git@main
111
+ git+https://github.com/ORGANIZATION/REPOSITORY .git@main
105
112
```
106
113
107
- A corresponding ` envionment.yml ` file for conda would look like this:
114
+ A corresponding ` envionment.yml ` file for conda would look like this (adapt the
115
+ names):
108
116
``` yaml
109
- name : countstars
117
+ name : experiment
110
118
channels :
111
119
- conda-forge
112
120
dependencies :
113
- - python= 3.12
121
+ - python <= 3.12
114
122
- pip
115
123
- pip :
116
- - git+https://github.com/workshop-material/countstars .git@main
124
+ - git+https://github.com/ORGANIZATION/REPOSITORY .git@main
117
125
` ` `
118
126
119
127
Does it install and run? If yes, move on to the next step (test-PyPI and later
141
149
jobs:
142
150
build:
143
151
permissions: write-all
144
- runs-on: ubuntu-latest
152
+ runs-on: ubuntu-24.04
145
153
146
154
steps:
147
155
- name: Switch branch
0 commit comments