Poetry Packages

Page content

Let’s play with Packages and Libraries

References

Switch to Root Folder

cd /some/path/you/want

Create a new Package

poetry new mypackage

add some libraries

poetry add requests

… add some code …

cat << 'EOF' > mypackage/__init__.py
print("importing", __name__)
EOF

cat << 'EOF' > mypackage/main.py
print("importing", __name__)

def test1():
  print("test1")

def test2(name: str):
  print("hello", name)

def test3(name: str, age:int):
  print(f"Hello {name} at age {age}")

if __name__ == "__main__":
  print("This is a Library or Package. You should import it into your Code and not run it directly ...")
EOF

Build Package

poetry build

List Tree

(mypackage-py3.11) stoege@host:~/git/demo/mypackage> tree
.
├── README.md
├── dist
│   ├── mypackage-0.1.0-py3-none-any.whl
│   └── mypackage-0.1.0.tar.gz
├── mypackage
│   ├── __init__.py
│   └── main.py
├── poetry.lock
├── pyproject.toml
└── tests
    └── __init__.py

4 directories, 8 files

you have a package called “mypackage-0.1.0” created. As ’tar.gz and ‘.whl’ File

Demo App bauen

now, we need a small app where we can install and test this Library.

Back to Root Folder

cd /some/path/you/want

create New App

poetry new myapp
cd myapp
poetry shell

add Fastapi (for example)

poetry add fastapi

Import our Library

poetry add ../mypackage/
(mypackage-py3.11) stoege@host:~/git/demo/myapp> poetry add ../mypackage/
Configuration file exists at /Users/stoege/Library/Preferences/pypoetry, reusing this directory.

Updating dependencies
Resolving dependencies... (0.1s)

Package operations: 14 installs, 0 updates, 0 removals

  • Installing idna (3.4)
  • Installing sniffio (1.3.0)
  • Installing typing-extensions (4.7.1)
  • Installing annotated-types (0.5.0)
  • Installing anyio (3.7.1)
  • Installing certifi (2023.7.22)
  • Installing charset-normalizer (3.2.0)
  • Installing pydantic-core (2.6.3)
  • Installing urllib3 (2.0.4)
  • Installing pydantic (2.3.0)
  • Installing requests (2.31.0)
  • Installing starlette (0.27.0)
  • Installing fastapi (0.101.1)
  • Installing mypackage (0.1.0 /Users/stoege/git/demo/mypackage)

-> mypackage v0.1.0 got installed as well !

Tree

(myapp-py3.11) stoege@host:~/git/demo/myapp> tree
.
├── README.md
├── myapp
│   └── __init__.py
├── poetry.lock
├── pyproject.toml
└── tests
    └── __init__.py

that’s fine, but there is a hidden Folder “.venv”

Tree -a

(myapp-py3.11) stoege@host:~/git/demo/myapp> tree -a |more
.
├── .venv
│   ├── .gitignore
│   ├── bin
│   │   ├── activate
│   │   ├── activate.csh
│   │   ├── activate.fish
│   │   ├── activate.nu
│   │   ├── activate.ps1
│   │   ├── activate_this.py
│   │   ├── normalizer
│   │   ├── pip
│   │   ├── pip-3.11
│   │   ├── pip3
│   │   ├── pip3.11
│   │   ├── python -> /usr/local/opt/python@3.11/bin/python3.11
│   │   ├── python3 -> python
│   │   ├── python3.11 -> python
│   │   ├── wheel
│   │   ├── wheel-3.11
│   │   ├── wheel3
│   │   └── wheel3.11
│   ├── lib
│   │   └── python3.11
│   │       └── site-packages
│   │           ├── __pycache__
│   │           │   └── _virtualenv.cpython-311.pyc
│   │           ├── _distutils_hack
│   │           │   ├── __init__.py
│   │           │   ├── __pycache__
│   │           │   │   └── __init__.cpython-311.pyc

--- snip ---

│   │           ├── mypackage
│   │           │   ├── __init__.py
│   │           │   └── main.py
│   │           ├── mypackage-0.1.0.dist-info
│   │           │   ├── INSTALLER
│   │           │   ├── METADATA
│   │           │   ├── RECORD
│   │           │   ├── WHEEL
│   │           │   └── direct_url.json

--- snip ---

pyproject.toml

(myapp-py3.11) stoege@host:~/git/demo/myapp> cat pyproject.toml
[tool.poetry]
name = "myapp"
version = "0.1.0"
description = ""
authors = ["Daniel Stocker <blog@stoege.net>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.11"
mypackage = {path = "../mypackage"}
fastapi = "^0.101.1"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

-> mypackage got added to pyproject.toml

List Apps

(myapp-py3.11) stoege@host:~/git/demo/myapp> poetry show


annotated-types    0.5.0              Reusable constraint types to use with typing.Annotated
anyio              3.7.1              High level compatibility layer for multiple asynchronous event loop implementations
certifi            2023.7.22          Python package for providing Mozilla's CA Bundle.
charset-normalizer 3.2.0              The Real First Universal Charset Detector. Open, modern and actively maintained alterna...
fastapi            0.101.1            FastAPI framework, high performance, easy to learn, fast to code, ready for production
idna               3.4                Internationalized Domain Names in Applications (IDNA)
mypackage          0.1.0 ../mypackage
pydantic           2.3.0              Data validation using Python type hints
pydantic-core      2.6.3
requests           2.31.0             Python HTTP for Humans.
sniffio            1.3.0              Sniff out which async library your code is running under
starlette          0.27.0             The little ASGI library that shines.
typing-extensions  4.7.1              Backported and Experimental Type Hints for Python 3.7+
urllib3            2.0.4              HTTP library with thread-safe connection pooling, file post, and more.

add Code

cat << 'EOF' > myapp/__init__.py
print("importing", __name__)
EOF

cat << 'EOF' > myapp/main.py
print("importing", __name__)

import myapp

from mypackage.main import test1
import mypackage.main as gugus
import mypackage.main


def main():
    print("run main function")

    test1()
    gugus.test2(name="Hans")
    mypackage.main.test3(name="Hans", age="25")


if __name__ == "__main__":
    print("run main code")
    main()

EOF

Run App

(myapp-py3.11) stoege@host:~/git/demo/myapp> python myapp/main.py
importing __main__
importing myapp
importing mypackage
importing mypackage.main
run main code
run main function
test1
hello Hans
Hello Hans at age 25

Update pyproject

[tool.poetry.scripts]
myapp = 'myapp.main:main'

Poetry install

poetry install

Run Shortcut

(myapp-py3.11) stoege@host:~/git/demo/myapp> myapp
importing myapp
importing myapp.main
importing mypackage
importing mypackage.main
run main function
test1
hello Hans
Hello Hans at age 25

Include as an editable external package

  • build another app, myapp2 for example
  • don’t add the package via ‘poetry add ../mypack…’

import as editable package

[tool.poetry.dependencies]
python = "^3.11"
fastapi = "^0.101.1"
mypackage = { path = "../mypackage/", develop = true }

-> add mypackage here

Add Code

cat << 'EOF' > myapp2/__init__.py
print("importing", __name__)
EOF

cat << 'EOF' > myapp2/main.py
print("importing", __name__)

import myapp

from mypackage.main import test1
import mypackage.main as gugus
import mypackage.main


def main():
    print("run main function")

    test1()
    gugus.test2(name="Hans")
    mypackage.main.test3(name="Hans", age="25")


if __name__ == "__main__":
    print("run main code")
    main()

EOF

Run Code

(myapp2-py3.11) stoege@host:~/git/demo/myapp2> python myapp2/main.py
importing __main__
importing myapp2
importing mypackage
importing mypackage.main
run main code
run main function
test1
hello Hans
Hello Hans at age 25

Update Package

replace the function “test1” in the mypackage/main.py File

def test1():
    print("test 12345")

Run Code

(myapp2-py3.11) stoege@host:~/git/demo/myapp2> python myapp2/main.py
importing __main__
importing myapp2
importing mypackage
importing mypackage.main
run main code
run main function
test 12345
hello Hans
Hello Hans at age 25

-> can you see the “test 12345” ?

let’s play the code on first “myapp” again:

(myapp-py3.11) stoege@host:~/git/demo/myapp> python myapp/main.py
importing __main__
importing myapp
importing mypackage
importing mypackage.main
run main code
run main function
test1
hello Hans
Hello Hans at age 25

Update mypackage

we have modified the package and need to rebuild it. Update Version

update poetry

[tool.poetry]
name = "mypackage"
version = "0.1.2"

-> update version to 0.1.2

build again

stoege@host:~/git/demo/mypackage> poetry build

Building mypackage (0.1.2)
  - Building sdist
  - Built mypackage-0.1.2.tar.gz
  - Building wheel
  - Built mypackage-0.1.2-py3-none-any.whl
stoege@play243:~/git/demo/mypackage>

Update Package in “myapp”

(myapp-py3.11) stoege@host:~/git/demo/myapp> poetry update

Updating dependencies
Resolving dependencies... (0.9s)

Package operations: 0 installs, 1 update, 0 removals

  • Downgrading mypackage (0.1.1 /Users/stoege/git/demo/mypackage -> 0.1.2 /Users/stoege/git/demo/mypackage)

Writing lock file

Run again

(myapp-py3.11) stoege@host:~/git/demo/myapp> myapp
importing myapp
importing myapp.main
importing mypackage
importing mypackage.main
run main function
test 12345
hello Hans
Hello Hans at age 25

-> and we also got ’test 12345’

how to Publish Package to test.pypi.org

create account on plattform

  • https://test.pypi.org/
  • confirm mail
  • login
  • create 2fa
  • go to setting, api-token
  • add api-token, note it down (you won’t see it again …)

build Package

python3 -m pip install --upgrade twine

package pushen

python3 -m twine upload --repository testpypi dist/*

username: __ token __

password: pypy-xXxXxX – your token – xXxXxX

packages on test.pypi.org

Install on your Test Project

pip install -i https://test.pypi.org/simple/ stolib

TODO

demo app2 bauen

add test.pypi.org to pyproject.org

poetry source add --priority=primary test https://test.pypi.org/simple/
cat  pyproject.toml
--- snip ---
[[tool.poetry.source]]
name = "test"
url = "https://test.pypi.org/simple/"
priority = "primary"
--- snip ---

show Sources

poetry source show
 name      : test                          
 url       : https://test.pypi.org/simple/ 
 priority  : primary   

library adden von test.pypi.org

poetry add stolib

Any Comments ?

sha256: cc7b26661a3a0f03ee55fc47b54f2f9acf15d51aff35e263c9e01ee593764055