| doc/assets | ||
| src | ||
| poetry.lock | ||
| pyproject.toml | ||
| README.md | ||
Python Application
Demonstration on how to create an application that uses a self-created package. This also shows how to use and configure poetry to use a self-hosted PyPi repository for custom packages.
Poetry initialization
Either poetry new python-application if the directory does not exist yet, or poetry init to fill-in the wizard if the directory already exists.
Package installation from a local whl file
poetry add <PATH_TO_PACKAGE>>/mypackage-0.1.0-py3-none-any.whl
That will create a direct link to the file into the pyproject.toml file
dependencies = [
"mypackage @ file:///home/alexandre/python-packages/python-package/dist/mypackage-0.1.0-py3-none-any.whl"
]
This is not the best option especially for packages update and deployment to multiple projects.
Package installation from a self-hosted PyPi server
- Configure the PyPi server
In the pyproject.toml file, add the following block
[[tool.poetry.source]]
name = "forgejo-registry"
url = "https://forgejo.mountyfox.ch/api/packages/<ORG_OR_USER>/pypi/simple"
priority = "explicit"
The explicit keyword is a security concern. By doing so, standard packages (Flask, requests, ....) will be installed from public PyPi without trying the local PyPi. For private packages however, poetry WILL NOT try public PyPi at all. It will expect to be asked to look for package into self-hosted PyPi. That's why when installing the package, we must precisely set the self-hosted PyPi server information.
It may also be needed to bypass SSL certificate verification if using self-signed certificates for lab and development.
poetry config certificates.forgejo-registry.cert false
- Add the package dependancy to the the project
poetry add "mypackage==0.1.0" --source forgejo-registry
Note: mypackage is a very badly choosen package name. A quick overvoew on pypi.org shows many packages with that name.
If I run poetry add mypackage==0.1.0, I can see a lot of dependancies that I know I don't have in my mypackage package
% poetry add "mypackage>=0.1.0"
Updating dependencies
Resolving dependencies... (3.1s)
Package operations: 7 installs, 1 update, 0 removals
- Installing mdurl (0.1.2)
- Installing markdown-it-py (4.2.0)
- Installing pygments (2.20.0)
- Installing rich (15.0.0)
- Installing pyperclip (1.11.0)
- Installing rich-argparse (1.8.0)
- Installing cmd2 (3.5.1)
- Updating mypackage (0.1.0 /home/alexandre/python-packages/python-package/dist/mypackage-0.1.0-py3-none-any.whl -> 0.1)
Writing lock file
Whereas if run poetry add mypackage==0.1.0 --source forgejo-registry, I can see I have only no dependancies, as I know my pakage do not have any.
poetry -v add mypackage==0.1.0 --source forgejo-registry [Fri 29/05/26 09:27:20]
Using virtualenv: /home/alexandre/.cache/pypoetry/virtualenvs/python-application-g9AWucRX-py3.11
Checking keyring availability: Available
/usr/local/lib/python3.11/dist-packages/urllib3/connectionpool.py:1110: InsecureRequestWarning: Unverified HTTPS request is being made to host 'forgejo.mountyfox.ch'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
warnings.warn(
Updating dependencies
Resolving dependencies... (0.1s)
Finding the necessary packages for the current system
Package operations: 1 install, 0 updates, 0 removals
- Installing mypackage (0.1.0): Pending...
/usr/local/lib/python3.11/dist-packages/urllib3/connectionpool.py:1110: InsecureRequestWarning: Unverified HTTPS request is being made to host 'forgejo.mountyfox.ch'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
- Installing mypackage (0.1.0)
Writing lock file
And the pyproject.toml file will explicitely contain that information
dependencies = [
"mypackage (==0.1.0)"
]
[[tool.poetry.source]]
name = "forgejo-registry"
url = "https://forgejo.mountyfox.ch/api/packages/alexandre/pypi/simple"
priority = "explicit"
[tool.poetry.dependencies]
mypackage = {source = "forgejo-registry"}
Then the package can be used as any other package.
import mypackage.libmountyfox
if __name__ == "__main__":
print ( mypackage.libmountyfox.get_name() )
from mypackage.libmountyfox import get_name
if __name__ == "__main__":
print ( get_name() )
# if __init__ in mypackage properly defined
from mypackage import *
if __name__ == "__main__":
print ( get_name() )
Standard package versionning can be applied with (==, >=, ^) and poetry update can also be used.
