lsst.daf.persistence  13.0-32-g7b14ddd
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
fmtPosixRepositoryCfg.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2017 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 import copy
24 import errno
25 import yaml
26 import os
27 import urllib
28 from . import PosixStorage, RepositoryCfg, safeFileIo, ParentsMismatch
29 
30 
32 
33  @classmethod
34  def write(cls, cfg, butlerLocation):
35  """Serialize a RepositoryCfg to a location.
36 
37  When the location is the same as cfg.root, the RepositoryCfg is to be written at the root location of
38  the repository. In that case, root is not written in the serialized cfg; it is implicit in the
39  location of the cfg. This allows the cfg to move from machine to machine without modification.
40 
41  Parameters
42  ----------
43  cfg : RepositoryCfg instance
44  The RepositoryCfg to be serialized.
45  butlerLocation : ButlerLocation
46  The location to write the RepositoryCfg.
47  """
48  def setRoot(cfg, loc):
49  loc = os.path.split(loc)[0] # remove the `repoistoryCfg.yaml` file name
50  if loc is None or cfg.root == loc:
51  cfg = copy.copy(cfg)
52  loc = cfg.root
53  cfg.root = None
54  return cfg
55 
56  # This class supports schema 'file' and also treats no schema as 'file'.
57  # Split the URI and take only the path; remove the schema from loc if it's there.
58  loc = butlerLocation.storage.root
59  parseRes = urllib.parse.urlparse(loc if loc is not None else cfg.root)
60  loc = os.path.join(parseRes.path, butlerLocation.getLocations()[0])
61  try:
62  with safeFileIo.SafeLockedFileForRead(loc) as f:
63  existingCfg = RepositoryCfgPosixFormatter._read(f, parseRes.path)
64  if existingCfg == cfg:
65  cfg.dirty = False
66  return
67  except IOError as e:
68  if e.errno != errno.ENOENT: # ENOENT is 'No such file or directory'
69  raise e
70  with safeFileIo.SafeLockedFileForWrite(loc) as f:
71  existingCfg = RepositoryCfgPosixFormatter._read(f, parseRes.path)
72  if existingCfg is None:
73  cfgToWrite = setRoot(cfg, loc)
74  else:
75  if existingCfg == cfg:
76  cfg.dirty = False
77  return
78  try:
79  existingCfg.extend(cfg)
80  cfgToWrite = setRoot(existingCfg, loc)
81  except ParentsMismatch as e:
82  raise RuntimeError("Can not extend existing repository cfg because: {}".format(e))
83  yaml.dump(cfgToWrite, f)
84  cfg.dirty = False
85 
86  @classmethod
87  def _read(cls, fileObject, uri):
88  """Get a persisted RepositoryCfg from an open file object.
89 
90  Parameters
91  ----------
92  fileObject : an open file object
93  the file that contains the RepositoryCfg.
94 
95  Returns
96  -------
97  A RepositoryCfg instance or None
98  """
99  repositoryCfg = yaml.load(fileObject)
100  if repositoryCfg is not None:
101  if repositoryCfg.root is None:
102  repositoryCfg.root = uri
103  return repositoryCfg
104 
105  @classmethod
106  def read(cls, butlerLocation):
107  repositoryCfg = None
108  loc = butlerLocation.storage.root
109  fileLoc = os.path.join(loc, butlerLocation.getLocations()[0])
110  try:
111  with safeFileIo.SafeLockedFileForRead(fileLoc) as f:
112  repositoryCfg = RepositoryCfgPosixFormatter._read(f, loc)
113  except IOError as e:
114  if e.errno != errno.ENOENT: # ENOENT is 'No such file or directory'
115  raise e
116  return repositoryCfg
117 
118 
119 PosixStorage.registerFormatter(RepositoryCfg, RepositoryCfgPosixFormatter)