Skip to main content

A python library for parsing debian package control headers and comparing version strings

Project description

Build Status

python-dpkg

This library can be used to:

  1. read and extract control data from Debian-format package files, even on platforms that generally lack a native implementation of dpkg

  2. compare dpkg version strings, using a pure Python implementation of the algorithm described in section 5.6.12 of the debian-policy manual: https://www.debian.org/doc/debian-policy/ch-controlfields.html#version

  3. Parse debian source description (dsc) files, inspect their contents and verify that their source files are present and checksums are correct.

This is primarily intended for use on platforms that do not normally ship python-apt due to licensing restrictions or the lack of a native libapt.so (e.g. macOS)

Currently only tested on CPython 3.x, but at least in theory should run on any python distribution that can install the arpy library.

(Note: python 2.7 compatibility was removed in version 1.4.0. We are keeping a 1.3 release branch alive and are trying to make a good faith effort to backport fixes there, but it's strictly on a best-effort / spare-time basis, and we urge users to update to py3 as soon as possible.)

Installing

Install the 'pydpkg' package from PyPi using the pip tool:

$ pip install pydpkg
Collecting pydpkg
  Downloading pydpkg-1.1-py2-none-any.whl
  Installing collected packages: pydpkg
  Successfully installed pydpkg-1.1

Usage

Binary Packages

Read and extract headers

>>> from pydpkg import Dpkg
>>> dp = Dpkg('/tmp/testdeb_1:0.0.0-test_all.deb')

>>> dp.headers
{'maintainer': u'Climate Corp Engineering <no-reply@climate.com>', 'description': u'testdeb\n a bogus debian package for testing dpkg builds', 'package': u'testdeb', 'section': u'base', 'priority': u'extra', 'installed-size': u'0', 'version': u'1:0.0.0-test', 'architecture': u'all'}

>>> print(dp)
Package: testdeb
Version: 1:0.0.0-test
Section: base
Priority: extra
Architecture: all
Installed-Size: 0
Maintainer: Climate Corp Engineering <no-reply@climate.com>
Description: testdeb
 a bogus debian package for testing dpkg builds

Interact directly with the package control message

>>> dp.message
<email.message.Message instance at 0x10895c6c8>
>>> dp.message.get_content_type()
'text/plain'

Get package file fingerprints

>>> dp.fileinfo
{'sha256': '547500652257bac6f6bc83f0667d0d66c8abd1382c776c4de84b89d0f550ab7f', 'sha1': 'a5d28ae2f23e726a797349d7dd5f21baf8aa02b4', 'filesize': 910, 'md5': '149e61536a9fe36374732ec95cf7945d'}
>>> dp.md5
'149e61536a9fe36374732ec95cf7945d'
>>> dp.sha1
'a5d28ae2f23e726a797349d7dd5f21baf8aa02b4'
>>> dp.sha256
'547500652257bac6f6bc83f0667d0d66c8abd1382c776c4de84b89d0f550ab7f'
>>> dp.filesize
910

Get the components of the package version

>>> d.epoch
1
>>> d.upstream_version
u'0.0.0'
>>> d.debian_revision
u'test'

Get an arbitrary control header, case-independent

>>> d.version
u'1:0.0.0-test'

>>> d.VERSION
u'1:0.0.0-test'

>>> d.description
u'testdeb\n a bogus debian package for testing dpkg builds'

>>> d.get('nosuchheader', 'default')
'default'

Compare current version to a candidate version

>>> dp.compare_version_with('1.0')
1

>>> dp.compare_version_with('1:1.0')
-1

Compare two arbitrary version strings

>>> from pydpkg import Dpkg
>>> ver_1 = '0:1.0-test1'
>>> ver_2 = '0:1.0-test2'
>>> Dpkg.compare_versions(ver_1, ver_2)
-1

Use as a key function to sort a list of version strings

>>> from pydpkg import Dpkg
>>> sorted(['0:1.0-test1', '1:0.0-test0', '0:1.0-test2'] , key=Dpkg.compare_versions_key)
['0:1.0-test1', '0:1.0-test2', '1:0.0-test0']

Use the dpkg-inspect.py script to inspect packages

$ dpkg-inspect.py ~/testdeb*deb
Filename: /Home/n/testdeb_1:0.0.0-test_all.deb
Size:     910
MD5:      149e61536a9fe36374732ec95cf7945d
SHA1:     a5d28ae2f23e726a797349d7dd5f21baf8aa02b4
SHA256:   547500652257bac6f6bc83f0667d0d66c8abd1382c776c4de84b89d0f550ab7f
Headers:
  Package: testdeb
  Version: 1:0.0.0-test
  Section: base
  Priority: extra
  Architecture: all
  Installed-Size: 0
  Maintainer: Nathan Mehl <n@climate.com>
  Description: testdeb
   a bogus debian package for testing dpkg builds

Source Packages

Read and extract headers

>>> from pydpkg import Dsc
>>> dsc = Dsc('testdeb_0.0.0.dsc')
>>> dsc.standards_version
'3.9.6'
>>> dsc.format
'3.0 (quilt)'
>>> x.build_depends
'python (>= 2.6.6-3), debhelper (>= 9)'

Get the full set of dsc headers as a dictionary

>>> dsc.headers
{'Architecture': 'all',
 'Binary': 'testdeb',
 'Build-Depends': 'python (>= 2.6.6-3), debhelper (>= 9)',
 'Checksums-Sha1': ' f250ac0a426b31df24fc2c98050f4fab90e456cd 280 testdeb_0.0.0.orig.tar.gz\n cb3474ff94053018957ebcf1d8a2b45f75dda449 232 testdeb_0.0.0-1.debian.tar.xz\n 80cd7b01014a269d445c63b037b885d6002cf533 841 testdeb_0.0.0.dsc',
 'Checksums-Sha256': ' aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 testdeb_0.0.0.orig.tar.gz\n 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 testdeb_0.0.0-1.debian.tar.xz\n b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a 841 testdeb_0.0.0.dsc',
 'Files': ' 142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz\n fc80e6e7f1c1a08b78a674aaee6c1548 232 testdeb_0.0.0-1.debian.tar.xz\n 893d13a2ef13f7409c9521e8ab1dbccb 841 testdeb_0.0.0.dsc',
 'Format': '3.0 (quilt)',
 'Homepage': 'https://github.com/TheClimateCorporation',
 'Maintainer': 'Nathan J. Mehl <n@climate.com>',
 'Package-List': 'testdeb',
 'Source': 'testdeb',
 'Standards-Version': '3.9.6',
 'Uploaders': 'Nathan J. Mehl <n@climate.com>',
 'Version': '0.0.0-1'}

Interact directly with the dsc message

>>> dsc.message
<email.message.Message instance at 0x106fedea8>
>>> dsc.message.get_content_type()
'text/plain'
>>> dsc.message.get('uploaders')
'Nathan J. Mehl <n@climate.com>'

Render the dsc message as a string

>>> print(dsc)
Format: 3.0 (quilt)
Source: testdeb
Binary: testdeb
Architecture: all
Version: 0.0.0-1
Maintainer: Nathan J. Mehl <n@climate.com>
Uploaders: Nathan J. Mehl <n@climate.com>
Homepage: https://github.com/TheClimateCorporation
Standards-Version: 3.9.6
Build-Depends: python (>= 2.6.6-3), debhelper (>= 9)
Package-List: testdeb
Checksums-Sha1:
 f250ac0a426b31df24fc2c98050f4fab90e456cd 280 testdeb_0.0.0.orig.tar.gz
 cb3474ff94053018957ebcf1d8a2b45f75dda449 232 testdeb_0.0.0-1.debian.tar.xz
 80cd7b01014a269d445c63b037b885d6002cf533 841 testdeb_0.0.0.dsc
Checksums-Sha256:
 aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 testdeb_0.0.0.orig.tar.gz
 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 testdeb_0.0.0-1.debian.tar.xz
 b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a 841 testdeb_0.0.0.dsc
Files:
 142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz
 fc80e6e7f1c1a08b78a674aaee6c1548 232 testdeb_0.0.0-1.debian.tar.xz
 893d13a2ef13f7409c9521e8ab1dbccb 841 testdeb_0.0.0.dsc

List the package source files from the dsc

>>> dsc.source_files
['/tmp/testdeb_0.0.0.orig.tar.gz',
 '/tmp/testdeb_0.0.0-1.debian.tar.xz',
 '/tmp/testdeb_0.0.0.dsc' ]

Validate that the package source files are present

>>> dsc.missing_files
[]
>>> dsc.all_files_present
True
>>> dsc.validate()
>>>

>>> bad = Dsc('testdeb_1.1.1-bad.dsc')
>>> bad.missing_files
['/tmp/testdeb_1.1.1.orig.tar.gz', '/tmp/testdeb_1.1.1-1.debian.tar.xz']
>>> bad.all_files_present
False
>>> bad.validate()
pydpkg.DscMissingFileError: ['/tmp/testdeb_1.1.1.orig.tar.gz', '/tmp/testdeb_1.1.1-1.debian.tar.xz']

Inspect the source file checksums from the dsc

>>> pp(dsc.checksums)
{'md5': {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'fc80e6e7f1c1a08b78a674aaee6c1548',
         '/tmp/testdeb_0.0.0.dsc': '893d13a2ef13f7409c9521e8ab1dbccb',
         '/tmp/testdeb_0.0.0.orig.tar.gz': '142ca7334ed1f70302b4504566e0c233'},
 'sha1': {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449',
          '/tmp/testdeb_0.0.0.dsc': '80cd7b01014a269d445c63b037b885d6002cf533',
          '/tmp/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'},
 'sha256': {'/tmp/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858',
            '/tmp/testdeb_0.0.0.dsc': 'b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a',
            '/tmp/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}}

Validate that all source file checksums are correct

>>> dsc.corrected_checksums
{}
>>> dsc.all_checksums_correct
True
>>> dsc.validate()
>>>

>>> bad = Dsc('testdeb_0.0.0-badchecksums.dsc')
>>> bad.corrected_checksums
{'sha256': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', '/tmp/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}), 'sha1': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', '/tmp/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'})}
>>> bad.all_checksums_correct
False
>>> bad.validate()
pydpkg.DscBadChecksumsError: {'sha256': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', '/tmp/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}), 'sha1': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', '/tmp/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'})}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydpkg-1.5.0.tar.gz (26.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydpkg-1.5.0-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file pydpkg-1.5.0.tar.gz.

File metadata

  • Download URL: pydpkg-1.5.0.tar.gz
  • Upload date:
  • Size: 26.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.53.0 CPython/3.8.6

File hashes

Hashes for pydpkg-1.5.0.tar.gz
Algorithm Hash digest
SHA256 ddff6e8504ebf502d65aafb207ed051a9bf0633856f4b1eb20aa55c0978ebb63
MD5 87ca22bcac3cc00d1c0f74cb512ab26f
BLAKE2b-256 56316c3e3cf506a508276b9eb67ad1febf7b7b8802db90fdb4997f92535351b6

See more details on using hashes here.

File details

Details for the file pydpkg-1.5.0-py3-none-any.whl.

File metadata

  • Download URL: pydpkg-1.5.0-py3-none-any.whl
  • Upload date:
  • Size: 13.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.25.0 setuptools/50.3.2 requests-toolbelt/0.9.1 tqdm/4.53.0 CPython/3.8.6

File hashes

Hashes for pydpkg-1.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6be4c1cdfe11c87094aa76b731e5b53d35b08223b58900ab3727bd3f94bb3a6a
MD5 99821119f7e6412346d4ccfda5e84f57
BLAKE2b-256 466c846bbf6f7271ec7e406d3844a72a5aedf49cc2d41c202d1afed62abc6c6d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page