HowTo: Wie paketiert man eine Python Bibliothek?

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 06.09.2023 14:19:20

Vor einigen Wochen wurde nach einer Anleitung gefragt wie man ein Python Paket/Bibliothek in ein Debian Paket verwandeln kann. Aktuell habe ich eine eine solche Bibliothek die als neue Abhängigkeit für ein anderes Paket benötigt wird. Es handelt sich dabei um ruyaml, eine Bibliothek die ein Fork von ruamel.yaml (Debianruamel.yaml) ist.

Die Bibliothek soll später vom Debian Python Team als Source Paket python-ruyaml betreut werden. Die Paketierung und Pflege des Pakets wird mit Debiangit-buildpackage erfolgen, dies ist das Tooling was das DPT durch die Team Policy zur Betreuung von Paketen vorgibt. Wenn dies nicht installiert ist muss dies zwingend installiert werden für die Schritte die ich versuchen zu zeigen.

Ein Paket zu erstellen benötigt mehr wie die rein technischen Schritte dich darstellen werde, Dinge wie einen ITP zu erstellen, oder die Besonder- und Eigenheiten was die DFSG und Lizenzen angeht lasse ich bewusst weg.

Arbeitsverzeichnis, Upstream Tarball, Initialisierung

Um starten zu können benötigt man ein dediziertes Verzeichnis und den Upstream Tarball der letzten Version. Plus diverse Dateien die man sich erstellen muss, entweder von Hand oder durch Tools die einem die Arbeit erleichtern. Ich werde hier den manuellen Weg zeigen.

Code: Alles auswählen

$ mkdir python-ruyaml && cd python-ruyaml
$ wget https://github.com/pycontribs/ruyaml/archive/refs/tags/v0.91.0.tar.gz -P ~/Downloads/
$ git init
$ mkdir debian
Konfigurationsdatei für git-buildpackage

git init hat einen leeres Git Repository angelegt, damit gbp (Abkürzung git-buildpackage) jetzt den ersten Import richtig einsortiert wird eine optionale Konfigurationsdatei debian/gbp.conf benötigt. Diese sollte folgenden Inhalt haben:

Code: Alles auswählen

[DEFAULT]
pristine-tar = True
compression = gz
debian-branch = debian/master
upstream-branch = upstream

[pq]
patch-numbers = False

[dch]
id-length = 7
Importieren des Upstream Tarballs
Mit diesen Daten weiß gbp was mit den Daten aus dem Tarball passieren soll, die Angaben sind eigentlich recht selbsterklärend.

gbp soll einen Commit mit Metadaten aus der importieren Version in den Branch pristine-tar erstellen. Als Kompressionstyp soll tar.gz benutzt werden, als Arbeits-/Paketierungsbranch soll debian/master heißen (bedingt durch DPT Policy), und als Upstream Branch soll upstream verwendet werden.

Die Angaben unter [pq] werden auf den patch-queue Branch angewendet, im Detail wird hier gesagt keine nummerierten Patches (z.B. 0001-foo.patch etc) zu verwenden.

Die Section [dch] findet Beachtung wenn später Changelog Einträge erstellt werden, es werden hier später CommitIDs mit 7 Stellen verwendet.

Der (Erst)Import der Sourcen stellt ein paar Fragen da es noch keine Datei debian/control gibt, der Import erfolgt dann mit folgenden Aufruf:

Code: Alles auswählen

$ gbp import-orig --sign-tags --pristine-tar ~/Downloads/v0.91.0.tar.gz
What will be the source package name? [] python-ruyaml
What is the upstream version? [] 0.91.0
gbp:info: Importing '/home/user/Downloads/v0.91.0.tar.gz' to branch 'upstream'...
gbp:info: Source package is python-ruyaml
gbp:info: Upstream version is 0.91.0
gbp:info: Successfully imported version 0.91.0 of ../python-ruyaml_0.91.0.orig.tar.gz
Weitere benötigte Dateien im Ordner debian/
Damit ein Paketbau angestoßen werden kann werden weitere Steuerungsdateien benötigt. Unter anderem die zentrale Datei debian/control die das Sourcepaket und auch Binärpakte definiert.

Code: Alles auswählen

$ cat debian/control 
Source: python-ruyaml
Maintainer: Debian Python Team <team+python@tracker.debian.org>
Uploaders:
 Uploader <uploader@email.de>,
Section: python
Priority: optional
Build-Depends:
 debhelper-compat (= 13),
 pybuild-plugin-pyproject,
 python3-all,
 python3-setuptools,
 python3-setuptools-scm,
Rules-Requires-Root: no
Standards-Version: 4.6.2
Vcs-Browser: https://salsa.debian.org/python-team/packages/python-ruyaml
Vcs-Git: https://salsa.debian.org/python-team/packages/python-ruyaml.git
Homepage: https://github.com/pycontribs/ruyaml

Package: python3-ruyaml
Architecture: all
Depends:
 ${misc:Depends},
 ${python3:Depends},
Description: YAML 1.2 loader/dumper package for Python
 The ruyaml package is a fork of ruamel.yaml aimed to made in order to secure
 the future of the library, mainly by having a pool of maintainers and can be
 used as a drop-in replacement for python3-ruamel.yaml.
 .
 This package contains the Python 3 version of the library.
Die Daten für das Feld Build-Depends muss man sich aus dem Sourcepaket holen, sprich setup.{cfg,py}, pyproject.toml etc. anschauen und die relevanten Debian Pakete zusammen suchen. Das kostet manchmal etwas Mühe.

Als auch die Datei debian/rules, die wohl wichtigste aller Dateien. Achtung, dies ist ein Makefile (Tabs in den Targets!) und muss ausführbar sein, also ein "chmod 775" nach den Anlegen nicht vergessen!

Code: Alles auswählen

$ cat debian/rules 
#!/usr/bin/make -f
# -*- makefile -*-

#export DH_VERBOSE = 1

export PYBUILD_NAME=ruyaml

%:
	dh $@ --with python3 --buildsystem=pybuild
Auch wird benötigt eine Datei debian/copyright. Folgendes ist noch nicht komplett richtig und tauglich um das Paket am Ende nach Debian laden zu können, zeigt aber den benötigten Inhalt.

Code: Alles auswählen

$ cat debian/copyright 
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: ruyaml
Upstream-Contact: Anthon van der Neut, Ruamel bvba <pycontribs@googlegroups.com>
 Sorin Sbarnea <sorin.sbarnea@gmail.com>
Source: https://github.com/pycontribs/ruyaml

Files: *
Copyright: Anthon van der Neut, Ruamel bvba <pycontribs@googlegroups.com>
 Sorin Sbarnea <sorin.sbarnea@gmail.com>
 Matthias Urlichs <matthias@urlichs.de>
License: MIT

Files: debian/*
Copyright: 2023, Uploader <uploader@email.de>
License: MIT

License: MIT
 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.
Und es wird auch noch der Ordner debian/source benötigt in dem dann folgende 2 Dateien benötigt werden, einmal die Datei debian/source/format die eben den Typ des Paketes angibt, die Datei hat nur eine Zeile. Wir bauen einen Formattyp 3.0 mit dem Typ quilt zur Verwaltung von Patches (die in diesem Paket nicht benötigt werden).

Code: Alles auswählen

$ cat debian/source/format 
3.0 (quilt)
Es wird auch noch die Datei debian/source/options benötigt die dpkg-source sagt was es beachten soll, es z.B. Ordner *egg-info igonrieren.

Code: Alles auswählen

$ cat debian/source/options 
extend-diff-ignore = "^[^/]*[.]egg-info/"
Es fehlt nun "nur" noch die Datei debian/changelog und dann kann man auch schon den ersten Bau anstoßen. Kommt beim nächsten Post.

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 07.09.2023 19:58:28

An der Stelle ist es nicht verkehrt den aktuellen Stand in debian/ Verzeichnis per Commit im aktuellen Arbeits- und Paketierungsbranch hinzuzufügen. Zu einen späteren Zeitpunkt können alle folgenden Commits per Rebase auch zu einem Commit zusammen gefasst werden wenn man dies alles zusammen gefasst haben will.

Code: Alles auswählen

$ git status
Auf Branch debian/master
Unversionierte Dateien:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
	debian/

nichts zum Commit vorgemerkt, aber es gibt unversionierte Dateien
(benutzen Sie "git add" zum Versionieren)
$ git add debian/
$ git commit
[debian/master 2386bc7] Initial debian/ packaging data
 Date: Thu Sep 7 20:20:15 2023 +0530
 6 files changed, 100 insertions(+)
 create mode 100644 debian/control
 create mode 100644 debian/copyright
 create mode 100644 debian/gbp.conf
 create mode 100755 debian/rules
 create mode 100644 debian/source/format
 create mode 100644 debian/source/options
Um nun einen Paketbau anstoßen zu können wird auch ein unstable chroot benötigt, dazu kann man entweder sbuild, cowbuilder oder pbuilder benutzen um eine passende Umgebung erstellen zu können. Ich benutze üblicher Weise Debianpbuilder. Eine Anleitung wie man ein chroot erstellen kann findet man im Debian Wiki https://wiki.debian.org/git-pbuilder Im folgende gehe ich davon aus, dass es ein pbuilder basiertes unstable chroot gibt auf das gbp zugreifen kann.

Erster Paketbau
Mit diesen Vorbereitungen kann ein erster Bau des Paketes angestoßen werden. Dazu ist noch die Datei debian/changelog nötig welche sich mit gbp automatisiert erstellen lässt.
Wenn diese Datei erstellt ist lässt sich mit gbp auch der Bau innerhalb eines chroots anstoßen. Wenn pbuilder Hooks gesetzt sind werden dieses ausgeführt.

Code: Alles auswählen

$ gbp dch -aR   # Erstellen des changlogs
gbp:info: Starting from first commit
$ gbp buildpackage --git-ignore-new # Starten des Paketsbaus, ignorieren von von eventuellen geänderten Dateien im debian/ Verzeichnis
gbp:info: Building with (cowbuilder) for sid
gbp:info: Tarballs 'python-ruyaml_0.91.0.orig.tar.gz' not found at '/home/user/gitprojects/tarballs/'
gbp:info: Performing the build
Building with cowbuilder for distribution sid
I: using cowbuilder as pbuilder
dpkg-source: info: using options from python-ruyaml/debian/source/options: --extend-diff-ignore=^[^/]*[.]egg-info/
dh clean --with python3 --buildsystem=pybuild
   dh_auto_clean -O--buildsystem=pybuild
   dh_autoreconf_clean -O--buildsystem=pybuild
   debian/rules override_dh_clean
 ...
dpkg-deb: building package 'python3-ruyaml' in '../python3-ruyaml_0.91.0-1_all.deb'.
 dpkg-genbuildinfo -O../python-ruyaml_0.91.0-1_amd64.buildinfo
 dpkg-genchanges -O../python-ruyaml_0.91.0-1_amd64.changes
dpkg-genchanges: info: including full source code in upload
 dpkg-source --after-build .
dpkg-source: info: using options from python-ruyaml-0.91.0/debian/source/options: --extend-diff-ignore=^[^/]*[.]egg-info/
dpkg-buildpackage: info: full upload (original source is included)
dpkg-genchanges: info: including full source code in upload
I: copying local configuration
I: user script /home/pbuilder/build/cow.798496/tmp/hooks/B20autopkgtest starting
+ cd /build/python-ruyaml-0.91.0/debian/..
+ [ ! -f debian/tests/control ]
+ echo Package does not have autopkgtest support, debian/tests/control is missing
Package does not have autopkgtest support, debian/tests/control is missing
+ exit 0
I: user script /home/pbuilder/build/cow.798496/tmp/hooks/B20autopkgtest finished
I: user script /home/pbuilder/build/cow.798496/tmp/hooks/B20shell starting
Reading package lists...
Building dependency tree...
Reading state information...
vim is already the newest version (2:9.0.1672-1).
less is already the newest version (590-2).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
root@x260:/build/python-ruyaml-0.91.0# 
Mit dem Hook B20shell bleibt der Bau innerhalb des chroots stehen, das ist hilfreich wenn man innerhalb dieser Umgebung weitere Dinge bearbeiten will oder muss, verlassen kann man das chroot mittels der Eingabe von exit.
Damit hat man nun zwar ein *.deb Paket, aber ob diese auch funktional ist muss nun noch geprüft werden.

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 08.09.2023 09:29:12

Qualitätskontrolle
Nachdem der Paketbau erfolgreich durchgelaufen ist müssen diverse QS Schritte durchlaufen werden damit am Ende ein technisch korrektes, den Debian Richtlinien entsprechend Paket ins Archiv geladen werden kann. Aber auch wer nur für sich lokal ein Paket erstellen will sollte seinen Bau prüfen.
Nun ist es mühsam und wäre sehr aufwendig solche Prüfungen komplett und immer wieder manuell durch zu führen, in Debian gibt es daher das Tool Debianlintian was hunderte Tests durchführt und entsprechend gefundene Fehler/Warnungen/Informationen ausgibt. Gegenbefalls muss das Paket nachinstalliert.

Code: Alles auswählen

$ lintian -IE
W: python3-ruyaml: initial-upload-closes-no-bugs [usr/share/doc/python3-ruyaml/changelog.Debian.gz:1]
I: python-ruyaml source: debian-watch-file-is-missing
I: python3-ruyaml: package-contains-documentation-outside-usr-share-doc [usr/lib/python3/dist-packages/ruyaml-0.91.0.dist-info/top_level.txt]
Das sieht für einen ersten Bau sehr gut aus. Die Warnung kann an der Stelle und hier ignoriert werden, das wird dann relevant wenn man das Paket nach Debian hochladen will. Der letzte Hinweis ist auch uninteressant, bleibt der Hinweis zur fehlenden Datei debian/watch, diese Datei zu haben macht Sinn. Damit prüft "das Archive" regelmäßig ob es neue Versionen für das Source Paket gibt.

Die benötigte Datei ist an sich auch recht einfach und eigentlich auch nur eine Perl Regular Expression und müsste für python-ruyaml so aussehen:

Code: Alles auswählen

$ cat debian/watch 
version=4

opts="mode=git, \
      compression=gz, \
      uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\.?\d*)$/$1~$2/, \
      dversionmangle=s/\+ds(\.?\d+)?$//" \
https://github.com/pycontribs/ruyaml.git \
      refs/tags/@ANY_VERSION@
Die diversen Optionen bedeuten folgendes.
mode=git uscan benutzt den Git-Modus
compression=gz uscan soll tar.gz als Tarballl Format benutzen
uversionmangle=... Die angegebene Expression wird benutzt um eventuelle Upstream Suffixes zu entfernen.
dversionmangle=... Die angegebene Expression wird benutzt um eventuelle Debian Suffixes zu ignorieren.

Die Datei kann git bekannt und auch committet werden.

Code: Alles auswählen

$ git add debian/watch 
$ git commit -m "d/watch: Add a watch file configuration"
[debian/master 491091e] d/watch: Add a watch file configuration
 1 file changed, 8 insertions(+)
 create mode 100644 debian/watch
Um zu sehen was uscan machen würde kann folgender Aufruf benutzt werden.

Code: Alles auswählen

$ uscan --verbose --no-download
...
uscan info: Looking at $base = https://github.com/pycontribs/ruyaml.git with
    $filepattern = refs/tags/(?:[-_]?v?(\d[\-+\.:\~\da-zA-Z]*)) found
    $newfile     = refs/tags/v0.91.0
    $newversion  = 0.91.0
    $lastversion = 0.91.0
uscan info: Upstream URL(+tag) to download is identified as    https://github.com/pycontribs/ruyaml.git refs/tags/v0.91.0
uscan info: Filename (filenamemangled) for downloaded file: python-ruyaml-0.91.0.tar.gz
uscan info: Newest version of python-ruyaml on remote site is 0.91.0, local version is 0.91.0
uscan info:  => Package is up to date from:
             => https://github.com/pycontribs/ruyaml.git refs/tags/v0.91.0
uscan info: Scan finished
Wie zu erkennen ist gibt es keine neueren Versionen im angegeben Upstream Tree. Mehr Informationen zur Datei debian/watch können im Debian Wiki gefunden werden. https://wiki.debian.org/debian/watch
Und weitere Hintergrundinfos in einem Blogpost http://eriberto.pro.br/blog/2013/10/07/ ... ch-easily/

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 09.09.2023 11:33:56

Mehr QS aka Running Upstream Tests während des Paketbaus
Nach dem das Paket nun erfolgreich gebaut werden kann kann und sollte man weitere Dinge noch prüfen und aktivieren. Eigentlich alle Pythonprojekte kommen mit einer Testsuite die beim Bauen des Paketes mit ausgeführt werden kann. Damit dies auch im Fall von ruyamel auch funktioniert sind nur wenige Änderungen nötig. Laut der Datei tox.ini wird pytest benutzt um die Unittests auszuführen. Ergo muss dies zu debian/control im Bereich des Source Pakete Definitionen im Feld Build-Depends hinzugefügt werden.
Eine kleine Besonderheit, es gibt neben Abhängigkeiten für Binärpakete (also Paketen mit Plattform spezifischen Code) auch die Möglichkeit optional Abhängigkeiten auf Plattform unabhängige Pakete zu setzen, das zugehörige Feld heißt dann analog Build-Depends-Indep. Folgende kleine Ergänzung muss nun in debian/control eingetragen werden.

Code: Alles auswählen

$ git diff debian/control
diff --git a/debian/control b/debian/control
index 314f461..1face16 100644
--- a/debian/control
+++ b/debian/control
@@ -10,6 +10,8 @@ Build-Depends:
  python3-all,
  python3-setuptools,
  python3-setuptools-scm,
+Build-Depends-Indep:
+ python3-pytest <!nocheck>,
 Rules-Requires-Root: no
 Standards-Version: 4.6.2
 Vcs-Browser: https://salsa.debian.org/python-team/packages/python-ruyaml
Neben dem Eintragen der nötigen Abhängigkeit müssen auch in debian/rules noch Änderungen erfolgen.

Hintergrung:
Die Usptream Unittests werden nicht im Ordner ausgeführt wo der Upstream Source Code liegt sondern im Verzeichnis wo der eigentliche Paketbau erfolgt, dort liegt aber ohne weiteres Zutun nur der Source Code und eben keine sonstigen Verzeichnisse wie in unserem Fall das benötigte Verzeichnis _test was die Unittests enthält. Auch keine weiteren Dateien die für die Unittests benötigt werden.
Über Variablen kann Pybuild angewiesen werden vor und nach dem Ausführen von Tests Aktionen auszuführen, wie das Kopieren der Daten für die Tests, als auch das Entfernen dieser Daten nach dem Durchlaufen der Tests. Folgende Erweiterung muss in den debian/rules durchgeführt werden.

Code: Alles auswählen

$ git diff debian/rules
diff --git a/debian/rules b/debian/rules
index 4d8cb46..df7c862 100755
--- a/debian/rules
+++ b/debian/rules
@@ -4,6 +4,8 @@
 #export DH_VERBOSE = 1
 
 export PYBUILD_NAME=ruyaml
+export PYBUILD_BEFORE_TEST=cp -a {dir}/_test {build_dir}
+export PYBUILD_AFTER_TEST=rm -rf {build_dir}/_test
 
 %:
        dh $@ --with python3 --buildsystem=pybuild
Mit diesen Änderungen bauen wir das Paket dann erneut.

Code: Alles auswählen

$ gbp buildpackage --git-ignore-new 
gbp:info: Building with (cowbuilder) for sid
...
   dh_auto_test -O--buildsystem=pybuild
I: pybuild pybuild:314: cp -a /build/python-ruyaml-0.91.0/_test /build/python-ruyaml-0.91.0/.pybuild/cpython3_3.11_ruyaml/build
I: pybuild base:291: cd /build/python-ruyaml-0.91.0/.pybuild/cpython3_3.11_ruyaml/build; python3.11 -m pytest 
============================= test session starts ==============================
platform linux -- Python 3.11.5, pytest-7.4.1, pluggy-1.3.0
rootdir: /build/python-ruyaml-0.91.0/.pybuild/cpython3_3.11_ruyaml/build
configfile: pyproject.toml
collected 519 items

_test/test_a_dedent.py ......                                            [  1%]
_test/test_add_xxx.py .......                                            [  2%]
_test/test_anchor.py ..............................                      [  8%]
_test/test_api_change.py ..................                              [ 11%]
_test/test_class_register.py ........                                    [ 13%]
_test/test_collections.py .                                              [ 13%]
_test/test_comment_manipulation.py ............................x         [ 19%]
_test/test_comments.py ........................................x........ [ 28%]
..................                                                       [ 31%]
_test/test_contextmanager.py ........                                    [ 33%]
_test/test_copy.py .....                                                 [ 34%]
_test/test_cyaml.py XsXX                                                 [ 35%]
_test/test_datetime.py ..............                                    [ 37%]
_test/test_deprecation.py s                                              [ 38%]
_test/test_documents.py ......                                           [ 39%]
_test/test_fail.py x.x.x.x.......                                        [ 42%]
_test/test_float.py ....                                                 [ 42%]
_test/test_flowsequencekey.py .                                          [ 42%]
_test/test_indentation.py ..........................                     [ 47%]
_test/test_int.py .                                                      [ 48%]
_test/test_issues.py ................................................... [ 57%]
                                                                         [ 57%]
_test/test_json_numbers.py ..                                            [ 58%]
_test/test_line_col.py .......                                           [ 59%]
_test/test_literal.py .........................                          [ 64%]
_test/test_none.py .....                                                 [ 65%]
_test/test_program_config.py ...                                         [ 66%]
_test/test_spec_examples.py .x.xxxx..xxxxxx.xxxx                         [ 69%]
_test/test_string.py ................                                    [ 73%]
_test/test_tag.py ......xx......                                         [ 75%]
_test/test_version.py ........                                           [ 77%]
_test/test_yamlfile.py .............                                     [ 79%]
_test/test_yamlobject.py ...                                             [ 80%]
_test/test_z_check_debug_leftovers.py ..                                 [ 80%]
_test/test_z_data.py s                                                   [ 80%]
_test/test_z_olddata.py ..                                               [ 81%]
_test/lib/test_canonical.py sss                                          [ 81%]
_test/lib/test_constructor.py ss                                         [ 82%]
_test/lib/test_emitter.py ssss                                           [ 83%]
_test/lib/test_errors.py sssss                                           [ 84%]
_test/lib/test_input_output.py sssss                                     [ 84%]
_test/lib/test_mark.py s                                                 [ 85%]
_test/lib/test_reader.py s                                               [ 85%]
_test/lib/test_recursive.py s                                            [ 85%]
_test/lib/test_representer.py s                                          [ 85%]
_test/lib/test_resolver.py sss                                           [ 86%]
_test/lib/test_structure.py sssss                                        [ 87%]
_test/lib/test_tokens.py ss                                              [ 87%]
_test/lib/test_yaml.py sssssssssssssssssssssssssssssssss                 [ 94%]
_test/lib/test_yaml_ext.py sssssssssssssssssssssssssssssss               [100%]

=============================== warnings summary ===============================
_test/test_z_olddata.py::test_data
  /build/python-ruyaml-0.91.0/.pybuild/cpython3_3.11_ruyaml/build/_test/lib/test_constructor.py:321: UnsafeLoaderWarning: 
  The default 'Loader' for 'load(stream)' without further arguments can be unsafe.
  Use 'load(stream, Loader=ruyaml.Loader)' explicitly if that is OK.
  Alternatively include the following in your code:
  
    import warnings
    warnings.simplefilter('ignore', ruyaml.error.UnsafeLoaderWarning)
  
  In most other cases you should consider using 'safe_load(stream)'
    native1 = list(ruyaml.load_all(fp0))

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
====== 393 passed, 100 skipped, 23 xfailed, 3 xpassed, 1 warning in 4.83s ======
...
root@x260:/build/python-ruyaml-0.91.0# exit
...
$
Wenn die Tests erfolgreich durchlaufen dann ist dies ein gutes Zeichen, es gibt ein paar Tests die übersprungen werden, die muss man sich manchmal anschauen warum diese übersprungen werden, hin und wieder möchte man auch diese Tests normal prozessieren. Hier in diesem Paket ist dies so o.k.

buhtz
Beiträge: 1106
Registriert: 04.12.2015 17:54:49
Kontaktdaten:

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von buhtz » 09.09.2023 20:12:33

Dieser Beitrag hier ist von unschätzbaren Wert. Herzliches Danke dafür! :hail:
Debian 11 & 12; Desktop-PC, Headless-NAS, Raspberry Pi 4
Teil des Upstream Betreuer Teams von Back In Time (Debianbackintime)

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 10.09.2023 10:13:18

Da der Bau des Paketes samt Unittests erfolgreich ist können und sollten die Änderungen commitet werden, wie Eingangs erwähnt können am Ende des Prozesses alle Änderungen vom debian/ Ordner auch zusammen gemerget werden, es sei denn man hat ein persönliches Interesse die wirklich sehr granulären Schritte später nochmal nachvollziehen zu können. Ich persönlich habe daran kein Interesse und weiß aus Erfahrung welche Dateien ich benötige um eine Paketierung beginnen und auch abschließen zu können um einen ersten Upload eines Paketes nach NEW durchzuführen.

Code: Alles auswählen

$ git status
Auf Branch debian/master
Änderungen, die nicht zum Commit vorgemerkt sind:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
  (benutzen Sie "git restore <Datei>...", um die Änderungen im Arbeitsverzeichnis zu verwerfen)
	geändert:       debian/control
	geändert:       debian/rules

Unversionierte Dateien:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
	debian/changelog

keine Änderungen zum Commit vorgemerkt (benutzen Sie "git add" und/oder "git commit -a")
$ git commit debian/control debian/rules -m"Run unittests while package build"
[debian/master dd94d01] Run unittests while package build
 2 files changed, 4 insertions(+)
Paketieren der Dokumentation
Das Upstream Paket kommt nun auch mit einer Dokumentation für das Pakete, und diese ist Sphinx basierend.
Damit diese Dokumentation mit gebaut werden kann werden technisch drei Dinge benötigt.
  1. Hinzufügen der benötigten Build-Depends in debian/control damit die Tools im chroot verfügbar sind.
  2. Hinzufügen eines weiteren Binärpaktes nach dem Schema python-foo-doc in debian/control.
  3. Erweitern von debian/rules so das die Dokumentation gebaut wird, und dies nur wenn das Build-Profil nodoc nicht aktiv ist.
Klingt nach viel Arbeit, ist es aber nicht. Fügen wir zuerst die neu benötigten Abhängigkeiten hinzu, das sind zum einen die Pakete mit den Sphinx Sachen als auch ein debhelper Addon was dann noch etwas Voodoo nach dem Sphinx Bau macht wie die nötigen Abhängigkeiten in das -doc Paket einzufügen. Welche Pakete genau benötigt werden muss man sich wieder in den üblichen Konfigurationsdateien heraus suchen.

Code: Alles auswählen

$ git diff debian/control
diff --git a/debian/control b/debian/control
index 1face16..34dd2d8 100644
--- a/debian/control
+++ b/debian/control
@@ -7,22 +7,41 @@ Priority: optional
 Build-Depends:
  debhelper-compat (= 13),
  pybuild-plugin-pyproject,
+ dh-sequence-sphinxdoc,
  python3-all,
  python3-setuptools,
  python3-setuptools-scm,
 Build-Depends-Indep:
  python3-pytest <!nocheck>,
+ python3-sphinx <!nodoc>,
+ python3-sphinx-rtd-theme <!nodoc>,
 Rules-Requires-Root: no
 Standards-Version: 4.6.2
 Vcs-Browser: https://salsa.debian.org/python-team/packages/python-ruyaml
 Vcs-Git: https://salsa.debian.org/python-team/packages/python-ruyaml.git
 Homepage: https://github.com/pycontribs/ruyaml
 ...
Und dann das weitere Binärpaket was die Dokumentation beinhalten soll. Da auch die Binärpakete alphabetisch sortiert abgelegt sein sollten (man findet dann Pakete einfach schneller wenn es mehr wie 2 oder 3 Binärpakete gibt) wird das neue Paket zwischen dem Source Paket und dem einen schon vorhandenen Binärpaket eingefügt. Es gibt aber keine harte Regel dies so erledigen zu müssen.

Code: Alles auswählen

 ...
 Vcs-Browser: https://salsa.debian.org/python-team/packages/python-ruyaml
 Vcs-Git: https://salsa.debian.org/python-team/packages/python-ruyaml.git
 Homepage: https://github.com/pycontribs/ruyaml
 
+Package: python-ruyaml-doc
+Architecture: all
+Section: doc
+Depends:
+ ${misc:Depends},
+ ${sphinxdoc:Depends}
+Multi-Arch: foreign
+Description: YAML 1.2 loader/dumper package for Python (Documentation)
+ The ruyaml package is a fork of ruamel.yaml aimed to made in order to secure
+ the future of the library, mainly by having a pool of maintainers and can be
+ used as a drop-in replacement for python3-ruamel.yaml.
+ .
+ This package installs the documentation for the library.
+
 Package: python3-ruyaml
 Architecture: all
 Depends:
  ${misc:Depends},
  ${python3:Depends},
+Suggests:
+ python-ruamel-doc,
 Description: YAML 1.2 loader/dumper package for Python
  The ruyaml package is a fork of ruamel.yaml aimed to made in order to secure
  the future of the library, mainly by having a pool of maintainers and can be
Und dann noch die nötigen Erweiterungen in der Datei debian/rules. Wer genau hinschaut erkennt, dass die produzierte HTML Dokumentation nach /usr/share/doc/python-ruyaml-doc/html paketiert wird. Das ist das übliche Schema.

Code: Alles auswählen

$ git diff debian/rules
diff --git a/debian/rules b/debian/rules
index df7c862..6c8b9ee 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,9 +7,20 @@ export PYBUILD_NAME=ruyaml
 export PYBUILD_BEFORE_TEST=cp -a {dir}/_test {build_dir}
 export PYBUILD_AFTER_TEST=rm -rf {build_dir}/_test
 
+include /usr/share/dpkg/pkg-info.mk
+
+BUILD_DATE  = $(shell LC_ALL=C date -u "+%d %B %Y" -d "@$(SOURCE_DATE_EPOCH)")
+SPHINXOPTS := -N -D html_last_updated_fmt="$(BUILD_DATE)"
+
 %:
        dh $@ --with python3 --buildsystem=pybuild
 
 override_dh_clean:
        dh_clean
        rm -rf .mypy_cache
+
+override_dh_sphinxdoc:
+ifeq (,$(findstring nodoc, $(DEB_BUILD_OPTIONS)))
+       PYTHONPATH=. python3 -m sphinx -b html $(SPHINXOPTS) _doc $(CURDIR)/debian/python-ruyaml-doc/usr/share/doc/python-ruyaml-doc/html
+       dh_sphinxdoc
+endif
Das sollte ausreichen um ein weiteres Paket mit bauen zu können, also einen weiteren Bau anstoßen um dies zu prüfen.
$ gbp buildpackage --git-ignore-new
...

Und auch wieder Lintian prüfen lassen ob es was zu korrigieren gibt.

Code: Alles auswählen

$ lintian -IE
W: python-ruyaml-doc: initial-upload-closes-no-bugs [usr/share/doc/python-ruyaml-doc/changelog.Debian.gz:1]
W: python3-ruyaml: initial-upload-closes-no-bugs [usr/share/doc/python3-ruyaml/changelog.Debian.gz:1]
W: python-ruyaml-doc: privacy-breach-generic [<img alt="https://readthedocs.org/projects/ruyaml/badge/?version=stable" src="https://readthedocs.org/projects/ruyaml/badge/?version=stable" />] (https://readthedocs.org/projects/ruyaml/badge/?version=stable) [usr/share/doc/python-ruyaml-doc/html/index.html]
I: python3-ruyaml: package-contains-documentation-outside-usr-share-doc [usr/lib/python3/dist-packages/ruyaml-0.91.0.dist-info/top_level.txt]
I: python-ruyaml-doc: possible-documentation-but-no-doc-base-registration
Die ersten beiden Punkte können hier ignoriert werden, das nächste Warning wäre etwas was man fixen kann, würde jetzt hier aber etwas aus dem Rahmen fallen.
Dann folgen noch zwei informative Hinweise, den ersten kann man auch ignorieren, den zweiten können wir aber jetzt noch mit angehen und korrigieren. Folgt man den Link der hinterlegt ist gelangt man auf die Seite https://lintian.debian.org/tags/possibl ... gistration
Um diesen Fehler zu korrigieren wird eine $(Paketname).doc-base Sequencer Datei benötigt die die passenden Daten mit ins Paket installiert. Die Datei muss unter debian/python-ruyaml-doc.doc-base abgelegt werden und folgenden Inhalt besitzen.

Code: Alles auswählen

$ cat debian/python-ruyaml-doc.doc-base 
Document: python-ruyaml-doc
Title: Python YAML package documentation
Abstract: YAML 1.2 loader/dumper package for Python
Section: Programming/Python

Format: HTML
Index: /usr/share/doc/python-ruyaml-doc/html/index.html
Files: /usr/share/doc/python-ruyaml-doc/html/*.html
Ein weiter Bau des Paketes plus Prüfen mittels Lintian sollte zeigen, dass der Hinweis von eben nun nicht mehr existiert. Dann können wir die Änderungen wieder dem Git Tree hinzufügen.

Code: Alles auswählen

$ git status
Auf Branch debian/master
Änderungen, die nicht zum Commit vorgemerkt sind:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
  (benutzen Sie "git restore <Datei>...", um die Änderungen im Arbeitsverzeichnis zu verwerfen)
	geändert:       debian/control
	geändert:       debian/rules

Unversionierte Dateien:
  (benutzen Sie "git add <Datei>...", um die Änderungen zum Commit vorzumerken)
	debian/changelog
	debian/python-ruyaml-doc.doc-base

keine Änderungen zum Commit vorgemerkt (benutzen Sie "git add" und/oder "git commit -a")
$ git add debian/python-ruyaml-doc.doc-base debian/control debian/rules
$ git commit -m"Add package python-ruyaml-doc to build"
[debian/master 14d03d5] Add package python-ruyaml-doc to build
 3 files changed, 38 insertions(+)
 create mode 100644 debian/python-ruyaml-doc.doc-base

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 11.09.2023 10:26:05

Hinzufügen eines Setups für Autopkgtest
Die Paketierung hat nun alle nötigen Konfigurationen um die aktuell zwei Binärpakete zu bauen und führt auch die Upstream Testsuite während des Paketbaus aus. Damit ist die Paketierung an sich fertig, es fehlen noch ein paar Dinge Nice to Have die hier in dem Kontext zu weit führen würden.

Was aber noch eine sinnvolle Zugabe wäre ist ein Setup für Autopkgtest. Mit dem Hinzufügen eines Setups werden für das Paket dann immer automatisch getriggert die hinterlegten Tests ausgeführt. Sollte so ein Test dann nicht mehr erfolgreich sein wird die Migration des Paketes nach testing was den fehlerhaften Test ausgelöst hat blockiert.

Achtung: Damit der Autopkgtest lokal im pbuilder chroot ausgeführt wird muss der Hook B20autopkgtest (siehe /usr/share/doc/pbuilder/examples/)getriggert werden. Das kann per gbp erfolgen, dazu muss gbp passend konfiguriert sein. Z.B. per Datei $(HOME)/.gbp.conf indem man dort folgende Option setzt:

Code: Alles auswählen

$ cat ~/.gbp.conf 
...
[buildpackage]
...
pbuilder-options=--source-only-changes --hookdir /home/YOUR_USER_NAME/.pbuilder
...
Ein Autopkgtest benötigt mindestens eine Datei control in einem Ordner debian/tests/, der Name ist angelehnt an die Datei debian/control und auch der Aufbau ist analog zu der anderen control Datei.
Wenn mehr wir ein Aufruf bzw. Tests, bzw. ein oder mehrere Skripte aufgerufen werden sollen dann legt man seine Skripte neben der Datei debian/test/control ab. Für unser Paket würde das dann prinzipiell so aussehen.

Code: Alles auswählen

$ mkdir debian/tests
... 
$ cat debian/tests/control 
Tests: smoke
Depends:
 python3-all,
 python-pytest,
 @,
Restrictions: allow-stderr
$ cat debian/tests/smoke 
#! /bin/bash

cp -r _test ${AUTOPKGTEST_TMP}

for py3vers in $(py3versions -s); do
    echo
    echo "***************************"
    echo "*** Testing with ${py3vers}"
    echo "***************************"
    echo
    cd ${AUTOPKGTEST_TMP} && \
        echo -e "Content of current working folder:\n" && \
        ls -la && \
        echo -e "Running tests...\n" && \
        PYTHONPATH=. ${py3vers} -m pytest
done
In der control Datei wird definiert welche Pakete installiert sein müssen damit der Test funktionieren kann, im einfachsten Fall wird nur das Paket selber benötigt (Referenziert durch die Variable '@'), da aber auch pytest benötigt wird, was natürlich keine Abhängigkeit vom Paket ist muss man auch die weiteren benötigten Pakete angeben (und so auch hier). Meistens werden auch gerne die kompletten Abhängigkeiten vom Paketbau benutzt (die Variable hierzu wäre '@builddeps@'), das ist aber teilweise unpraktisch und versteckt Fehler da dadurch eventuell Pakete im Test installiert sein könnten die eigentlich durch die Paketabhängigkeiten hätten installiert werden müssen, dann funktioniert der Test zwar, aber beim Benutzer kann ein Fehlverhalten auftreten.

Baut man nun die Konfiguration ist im Buildlog folgendes zu finden:

Code: Alles auswählen

dpkg-genchanges: info: including full source code in upload
 dpkg-source --after-build .
dpkg-source: info: using options from python-ruyaml-0.91.0/debian/source/options: --extend-diff-ignore=^[^/]*[.]egg-info/
dpkg-buildpackage: info: full upload (original source is included)
dpkg-genchanges: info: including full source code in upload
I: copying local configuration
I: user script /home/pbuilder/build/cow.597828/tmp/hooks/B20autopkgtest starting
+ cd /build/python-ruyaml-0.91.0/debian/..
+ [ ! -f debian/tests/control ]
+ [ ! -f debian/files ]
+ [ -n  ]
+ unset newpid_name
+ apt-cache policy newpid
+ grep -q newpid:
+ echo The newpid package seems to be available, considering for installation
The newpid package seems to be available, considering for installation
+ newpid_name=newpid
+ apt-get install -y autopkgtest apt-utils pbuilder newpid
...
autopkgtest: WARNING: Using --- to separate virt server arguments is deprecated; use -- instead
autopkgtest [08:06:47]: starting date and time: 2023-09-11 08:06:47+0000
autopkgtest [08:06:47]: version 5.30
autopkgtest [08:06:47]: host x260; command line: /usr/bin/autopkgtest --output-dir /build/autopkgtest.out --summary /build/autopkgtest.summary /build/python-ruyaml-0.91.0 /build/python-ruyaml-doc_0.91.0-1_all.deb /build/python3-ruyaml_0.91.0-1_all.deb --- autopkgtest-virt-null
autopkgtest [08:06:47]: testbed dpkg architecture: amd64
autopkgtest [08:06:47]: testbed apt version: 2.7.3
autopkgtest [08:06:47]: testbed running kernel: Linux 6.4.0-4-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.4.13-1 (2023-08-31)
autopkgtest [08:06:47]: @@@@@@@@@@@@@@@@@@@@ built-tree /build/python-ruyaml-0.91.0
autopkgtest [08:06:47]: testing package python-ruyaml version 0.91.0-1
autopkgtest [08:06:47]: test smoke: preparing testbed
...
autopkgtest [08:06:52]: test smoke: [-----------------------

***************************
*** Testing with python3.11
***************************

Content of current working folder:

total 12
drwxr-xr-x 3 root root 4096 Sep 11 08:06 .
drwxrwxrwt 6 root root 4096 Sep 11 08:06 ..
drwxr-xr-x 4 root root 4096 Sep 11 08:06 _test
Running tests...

============================= test session starts ==============================
platform linux -- Python 3.11.5, pytest-7.4.1, pluggy-1.3.0
rootdir: /tmp/autopkgtest.eFVTCW/autopkgtest_tmp
collected 519 items

_test/test_a_dedent.py ......                                            [  1%]
_test/test_add_xxx.py .......                                            [  2%]
...
_test/lib/test_yaml.py sssssssssssssssssssssssssssssssss                 [ 94%]
_test/lib/test_yaml_ext.py sssssssssssssssssssssssssssssss               [100%]

=============================== warnings summary ===============================
_test/test_z_olddata.py::test_data
  /tmp/autopkgtest.eFVTCW/autopkgtest_tmp/_test/lib/test_constructor.py:321: UnsafeLoaderWarning: 
  The default 'Loader' for 'load(stream)' without further arguments can be unsafe.
  Use 'load(stream, Loader=ruyaml.Loader)' explicitly if that is OK.
  Alternatively include the following in your code:
  
    import warnings
    warnings.simplefilter('ignore', ruyaml.error.UnsafeLoaderWarning)
  
  In most other cases you should consider using 'safe_load(stream)'
    native1 = list(ruyaml.load_all(fp0))

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
====== 393 passed, 100 skipped, 23 xfailed, 3 xpassed, 1 warning in 4.97s ======
autopkgtest [08:06:58]: test smoke: -----------------------]
autopkgtest [08:06:58]: test smoke:  - - - - - - - - - - results - - - - - - - - - -
smoke                PASS
autopkgtest [08:06:58]: @@@@@@@@@@@@@@@@@@@@ summary
smoke                PASS
...
Wenn dies zu sehen ist dann ist das Setup korrekt als auch der Autopkgtest im chroot erfolgreich.

Benutzeravatar
shoening
Beiträge: 898
Registriert: 28.01.2005 21:05:59
Lizenz eigener Beiträge: MIT Lizenz

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von shoening » 11.09.2023 16:53:32

Ich kann mich dem Lob von buhtz nur anschliessen.

Zwei Anmerkungen hätte ich aber:
Im Betreff würde ich fragen: „Wie paketiert man eine Python Bibliothek für Debian?“.
Sollten solche Anleitungen aber nicht besser im Forum abgelegt werden?

Viele Grüße
Stefan
Bürokratie kann man nur durch ihre Anwendung bekämpfen.

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 12.09.2023 08:43:35

shoening hat geschrieben: ↑ zum Beitrag ↑
11.09.2023 16:53:32
Im Betreff würde ich fragen: „Wie paketiert man eine Python Bibliothek für Debian?“.
Wir sind hier im Debianforum, daher habe ich angenommen, dass jeder voraussetzt, dass wir über Paketierung für Debian reden und nicht für Fedora z.B.. :wink:

Weiteres hinzuzufügen hatte ich aktuell nicht vor, es gibt zwar schon noch Dinge wie eine Datei README.source oder einen Ordner debian/upstream was man auch noch hinzufügen kann und m.A. sollte, sind aber Dinge die man sich einfach in vorhandenen Paketen anschauen, kopieren und anpassen kann. Das wäre auch ein allgemeiner Tipp, schaut Euch an wie andere Pakete paketiert sind.

Salsa Gruppe DPT
https://salsa.debian.org/python-team/packages

Tracker Seite vom DPT
https://tracker.debian.org/teams/python/

Maintainer Übersicht für DPT
https://qa.debian.org/developer.php?ema ... debian.org

Nicht jedes Paket was im Namen mit "python" beginnt wird durch das Python Team betreut (per Feld Maintainer), es gibt auch einige Pakete die im Maintainer Feld eine Person stehen haben und wiederum im Upload Feld das DPT, diese Pakete sind unter den oben aufgeführten URLs nicht zu finden!

Wer was zum DPT beitragen will kann dies in verschiedener Form tun, gern gesehen sind immer Patches oder Hinweise wie ein Bugreport gelöst und geschlossen werden kann. Auch sind Hinweise wie eine Autopkgtest erweitert werden kann hilfreich. Probleme mit dem Source selber können per BTS gemeldet werden, aber wenn möglich sollte der Fehler auch direkt an Upstream gemeldet werden, denn dort macht ein Fixing mehr Sinn.
Keine Angst wenn man mal den letzten Uploader wegen einer Frage oder eines Problems per E-Mail anschreibt, er sollte in einem vertretbaren Zeitfenstern auch antworten, meistens sind die Mitglieder sehr schnell mit einer Antwort.

Viel Erfolg beim Nachbauen oder Paketieren von anderen Paketen.

buhtz
Beiträge: 1106
Registriert: 04.12.2015 17:54:49
Kontaktdaten:

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von buhtz » 17.09.2023 19:55:43

Also ich versuche das gerade Übungsweise für Debianbackintime zu machen und dokumentiere alles (https://codeberg.org/buhtz/bit_pack).
tijuca hat geschrieben: ↑ zum Beitrag ↑
06.09.2023 14:19:20

Code: Alles auswählen

debian-branch = debian/master
Muss es eigentlich noch "master" sein? Sind die Tools noch darauf festgelegt?
tijuca hat geschrieben: ↑ zum Beitrag ↑
06.09.2023 14:19:20

Code: Alles auswählen

$ gbp import-orig --sign-tags --pristine-tar ~/Downloads/v0.91.0.tar.gz
What will be the source package name? [] python-ruyaml
What is the upstream version? [] 0.91.0
Wozu genau ist "--sign-tags" notwendig? Bei mir schlägt das fehl. Aus der Fehlermeldung wird allerdings nicht klar, was gdb erwartet. Ich habe die Option einfach weggelassen und komme damit erst einmal weiter.

Noch was anderes: Laut manpage (nicht "gbp" sondern "gb-packagebuild" übrigens) konnte ich dazu nichts finden, aber frage trotzdem. Kann man die Abfrage umgehen, in dem man den Paketnamen und Versionsnummer als Parameter übergibt?

Ich mach dann erst mal weiter...

EDIT:
tijuca hat geschrieben: ↑ zum Beitrag ↑
06.09.2023 14:19:20
Die Daten für das Feld Build-Depends muss man sich aus dem Sourcepaket holen, sprich setup.{cfg,py}, pyproject.toml etc. anschauen und die relevanten Debian Pakete zusammen suchen. Das kostet manchmal etwas Mühe.
Ich hatte mal auf irgend einer Mailingliste "gehört", dass sauber/modern paketierte Python Pakete (also pyproject.toml, PEP621, src-Layout, usw), diesen manuellen Schritt bei Debian nicht benötigen würden. Es gäbe hier Tools die alles nötige aus einem "pip install ." ableiten würden. Aber vielleicht hab ich da auch was falsch verstanden. Bei meinem Versuch mit Debianbackintime ist das eh nicht relevant, weil das noch (Python) altbacken auf "make" setzt.

EDIT2:
tijuca hat geschrieben: ↑ zum Beitrag ↑
06.09.2023 14:19:20
Es wird auch noch die Datei debian/source/options benötigt die dpkg-source sagt was es beachten soll, es z.B. Ordner *egg-info igonrieren.

Code: Alles auswählen

$ cat debian/source/options 
extend-diff-ignore = "^[^/]*[.]egg-info/"
Der Sinn dieses ignore ist mir nicht klar. Ein egg-info Ordner sollte doch erst gar nicht Bestandteil des source-tarballs sein. In der Realität ist es häufig anders, dass ist mir klar. Aber sollte man hier in diesem Thread nicht eher darauf hinweisen, dass die Leute vorher einen sauberen source-tarball erzeugen, ohne den sonstigen Kladaradatsch? Vielleicht definieren ich source-tarball auch anders? Was muss da drin sein? Würde ich einfach das komplette upstream repo 1 zu 1 kopieren, ist dort ja in der Regel Unmengen an für das Release unnötige Zeug drin. So ein einfaches extend-diff-ignore reicht da gar nicht aus.
Debian 11 & 12; Desktop-PC, Headless-NAS, Raspberry Pi 4
Teil des Upstream Betreuer Teams von Back In Time (Debianbackintime)

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 19.09.2023 05:29:11

buhtz hat geschrieben: ↑ zum Beitrag ↑
17.09.2023 19:55:43
Muss es eigentlich noch "master" sein? Sind die Tools noch darauf festgelegt?
It's the team policy. Den Buildtools sind die Branch Namen egal, die kennen diese nicht, und was der Debian Branch ist muss man git-buildpackage sagen, wenn nicht der Standartname benutzt wird..
https://salsa.debian.org/python-team/to ... anch-names
buhtz hat geschrieben: ↑ zum Beitrag ↑
17.09.2023 19:55:43
Wozu genau ist "--sign-tags" notwendig? Bei mir schlägt das fehl. Aus der Fehlermeldung wird allerdings nicht klar, was gdb erwartet. Ich habe die Option einfach weggelassen und komme damit erst einmal weiter.
In die Manpage mal geschaut? Und nach was sieht es denn aus?
https://manpages.debian.org/bookworm/gi ... .1.en.html
Man kann einige Optionen weglassen, auch hier ist wieder die Team Policy der eigentliche Grund diesen Switch nutzen zu müssen.
buhtz hat geschrieben: ↑ zum Beitrag ↑
17.09.2023 19:55:43
Noch was anderes: Laut manpage (nicht "gbp" sondern "gb-packagebuild" übrigens) konnte ich dazu nichts finden, aber frage trotzdem. Kann man die Abfrage umgehen, in dem man den Paketnamen und Versionsnummer als Parameter übergibt?
Die Manpage gibt es nicht, sicherlich ist gbp-buildpackage gemeint. Wieso will man den Paketnamen und eine Version übergeben, so ist das nicht gedacht, dpkg-buildpackage macht das alles alleine weil es eine vergebenen Struktur mit Daten geben muss. gbp ist "nur" ein High Level Tool was die Low Level Tools aufruft, auf der Konsole ist doch zu sehen was da passiert.
buhtz hat geschrieben: ↑ zum Beitrag ↑
17.09.2023 19:55:43
ch hatte mal auf irgend einer Mailingliste "gehört", dass sauber/modern paketierte Python Pakete (also pyproject.toml, PEP621, src-Layout, usw), diesen manuellen Schritt bei Debian nicht benötigen würden. Es gäbe hier Tools die alles nötige aus einem "pip install ." ableiten würden. Aber vielleicht hab ich da auch was falsch verstanden. Bei meinem Versuch mit Debianbackintime ist das eh nicht relevant, weil das noch (Python) altbacken auf "make" setzt.
Nein, für die Build-Depends ist dies nicht der Fall, die Paketabhängigkeiten wird dies so gemacht, deswegen ja auch die Variable ${python3:Depends}.
buhtz hat geschrieben: ↑ zum Beitrag ↑
17.09.2023 19:55:43

Das Paket backintime hat schon alle benötigten Daten um es bauen und auch aktualisieren zu können mit gbp, die Schritte aus dem Thread sind so nur bedingt anwendbar.
Der Sinn dieses ignore ist mir nicht klar. Ein egg-info Ordner sollte doch erst gar nicht Bestandteil des source-tarballs sein. In der Realität ist es häufig anders, dass ist mir klar. Aber sollte man hier in diesem Thread nicht eher darauf hinweisen, dass die Leute vorher einen sauberen source-tarball erzeugen, ohne den sonstigen Kladaradatsch? Vielleicht definieren ich source-tarball auch anders? Was muss da drin sein? Würde ich einfach das komplette upstream repo 1 zu 1 kopieren, ist dort ja in der Regel Unmengen an für das Release unnötige Zeug drin. So ein einfaches extend-diff-ignore reicht da gar nicht aus.
Dann ist Dir nicht klar was der Sinn der Datei debian/source/options ist. Über diese Datei kann man steuern wie sich dpkg-source verhalten soll, und ja, es soll genau diesen Pattern ignorieren (aus verschiedenen Gründen). Diese Daten werden beim Paketbau neu erstellt, manche Upstream Projekte habe diese aber im Source Tarball mit enthalten. Nicht jeder Paketmaintainer benutzt git-buildpackage oder hat debian/changelog entsprechend präpariert. Der pragmatische Ansatz ist dann diese Datei / Daten zu ignorieren.

buhtz
Beiträge: 1106
Registriert: 04.12.2015 17:54:49
Kontaktdaten:

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von buhtz » 19.09.2023 09:59:07

Hallo Tijuca,
danke für deine geduldigen Erklärungen.

Zu --sign-tags: Natürlich hab ich die manpage konsultiert, aber auch ohne ist technisch klar, worum es da geht. Ich frage, weil ich das "große Bild" dazu verstehen möchte. In deinem Beispiel sehe ich keine Tags. Also warum soll da was signiert werden? Und brauche ich das, wenn ich nicht Maintainer/Uploader bin, sondern meine Paketierung dem eigentlichen Maintainer zur Verfügung stelle?
tijuca hat geschrieben: ↑ zum Beitrag ↑
19.09.2023 05:29:11
Wieso will man den Paketnamen und eine Version übergeben
Kann ich dir sagen. 8) Das ist IMHO ein unnötiger Schritt, weil die Info ja schon in den Metadaten des Python-Paketes (z.B. pyproject.toml) drin steht. Das kann ich mit einem Script extrahieren und dann übergeben. Ist nicht nur bequemer, sondern reduziert auch Potential für Übertragungsfehler.
tijuca hat geschrieben: ↑ zum Beitrag ↑
19.09.2023 05:29:11
Dann ist Dir nicht klar was der Sinn der Datei debian/source/options ist. Über diese Datei kann man steuern wie sich dpkg-source verhalten soll, und ja, es soll genau diesen Pattern ignorieren (aus verschiedenen Gründen).
Verstehe, so halb.
Da kommen mir die Unittests in den Sinn. Die Debian-Server lassen ja (im besten Fall) die unittests durchlaufen. Aber im finalen deb-file, dass im stable repo landet und der user per "apt install package" installiert, sollten die test_*.py files ja nicht mehr drin sein.

An welcher Stelle im zeitlichen Verlauf befindet sich debian/source/options ? Werden die unittests vorher abgearbeitet und dann erst diese exclude patterns angewendet?
Debian 11 & 12; Desktop-PC, Headless-NAS, Raspberry Pi 4
Teil des Upstream Betreuer Teams von Back In Time (Debianbackintime)

tijuca
Beiträge: 297
Registriert: 22.06.2017 22:12:20

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von tijuca » 23.09.2023 09:24:03

buhtz hat geschrieben: ↑ zum Beitrag ↑
19.09.2023 09:59:07
Zu --sign-tags: Natürlich hab ich die manpage konsultiert, aber auch ohne ist technisch klar, worum es da geht. Ich frage, weil ich das "große Bild" dazu verstehen möchte. In deinem Beispiel sehe ich keine Tags. Also warum soll da was signiert werden? Und brauche ich das, wenn ich nicht Maintainer/Uploader bin, sondern meine Paketierung dem eigentlichen Maintainer zur Verfügung stelle?
Wenn Du rein privat arbeitest wird man mit großer Wahrscheinlichkeit keine signierten Tags benötigen, mein Beispiel war aber wiederum eher gedacht den Workflow zu zeigen der im DPT gelebt wird und auf einer Policy basiert.
Der Sinn von Signaturen ist ganz einfach, nur damit ist es möglich zu verifizieren ob die ID die den Tag erstellt hat auch zum passt was dann dort als Author zu finden ist.
buhtz hat geschrieben: ↑ zum Beitrag ↑
19.09.2023 09:59:07
Kann ich dir sagen. 8) Das ist IMHO ein unnötiger Schritt, weil die Info ja schon in den Metadaten des Python-Paketes (z.B. pyproject.toml) drin steht. Das kann ich mit einem Script extrahieren und dann übergeben. Ist nicht nur bequemer, sondern reduziert auch Potential für Übertragungsfehler.
Das ist aber so nicht vorgesehen im Debian Paketbau, die Versionsnummer für den Bau von Binärpakten kommt aus dem aktuellsten Eintrag in debian/changelog, eventuelle Infos aus den Dateien setup.{cfg,py} oder pyproject.toml werden ignoriert und überhaupt nicht beachtet. Und, die Upstreamversion ist bei nicht nativen Versionen nur ein Teil der Debian Versionsnummer. Auch gibt es alte Projekte wo man keine Version leicht automatisiert irgendwo auslesen kann, alte setuptools Versionen sind dort leider der Standard.
Wenn Du "Deine Version" automatisiert benutzen willst musst Du Dich selber darum kümmern, in Debian wollen wir keine automatisierten Versionsnummern. Wenn eine Version im Archiv ist dann ist die dort bis in alle Ewigkeit, wenn aus 1.0.1 durch Logikfehler automatisiert 10.1 wird gibt es ein kleines Problem für die Version >= 1.0.2.
buhtz hat geschrieben: ↑ zum Beitrag ↑
19.09.2023 09:59:07
Verstehe, so halb.
Da kommen mir die Unittests in den Sinn. Die Debian-Server lassen ja (im besten Fall) die unittests durchlaufen. Aber im finalen deb-file, dass im stable repo landet und der user per "apt install package" installiert, sollten die test_*.py files ja nicht mehr drin sein.
Was haben die Tests mit dem ursprünglichen Problem zu tun? Das erschließt sich mir nicht. Die Tests benötigen keine egg-info Dateien. Und während des Paketbaus werden die Dateien neu erstellt und verpackt. Unittests sind was anderes wie Integrationstests die manchmal solche Infos benötigen oder auslesen.

buhtz
Beiträge: 1106
Registriert: 04.12.2015 17:54:49
Kontaktdaten:

Re: HowTo: Wie paketiert man eine Python Bibliothek?

Beitrag von buhtz » 25.09.2023 16:07:18

tijuca hat geschrieben: ↑ zum Beitrag ↑
23.09.2023 09:24:03
buhtz hat geschrieben: ↑ zum Beitrag ↑
19.09.2023 09:59:07
Da kommen mir die Unittests in den Sinn. Die Debian-Server lassen ja (im besten Fall) die unittests durchlaufen. Aber im finalen deb-file, dass im stable repo landet und der user per "apt install package" installiert, sollten die test_*.py files ja nicht mehr drin sein.
Was haben die Tests mit dem ursprünglichen Problem zu tun? Das erschließt sich mir nicht. Die Tests benötigen keine egg-info Dateien. Und während des Paketbaus werden die Dateien neu erstellt und verpackt. Unittests sind was anderes wie Integrationstests die manchmal solche Infos benötigen oder auslesen.
Sorry, ich verstehe die Rückfrage nicht. Das liegt evtl. an unseren verschiedenen Grundannahmen.

IMHO tests (egal ob unit, integration oder system) gehören nicht in ein "release-deb-file", also das was ich als "normaler" User am Ende mit "apt install" installiere.
Aber die Debian Build/CI Server lassen ja solche Tests laufen. Also muss ich ja darauf achten, dass die Testdateien im (source?) Paket bleiben und erst nach dem Testen auf den Debian Systemen irgendwie (?) entfernt werden.
Debian 11 & 12; Desktop-PC, Headless-NAS, Raspberry Pi 4
Teil des Upstream Betreuer Teams von Back In Time (Debianbackintime)

Antworten