29 from .
import iterify, doImport, Storage, ParentsMismatch
33 """RepositoryCfg stores the configuration of a repository. Its contents are persisted to the repository
34 when the repository is created in persistent storage. Thereafter the the RepositoryCfg should not change.
39 The mapper associated with the repository. The string should be importable to a class object.
41 Arguments & values to pass to the mapper when initializing it.
43 URIs to the locaiton of the parent RepositoryCfgs of this repository.
45 Policy associated with this repository, overrides all other policy data (which may be loaded from
46 policies in derived packages).
48 Butler internal use only. This flag is used to indicate to the init funciton that the repository class
49 is being deserialized and should not perform certain operations that normally happen in other uses of
52 yaml_tag =
u"!RepositoryCfg_v1"
54 def __init__(self, root, mapper, mapperArgs, parents, policy):
55 self.
_root_root = root
57 self.
_mapperArgs_mapperArgs = {}
if mapperArgs
is None else mapperArgs
65 """Constructor for 'version 1' of the serlized RepositoryCfg.
67 If new parameters are added to RepositoryCfg they will have to be checked for in d; if they are there
68 then their value should be used and if they are not there a default value must be used in place.
70 In case the structure of the serialzed file must be changed in a way that invalidates some of the
72 1. Increment the version number (after _v1) in the yaml_tag of this class.
73 2. Add a new constructor (similar to this one) to deserialze new serializations of this class.
74 3. Registered the new constructor for the new version with yaml, the same way it is done at the bottom
76 4. All constructors for the older version(s) of persisted RepositoryCfg must be changed to adapt
77 the old keys to their new uses and create the current (new) version of a repository cfg, or raise a
78 RuntimeError in the case that older versions of serialized RepositoryCfgs can not be adapted.
79 There is an example of migrating from a fictitious v0 to v1 in tests/repositoryCfg.py
81 d = loader.construct_mapping(node)
82 cfg =
RepositoryCfg(root=d[
'_root'], mapper=d[
'_mapper'], mapperArgs=d[
'_mapperArgs'],
83 parents=[], policy=d.get(
'_policy',
None))
87 cfg._parents = d[
'_parents']
88 if cfg._parents
is None:
103 return not self.
__eq____eq__(other)
106 """Extend this RepositoryCfg with extendable values from the other RepositoryCfg.
108 Currently the only extendable value is parents; see `extendParents` for more detials about extending
113 other : RepositoryCfg
114 A RepositoryCfg instance to update values from.
119 If non-extendable parameters do not match a RuntimeError will be raised.
120 (If this RepositoryCfg's parents can not be extended with the parents of the other repository,
121 extendParents will raise).
127 raise RuntimeError(
"{} can not be extended with cfg:{}".
format(self, other))
130 def _extendsParents(self, newParents):
131 """Query if a list of parents starts with the same list of parents as this RepositoryCfg's parents,
132 with new parents at the end.
136 newParents : list of string and/or RepositoryCfg
137 A list of parents that contains all the parents that would be in this RepositoryCfg.
138 This must include parents that may already be in this RepositoryCfg's parents list. Paths must be
139 in absolute form (not relative).
144 True if the beginning of the new list matches this RepositoryCfg's parents list, False if not.
146 doesExtendParents =
False
147 return doesExtendParents
150 """Determine if a parents list matches our parents list, with extra items at the end. If a list of
151 parents does not match but the mismatch is because of new parents at the end of the list, then they
152 can be added to the cfg.
156 newParents : list of string
157 A list of parents that contains all the parents that are to be recorded into this RepositoryCfg.
158 This must include parents that may already be in this RepositoryCfg's parents list
167 if self.
_parents_parents != newParents:
168 if all(x == y
for (x, y)
in zip(self.
_parents_parents, newParents)):
169 if len(self.
_parents_parents) < len(newParents):
171 self.
dirtydirty =
True
172 elif len(self.
_parents_parents) == len(newParents):
179 raise ParentsMismatch((
"The beginning of the passed-in parents list: {} does not match the "
180 "existing parents list in this RepositoryCfg: {}").
format(
185 return self.
_root_root
189 if root
is not None and self.
_root_root
is not None:
190 raise RuntimeError(
"Explicity clear root (set to None) before changing the value of root.")
191 self.
_root_root = root
199 if self.
_mapper_mapper
is not None:
200 raise RuntimeError(
"Should not set mapper over previous not-None value.")
201 self.
dirtydirty =
True
210 self.
dirtydirty =
True
218 def _normalizeParents(root, newParents):
219 """Eliminate symlinks in newParents and get the relative path (if one exists) from root to each parent
224 newParents : list containing strings and RepoistoryCfg instances
225 Same as in `addParents`.
229 list of strings and RepositoryCfg instances.
230 Normalized list of parents
232 newParents =
iterify(newParents)
233 for i
in range(len(newParents)):
234 if isinstance(newParents[i], RepositoryCfg):
235 newParents[i] = copy.copy(newParents[i])
236 parentRoot = newParents[i].root
237 newParents[i].root =
None
238 newParents[i].root = Storage.relativePath(root, parentRoot)
240 newParents[i] = Storage.relativePath(root, newParents[i])
244 def _denormalizeParents(root, parents):
245 def getAbs(root, parent):
246 if isinstance(parent, RepositoryCfg):
247 parentRoot = parent.root
249 parent.root = Storage.absolutePath(root, parentRoot)
251 parent = Storage.absolutePath(root, parent)
253 return [getAbs(root, parent)
for parent
in parents]
256 """Add a parent or list of parents to this RepositoryCfg
260 newParents : string or RepositoryCfg instance, or list of these.
261 If string, newParents should be a path or URI to the parent
262 repository. If RepositoryCfg, newParents should be a RepositoryCfg
263 that describes the parent repository in part or whole.
266 for newParent
in newParents:
267 if newParent
not in self.
_parents_parents:
268 self.
dirtydirty =
True
278 mapper=repositoryArgs.mapper,
279 mapperArgs=repositoryArgs.mapperArgs,
281 policy=repositoryArgs.policy)
285 """Checks that a repositoryArgs instance will work with this repositoryCfg. This is useful
286 when loading an already-existing repository that has a persisted cfg, to ensure that the args that are
287 passed into butler do not conflict with the persisted cfg."""
288 if repositoryArgs.root
is not None and self.
_root_root != repositoryArgs.root:
291 repoArgsMapper = repositoryArgs.mapper
292 cfgMapper = self.
_mapper_mapper
293 if isinstance(repoArgsMapper, str):
294 repoArgsMapper =
doImport(repoArgsMapper)
295 if isinstance(cfgMapper, str):
297 if repoArgsMapper
is not None and repoArgsMapper != cfgMapper:
300 if self.
_mapperArgs_mapperArgs
is not None and repositoryArgs.mapperArgs
is not None:
302 if self.
_mapperArgs_mapperArgs[key] != repositoryArgs.mapperArgs[key]:
304 if repositoryArgs.policy
and repositoryArgs.policy != self.
_policy_policy:
310 return "%s(root=%r, mapper=%r, mapperArgs=%r, parents=%s, policy=%s)" % (
311 self.__class__.__name__,
319 loaderList = [yaml.Loader, ]
321 loaderList.append(yaml.UnsafeLoader)
322 except AttributeError:
325 for loader
in loaderList:
326 yaml.add_constructor(
u"!RepositoryCfg_v1", RepositoryCfg.v1Constructor, Loader=loader)
def _normalizeParents(root, newParents)
def matchesArgs(self, repositoryArgs)
def __init__(self, root, mapper, mapperArgs, parents, policy)
def extendParents(self, newParents)
def makeFromArgs(repositoryArgs)
def v1Constructor(loader, node)
def addParents(self, newParents)
def _denormalizeParents(root, parents)
def mapperArgs(self, newDict)
daf::base::PropertySet * set
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
bool all(CoordinateExpr< N > const &expr) noexcept
Return true if all elements are true.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)