LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
repositoryCfg.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 #
4 # LSST Data Management System
5 # Copyright 2016 LSST Corporation.
6 #
7 # This product includes software developed by the
8 # LSST Project (http://www.lsst.org/).
9 #
10 # This program is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the LSST License Statement and
21 # the GNU General Public License along with this program. If not,
22 # see <http://www.lsstcorp.org/LegalNotices/>.
23 #
24 
25 # -*- python -*-
26 
27 import inspect
28 import yaml
29 
30 from lsst.daf.persistence import listify, iterify, doImport
31 from past.builtins import basestring
32 
33 
34 class RepositoryCfg(yaml.YAMLObject):
35  yaml_tag = u"!RepositoryCfg_v1"
36 
37  def __init__(self, root, mapper, mapperArgs, parents, policy):
38  self._root = root
39  self._mapper = mapper
40  self._mapperArgs = mapperArgs
41  self._parents = iterify(parents)
42  self._policy = policy
43 
44  @staticmethod
45  def v1Constructor(loader, node):
46  """Constructor for 'version 1' of the serlized RepositoryCfg.
47 
48  If new parameters are added to RepositoryCfg they will have to be checked for in d; if they are there
49  then their value should be used and if they are not there a default value must be used in place.
50 
51  In case the structure of the serialzed file must be changed in a way that invalidates some of the
52  keys:
53  1. Increment the version number (after _v1) in the yaml_tag of this class.
54  2. Add a new constructor (similar to this one) to deserialze new serializations of this class.
55  3. Registered the new constructor for the new version with yaml, the same way it is done at the bottom
56  of this file.
57  4. All constructors for the older version(s) of persisted RepositoryCfg must be changed to adapt
58  the old keys to their new uses and create the current (new) version of a repository cfg, or raise a
59  RuntimeError in the case that older versions of serialized RepositoryCfgs can not be adapted.
60  There is an example of migrating from a fictitious v0 to v1 in tests/repositoryCfg.py
61  """
62  d = loader.construct_mapping(node)
63  cfg = RepositoryCfg(root=d['_root'], mapper=d['_mapper'], mapperArgs=d['_mapperArgs'],
64  parents=d['_parents'], policy=d.get('_policy', None))
65  return cfg
66 
67  def __eq__(self, other):
68  if not other:
69  return False
70  return self._root == other._root and \
71  self.mapper == other._mapper and \
72  self.mapperArgs == other._mapperArgs and \
73  self.parents == other._parents
74 
75  def __ne__(self, other):
76  return not self.__eq__(other)
77 
78  @property
79  def root(self):
80  return self._root
81 
82  @root.setter
83  def root(self, root):
84  if root is not None and self._root is not None:
85  raise RuntimeError("Explicity clear root (set to None) before changing the value of root.")
86  self._root = root
87 
88  @property
89  def mapper(self):
90  return self._mapper
91 
92  @mapper.setter
93  def mapper(self, mapper):
94  if self._mapper != None:
95  raise RuntimeError("Should not set mapper over previous not-None value.")
96  self._mapper = mapper
97 
98  @property
99  def mapperArgs(self):
100  return self._mapperArgs
101 
102  @mapperArgs.setter
103  def mapperArgs(self, newDict):
104  self._mapperArgs = newDict
105 
106  @property
107  def parents(self):
108  return self._parents
109 
110  def addParents(self, newParents):
111  newParents = listify(newParents)
112  for newParent in newParents:
113  if newParent not in self._parents:
114  self._parents.append(newParent)
115 
116  @property
117  def policy(self):
118  return self._policy
119 
120  @staticmethod
121  def makeFromArgs(repositoryArgs, parents):
122  cfg = RepositoryCfg(root=repositoryArgs.root,
123  mapper=repositoryArgs.mapper,
124  mapperArgs=repositoryArgs.mapperArgs,
125  parents=parents,
126  policy=repositoryArgs.policy)
127  return cfg
128 
129  def matchesArgs(self, repositoryArgs):
130  """Checks that a repositoryArgs instance will work with this repositoryCfg. This is useful
131  when loading an already-existing repository that has a persisted cfg, to ensure that the args that are
132  passed into butler do not conflict with the persisted cfg."""
133  if repositoryArgs.root is not None and self._root != repositoryArgs.root:
134  return False
135 
136  repoArgsMapper = repositoryArgs.mapper
137  cfgMapper = self._mapper
138  if isinstance(repoArgsMapper, basestring):
139  repoArgsMapper = doImport(repoArgsMapper)
140  if isinstance(cfgMapper, basestring):
141  cfgMapper = doImport(cfgMapper)
142  if repoArgsMapper is not None and repoArgsMapper != cfgMapper:
143  return False
144  # check mapperArgs for any keys in common and if their value does not match then return false.
145  if self._mapperArgs is not None and repositoryArgs.mapperArgs is not None:
146  for key in set(self._mapperArgs.keys()) & set(repositoryArgs.mapperArgs):
147  if self._mapperArgs[key] != repositoryArgs.mapperArgs[key]:
148  return False
149  if repositoryArgs.policy and repositoryArgs.policy != self._policy:
150  return False
151 
152  return True
153 
154  def __repr__(self):
155  return "%s(root=%r, mapper=%r, mapperArgs=%r, parents=%s, policy=%s)" % (
156  self.__class__.__name__,
157  self._root,
158  self._mapper,
159  self._mapperArgs,
160  self._parents,
161  self._policy)
162 
163 yaml.add_constructor(u"!RepositoryCfg_v1", RepositoryCfg.v1Constructor)