from inspect import getargspec
import sqlalchemy
-from sqlalchemy import create_engine, Table, MetaData
+from sqlalchemy import create_engine, Table, MetaData, Column, Integer
from sqlalchemy.orm import sessionmaker, mapper, relation
from sqlalchemy import types as sqltypes
# in the database
from config import Config
from textutils import fix_maintainer
+from dak_exceptions import NoSourceFieldError
################################################################################
# Patch in support for the debversion field type so that it works during
# reflection
-class DebVersion(sqltypes.Text):
- """
- Support the debversion type
- """
+try:
+ # that is for sqlalchemy 0.6
+ UserDefinedType = sqltypes.UserDefinedType
+except:
+ # this one for sqlalchemy 0.5
+ UserDefinedType = sqltypes.TypeEngine
+class DebVersion(UserDefinedType):
def get_col_spec(self):
return "DEBVERSION"
+ def bind_processor(self, dialect):
+ return None
+
+ # ' = None' is needed for sqlalchemy 0.5:
+ def result_processor(self, dialect, coltype = None):
+ return None
+
sa_major_version = sqlalchemy.__version__[0:3]
-if sa_major_version == "0.5":
+if sa_major_version in ["0.5", "0.6"]:
from sqlalchemy.databases import postgres
postgres.ischema_names['debversion'] = DebVersion
else:
- raise Exception("dak isn't ported to SQLA versions != 0.5 yet. See daklib/dbconn.py")
+ raise Exception("dak only ported to SQLA versions 0.5 and 0.6. See daklib/dbconn.py")
################################################################################
-__all__ = ['IntegrityError', 'SQLAlchemyError']
+__all__ = ['IntegrityError', 'SQLAlchemyError', 'DebVersion']
################################################################################
################################################################################
class Architecture(object):
- def __init__(self, *args, **kwargs):
- pass
+ def __init__(self, arch_string = None, description = None):
+ self.arch_string = arch_string
+ self.description = description
def __eq__(self, val):
if isinstance(val, str):
session.commit()
for f in os.listdir(self.path):
- if f.startswith('Packages') or f.startswith('Source') or f.startswith('Release'):
+ if f.startswith('Packages') or f.startswith('Source') or f.startswith('Release') or f.startswith('advisory'):
continue
try:
################################################################################
class Fingerprint(object):
- def __init__(self, *args, **kwargs):
- pass
+ def __init__(self, fingerprint = None):
+ self.fingerprint = fingerprint
def __repr__(self):
return '<Fingerprint %s>' % self.fingerprint
esclist[x] = "%c" % (int(esclist[x][2:],16))
return "".join(esclist)
- def load_keys(self, keyring):
+ def parse_address(self, uid):
+ """parses uid and returns a tuple of real name and email address"""
import email.Utils
+ (name, address) = email.Utils.parseaddr(uid)
+ name = re.sub(r"\s*[(].*[)]", "", name)
+ name = self.de_escape_gpg_str(name)
+ if name == "":
+ name = uid
+ return (name, address)
+ def load_keys(self, keyring):
if not self.keyring_id:
raise Exception('Must be initialized with database information')
field = line.split(":")
if field[0] == "pub":
key = field[4]
- (name, addr) = email.Utils.parseaddr(field[9])
- name = re.sub(r"\s*[(].*[)]", "", name)
- if name == "" or addr == "" or "@" not in addr:
- name = field[9]
- addr = "invalid-uid"
- name = self.de_escape_gpg_str(name)
- self.keys[key] = {"email": addr}
- if name != "":
+ self.keys[key] = {}
+ (name, addr) = self.parse_address(field[9])
+ if "@" in addr:
+ self.keys[key]["email"] = addr
self.keys[key]["name"] = name
- self.keys[key]["aliases"] = [name]
self.keys[key]["fingerprints"] = []
signingkey = True
elif key and field[0] == "sub" and len(field) >= 12:
signingkey = ("s" in field[11])
elif key and field[0] == "uid":
- (name, addr) = email.Utils.parseaddr(field[9])
- if name and name not in self.keys[key]["aliases"]:
- self.keys[key]["aliases"].append(name)
+ (name, addr) = self.parse_address(field[9])
+ if "email" not in self.keys[key] and "@" in addr:
+ self.keys[key]["email"] = addr
+ self.keys[key]["name"] = name
elif signingkey and field[0] == "fpr":
self.keys[key]["fingerprints"].append(field[9])
self.fpr_lookup[field[9]] = key
byname = {}
any_invalid = False
for x in self.keys.keys():
- if self.keys[x]["email"] == "invalid-uid":
+ if "email" not in self.keys[x]:
any_invalid = True
self.keys[x]["uid"] = format % "invalid-uid"
else:
bin_sources = get_sources_from_name(entry["source package"], entry["source version"], session=session)
if len(bin_sources) != 1:
raise NoSourceFieldError, "Unable to find a unique source id for %s (%s), %s, file %s, type %s, signed by %s" % \
- (bin.package, bin.version, bin.architecture.arch_string,
+ (bin.package, bin.version, entry["architecture"],
filename, bin.binarytype, u.pkg.changes["fingerprint"])
bin.source_id = bin_sources[0].source_id
('Priority', 'priority'),
('NotAutomatic', 'notautomatic'),
('CopyChanges', 'copychanges'),
- ('CopyDotDak', 'copydotdak'),
- ('CommentsDir', 'commentsdir'),
- ('OverrideSuite', 'overridesuite'),
- ('ChangelogBase', 'changelogbase')]
+ ('OverrideSuite', 'overridesuite')]
class Suite(object):
- def __init__(self, *args, **kwargs):
- pass
+ def __init__(self, suite_name = None, version = None):
+ self.suite_name = suite_name
+ self.version = version
def __repr__(self):
return '<Suite %s>' % self.suite_name
################################################################################
class Uid(object):
- def __init__(self, *args, **kwargs):
- pass
+ def __init__(self, uid = None, name = None):
+ self.uid = uid
+ self.name = name
def __eq__(self, val):
if isinstance(val, str):
self.__createconn()
def __setuptables(self):
- tables = (
+ tables_with_primary = (
'architecture',
'archive',
'bin_associations',
'binaries',
'binary_acl',
'binary_acl_map',
- 'bin_contents',
'build_queue',
- 'build_queue_files',
+ 'changelogs_text',
'component',
'config',
'changes_pending_binaries',
'changes_pending_files',
- 'changes_pending_files_map',
'changes_pending_source',
- 'changes_pending_source_files',
- 'changes_pool_files',
- 'deb_contents',
'dsc_files',
'files',
'fingerprint',
'keyrings',
- 'changes',
'keyring_acl_map',
'location',
'maintainer',
'new_comments',
- 'override',
'override_type',
'pending_bin_contents',
'policy_queue',
'src_format',
'src_uploaders',
'suite',
+ 'uid',
+ 'upload_blocks',
+ # The following tables have primary keys but sqlalchemy
+ # version 0.5 fails to reflect them correctly with database
+ # versions before upgrade #41.
+ #'changes',
+ #'build_queue_files',
+ )
+
+ tables_no_primary = (
+ 'bin_contents',
+ 'changes_pending_files_map',
+ 'changes_pending_source_files',
+ 'changes_pool_files',
+ 'deb_contents',
+ 'override',
'suite_architectures',
'suite_src_formats',
'suite_build_queue_copy',
'udeb_contents',
- 'uid',
- 'upload_blocks',
+ # see the comment above
+ 'changes',
+ 'build_queue_files',
)
- for table_name in tables:
+ views = (
+ 'almost_obsolete_all_associations',
+ 'almost_obsolete_src_associations',
+ 'any_associations_source',
+ 'bin_assoc_by_arch',
+ 'bin_associations_binaries',
+ 'binaries_suite_arch',
+ 'binfiles_suite_component_arch',
+ 'changelogs',
+ 'file_arch_suite',
+ 'newest_all_associations',
+ 'newest_any_associations',
+ 'newest_source',
+ 'newest_src_association',
+ 'obsolete_all_associations',
+ 'obsolete_any_associations',
+ 'obsolete_any_by_all_associations',
+ 'obsolete_src_associations',
+ 'source_suite',
+ 'src_associations_bin',
+ 'src_associations_src',
+ 'suite_arch_by_name',
+ )
+
+ # Sqlalchemy version 0.5 fails to reflect the SERIAL type
+ # correctly and that is why we have to use a workaround. It can
+ # be removed as soon as we switch to version 0.6.
+ for table_name in tables_with_primary:
+ table = Table(table_name, self.db_meta, \
+ Column('id', Integer, primary_key = True), \
+ autoload=True, useexisting=True)
+ setattr(self, 'tbl_%s' % table_name, table)
+
+ for table_name in tables_no_primary:
table = Table(table_name, self.db_meta, autoload=True)
setattr(self, 'tbl_%s' % table_name, table)
+ for view_name in views:
+ view = Table(view_name, self.db_meta, autoload=True)
+ setattr(self, 'view_%s' % view_name, view)
+
def __setupmappers(self):
mapper(Architecture, self.tbl_architecture,
- properties = dict(arch_id = self.tbl_architecture.c.id))
+ properties = dict(arch_id = self.tbl_architecture.c.id,
+ suites = relation(Suite, secondary=self.tbl_suite_architectures, backref='architectures')))
mapper(Archive, self.tbl_archive,
properties = dict(archive_id = self.tbl_archive.c.id,