33 """Arguments passed into a Butler that are used to instantiate a repository. This includes arguments that
34 can be used to create a new repository (cfgRoot, root, mapper, mapperArgs, policy) and are persisted along
35 with the new repository
's configuration file. These arguments can also describe how a new or existing
36 repository are to be used (cfgRoot or root, tags, mode). When indicating an existing repository it
is
37 better to
not specify unnecessary arguments,
as if they conflict
with the persisted repository
38 configuration then a RuntimeError will be raised during Butler init.
40 A RepositoryArgs
class can be initialized
from a dict, if the first argument
to the initializer is
a dict.
44 cfgRoot : URI
or dict, optional
45 If dict, the initalizer
is re-called
with the expanded dict.
46 If URI, this
is the location where the RepositoryCfg should be found (existing repo)
or put (new repo)
48 If different than cfgRoot then this
is the location where the repository should exist. A RepositoryCfg
49 will be put at cfgRoot
and its root will be a path to root.
50 mapper : string
or class object, optional
51 The mapper to use
with this repository. If string, should refer an importable object. If
class object,
52 should be a mapper to be instantiated by the Butler during Butler init.
54 Arguments & values to
pass to the mapper when initializing it.
55 tags : list
or object, optional
56 One
or more unique identifiers to uniquely identify this repository
and its parents when performing
58 mode : string, optional
59 should be one of
'r',
'w',
or 'rw',
for 'read',
'write',
or 'read-write'. Can be omitted; input
60 repositories will default to
'r', output repositories will default to
'w'.
'w' on an input repository
61 will
raise a RuntimeError during Butler init, although
'rw' works
and is equivalent to
'r'. Output
62 repositories may be
'r' or 'rw',
'r' for an output repository will
raise a RuntimeError during Butler
65 Policy associated
with this repository, overrides all other policy data (which may be loaded
from
66 policies
in derived packages).
68 def __init__(self, cfgRoot=None, root=None, mapper=None, mapperArgs=None, tags=None,
69 mode=None, policy=None):
74 self.
_root = Storage.absolutePath(os.getcwd(), root.rstrip(os.sep))
if root
else root
75 self.
_cfgRoot = Storage.absolutePath(os.getcwd(), cfgRoot.rstrip(os.sep))
if cfgRoot
else cfgRoot
83 return "%s(root=%r, cfgRoot=%r, mapper=%r, mapperArgs=%r, tags=%s, mode=%r, policy=%s)" % (
93 if mapper
is not None and self.
_mapper:
94 raise RuntimeError(
"Explicity clear mapper (set to None) before changing its value.")
110 def outputRepo(storage, mapper=None, mapperArgs=None, tags=None, mode=None):
114 """add a tag to the repository cfg"""
115 if isinstance(tag, str):
119 self.
tags.update(tag)
125 """Represents a repository of persisted data and has methods to access that data.
129 """Initialize a Repository with parameters input via RepoData.
134 Object that contains the parameters with which to init the Repository.
136 self._storage = Storage.makeFromURI(repoData.cfg.root)
137 if repoData.cfg.dirty
and not repoData.isV1Repository
and repoData.cfgOrigin !=
'nested':
138 self.
_storage.putRepositoryCfg(repoData.cfg, repoData.cfgRoot)
142 def _initMapper(self, repoData):
143 '''Initialize and keep the mapper in a member var.
148 The RepoData with the properties of this Repository.
155 mapper = repoData.cfg.mapper
158 if isinstance(mapper, str):
159 mapper = doImport(mapper)
161 if inspect.isclass(mapper):
162 mapperArgs = copy.copy(repoData.cfg.mapperArgs)
163 if mapperArgs
is None:
165 if 'root' not in mapperArgs:
166 mapperArgs[
'root'] = repoData.cfg.root
167 mapper = mapper(parentRegistry=repoData.parentRegistry,
168 repositoryCfg=repoData.cfg,
173 def write(self, butlerLocation, obj):
174 """Write a dataset to Storage.
176 :param butlerLocation: Contains the details needed to find the desired dataset.
177 :param dataset: The dataset to be written.
180 butlerLocationStorage = butlerLocation.getStorage()
181 if butlerLocationStorage:
182 return butlerLocationStorage.write(butlerLocation, obj)
186 def read(self, butlerLocation):
187 """Read a dataset from Storage.
189 :param butlerLocation: Contains the details needed to find the desired dataset.
190 :return: An instance of the dataset requested by butlerLocation.
192 butlerLocationStorage = butlerLocation.getStorage()
193 if butlerLocationStorage:
194 return butlerLocationStorage.read(butlerLocation)
205 """Get the registry from the mapper
210 The registry
from the mapper
or None if the mapper does
not have one.
218 Get the keys available in the repository/repositories.
221 :
return: A dict of {key:valueType}
229 def map(self, *args, **kwargs):
230 """Find a butler location for the given arguments.
231 See mapper.map for more information about args
and kwargs.
233 :param args: arguments to be passed on to mapper.map
234 :param kwargs: keyword arguments to be passed on to mapper.map
235 :
return: The type of item
is dependent on the mapper being used but
is typically a ButlerLocation.
238 raise RuntimeError(
"No mapper assigned to Repository")
242 loc.setRepository(self)
246 """Gets possible values for keys given a partial data id.
248 See mapper documentation for more explanation about queryMetadata.
250 :param args: arguments to be passed on to mapper.queryMetadata
251 :param kwargs: keyword arguments to be passed on to mapper.queryMetadata
252 :
return:The type of item
is dependent on the mapper being used but
is typically a set that contains
253 available values
for the keys
in the format input argument.
261 """Perform mapper.backup.
263 See mapper.backup for more information about args
and kwargs.
265 :param args: arguments to be passed on to mapper.backup
266 :param kwargs: keyword arguments to be passed on to mapper.backup
274 """Get the default level of the mapper.
276 This is typically used
if no level
is passed into butler methods that call repository.getKeys
and/
or
277 repository.queryMetadata. There
is a bug
in that code because it gets the default level
from this
278 repository but then uses that value when searching all repositories. If this
and other repositories
279 have dissimilar data, the default level value will be nonsensical. A good example of this issue
is in
280 Butler.subset; it needs refactoring.
286 return self.
_mapper.getDefaultLevel()
289 """Check if location exists in storage.
293 location : ButlerLocation
294 Desrcibes a location in storage to look
for.
299 True if location exists,
False if not.
301 butlerLocationStorage = location.getStorage()
302 if butlerLocationStorage:
303 return butlerLocationStorage.exists(location)
def __init__(self, cfgRoot=None, root=None, mapper=None, mapperArgs=None, tags=None, mode=None, policy=None)
def inputRepo(storage, tags=None)
def outputRepo(storage, mapper=None, mapperArgs=None, tags=None, mode=None)
def mappers(self)
Mapper Access #.
def getKeys(self, *args, **kwargs)
def exists(self, location)
def backup(self, *args, **kwargs)
def getMapperDefaultLevel(self)
def map(self, *args, **kwargs)
def queryMetadata(self, *args, **kwargs)
def write(self, butlerLocation, obj)
def _initMapper(self, repoData)
def read(self, butlerLocation)
def __init__(self, repoData)
daf::base::PropertySet * set