Package qm :: Package test :: Package classes :: Module mount_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.mount_database

  1  ######################################################################## 
  2  # 
  3  # File:   mount_database.py 
  4  # Author: Mark Mitchell 
  5  # Date:   03/19/2003 
  6  # 
  7  # Contents: 
  8  #   MountDatabase 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import dircache 
 19  import os.path 
 20  from   qm.test.database import * 
 21  from   qm.test.suite import Suite 
 22  from   qm.fields import * 
 23  import qm.test.database 
 24   
 25  ######################################################################## 
 26  # Classes 
 27  ######################################################################## 
 28   
29 -class MountDatabase(Database):
30 """A 'MountDatabase' contains other databases. 31 32 Every contained database has a "mount point", which is a label 33 giving the root of the database. A test with the ID "x" in a 34 database with a mount point of "y" has the ID "x.y" in the 35 containing database. 36 37 The contained databases are found by looking for subdirectories of 38 the 'MountDatabase' directory. Every immediate subdirectory which 39 is itself a QMTest database is mounted; its mount point is the 40 name of the subdirectory.""" 41
42 - class MountedSuite(Suite):
43 """A 'MountedSuite' is a suite from a mounted database.""" 44
45 - def __init__(self, database, suite_id, joiner, suite):
46 47 super(MountDatabase.MountedSuite, self).\ 48 __init__({}, 49 qmtest_id = suite_id, 50 qmtest_database = database) 51 self.__suite = suite 52 self.__joiner = joiner
53 54
55 - def IsImplicit(self):
56 57 return self.__suite.IsImplicit()
58 59
60 - def GetTestIds(self):
61 62 return map(self.__joiner, self.__suite.GetTestIds())
63 64
65 - def GetSuiteIds(self):
66 67 return map(self.__joiner, self.__suite.GetSuiteIds())
68 69 70 mounts = DictionaryField(key_field = TextField(), 71 value_field = TextField(), 72 description=\ 73 """Dictionary mapping mount points to (sub-)database paths. 74 If empty, the database directory is scanned for subdirectories.""") 75 76
77 - def __init__(self, path, arguments):
78 79 # The label class used by the MountDatabase is the label class 80 # used by the databases it contains. They must all use the 81 # same label class. 82 label_class = None 83 implicit = False 84 # Find the contained databases. 85 self.mounts = arguments.pop('mounts', {}) 86 self._mounts = {} 87 if not self.mounts: 88 # Scan local directory. 89 implicit = True 90 self.mounts = dict([(d, os.path.join(path, d)) 91 for d in dircache.listdir(path)]) 92 else: 93 # Translate relative paths into absolute paths. 94 tmp = {} 95 for k,v in self.mounts.iteritems(): 96 tmp[k] = os.path.join(path, v) 97 self.mounts = tmp 98 # Now translate the value from path to database 99 for k,v in self.mounts.iteritems(): 100 if is_database(v): 101 db = load_database(v) 102 self._mounts[k] = db 103 if not label_class: 104 label_class = db.label_class 105 elif label_class != db.label_class: 106 raise QMException, \ 107 "mounted databases use differing label classes" 108 elif not implicit: 109 raise QMException, "%s does not contain a test database"%v 110 111 # Initialize the base class. 112 arguments["modifiable"] = "false" 113 if label_class: 114 arguments["label_class"] = label_class 115 116 Database.__init__(self, path, arguments)
117 118 119
120 - def GetIds(self, kind, directory="", scan_subdirs=1):
121 122 ids = [] 123 if directory == "" and kind == Database.SUITE: 124 ids.extend(self._mounts.keys()) 125 if scan_subdirs: 126 dirs = directory and [directory] or self._mounts.keys() 127 for d in dirs: 128 database, joiner, subdir = self._SelectDatabase(d) 129 ids += [joiner(i) for i in database.GetIds(kind, subdir, 1)] 130 return ids
131
132 - def GetTest(self, test_id):
133 134 joiner, contained_test \ 135 = self._GetContainedItem(Database.TEST, test_id) 136 137 # Remap the prerequisites. 138 arguments = contained_test.GetArguments() 139 prerequisites = contained_test.GetPrerequisites() 140 if prerequisites: 141 new_prerequisites = map(lambda p: (joiner(p[0]), p[1]), 142 prerequisites.items()) 143 arguments[Test.PREREQUISITES_FIELD_ID] = new_prerequisites 144 145 # Remap the resources. 146 self._AdjustResources(joiner, arguments) 147 148 return TestDescriptor(self, 149 test_id, 150 contained_test.GetClassName(), 151 arguments)
152 153
154 - def GetResource(self, resource_id):
155 156 joiner, contained_resource \ 157 = self._GetContainedItem(Database.RESOURCE, resource_id) 158 159 # Remap the resources. 160 arguments = contained_resource.GetArguments() 161 self._AdjustResources(joiner, arguments) 162 163 return ResourceDescriptor(self, resource_id, 164 contained_resource.GetClassName(), 165 arguments)
166 167
168 - def GetSuite(self, suite_id):
169 170 if suite_id == "": 171 return Database.GetSuite(self, suite_id) 172 173 joiner, contained_suite \ 174 = self._GetContainedItem(Database.SUITE, suite_id) 175 test_ids = map(joiner, contained_suite.GetTestIds()) 176 suite_ids = map(joiner, contained_suite.GetSuiteIds()) 177 return MountDatabase.MountedSuite(self, suite_id, 178 joiner, 179 contained_suite)
180 181
182 - def GetSubdirectories(self, directory):
183 184 if directory == "": 185 return self._mounts.keys() 186 database, joiner, dir = self._SelectDatabase(directory) 187 return database.GetSubdirectories(dir)
188 189
190 - def GetClassPaths(self):
191 192 paths = [] 193 for db in self._mounts.values(): 194 paths.extend(db.GetClassPaths()) 195 paths.append(get_configuration_directory(db.GetPath())) 196 return paths
197 198
199 - def _AdjustResources(self, joiner, arguments):
200 """Adjust the resource IDs stored in the 'arguments'. 201 202 'joiner' -- A function of one argument which prepends the 203 label for a mount point to the label it is given. 204 205 'arguments' -- The arguments to a test or resource class. 206 207 Modifies the arguments to contain resource names that are 208 relative to the containing database.""" 209 210 resources = arguments.get(Runnable.RESOURCE_FIELD_ID) 211 if resources: 212 new_resources = map(joiner, resources) 213 arguments[Runnable.RESOURCE_FIELD_ID] = new_resources
214 215
216 - def _GetContainedItem(self, kind, item_id):
217 """Return 'item_id' from a mounted database. 218 219 'kind' -- The kind of item to return. 220 221 'item_id' -- The name of the item, in the containing 222 database. 223 224 returns -- A tuple '(joiner, item). The 'item' will be from 225 one of the mounted databases. 'joiner' is a function of one 226 argument which prepends the mount point to its argument.""" 227 228 try: 229 database, joiner, item_id = self._SelectDatabase(item_id) 230 231 # Look for the item in the contained database. 232 try: 233 item = database.GetItem(kind, item_id) 234 except NoSuchItemError, e: 235 # Reset the id. 236 e.item_id = joiner(item_id) 237 raise 238 239 return joiner, item 240 except: 241 raise Database._item_exceptions[kind](item_id)
242 243
244 - def _SelectDatabase(self, item_id):
245 """Return the contained database in which 'item_id' can be found. 246 247 'item_id' -- The name of an item in this database. 248 249 returns -- A tuple '(database, joiner, id)' where 'database' 250 is a 'Database', 'joiner' is a function of one argument which 251 prepends the mount point to a label, and 'id' is the portion 252 of 'item_id' that remains after stripping off the mount point 253 of 'database'. If 'item_id' does not correspond to any mount 254 point, an exception is raised.""" 255 256 mount_point, item_id = self.SplitLabelLeft(item_id) 257 db = self._mounts[mount_point] 258 return (db, lambda p: self.JoinLabels(mount_point, p), item_id)
259