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 ################################################################################
114 class Archive(object):
115 def __init__(self, *args, **kwargs):
119 return '<Archive %s>' % self.name
121 __all__.append('Archive')
123 def get_archive(archive, session=None):
125 returns database id for given c{archive}.
127 @type archive: string
128 @param archive: the name of the arhive
130 @type session: Session
131 @param session: Optional SQLA session object (a temporary one will be
132 generated if not supplied)
135 @return: Archive object for the given name (None if not present)
138 archive = archive.lower()
140 session = DBConn().session()
141 q = session.query(Archive).filter_by(archive_name=archive)
146 __all__.append('get_archive')
148 ################################################################################
150 class BinAssociation(object):
151 def __init__(self, *args, **kwargs):
155 return '<BinAssociation %s (%s, %s)>' % (self.ba_id, self.binary, self.suite)
157 __all__.append('BinAssociation')
159 ################################################################################
161 class Binary(object):
162 def __init__(self, *args, **kwargs):
166 return '<Binary %s (%s, %s)>' % (self.package, self.version, self.architecture)
168 __all__.append('Binary')
170 def get_binary_from_id(id, session=None):
172 Returns Binary object for given C{id}
175 @param id: Id of the required binary
177 @type session: Session
178 @param session: Optional SQLA session object (a temporary one will be
179 generated if not supplied)
182 @return: Binary object for the given binary (None if not present)
185 session = DBConn().session()
186 q = session.query(Binary).filter_by(binary_id=id)
191 __all__.append('get_binary_from_id')
193 def get_binaries_from_name(package, session=None):
195 Returns list of Binary objects for given C{package} name
198 @param package: Binary package name to search for
200 @type session: Session
201 @param session: Optional SQL session object (a temporary one will be
202 generated if not supplied)
205 @return: list of Binary objects for the given name (may be empty)
208 session = DBConn().session()
209 return session.query(Binary).filter_by(package=package).all()
211 __all__.append('get_binaries_from_name')
213 ################################################################################
215 class Component(object):
216 def __init__(self, *args, **kwargs):
220 return '<Component %s>' % self.component_name
223 __all__.append('Component')
225 def get_component(component, session=None):
227 Returns database id for given C{component}.
229 @type component: string
230 @param component: The name of the override type
233 @return: the database id for the given component
236 component = component.lower()
238 session = DBConn().session()
239 q = session.query(Component).filter_by(component_name=component)
244 __all__.append('get_component')
246 ################################################################################
248 class DBConfig(object):
249 def __init__(self, *args, **kwargs):
253 return '<DBConfig %s>' % self.name
255 __all__.append('DBConfig')
257 ################################################################################
259 class ContentFilename(object):
260 def __init__(self, *args, **kwargs):
264 return '<ContentFilename %s>' % self.filename
266 __all__.append('ContentFilename')
268 def get_or_set_contents_file_id(filename, session=None):
270 Returns database id for given filename.
272 If no matching file is found, a row is inserted.
274 @type filename: string
275 @param filename: The filename
276 @type session: SQLAlchemy
277 @param session: Optional SQL session object (a temporary one will be
278 generated if not supplied)
281 @return: the database id for the given component
284 session = DBConn().session()
287 q = session.query(ContentFilename).filter_by(filename=filename)
289 cf = ContentFilename()
290 cf.filename = filename
292 return cf.cafilename_id
294 return q.one().cafilename_id
297 traceback.print_exc()
300 __all__.append('get_or_set_contents_file_id')
302 ################################################################################
304 class ContentFilepath(object):
305 def __init__(self, *args, **kwargs):
309 return '<ContentFilepath %s>' % self.filepath
311 __all__.append('ContentFilepath')
313 def get_or_set_contents_path_id(filepath, session):
315 Returns database id for given path.
317 If no matching file is found, a row is inserted.
319 @type filename: string
320 @param filename: The filepath
321 @type session: SQLAlchemy
322 @param session: Optional SQL session object (a temporary one will be
323 generated if not supplied)
326 @return: the database id for the given path
329 session = DBConn().session()
332 q = session.query(ContentFilepath).filter_by(filepath=filepath)
334 cf = ContentFilepath()
335 cf.filepath = filepath
337 return cf.cafilepath_id
339 return q.one().cafilepath_id
342 traceback.print_exc()
345 __all__.append('get_or_set_contents_path_id')
347 ################################################################################
349 class ContentAssociation(object):
350 def __init__(self, *args, **kwargs):
354 return '<ContentAssociation %s>' % self.ca_id
356 __all__.append('ContentAssociation')
358 def insert_content_paths(binary_id, fullpaths, session=None):
360 Make sure given path is associated with given binary id
363 @param binary_id: the id of the binary
364 @type fullpaths: list
365 @param fullpaths: the list of paths of the file being associated with the binary
366 @type session: SQLAlchemy session
367 @param session: Optional SQLAlchemy session. If this is passed, the caller
368 is responsible for ensuring a transaction has begun and committing the
369 results or rolling back based on the result code. If not passed, a commit
370 will be performed at the end of the function
372 @return: True upon success
378 session = DBConn().session()
382 for fullpath in fullpaths:
383 (path, file) = os.path.split(fullpath)
385 # Get the necessary IDs ...
386 ca = ContentAssociation()
387 ca.binary_id = binary_id
388 ca.filename_id = get_or_set_contents_file_id(file)
389 ca.filepath_id = get_or_set_contents_path_id(path)
392 # Only commit if we set up the session ourself
398 traceback.print_exc()
400 # Only rollback if we set up the session ourself
406 __all__.append('insert_content_paths')
408 ################################################################################
410 class DSCFile(object):
411 def __init__(self, *args, **kwargs):
415 return '<DSCFile %s>' % self.dscfile_id
417 __all__.append('DSCFile')
419 ################################################################################
421 class PoolFile(object):
422 def __init__(self, *args, **kwargs):
426 return '<PoolFile %s>' % self.filename
428 __all__.append('PoolFile')
430 def get_poolfile_by_name(filename, location_id=None, session=None):
432 Returns an array of PoolFile objects for the given filename and
433 (optionally) location_id
435 @type filename: string
436 @param filename: the filename of the file to check against the DB
438 @type location_id: int
439 @param location_id: the id of the location to look in (optional)
442 @return: array of PoolFile objects
445 if session is not None:
446 session = DBConn().session()
448 q = session.query(PoolFile).filter_by(filename=filename)
450 if location_id is not None:
451 q = q.join(Location).filter_by(location_id=location_id)
455 __all__.append('get_poolfile_by_name')
457 ################################################################################
459 class Fingerprint(object):
460 def __init__(self, *args, **kwargs):
464 return '<Fingerprint %s>' % self.fingerprint
466 __all__.append('Fingerprint')
468 ################################################################################
470 class Keyring(object):
471 def __init__(self, *args, **kwargs):
475 return '<Keyring %s>' % self.keyring_name
477 __all__.append('Keyring')
479 ################################################################################
481 class Location(object):
482 def __init__(self, *args, **kwargs):
486 return '<Location %s (%s)>' % (self.path, self.location_id)
488 __all__.append('Location')
490 def get_location(location, component=None, archive=None, session=None):
492 Returns Location object for the given combination of location, component
495 @type location: string
496 @param location: the path of the location, e.g. I{/srv/ftp.debian.org/ftp/pool/}
498 @type component: string
499 @param component: the component name (if None, no restriction applied)
501 @type archive: string
502 @param archive_id: the archive name (if None, no restriction applied)
504 @rtype: Location / None
505 @return: Either a Location object or None if one can't be found
509 session = DBConn().session()
511 q = session.query(Location).filter_by(path=location)
513 if archive is not None:
514 q = q.join(Archive).filter_by(archive_name=archive)
516 if component is not None:
517 q = q.join(Component).filter_by(component_name=component)
524 __all__.append('get_location')
526 ################################################################################
528 class Maintainer(object):
529 def __init__(self, *args, **kwargs):
533 return '''<Maintainer '%s' (%s)>''' % (self.name, self.maintainer_id)
535 __all__.append('Maintainer')
537 ################################################################################
539 class Override(object):
540 def __init__(self, *args, **kwargs):
544 return '<Override %s (%s)>' % (self.package, self.suite_id)
546 __all__.append('Override')
548 ################################################################################
550 class OverrideType(object):
551 def __init__(self, *args, **kwargs):
555 return '<OverrideType %s>' % self.overridetype
557 __all__.append('OverrideType')
559 def get_override_type(override_type, session=None):
561 Returns OverrideType object for given C{override type}.
563 @type override_type: string
564 @param override_type: The name of the override type
566 @type session: Session
567 @param session: Optional SQLA session object (a temporary one will be
568 generated if not supplied)
571 @return: the database id for the given override type
575 session = DBConn().session()
576 q = session.query(Priority).filter_by(priority=priority)
581 __all__.append('get_override_type')
583 ################################################################################
585 class PendingContentAssociation(object):
586 def __init__(self, *args, **kwargs):
590 return '<PendingContentAssociation %s>' % self.pca_id
592 __all__.append('PendingContentAssociation')
594 def insert_pending_content_paths(package, fullpaths, session=None):
596 Make sure given paths are temporarily associated with given
600 @param package: the package to associate with should have been read in from the binary control file
601 @type fullpaths: list
602 @param fullpaths: the list of paths of the file being associated with the binary
603 @type session: SQLAlchemy session
604 @param session: Optional SQLAlchemy session. If this is passed, the caller
605 is responsible for ensuring a transaction has begun and committing the
606 results or rolling back based on the result code. If not passed, a commit
607 will be performed at the end of the function
609 @return: True upon success, False if there is a problem
615 session = DBConn().session()
619 arch = get_architecture(package['Architecture'], session)
620 arch_id = arch.arch_id
622 # Remove any already existing recorded files for this package
623 q = session.query(PendingContentAssociation)
624 q = q.filter_by(package=package['Package'])
625 q = q.filter_by(version=package['Version'])
626 q = q.filter_by(architecture=arch_id)
630 for fullpath in fullpaths:
631 (path, file) = os.path.split(fullpath)
633 if path.startswith( "./" ):
636 pca = PendingContentAssociation()
637 pca.package = package['Package']
638 pca.version = package['Version']
639 pca.filename_id = get_or_set_contents_file_id(file, session)
640 pca.filepath_id = get_or_set_contents_path_id(path, session)
641 pca.architecture = arch_id
644 # Only commit if we set up the session ourself
650 traceback.print_exc()
652 # Only rollback if we set up the session ourself
658 __all__.append('insert_pending_content_paths')
660 ################################################################################
662 class Priority(object):
663 def __init__(self, *args, **kwargs):
667 return '<Priority %s (%s)>' % (self.priority, self.priority_id)
669 __all__.append('Priority')
671 def get_priority(priority, session=None):
673 Returns Priority object for given C{priority name}.
675 @type priority: string
676 @param priority: The name of the priority
678 @type session: Session
679 @param session: Optional SQLA session object (a temporary one will be
680 generated if not supplied)
683 @return: Priority object for the given priority
687 session = DBConn().session()
688 q = session.query(Priority).filter_by(priority=priority)
693 __all__.append('get_priority')
695 ################################################################################
698 def __init__(self, *args, **kwargs):
702 return '<Queue %s>' % self.queue_name
704 __all__.append('Queue')
706 ################################################################################
708 class QueueBuild(object):
709 def __init__(self, *args, **kwargs):
713 return '<QueueBuild %s (%s)>' % (self.filename, self.queue_id)
715 __all__.append('QueueBuild')
717 ################################################################################
719 class Section(object):
720 def __init__(self, *args, **kwargs):
724 return '<Section %s>' % self.section
726 __all__.append('Section')
728 def get_section(section, session=None):
730 Returns Section object for given C{section name}.
732 @type section: string
733 @param section: The name of the section
735 @type session: Session
736 @param session: Optional SQLA session object (a temporary one will be
737 generated if not supplied)
740 @return: Section object for the given section name
744 session = DBConn().session()
745 q = session.query(Section).filter_by(section=section)
750 __all__.append('get_section')
752 ################################################################################
754 class Source(object):
755 def __init__(self, *args, **kwargs):
759 return '<Source %s (%s)>' % (self.source, self.version)
761 __all__.append('Source')
763 def get_sources_from_name(source, session=None):
765 Returns list of Source objects for given C{source} name
768 @param source: Source package name to search for
770 @type session: Session
771 @param session: Optional SQL session object (a temporary one will be
772 generated if not supplied)
775 @return: list of Source objects for the given name (may be empty)
778 session = DBConn().session()
779 return session.query(Source).filter_by(source=source).all()
781 __all__.append('get_sources_from_name')
783 def get_source_in_suite(source, suite, session=None):
785 Returns list of Source objects for a combination of C{source} and C{suite}.
787 - B{source} - source package name, eg. I{mailfilter}, I{bbdb}, I{glibc}
788 - B{suite} - a suite name, eg. I{unstable}
791 @param source: source package name
794 @param suite: the suite name
797 @return: the version for I{source} in I{suite}
801 session = DBConn().session()
802 q = session.query(SrcAssociation)
803 q = q.join('source').filter_by(source=source)
804 q = q.join('suite').filter_by(suite_name=suite)
807 # ???: Maybe we should just return the SrcAssociation object instead
808 return q.one().source
810 __all__.append('get_source_in_suite')
812 ################################################################################
814 class SrcAssociation(object):
815 def __init__(self, *args, **kwargs):
819 return '<SrcAssociation %s (%s, %s)>' % (self.sa_id, self.source, self.suite)
821 __all__.append('SrcAssociation')
823 ################################################################################
825 class SrcUploader(object):
826 def __init__(self, *args, **kwargs):
830 return '<SrcUploader %s>' % self.uploader_id
832 __all__.append('SrcUploader')
834 ################################################################################
837 def __init__(self, *args, **kwargs):
841 return '<Suite %s>' % self.suite_name
843 __all__.append('Suite')
845 def get_suite_architecture(suite, architecture, session=None):
847 Returns a SuiteArchitecture object given C{suite} and ${arch} or None if it
851 @param suite: Suite name to search for
853 @type architecture: str
854 @param architecture: Architecture name to search for
856 @type session: Session
857 @param session: Optional SQL session object (a temporary one will be
858 generated if not supplied)
860 @rtype: SuiteArchitecture
861 @return: the SuiteArchitecture object or None
865 session = DBConn().session()
867 q = session.query(SuiteArchitecture)
868 q = q.join(Architecture).filter_by(arch_string=architecture)
869 q = q.join(Suite).filter_by(suite_name=suite)
874 __all__.append('get_suite_architecture')
876 def get_suite(suite, session=None):
878 Returns Suite object for given C{suite name}.
881 @param suite: The name of the suite
883 @type session: Session
884 @param session: Optional SQLA session object (a temporary one will be
885 generated if not supplied)
888 @return: Suite object for the requested suite name (None if not presenT)
892 session = DBConn().session()
893 q = session.query(Suite).filter_by(suite_name=suite)
898 __all__.append('get_suite')
900 ################################################################################
902 class SuiteArchitecture(object):
903 def __init__(self, *args, **kwargs):
907 return '<SuiteArchitecture (%s, %s)>' % (self.suite_id, self.arch_id)
909 __all__.append('SuiteArchitecture')
911 def get_suite_architectures(suite, session=None):
913 Returns list of Architecture objects for given C{suite} name
916 @param source: Suite name to search for
918 @type session: Session
919 @param session: Optional SQL session object (a temporary one will be
920 generated if not supplied)
923 @return: list of Architecture objects for the given name (may be empty)
927 session = DBConn().session()
929 q = session.query(Architecture)
930 q = q.join(SuiteArchitecture)
931 q = q.join(Suite).filter_by(suite_name=suite).order_by('arch_string')
934 __all__.append('get_suite_architectures')
936 ################################################################################
939 def __init__(self, *args, **kwargs):
943 return '<Uid %s (%s)>' % (self.uid, self.name)
945 __all__.append('Uid')
947 ################################################################################
949 class DBConn(Singleton):
951 database module init.
953 def __init__(self, *args, **kwargs):
954 super(DBConn, self).__init__(*args, **kwargs)
956 def _startup(self, *args, **kwargs):
958 if kwargs.has_key('debug'):
962 def __setuptables(self):
963 self.tbl_architecture = Table('architecture', self.db_meta, autoload=True)
964 self.tbl_archive = Table('archive', self.db_meta, autoload=True)
965 self.tbl_bin_associations = Table('bin_associations', self.db_meta, autoload=True)
966 self.tbl_binaries = Table('binaries', self.db_meta, autoload=True)
967 self.tbl_component = Table('component', self.db_meta, autoload=True)
968 self.tbl_config = Table('config', self.db_meta, autoload=True)
969 self.tbl_content_associations = Table('content_associations', self.db_meta, autoload=True)
970 self.tbl_content_file_names = Table('content_file_names', self.db_meta, autoload=True)
971 self.tbl_content_file_paths = Table('content_file_paths', self.db_meta, autoload=True)
972 self.tbl_dsc_files = Table('dsc_files', self.db_meta, autoload=True)
973 self.tbl_files = Table('files', self.db_meta, autoload=True)
974 self.tbl_fingerprint = Table('fingerprint', self.db_meta, autoload=True)
975 self.tbl_keyrings = Table('keyrings', self.db_meta, autoload=True)
976 self.tbl_location = Table('location', self.db_meta, autoload=True)
977 self.tbl_maintainer = Table('maintainer', self.db_meta, autoload=True)
978 self.tbl_override = Table('override', self.db_meta, autoload=True)
979 self.tbl_override_type = Table('override_type', self.db_meta, autoload=True)
980 self.tbl_pending_content_associations = Table('pending_content_associations', self.db_meta, autoload=True)
981 self.tbl_priority = Table('priority', self.db_meta, autoload=True)
982 self.tbl_queue = Table('queue', self.db_meta, autoload=True)
983 self.tbl_queue_build = Table('queue_build', self.db_meta, autoload=True)
984 self.tbl_section = Table('section', self.db_meta, autoload=True)
985 self.tbl_source = Table('source', self.db_meta, autoload=True)
986 self.tbl_src_associations = Table('src_associations', self.db_meta, autoload=True)
987 self.tbl_src_uploaders = Table('src_uploaders', self.db_meta, autoload=True)
988 self.tbl_suite = Table('suite', self.db_meta, autoload=True)
989 self.tbl_suite_architectures = Table('suite_architectures', self.db_meta, autoload=True)
990 self.tbl_uid = Table('uid', self.db_meta, autoload=True)
992 def __setupmappers(self):
993 mapper(Architecture, self.tbl_architecture,
994 properties = dict(arch_id = self.tbl_architecture.c.id))
996 mapper(Archive, self.tbl_archive,
997 properties = dict(archive_id = self.tbl_archive.c.id,
998 archive_name = self.tbl_archive.c.name))
1000 mapper(BinAssociation, self.tbl_bin_associations,
1001 properties = dict(ba_id = self.tbl_bin_associations.c.id,
1002 suite_id = self.tbl_bin_associations.c.suite,
1003 suite = relation(Suite),
1004 binary_id = self.tbl_bin_associations.c.bin,
1005 binary = relation(Binary)))
1007 mapper(Binary, self.tbl_binaries,
1008 properties = dict(binary_id = self.tbl_binaries.c.id,
1009 package = self.tbl_binaries.c.package,
1010 version = self.tbl_binaries.c.version,
1011 maintainer_id = self.tbl_binaries.c.maintainer,
1012 maintainer = relation(Maintainer),
1013 source_id = self.tbl_binaries.c.source,
1014 source = relation(Source),
1015 arch_id = self.tbl_binaries.c.architecture,
1016 architecture = relation(Architecture),
1017 poolfile_id = self.tbl_binaries.c.file,
1018 poolfile = relation(PoolFile),
1019 binarytype = self.tbl_binaries.c.type,
1020 fingerprint_id = self.tbl_binaries.c.sig_fpr,
1021 fingerprint = relation(Fingerprint),
1022 install_date = self.tbl_binaries.c.install_date,
1023 binassociations = relation(BinAssociation,
1024 primaryjoin=(self.tbl_binaries.c.id==self.tbl_bin_associations.c.bin))))
1026 mapper(Component, self.tbl_component,
1027 properties = dict(component_id = self.tbl_component.c.id,
1028 component_name = self.tbl_component.c.name))
1030 mapper(DBConfig, self.tbl_config,
1031 properties = dict(config_id = self.tbl_config.c.id))
1033 mapper(ContentAssociation, self.tbl_content_associations,
1034 properties = dict(ca_id = self.tbl_content_associations.c.id,
1035 filename_id = self.tbl_content_associations.c.filename,
1036 filename = relation(ContentFilename),
1037 filepath_id = self.tbl_content_associations.c.filepath,
1038 filepath = relation(ContentFilepath),
1039 binary_id = self.tbl_content_associations.c.binary_pkg,
1040 binary = relation(Binary)))
1043 mapper(ContentFilename, self.tbl_content_file_names,
1044 properties = dict(cafilename_id = self.tbl_content_file_names.c.id,
1045 filename = self.tbl_content_file_names.c.file))
1047 mapper(ContentFilepath, self.tbl_content_file_paths,
1048 properties = dict(cafilepath_id = self.tbl_content_file_paths.c.id,
1049 filepath = self.tbl_content_file_paths.c.path))
1051 mapper(DSCFile, self.tbl_dsc_files,
1052 properties = dict(dscfile_id = self.tbl_dsc_files.c.id,
1053 source_id = self.tbl_dsc_files.c.source,
1054 source = relation(Source),
1055 poolfile_id = self.tbl_dsc_files.c.file,
1056 poolfile = relation(PoolFile)))
1058 mapper(PoolFile, self.tbl_files,
1059 properties = dict(file_id = self.tbl_files.c.id,
1060 filesize = self.tbl_files.c.size,
1061 location_id = self.tbl_files.c.location,
1062 location = relation(Location)))
1064 mapper(Fingerprint, self.tbl_fingerprint,
1065 properties = dict(fingerprint_id = self.tbl_fingerprint.c.id,
1066 uid_id = self.tbl_fingerprint.c.uid,
1067 uid = relation(Uid),
1068 keyring_id = self.tbl_fingerprint.c.keyring,
1069 keyring = relation(Keyring)))
1071 mapper(Keyring, self.tbl_keyrings,
1072 properties = dict(keyring_name = self.tbl_keyrings.c.name,
1073 keyring_id = self.tbl_keyrings.c.id))
1075 mapper(Location, self.tbl_location,
1076 properties = dict(location_id = self.tbl_location.c.id,
1077 component_id = self.tbl_location.c.component,
1078 component = relation(Component),
1079 archive_id = self.tbl_location.c.archive,
1080 archive = relation(Archive),
1081 archive_type = self.tbl_location.c.type))
1083 mapper(Maintainer, self.tbl_maintainer,
1084 properties = dict(maintainer_id = self.tbl_maintainer.c.id))
1086 mapper(Override, self.tbl_override,
1087 properties = dict(suite_id = self.tbl_override.c.suite,
1088 suite = relation(Suite),
1089 component_id = self.tbl_override.c.component,
1090 component = relation(Component),
1091 priority_id = self.tbl_override.c.priority,
1092 priority = relation(Priority),
1093 section_id = self.tbl_override.c.section,
1094 section = relation(Section),
1095 overridetype_id = self.tbl_override.c.type,
1096 overridetype = relation(OverrideType)))
1098 mapper(OverrideType, self.tbl_override_type,
1099 properties = dict(overridetype = self.tbl_override_type.c.type,
1100 overridetype_id = self.tbl_override_type.c.id))
1102 mapper(PendingContentAssociation, self.tbl_pending_content_associations,
1103 properties = dict(pca_id = self.tbl_pending_content_associations.c.id,
1104 filepath_id = self.tbl_pending_content_associations.c.filepath,
1105 filepath = relation(ContentFilepath),
1106 filename_id = self.tbl_pending_content_associations.c.filename,
1107 filename = relation(ContentFilename)))
1109 mapper(Priority, self.tbl_priority,
1110 properties = dict(priority_id = self.tbl_priority.c.id))
1112 mapper(Queue, self.tbl_queue,
1113 properties = dict(queue_id = self.tbl_queue.c.id))
1115 mapper(QueueBuild, self.tbl_queue_build,
1116 properties = dict(suite_id = self.tbl_queue_build.c.suite,
1117 queue_id = self.tbl_queue_build.c.queue,
1118 queue = relation(Queue)))
1120 mapper(Section, self.tbl_section,
1121 properties = dict(section_id = self.tbl_section.c.id))
1123 mapper(Source, self.tbl_source,
1124 properties = dict(source_id = self.tbl_source.c.id,
1125 version = self.tbl_source.c.version,
1126 maintainer_id = self.tbl_source.c.maintainer,
1127 maintainer = relation(Maintainer,
1128 primaryjoin=(self.tbl_source.c.maintainer==self.tbl_maintainer.c.id)),
1129 poolfile_id = self.tbl_source.c.file,
1130 poolfile = relation(PoolFile),
1131 fingerprint_id = self.tbl_source.c.sig_fpr,
1132 fingerprint = relation(Fingerprint),
1133 changedby_id = self.tbl_source.c.changedby,
1134 changedby = relation(Maintainer,
1135 primaryjoin=(self.tbl_source.c.changedby==self.tbl_maintainer.c.id)),
1136 srcfiles = relation(DSCFile,
1137 primaryjoin=(self.tbl_source.c.id==self.tbl_dsc_files.c.source)),
1138 srcassociations = relation(SrcAssociation,
1139 primaryjoin=(self.tbl_source.c.id==self.tbl_src_associations.c.source))))
1141 mapper(SrcAssociation, self.tbl_src_associations,
1142 properties = dict(sa_id = self.tbl_src_associations.c.id,
1143 suite_id = self.tbl_src_associations.c.suite,
1144 suite = relation(Suite),
1145 source_id = self.tbl_src_associations.c.source,
1146 source = relation(Source)))
1148 mapper(SrcUploader, self.tbl_src_uploaders,
1149 properties = dict(uploader_id = self.tbl_src_uploaders.c.id,
1150 source_id = self.tbl_src_uploaders.c.source,
1151 source = relation(Source,
1152 primaryjoin=(self.tbl_src_uploaders.c.source==self.tbl_source.c.id)),
1153 maintainer_id = self.tbl_src_uploaders.c.maintainer,
1154 maintainer = relation(Maintainer,
1155 primaryjoin=(self.tbl_src_uploaders.c.maintainer==self.tbl_maintainer.c.id))))
1157 mapper(Suite, self.tbl_suite,
1158 properties = dict(suite_id = self.tbl_suite.c.id))
1160 mapper(SuiteArchitecture, self.tbl_suite_architectures,
1161 properties = dict(suite_id = self.tbl_suite_architectures.c.suite,
1162 suite = relation(Suite),
1163 arch_id = self.tbl_suite_architectures.c.architecture,
1164 architecture = relation(Architecture)))
1166 mapper(Uid, self.tbl_uid,
1167 properties = dict(uid_id = self.tbl_uid.c.id))
1169 ## Connection functions
1170 def __createconn(self):
1171 from config import Config
1175 connstr = "postgres://%s" % cnf["DB::Host"]
1176 if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
1177 connstr += ":%s" % cnf["DB::Port"]
1178 connstr += "/%s" % cnf["DB::Name"]
1181 connstr = "postgres:///%s" % cnf["DB::Name"]
1182 if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
1183 connstr += "?port=%s" % cnf["DB::Port"]
1185 self.db_pg = create_engine(connstr, echo=self.debug)
1186 self.db_meta = MetaData()
1187 self.db_meta.bind = self.db_pg
1188 self.db_smaker = sessionmaker(bind=self.db_pg,
1192 self.__setuptables()
1193 self.__setupmappers()
1196 return self.db_smaker()
1198 __all__.append('DBConn')