Python is a great tool for automation of tasks, web development, IoT , AI, robotics, and several other fields.
It’s among the top 5 most-used programming languages in the world. The reason for the popularity of python is because of the general approach of python which emphasizes on code readability and the thousands of python packages available.
It makes sense to understand how to create your own package, this way you can share your codes with the world or even contribute your codes to open-source packages that have been essential in your programming journey.
Python Package Index abbreviated as "PyPI" is a third-party software repository for python. Anyone with the might and will can publish their packages on PyPi which anyone in the world can install and use.
Creating Package Locally and Deploying to PyPI
Run the following command to upgrade pip and ensure you are using the latest pip package.
Structuring Your Project
We will be structuring our code as below.
packaging_tutorial/ ├── LICENSE ├── pyproject.toml ├── README.md ├── setup.cfg ├── src/ │ └── example_package/ │ ├── __init__.py │ └── example.py └── tests/
__init__.py is required to import the directory as a package, and should be empty.
This is where we write our python module. In our case, the module does simple addition.
This tells build tools pip and build what is required to build your project in our case we’ll use
[build-system] requires = [ "setuptools>=42", "wheel" ] build-backend = "setuptools.build_meta"
This gives more information to setuptools about the package.
NB: Change the name to include your username; this ensures that you have a unique package name and that your package doesn’t conflict with packages uploaded by other people following this tutorial
[metadata] name = example-pkg-YOUR-USERNAME-HERE version = 0.0.1 author = Example Author author_email = email@example.com description = A small example package long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/pypa/sampleproject project_urls = Bug Tracker = https://github.com/pypa/sampleproject/issues classifiers = Programming Language :: Python :: 3 License :: OSI Approved :: MIT License Operating System :: OS Independent [options] package_dir = = src packages = find: python_requires = >=3.6 [options.packages.find] where = src
# Example Package This is a simple example package. You can use [Github-flavored Markdown](https://guides.github.com/features/mastering-markdown/) to write your content.
Copyright (c) 2018 The Python Packaging Authority Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Generating Distribution and Publishing Locally
You will need a PyPI account for this. So go ahead and create a PyPI account. https://pypi.org/ .
To securely upload your project, you’ll need a PyPI API token. Create one at https://pypi.org/manage/account/#api-tokens, setting the “Scope” to “Entire account”. Don’t close the page until you have copied and saved the token — you won’t see that token again.
Now run the following commands while inside your :
$ python3 -m pip install — upgrade build // Upgrade PIP $ python3 -m build // Build distribution, will create dist folder $ python3 -m pip install --upgrade twine // Install twine $ python3 -m twine upload --repository pypi dist/* // Upload package
Test the package by trying to install it.
pip install PackageName
Auto deploying on GitLab CI
Now that we know the process for manually deploying a package on PyPI the next task is automating deployment of code using GitLab CI.
Navigate to your project settings under CI/CD and add to variables,
PYPI_USERNAME. The value of the keys should be the PyPI password which is the token we created and your PyPI username respectively.
We are also required to protect the tags we will be using since we will be using tags to auto-deploy. Otherwise, our deployment will fail.
To do that Navigate to Settings>Repositories
In this case, we protect
v*. This implies tags that start with
v will be run as protected and will be supplied with the variable we created. Tags that don't start with
v will not be supplied with variables.
Crafting our CI/CD with .gitlab-ci.yml
We will let our GitLab auto-deploy our code however to do that we require
The main challenge we face during auto-deployment is the management of the project version. We sort this by only deploying when we tag the project version.
Go ahead and create it and add the following code:
build-package: stage: deploy image: python:3.7 before_script: - python3 -m pip install --upgrade twine - python3 -m pip install --upgrade build - sed -i -e "s/v-latest/$CI_COMMIT_TAG/" setup.cfg - cat setup.cfg variables: TWINE_USERNAME: $PYPI_USERNAME TWINE_PASSWORD: $PYPI_PASSWORD script: - python3 -m build - python3 -m twine upload dist/* only: - tags
In order for the package version to be replaced with the version we want to release, we use
sed command to replace
v-latest with the version we specify in our tag. We are therefore required to change the version in
[metadata] name = example-pkg-YOUR-USERNAME-HERE version = v-latest author = Example Author author_email = firstname.lastname@example.org description = A small example package long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/pypa/sampleproject project_urls = Bug Tracker = https://github.com/pypa/sampleproject/issues classifiers = Programming Language :: Python :: 3 License :: OSI Approved :: MIT License Operating System :: OS Independent [options] package_dir = = src packages = find: python_requires = >=3.6 [options.packages.find] where = src
With the above codes, our project should automatically deploy every time we tag the project.