from inspect import getargspec
import sqlalchemy
-from sqlalchemy import create_engine, Table, MetaData, Column, Integer
+from sqlalchemy import create_engine, Table, MetaData, Column, Integer, desc
from sqlalchemy.orm import sessionmaker, mapper, relation, object_session, \
backref, MapperExtension, EXT_CONTINUE
from sqlalchemy import types as sqltypes
return ['package', 'version', 'maintainer', 'source', 'poolfile', \
'binarytype']
+ def get_component_name(self):
+ return self.poolfile.location.component.component_name
+
__all__.append('DBBinary')
@session_wrapper
__all__.append('get_suites_binary_in')
@session_wrapper
-def get_binary_from_name_suite(package, suitename, session=None):
- ### For dak examine-package
- ### XXX: Doesn't use object API yet
+def get_component_by_package_suite(package, suite_list, arch_list=[], session=None):
+ '''
+ Returns the component name of the newest binary package in suite_list or
+ None if no package is found. The result can be optionally filtered by a list
+ of architecture names.
- sql = """SELECT DISTINCT(b.package), b.version, c.name, su.suite_name
- FROM binaries b, files fi, location l, component c, bin_associations ba, suite su
- WHERE b.package='%(package)s'
- AND b.file = fi.id
- AND fi.location = l.id
- AND l.component = c.id
- AND ba.bin=b.id
- AND ba.suite = su.id
- AND su.suite_name %(suitename)s
- ORDER BY b.version DESC"""
+ @type package: str
+ @param package: DBBinary package name to search for
- return session.execute(sql % {'package': package, 'suitename': suitename})
+ @type suite_list: list of str
+ @param suite_list: list of suite_name items
-__all__.append('get_binary_from_name_suite')
+ @type arch_list: list of str
+ @param arch_list: optional list of arch_string items that defaults to []
-@session_wrapper
-def get_binary_components(package, suitename, arch, session=None):
- # Check for packages that have moved from one component to another
- query = """SELECT c.name FROM binaries b, bin_associations ba, suite s, location l, component c, architecture a, files f
- WHERE b.package=:package AND s.suite_name=:suitename
- AND (a.arch_string = :arch OR a.arch_string = 'all')
- AND ba.bin = b.id AND ba.suite = s.id AND b.architecture = a.id
- AND f.location = l.id
- AND l.component = c.id
- AND b.file = f.id"""
-
- vals = {'package': package, 'suitename': suitename, 'arch': arch}
+ @rtype: str or NoneType
+ @return: name of component or None
+ '''
- return session.execute(query, vals)
+ q = session.query(DBBinary).filter_by(package = package). \
+ join(DBBinary.suites).filter(Suite.suite_name.in_(suite_list))
+ if len(arch_list) > 0:
+ q = q.join(DBBinary.architecture). \
+ filter(Architecture.arch_string.in_(arch_list))
+ binary = q.order_by(desc(DBBinary.version)).first()
+ if binary is None:
+ return None
+ else:
+ return binary.get_component_name()
-__all__.append('get_binary_components')
+__all__.append('get_component_by_package_suite')
################################################################################
################################################################################
-class Component(object):
- def __init__(self, *args, **kwargs):
- pass
+class Component(ORMObject):
+ def __init__(self, component_name = None):
+ self.component_name = component_name
def __eq__(self, val):
if isinstance(val, str):
# This signals to use the normal comparison operator
return NotImplemented
- def __repr__(self):
- return '<Component %s>' % self.component_name
+ def properties(self):
+ return ['component_name', 'component_id', 'description', 'location', \
+ 'meets_dfsg']
+
+ def not_null_constraints(self):
+ return ['component_name']
__all__.append('Component')
def fullpath(self):
return os.path.join(self.location.path, self.filename)
- def is_valid(self, filesize = -1, md5sum = None):\
- return self.filesize == filesize and self.md5sum == md5sum
+ def is_valid(self, filesize = -1, md5sum = None):
+ return self.filesize == long(filesize) and self.md5sum == md5sum
def properties(self):
return ['filename', 'file_id', 'filesize', 'md5sum', 'sha1sum', \
################################################################################
class Location(ORMObject):
- def __init__(self, path = None):
+ def __init__(self, path = None, component = None):
self.path = path
+ self.component = component
# the column 'type' should go away, see comment at mapper
self.archive_type = 'pool'
def properties(self):
- return ['path', 'archive_type', 'component', 'files_count']
+ return ['path', 'location_id', 'archive_type', 'component', \
+ 'files_count']
def not_null_constraints(self):
return ['path', 'archive_type']
mapper(Component, self.tbl_component,
properties = dict(component_id = self.tbl_component.c.id,
- component_name = self.tbl_component.c.name))
+ component_name = self.tbl_component.c.name),
+ extension = validator)
mapper(DBConfig, self.tbl_config,
properties = dict(config_id = self.tbl_config.c.id))
mapper(Location, self.tbl_location,
properties = dict(location_id = self.tbl_location.c.id,
component_id = self.tbl_location.c.component,
- component = relation(Component),
+ component = relation(Component, \
+ backref=backref('location', uselist = False)),
archive_id = self.tbl_location.c.archive,
archive = relation(Archive),
# FIXME: the 'type' column is old cruft and