Commit 2230cfba authored by A. Wilcox's avatar A. Wilcox 🦊
Browse files

Add initial code for reading in APK files.

parent 033db487
"""Contains the Package class and related helper classes and functions."""
pkginfo_template = """
# Generated by APK Kit for Adélie Linux
# {builduser}@{buildhost} {builddate}
pkgname = {name}
pkgver = {ver}
pkgdesc = {desc}
arch = {arch}
class Package:
"""The base package class."""
def __init__(self, name, version, arch, description=None, url=None, size=0,
provides=None, depends=None):
"""Initialise a package object.
:param str name:
The name of the package.
:param str version:
The version of the package.
:param str arch:
The architecture of the package.
:param str description:
(Recommended) The description of the package. Defaults to the name
if not set.
:param int size:
(Recommended) The installed size of the package. You almost always
want to set this to something other than 0 if you don't want unhappy
users. :)
:param str url:
(Optional) The URL of the homepage for the package.
:param list provides:
(Optional) One or more virtuals that this package provides.
:param list depends:
(Optional) One or more packages that are required to be installed
to use this package.
self._pkgname = name
self._pkgver = version
self._pkgdesc = description or name
self._url = url
self._size = int(size)
self._arch = arch
self._provides = provides or list()
self._depends = depends or list()
def name(self):
"""The name of the package."""
return self._pkgname
def version(self):
"""The version of the package."""
return self._pkgver
def description(self):
"""The description of the package."""
return self._pkgdesc
def url(self):
"""The URL of the homepage of the package."""
return self._url
def size(self):
"""The installed size of the package in bytes."""
return self._size
def arch(self):
"""The architecture of the package."""
return self._arch
def depends(self):
"""The dependencies of the package."""
return self._depends
def __repr__(self):
return 'Package(name="{name}", version="{ver}", arch="{arch}", '\
'description="{desc}", url="{url}", size={size}, '\
'provides={prov}, depends={dep})'.format(
name=self._pkgname, ver=self._pkgver, arch=self._arch,
desc=self._pkgdesc, prov=self._provides, dep=self._depends,
url=self._url, size=self._size)
def to_pkginfo(self):
"""Serialises the package's information into the PKGINFO format.
:returns str: The PKGINFO for this package. Unicode str, ready to be
written to a file.
.. note:: To write a file, see the :py:meth:`.write_pkginfo` helper
def from_pkginfo(cls, buf):
"""Create a new :py:class:`Package` object from an existing PKGINFO.
:param buf:
The buffer to read from (whether file, StringIO, etc).
A :py:class:`Package` object with the details from the PKGINFO.
:throws ValueError:
If a required field is missing from the PKGINFO.
params = {}
param_map = {'pkgname': 'name', 'pkgver': 'version', 'arch': 'arch',
'pkgdesc': 'description', 'provides': 'provides',
'depend': 'depends', 'url': 'url', 'size': 'size'}
list_keys = {'provides', 'depend'}
params['provides'] = list()
params['depends'] = list()
for line in buf.readlines():
# XXX TODO make this better
if type(line) != str:
line = line.decode('utf-8')
# Skip comments.
if len(line) == 0 or line[0] == '#':
if line.index('=') == -1:
print('!!! malformed line? {} !!!'.format(line))
(key, value) = line.split('=', 1)
key = key.strip()
value = value.strip()
if key in param_map:
if key in list_keys:
params[param_map[key]] = value
print('!!! unrecognised PKGINFO key {} !!!'.format(key))
return cls(**params)
from apkkit.base.package import Package
import gzip # Not used, but we need to raise ImportError if gzip isn't built.
import tarfile
class APKFile:
"""Represents an APK file on disk (or in memory)."""
def __init__(self, filename, mode='r'):
self.tar =, mode)
self.package = Package.from_pkginfo(self.tar.extractfile('.PKGINFO'))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment