5 @contact: Debian FTPMaster <ftpmaster@debian.org>
6 @copyright: 2000, 2001, 2002, 2003, 2004, 2006 James Troup <james@nocrew.org>
7 @copyright: 2008-2009 Mark Hymers <mhy@debian.org>
8 @copyright: 2009 Joerg Jaspert <joerg@debian.org>
9 @copyright: 2009 Mike O'Connor <stew@debian.org>
10 @license: GNU General Public License version 2 or later
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2 of the License, or
16 # (at your option) any later version.
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 ################################################################################
29 # < mhy> I need a funny comment
30 # < sgran> two peanuts were walking down a dark street
31 # < sgran> one was a-salted
32 # * mhy looks up the definition of "funny"
34 ################################################################################
40 from sqlalchemy import create_engine, Table, MetaData, select
41 from sqlalchemy.orm import sessionmaker, mapper, relation
43 # Don't remove this, we re-export the exceptions to scripts which import us
44 from sqlalchemy.exc import *
46 from singleton import Singleton
48 ################################################################################
52 ################################################################################
54 class Architecture(object):
55 def __init__(self, *args, **kwargs):
59 return '<Architecture %s>' % self.arch_string
61 __all__.append('Architecture')
63 def get_architecture(architecture, session=None):
65 Returns database id for given C{architecture}.
67 @type architecture: string
68 @param architecture: The name of the architecture
70 @type session: Session
71 @param session: Optional SQLA session object (a temporary one will be
72 generated if not supplied)
75 @return: Architecture object for the given arch (None if not present)
79 session = DBConn().session()
80 q = session.query(Architecture).filter_by(arch_string=architecture)
85 __all__.append('get_architecture')
87 def get_architecture_suites(architecture, session=None):
89 Returns list of Suite objects for given C{architecture} name
92 @param source: Architecture name to search for
94 @type session: Session
95 @param session: Optional SQL session object (a temporary one will be
96 generated if not supplied)
99 @return: list of Suite objects for the given name (may be empty)
103 session = DBConn().session()
105 q = session.query(Suite)
106 q = q.join(SuiteArchitecture)
107 q = q.join(Architecture).filter_by(arch_string=architecture).order_by('suite_name')
110 __all__.append('get_architecture_suites')
112 class Archive(object):
113 def __init__(self, *args, **kwargs):
117 return '<Archive %s>' % self.name
119 __all__.append('Archive')
121 def get_archive(archive, session=None):
123 returns database id for given c{archive}.
125 @type archive: string
126 @param archive: the name of the arhive
128 @type session: Session
129 @param session: Optional SQLA session object (a temporary one will be
130 generated if not supplied)
133 @return: Archive object for the given name (None if not present)
136 archive = archive.lower()
138 session = DBConn().session()
139 q = session.query(Archive).filter_by(archive_name=archive)
144 __all__.append('get_archive')
146 class BinAssociation(object):
147 def __init__(self, *args, **kwargs):
151 return '<BinAssociation %s (%s, %s)>' % (self.ba_id, self.binary, self.suite)
153 __all__.append('BinAssociation')
155 class Binary(object):
156 def __init__(self, *args, **kwargs):
160 return '<Binary %s (%s, %s)>' % (self.package, self.version, self.architecture)
162 __all__.append('Binary')
164 def get_binary_from_id(id, session=None):
166 Returns Binary object for given C{id}
169 @param id: Id of the required binary
171 @type session: Session
172 @param session: Optional SQLA session object (a temporary one will be
173 generated if not supplied)
176 @return: Binary object for the given binary (None if not present)
179 session = DBConn().session()
180 q = session.query(Binary).filter_by(binary_id=id)
185 __all__.append('get_binary_from_id')
187 def get_binaries_from_name(package, session=None):
189 Returns list of Binary objects for given C{package} name
192 @param package: Binary package name to search for
194 @type session: Session
195 @param session: Optional SQL session object (a temporary one will be
196 generated if not supplied)
199 @return: list of Binary objects for the given name (may be empty)
202 session = DBConn().session()
203 return session.query(Binary).filter_by(package=package).all()
205 __all__.append('get_binaries_from_name')
207 class Component(object):
208 def __init__(self, *args, **kwargs):
212 return '<Component %s>' % self.component_name
215 __all__.append('Component')
217 def get_component(component, session=None):
219 Returns database id for given C{component}.
221 @type component: string
222 @param component: The name of the override type
225 @return: the database id for the given component
228 component = component.lower()
230 session = DBConn().session()
231 q = session.query(Component).filter_by(component_name=component)
236 __all__.append('get_component')
238 class DBConfig(object):
239 def __init__(self, *args, **kwargs):
243 return '<DBConfig %s>' % self.name
245 __all__.append('DBConfig')
247 class ContentFilename(object):
248 def __init__(self, *args, **kwargs):
252 return '<ContentFilename %s>' % self.filename
254 __all__.append('ContentFilename')
256 def get_or_set_contents_file_id(filename, session=None):
258 Returns database id for given filename.
260 If no matching file is found, a row is inserted.
262 @type filename: string
263 @param filename: The filename
264 @type session: SQLAlchemy
265 @param session: Optional SQL session object (a temporary one will be
266 generated if not supplied)
269 @return: the database id for the given component
272 session = DBConn().session()
275 q = session.query(ContentFilename).filter_by(filename=filename)
277 cf = ContentFilename()
278 cf.filename = filename
280 return cf.cafilename_id
282 return q.one().cafilename_id
285 traceback.print_exc()
288 __all__.append('get_or_set_contents_file_id')
290 class ContentFilepath(object):
291 def __init__(self, *args, **kwargs):
295 return '<ContentFilepath %s>' % self.filepath
297 __all__.append('ContentFilepath')
299 def get_or_set_contents_path_id(filepath, session):
301 Returns database id for given path.
303 If no matching file is found, a row is inserted.
305 @type filename: string
306 @param filename: The filepath
307 @type session: SQLAlchemy
308 @param session: Optional SQL session object (a temporary one will be
309 generated if not supplied)
312 @return: the database id for the given path
315 session = DBConn().session()
318 q = session.query(ContentFilepath).filter_by(filepath=filepath)
320 cf = ContentFilepath()
321 cf.filepath = filepath
323 return cf.cafilepath_id
325 return q.one().cafilepath_id
328 traceback.print_exc()
331 __all__.append('get_or_set_contents_path_id')
333 class ContentAssociation(object):
334 def __init__(self, *args, **kwargs):
338 return '<ContentAssociation %s>' % self.ca_id
340 __all__.append('ContentAssociation')
342 def insert_content_paths(binary_id, fullpaths, session=None):
344 Make sure given path is associated with given binary id
347 @param binary_id: the id of the binary
348 @type fullpaths: list
349 @param fullpaths: the list of paths of the file being associated with the binary
350 @type session: SQLAlchemy session
351 @param session: Optional SQLAlchemy session. If this is passed, the caller
352 is responsible for ensuring a transaction has begun and committing the
353 results or rolling back based on the result code. If not passed, a commit
354 will be performed at the end of the function
356 @return: True upon success
362 session = DBConn().session()
366 for fullpath in fullpaths:
367 (path, file) = os.path.split(fullpath)
369 # Get the necessary IDs ...
370 ca = ContentAssociation()
371 ca.binary_id = binary_id
372 ca.filename_id = get_or_set_contents_file_id(file)
373 ca.filepath_id = get_or_set_contents_path_id(path)
376 # Only commit if we set up the session ourself
382 traceback.print_exc()
384 # Only rollback if we set up the session ourself
390 __all__.append('insert_content_paths')
392 class DSCFile(object):
393 def __init__(self, *args, **kwargs):
397 return '<DSCFile %s>' % self.dscfile_id
399 __all__.append('DSCFile')
401 class PoolFile(object):
402 def __init__(self, *args, **kwargs):
406 return '<PoolFile %s>' % self.filename
408 __all__.append('PoolFile')
410 def get_poolfile_by_name(filename, location_id=None, session=None):
412 Returns an array of PoolFile objects for the given filename and
413 (optionally) location_id
415 @type filename: string
416 @param filename: the filename of the file to check against the DB
418 @type location_id: int
419 @param location_id: the id of the location to look in (optional)
422 @return: array of PoolFile objects
425 if session is not None:
426 session = DBConn().session()
428 q = session.query(PoolFile).filter_by(filename=filename)
430 if location_id is not None:
431 q = q.join(Location).filter_by(location_id=location_id)
435 __all__.append('get_poolfile_by_name')
437 class Fingerprint(object):
438 def __init__(self, *args, **kwargs):
442 return '<Fingerprint %s>' % self.fingerprint
444 __all__.append('Fingerprint')
446 class Keyring(object):
447 def __init__(self, *args, **kwargs):
451 return '<Keyring %s>' % self.keyring_name
453 __all__.append('Keyring')
455 class Location(object):
456 def __init__(self, *args, **kwargs):
460 return '<Location %s (%s)>' % (self.path, self.location_id)
462 __all__.append('Location')
464 def get_location(location, component=None, archive=None, session=None):
466 Returns Location object for the given combination of location, component
469 @type location: string
470 @param location: the path of the location, e.g. I{/srv/ftp.debian.org/ftp/pool/}
472 @type component: string
473 @param component: the component name (if None, no restriction applied)
475 @type archive: string
476 @param archive_id: the archive name (if None, no restriction applied)
478 @rtype: Location / None
479 @return: Either a Location object or None if one can't be found
483 session = DBConn().session()
485 q = session.query(Location).filter_by(path=location)
487 if archive is not None:
488 q = q.join(Archive).filter_by(archive_name=archive)
490 if component is not None:
491 q = q.join(Component).filter_by(component_name=component)
498 __all__.append('get_location')
500 class Maintainer(object):
501 def __init__(self, *args, **kwargs):
505 return '''<Maintainer '%s' (%s)>''' % (self.name, self.maintainer_id)
507 __all__.append('Maintainer')
509 class Override(object):
510 def __init__(self, *args, **kwargs):
514 return '<Override %s (%s)>' % (self.package, self.suite_id)
516 __all__.append('Override')
518 class OverrideType(object):
519 def __init__(self, *args, **kwargs):
523 return '<OverrideType %s>' % self.overridetype
525 __all__.append('OverrideType')
527 def get_override_type(override_type, session=None):
529 Returns OverrideType object for given C{override type}.
531 @type override_type: string
532 @param override_type: The name of the override type
534 @type session: Session
535 @param session: Optional SQLA session object (a temporary one will be
536 generated if not supplied)
539 @return: the database id for the given override type
543 session = DBConn().session()
544 q = session.query(Priority).filter_by(priority=priority)
549 __all__.append('get_override_type')
551 class PendingContentAssociation(object):
552 def __init__(self, *args, **kwargs):
556 return '<PendingContentAssociation %s>' % self.pca_id
558 __all__.append('PendingContentAssociation')
560 def insert_pending_content_paths(package, fullpaths, session=None):
562 Make sure given paths are temporarily associated with given
566 @param package: the package to associate with should have been read in from the binary control file
567 @type fullpaths: list
568 @param fullpaths: the list of paths of the file being associated with the binary
569 @type session: SQLAlchemy session
570 @param session: Optional SQLAlchemy session. If this is passed, the caller
571 is responsible for ensuring a transaction has begun and committing the
572 results or rolling back based on the result code. If not passed, a commit
573 will be performed at the end of the function
575 @return: True upon success, False if there is a problem
581 session = DBConn().session()
585 arch = get_architecture(package['Architecture'], session)
586 arch_id = arch.arch_id
588 # Remove any already existing recorded files for this package
589 q = session.query(PendingContentAssociation)
590 q = q.filter_by(package=package['Package'])
591 q = q.filter_by(version=package['Version'])
592 q = q.filter_by(architecture=arch_id)
596 for fullpath in fullpaths:
597 (path, file) = os.path.split(fullpath)
599 if path.startswith( "./" ):
602 pca = PendingContentAssociation()
603 pca.package = package['Package']
604 pca.version = package['Version']
605 pca.filename_id = get_or_set_contents_file_id(file, session)
606 pca.filepath_id = get_or_set_contents_path_id(path, session)
607 pca.architecture = arch_id
610 # Only commit if we set up the session ourself
616 traceback.print_exc()
618 # Only rollback if we set up the session ourself
624 __all__.append('insert_pending_content_paths')
626 class Priority(object):
627 def __init__(self, *args, **kwargs):
631 return '<Priority %s (%s)>' % (self.priority, self.priority_id)
633 __all__.append('Priority')
635 def get_priority(priority, session=None):
637 Returns Priority object for given C{priority name}.
639 @type priority: string
640 @param priority: The name of the priority
642 @type session: Session
643 @param session: Optional SQLA session object (a temporary one will be
644 generated if not supplied)
647 @return: Priority object for the given priority
651 session = DBConn().session()
652 q = session.query(Priority).filter_by(priority=priority)
657 __all__.append('get_priority')
660 def __init__(self, *args, **kwargs):
664 return '<Queue %s>' % self.queue_name
666 __all__.append('Queue')
668 class QueueBuild(object):
669 def __init__(self, *args, **kwargs):
673 return '<QueueBuild %s (%s)>' % (self.filename, self.queue_id)
675 __all__.append('QueueBuild')
677 class Section(object):
678 def __init__(self, *args, **kwargs):
682 return '<Section %s>' % self.section
684 __all__.append('Section')
686 def get_section(section, session=None):
688 Returns Section object for given C{section name}.
690 @type section: string
691 @param section: The name of the section
693 @type session: Session
694 @param session: Optional SQLA session object (a temporary one will be
695 generated if not supplied)
698 @return: Section object for the given section name
702 session = DBConn().session()
703 q = session.query(Section).filter_by(section=section)
708 __all__.append('get_section')
710 class Source(object):
711 def __init__(self, *args, **kwargs):
715 return '<Source %s (%s)>' % (self.source, self.version)
717 __all__.append('Source')
719 def get_sources_from_name(source, session=None):
721 Returns list of Source objects for given C{source} name
724 @param source: Source package name to search for
726 @type session: Session
727 @param session: Optional SQL session object (a temporary one will be
728 generated if not supplied)
731 @return: list of Source objects for the given name (may be empty)
734 session = DBConn().session()
735 return session.query(Source).filter_by(source=source).all()
737 __all__.append('get_sources_from_name')
739 def get_source_in_suite(source, suite, session=None):
741 Returns list of Source objects for a combination of C{source} and C{suite}.
743 - B{source} - source package name, eg. I{mailfilter}, I{bbdb}, I{glibc}
744 - B{suite} - a suite name, eg. I{unstable}
747 @param source: source package name
750 @param suite: the suite name
753 @return: the version for I{source} in I{suite}
757 session = DBConn().session()
758 q = session.query(SrcAssociation)
759 q = q.join('source').filter_by(source=source)
760 q = q.join('suite').filter_by(suite_name=suite)
763 # ???: Maybe we should just return the SrcAssociation object instead
764 return q.one().source
766 __all__.append('get_source_in_suite')
768 class SrcAssociation(object):
769 def __init__(self, *args, **kwargs):
773 return '<SrcAssociation %s (%s, %s)>' % (self.sa_id, self.source, self.suite)
775 __all__.append('SrcAssociation')
777 class SrcUploader(object):
778 def __init__(self, *args, **kwargs):
782 return '<SrcUploader %s>' % self.uploader_id
784 __all__.append('SrcUploader')
787 def __init__(self, *args, **kwargs):
791 return '<Suite %s>' % self.suite_name
793 __all__.append('Suite')
795 def get_suite_architecture(suite, architecture, session=None):
797 Returns a SuiteArchitecture object given C{suite} and ${arch} or None if it
801 @param suite: Suite name to search for
803 @type architecture: str
804 @param architecture: Architecture name to search for
806 @type session: Session
807 @param session: Optional SQL session object (a temporary one will be
808 generated if not supplied)
810 @rtype: SuiteArchitecture
811 @return: the SuiteArchitecture object or None
815 session = DBConn().session()
817 q = session.query(SuiteArchitecture)
818 q = q.join(Architecture).filter_by(arch_string=architecture)
819 q = q.join(Suite).filter_by(suite_name=suite)
824 __all__.append('get_suite_architecture')
826 def get_suite(suite, session=None):
828 Returns Suite object for given C{suite name}.
831 @param suite: The name of the suite
833 @type session: Session
834 @param session: Optional SQLA session object (a temporary one will be
835 generated if not supplied)
838 @return: Suite object for the requested suite name (None if not presenT)
842 session = DBConn().session()
843 q = session.query(Suite).filter_by(suite_name=suite)
848 __all__.append('get_suite')
850 class SuiteArchitecture(object):
851 def __init__(self, *args, **kwargs):
855 return '<SuiteArchitecture (%s, %s)>' % (self.suite_id, self.arch_id)
857 __all__.append('SuiteArchitecture')
859 def get_suite_architectures(suite, session=None):
861 Returns list of Architecture objects for given C{suite} name
864 @param source: Suite name to search for
866 @type session: Session
867 @param session: Optional SQL session object (a temporary one will be
868 generated if not supplied)
871 @return: list of Architecture objects for the given name (may be empty)
875 session = DBConn().session()
877 q = session.query(Architecture)
878 q = q.join(SuiteArchitecture)
879 q = q.join(Suite).filter_by(suite_name=suite).order_by('arch_string')
882 __all__.append('get_suite_architectures')
885 def __init__(self, *args, **kwargs):
889 return '<Uid %s (%s)>' % (self.uid, self.name)
891 __all__.append('Uid')
893 ################################################################################
895 class DBConn(Singleton):
897 database module init.
899 def __init__(self, *args, **kwargs):
900 super(DBConn, self).__init__(*args, **kwargs)
902 def _startup(self, *args, **kwargs):
904 if kwargs.has_key('debug'):
908 def __setuptables(self):
909 self.tbl_architecture = Table('architecture', self.db_meta, autoload=True)
910 self.tbl_archive = Table('archive', self.db_meta, autoload=True)
911 self.tbl_bin_associations = Table('bin_associations', self.db_meta, autoload=True)
912 self.tbl_binaries = Table('binaries', self.db_meta, autoload=True)
913 self.tbl_component = Table('component', self.db_meta, autoload=True)
914 self.tbl_config = Table('config', self.db_meta, autoload=True)
915 self.tbl_content_associations = Table('content_associations', self.db_meta, autoload=True)
916 self.tbl_content_file_names = Table('content_file_names', self.db_meta, autoload=True)
917 self.tbl_content_file_paths = Table('content_file_paths', self.db_meta, autoload=True)
918 self.tbl_dsc_files = Table('dsc_files', self.db_meta, autoload=True)
919 self.tbl_files = Table('files', self.db_meta, autoload=True)
920 self.tbl_fingerprint = Table('fingerprint', self.db_meta, autoload=True)
921 self.tbl_keyrings = Table('keyrings', self.db_meta, autoload=True)
922 self.tbl_location = Table('location', self.db_meta, autoload=True)
923 self.tbl_maintainer = Table('maintainer', self.db_meta, autoload=True)
924 self.tbl_override = Table('override', self.db_meta, autoload=True)
925 self.tbl_override_type = Table('override_type', self.db_meta, autoload=True)
926 self.tbl_pending_content_associations = Table('pending_content_associations', self.db_meta, autoload=True)
927 self.tbl_priority = Table('priority', self.db_meta, autoload=True)
928 self.tbl_queue = Table('queue', self.db_meta, autoload=True)
929 self.tbl_queue_build = Table('queue_build', self.db_meta, autoload=True)
930 self.tbl_section = Table('section', self.db_meta, autoload=True)
931 self.tbl_source = Table('source', self.db_meta, autoload=True)
932 self.tbl_src_associations = Table('src_associations', self.db_meta, autoload=True)
933 self.tbl_src_uploaders = Table('src_uploaders', self.db_meta, autoload=True)
934 self.tbl_suite = Table('suite', self.db_meta, autoload=True)
935 self.tbl_suite_architectures = Table('suite_architectures', self.db_meta, autoload=True)
936 self.tbl_uid = Table('uid', self.db_meta, autoload=True)
938 def __setupmappers(self):
939 mapper(Architecture, self.tbl_architecture,
940 properties = dict(arch_id = self.tbl_architecture.c.id))
942 mapper(Archive, self.tbl_archive,
943 properties = dict(archive_id = self.tbl_archive.c.id,
944 archive_name = self.tbl_archive.c.name))
946 mapper(BinAssociation, self.tbl_bin_associations,
947 properties = dict(ba_id = self.tbl_bin_associations.c.id,
948 suite_id = self.tbl_bin_associations.c.suite,
949 suite = relation(Suite),
950 binary_id = self.tbl_bin_associations.c.bin,
951 binary = relation(Binary)))
953 mapper(Binary, self.tbl_binaries,
954 properties = dict(binary_id = self.tbl_binaries.c.id,
955 package = self.tbl_binaries.c.package,
956 version = self.tbl_binaries.c.version,
957 maintainer_id = self.tbl_binaries.c.maintainer,
958 maintainer = relation(Maintainer),
959 source_id = self.tbl_binaries.c.source,
960 source = relation(Source),
961 arch_id = self.tbl_binaries.c.architecture,
962 architecture = relation(Architecture),
963 poolfile_id = self.tbl_binaries.c.file,
964 poolfile = relation(PoolFile),
965 binarytype = self.tbl_binaries.c.type,
966 fingerprint_id = self.tbl_binaries.c.sig_fpr,
967 fingerprint = relation(Fingerprint),
968 install_date = self.tbl_binaries.c.install_date,
969 binassociations = relation(BinAssociation,
970 primaryjoin=(self.tbl_binaries.c.id==self.tbl_bin_associations.c.bin))))
972 mapper(Component, self.tbl_component,
973 properties = dict(component_id = self.tbl_component.c.id,
974 component_name = self.tbl_component.c.name))
976 mapper(DBConfig, self.tbl_config,
977 properties = dict(config_id = self.tbl_config.c.id))
979 mapper(ContentAssociation, self.tbl_content_associations,
980 properties = dict(ca_id = self.tbl_content_associations.c.id,
981 filename_id = self.tbl_content_associations.c.filename,
982 filename = relation(ContentFilename),
983 filepath_id = self.tbl_content_associations.c.filepath,
984 filepath = relation(ContentFilepath),
985 binary_id = self.tbl_content_associations.c.binary_pkg,
986 binary = relation(Binary)))
989 mapper(ContentFilename, self.tbl_content_file_names,
990 properties = dict(cafilename_id = self.tbl_content_file_names.c.id,
991 filename = self.tbl_content_file_names.c.file))
993 mapper(ContentFilepath, self.tbl_content_file_paths,
994 properties = dict(cafilepath_id = self.tbl_content_file_paths.c.id,
995 filepath = self.tbl_content_file_paths.c.path))
997 mapper(DSCFile, self.tbl_dsc_files,
998 properties = dict(dscfile_id = self.tbl_dsc_files.c.id,
999 source_id = self.tbl_dsc_files.c.source,
1000 source = relation(Source),
1001 poolfile_id = self.tbl_dsc_files.c.file,
1002 poolfile = relation(PoolFile)))
1004 mapper(PoolFile, self.tbl_files,
1005 properties = dict(file_id = self.tbl_files.c.id,
1006 filesize = self.tbl_files.c.size,
1007 location_id = self.tbl_files.c.location,
1008 location = relation(Location)))
1010 mapper(Fingerprint, self.tbl_fingerprint,
1011 properties = dict(fingerprint_id = self.tbl_fingerprint.c.id,
1012 uid_id = self.tbl_fingerprint.c.uid,
1013 uid = relation(Uid),
1014 keyring_id = self.tbl_fingerprint.c.keyring,
1015 keyring = relation(Keyring)))
1017 mapper(Keyring, self.tbl_keyrings,
1018 properties = dict(keyring_name = self.tbl_keyrings.c.name,
1019 keyring_id = self.tbl_keyrings.c.id))
1021 mapper(Location, self.tbl_location,
1022 properties = dict(location_id = self.tbl_location.c.id,
1023 component_id = self.tbl_location.c.component,
1024 component = relation(Component),
1025 archive_id = self.tbl_location.c.archive,
1026 archive = relation(Archive),
1027 archive_type = self.tbl_location.c.type))
1029 mapper(Maintainer, self.tbl_maintainer,
1030 properties = dict(maintainer_id = self.tbl_maintainer.c.id))
1032 mapper(Override, self.tbl_override,
1033 properties = dict(suite_id = self.tbl_override.c.suite,
1034 suite = relation(Suite),
1035 component_id = self.tbl_override.c.component,
1036 component = relation(Component),
1037 priority_id = self.tbl_override.c.priority,
1038 priority = relation(Priority),
1039 section_id = self.tbl_override.c.section,
1040 section = relation(Section),
1041 overridetype_id = self.tbl_override.c.type,
1042 overridetype = relation(OverrideType)))
1044 mapper(OverrideType, self.tbl_override_type,
1045 properties = dict(overridetype = self.tbl_override_type.c.type,
1046 overridetype_id = self.tbl_override_type.c.id))
1048 mapper(PendingContentAssociation, self.tbl_pending_content_associations,
1049 properties = dict(pca_id = self.tbl_pending_content_associations.c.id,
1050 filepath_id = self.tbl_pending_content_associations.c.filepath,
1051 filepath = relation(ContentFilepath),
1052 filename_id = self.tbl_pending_content_associations.c.filename,
1053 filename = relation(ContentFilename)))
1055 mapper(Priority, self.tbl_priority,
1056 properties = dict(priority_id = self.tbl_priority.c.id))
1058 mapper(Queue, self.tbl_queue,
1059 properties = dict(queue_id = self.tbl_queue.c.id))
1061 mapper(QueueBuild, self.tbl_queue_build,
1062 properties = dict(suite_id = self.tbl_queue_build.c.suite,
1063 queue_id = self.tbl_queue_build.c.queue,
1064 queue = relation(Queue)))
1066 mapper(Section, self.tbl_section,
1067 properties = dict(section_id = self.tbl_section.c.id))
1069 mapper(Source, self.tbl_source,
1070 properties = dict(source_id = self.tbl_source.c.id,
1071 version = self.tbl_source.c.version,
1072 maintainer_id = self.tbl_source.c.maintainer,
1073 maintainer = relation(Maintainer,
1074 primaryjoin=(self.tbl_source.c.maintainer==self.tbl_maintainer.c.id)),
1075 poolfile_id = self.tbl_source.c.file,
1076 poolfile = relation(PoolFile),
1077 fingerprint_id = self.tbl_source.c.sig_fpr,
1078 fingerprint = relation(Fingerprint),
1079 changedby_id = self.tbl_source.c.changedby,
1080 changedby = relation(Maintainer,
1081 primaryjoin=(self.tbl_source.c.changedby==self.tbl_maintainer.c.id)),
1082 srcfiles = relation(DSCFile,
1083 primaryjoin=(self.tbl_source.c.id==self.tbl_dsc_files.c.source)),
1084 srcassociations = relation(SrcAssociation,
1085 primaryjoin=(self.tbl_source.c.id==self.tbl_src_associations.c.source))))
1087 mapper(SrcAssociation, self.tbl_src_associations,
1088 properties = dict(sa_id = self.tbl_src_associations.c.id,
1089 suite_id = self.tbl_src_associations.c.suite,
1090 suite = relation(Suite),
1091 source_id = self.tbl_src_associations.c.source,
1092 source = relation(Source)))
1094 mapper(SrcUploader, self.tbl_src_uploaders,
1095 properties = dict(uploader_id = self.tbl_src_uploaders.c.id,
1096 source_id = self.tbl_src_uploaders.c.source,
1097 source = relation(Source,
1098 primaryjoin=(self.tbl_src_uploaders.c.source==self.tbl_source.c.id)),
1099 maintainer_id = self.tbl_src_uploaders.c.maintainer,
1100 maintainer = relation(Maintainer,
1101 primaryjoin=(self.tbl_src_uploaders.c.maintainer==self.tbl_maintainer.c.id))))
1103 mapper(Suite, self.tbl_suite,
1104 properties = dict(suite_id = self.tbl_suite.c.id))
1106 mapper(SuiteArchitecture, self.tbl_suite_architectures,
1107 properties = dict(suite_id = self.tbl_suite_architectures.c.suite,
1108 suite = relation(Suite),
1109 arch_id = self.tbl_suite_architectures.c.architecture,
1110 architecture = relation(Architecture)))
1112 mapper(Uid, self.tbl_uid,
1113 properties = dict(uid_id = self.tbl_uid.c.id))
1115 ## Connection functions
1116 def __createconn(self):
1117 from config import Config
1121 connstr = "postgres://%s" % cnf["DB::Host"]
1122 if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
1123 connstr += ":%s" % cnf["DB::Port"]
1124 connstr += "/%s" % cnf["DB::Name"]
1127 connstr = "postgres:///%s" % cnf["DB::Name"]
1128 if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
1129 connstr += "?port=%s" % cnf["DB::Port"]
1131 self.db_pg = create_engine(connstr, echo=self.debug)
1132 self.db_meta = MetaData()
1133 self.db_meta.bind = self.db_pg
1134 self.db_smaker = sessionmaker(bind=self.db_pg,
1138 self.__setuptables()
1139 self.__setupmappers()
1142 return self.db_smaker()
1144 __all__.append('DBConn')