Skip to content

Commit

Permalink
adds docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
n8pease committed Mar 4, 2016
1 parent fd592aa commit c6a7861
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 24 deletions.
69 changes: 63 additions & 6 deletions python/lsst/daf/persistence/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,20 @@ class PosixStorage:

@classmethod
def cfg(cls, root):
"""Helper func to create a properly formatted Policy to configure a PosixStorage instance.
:param root: a posix path where the repository is or should be created.
:return:
"""
return Policy({'root':root, 'cls':cls})

def __init__(self, cfg):
"""Initializer
:param cfg: a Policy that defines the configuration for this class. It is recommended that the cfg be
created by calling PosixStorage.cfg()
:return:
"""
self.log = pexLog.Log(pexLog.Log.getDefaultLog(), "daf.persistence.butler")
self.root = cfg['root']
if self.root and not os.path.exists(self.root):
Expand All @@ -59,7 +70,7 @@ def __init__(self, cfg):

@staticmethod
def getMapperClass(root):
"""Return the mapper class associated with a repository root.
"""Returns the mapper class associated with a repository root.
Supports the legacy _parent symlink search (which was only ever posix-only. This should not be used by
new code and repositories; they should use the Repository parentCfg mechanism."""
Expand Down Expand Up @@ -92,23 +103,36 @@ def getMapperClass(root):

def mapperClass(self):
"""Get the class object for the mapper specified in the stored repository"""

#todo would be better to use a generic statement instead of PosixStorage.
return PosixStorage.getMapperClass(self.root)

def setCfg(self, repoCfg):
"""Writes the configuration to root in the repository on disk.
:param repoCfg: the Policy cfg to be written
:return: None
"""
if not self.root:
raise RuntimeError("Storage root was declared to be None.")
path = os.path.join(self.root, 'repoCfg.yaml')
repoCfg.dumpToFile(path)

def loadCfg(self):
"""Reads the configuration from the repository on disk at root.
:return: the Policy cfg
"""
if not self.root:
raise RuntimeError("Storage root was declared to be None.")
path = os.path.join(self.root, 'repoCfg.yaml')
return Policy(filePath=path)

def write(self, butlerLocation, obj):
"""Writes an object to a location and persistence format specified by ButlerLocation
:param butlerLocation: the location & formatting for the object to be written.
:param obj: the object to be written.
:return: None
"""
self.log.log(pexLog.Log.DEBUG, "Put location=%s obj=%s" % (butlerLocation, obj))
additionalData = butlerLocation.getAdditionalData()
storageName = butlerLocation.getStorageName()
Expand Down Expand Up @@ -151,25 +175,58 @@ class Access:

@classmethod
def cfg(cls, storageCfg):
"""Helper func to create a properly formatted Policy to configure an Access instance.
:param storageCfg: a cfg to instantiate a storage.
:return:
"""
return Policy({'storageCfg': storageCfg})

def __init__(self, cfg):
"""Initializer
:param cfg: a Policy that defines the configuration for this class. It is recommended that the cfg be
created by calling Access.cfg()
:return:
"""
self.storage = cfg['storageCfg.cls'](cfg['storageCfg'])

def mapperClass(self):
"""Get the mapper class associated with a repository root.
:return: the mapper class
"""
return self.storage.mapperClass()

def root(self):
"""Root refers to the 'top' of a persisted repository.
Presumably its form can vary depending on the type of storage although currently the only Butler
storage that exists is posix, and root is the repo path."""
"""Get the repository root as defined by the Storage class, this refers to the 'top' of a persisted
repository. The exact type of Root can vary based on Storage type.
:return: the root of the persisted repository.
"""

return self.storage.root

def setCfg(self, repoCfg):
"""Writes the repository configuration to Storage.
:param repoCfg: the Policy cfg to be written
:return: None
"""
self.storage.setCfg(repoCfg)

def loadCfg(self):
"""Reads the repository configuration from Storage.
:return: the Policy cfg
"""
return self.storage.loadCfg()

def write(self, butlerLocation, obj):
"""Passes an object to Storage to be written into the repository.
:param butlerLocation: the location & formatting for the object to be written.
:param obj: the object to be written.
:return: None
"""
self.storage.write(butlerLocation, obj)
58 changes: 40 additions & 18 deletions python/lsst/daf/persistence/butler.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,49 @@ class Butler(object):

@classmethod
def cfg(cls, repoCfg):
"""Helper func to create a properly formatted Policy to configure a Repository.
:param repoCfg: Cfg used to instantiate the repository.
:return: a properly populated cfg Policy.
"""
return Policy({'repoCfg':repoCfg})

def __init__(self, root, mapper=None, **mapperArgs):
"""Initializer for the Class.
The prefered initialization argument is to pass a single arg; cfg created by Butler.cfg();
butler = Butler(Butler.cfg(repoCfg))
For backward compatibility: this initialization method signature can take a posix root path, and
optionally a mapper class instance or class type that will be instantiated using the mapperArgs input
argument.
However, for this to work in a backward compatible way it creates a single repository that is used as
both an input and an output repository. This is NOT preferred, and will likely break any provenance
system we have in place.
:param root: Best practice is to pass in a cfg created by Butler.cfg(). But for backward
compatibility this can also be a fileysystem path. Will only work with a
PosixRepository.
:param mapper: Deprecated. Provides a mapper to be used with Butler.
:param mapperArgs: Deprecated. Provides arguments to be passed to the mapper if the mapper input arg
is a class type to be instantiated by Butler.
:return:
"""
if (isinstance(root, Policy)):
config = root
else:
parentCfg = posixRepoCfg(root=root, mapper=mapper, mapperArgs=mapperArgs)
repoCfg = posixRepoCfg(root=root, mapper=mapper, mapperArgs=mapperArgs, parentRepoCfgs=(parentCfg,))
config = Butler.cfg(repoCfg=repoCfg)
self._initWithCfg(config)

def _initWithCfg(self, cfg):
"""Initialize this Butler with cfg
def initWithCfg(self, cfg):
:param cfg: a dict (or daf_persistence.Policy) of key-value pairs that describe the configuration.
Best practice is to create this object by calling Butler.cfg()
:return: None
"""
self._cfg = cfg
self.datasetTypeAliasDict = {}

Expand All @@ -113,23 +152,6 @@ def initWithCfg(self, cfg):
self.persistence = Persistence.getPersistence(persistencePolicy)
self.log = pexLog.Log(pexLog.Log.getDefaultLog(), "daf.persistence.butler")


def __init__(self, root, mapper=None, **mapperArgs):
# prefered init arg is to pass a single arg; an instance of butlerCfg:
# butler = Butler(butlerCfg(...))
# For backward compatibility: init signature can take a posix root path, and optionally a mapper class
# that will be init'ed with mapperArgs.
# However, it is NOT preferred to have a repo be both input (parent) and output (self/peer), and will
# likely break any provenance system we have in place.
if (isinstance(root, Policy)):
config = root
else:
parentCfg = posixRepoCfg(root=root, mapper=mapper, mapperArgs=mapperArgs)
repoCfg = posixRepoCfg(root=root, mapper=mapper, mapperArgs=mapperArgs, parentRepoCfgs=(parentCfg,))
config = Butler.cfg(repoCfg=repoCfg)
self.initWithCfg(config)


@staticmethod
def getMapperClass(root):
"""posix-only; gets the mapper class at the path specifed by root (if a file _mapper can be found at
Expand Down

0 comments on commit c6a7861

Please sign in to comment.