30 from .
import listify, iterify, doImport, Storage
31 from past.builtins
import basestring
35 """RepositoryCfg stores the configuration of a repository. Its contents are persisted to the repository
36 when the repository is created in persistent storage. Thereafter the the RepositoryCfg should not change.
41 The mapper associated with the repository. The string should be importable to a class object.
43 Arguments & values to pass to the mapper when initializing it.
45 URIs to the locaiton of the parent RepositoryCfgs of this repository.
47 Policy associated with this repository, overrides all other policy data (which may be loaded from
48 policies in derived packages).
50 Butler internal use only. This flag is used to indicate to the init funciton that the repository class
51 is being deserialized and should not perform certain operations that normally happen in other uses of
54 yaml_tag =
u"!RepositoryCfg_v1"
56 def __init__(self, root, mapper, mapperArgs, parents, policy, deserializing=False):
72 """Constructor for 'version 1' of the serlized RepositoryCfg.
74 If new parameters are added to RepositoryCfg they will have to be checked for in d; if they are there
75 then their value should be used and if they are not there a default value must be used in place.
77 In case the structure of the serialzed file must be changed in a way that invalidates some of the
79 1. Increment the version number (after _v1) in the yaml_tag of this class.
80 2. Add a new constructor (similar to this one) to deserialze new serializations of this class.
81 3. Registered the new constructor for the new version with yaml, the same way it is done at the bottom
83 4. All constructors for the older version(s) of persisted RepositoryCfg must be changed to adapt
84 the old keys to their new uses and create the current (new) version of a repository cfg, or raise a
85 RuntimeError in the case that older versions of serialized RepositoryCfgs can not be adapted.
86 There is an example of migrating from a fictitious v0 to v1 in tests/repositoryCfg.py
88 d = loader.construct_mapping(node)
89 cfg =
RepositoryCfg(root=d[
'_root'], mapper=d[
'_mapper'], mapperArgs=d[
'_mapperArgs'],
90 parents=d[
'_parents'], policy=d.get(
'_policy',
None), deserializing=
True)
96 return self.
root == other.root
and \
102 return not self.
__eq__(other)
110 if root
is not None and self.
_root is not None:
111 raise RuntimeError(
"Explicity clear root (set to None) before changing the value of root.")
121 raise RuntimeError(
"Should not set mapper over previous not-None value.")
134 return [Storage.absolutePath(self.
root, p)
for p
in self.
_parents]
137 newParents =
listify(newParents)
138 for newParent
in newParents:
139 newParent = Storage.relativePath(self.
root, newParent)
141 self._parents.append(newParent)
150 mapper=repositoryArgs.mapper,
151 mapperArgs=repositoryArgs.mapperArgs,
153 policy=repositoryArgs.policy)
157 """Checks that a repositoryArgs instance will work with this repositoryCfg. This is useful
158 when loading an already-existing repository that has a persisted cfg, to ensure that the args that are
159 passed into butler do not conflict with the persisted cfg."""
160 if repositoryArgs.root
is not None and self.
_root != repositoryArgs.root:
163 repoArgsMapper = repositoryArgs.mapper
165 if isinstance(repoArgsMapper, basestring):
166 repoArgsMapper =
doImport(repoArgsMapper)
167 if isinstance(cfgMapper, basestring):
169 if repoArgsMapper
is not None and repoArgsMapper != cfgMapper:
172 if self.
_mapperArgs is not None and repositoryArgs.mapperArgs
is not None:
173 for key
in set(self._mapperArgs.keys()) & set(repositoryArgs.mapperArgs):
174 if self.
_mapperArgs[key] != repositoryArgs.mapperArgs[key]:
176 if repositoryArgs.policy
and repositoryArgs.policy != self.
_policy:
182 return "%s(root=%r, mapper=%r, mapperArgs=%r, parents=%s, policy=%s)" % (
183 self.__class__.__name__,
190 yaml.add_constructor(
u"!RepositoryCfg_v1", RepositoryCfg.v1Constructor)