lsst.daf.persistence  13.0-31-g48013df+4
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 fcntl
26 import yaml
27 import os
28 import urllib
29 from . import PosixStorage, RepositoryCfg, safeFileIo, ParentsMismatch
30 from lsst.log import Log
31 
32 
34 
35  @classmethod
36  def write(cls, cfg, butlerLocation):
37  """Serialize a RepositoryCfg to a location.
38 
39  When the location is the same as cfg.root, the RepositoryCfg is to be written at the root location of
40  the repository. In that case, root is not written in the serialized cfg; it is implicit in the
41  location of the cfg. This allows the cfg to move from machine to machine without modification.
42 
43  Parameters
44  ----------
45  cfg : RepositoryCfg instance
46  The RepositoryCfg to be serialized.
47  butlerLocation : ButlerLocation
48  The location to write the RepositoryCfg.
49  """
50  def setRoot(cfg, loc):
51  loc = os.path.split(loc)[0] # remove the `repoistoryCfg.yaml` file name
52  if loc is None or cfg.root == loc:
53  cfg = copy.copy(cfg)
54  loc = cfg.root
55  cfg.root = None
56  return cfg
57 
58  # This class supports schema 'file' and also treats no schema as 'file'.
59  # Split the URI and take only the path; remove the schema from loc if it's there.
60  loc = butlerLocation.storage.root
61  parseRes = urllib.parse.urlparse(loc if loc is not None else cfg.root)
62  loc = os.path.join(parseRes.path, butlerLocation.getLocations()[0])
63  try:
64  with safeFileIo.SafeLockedFileForRead(loc) as f:
65  existingCfg = RepositoryCfgPosixFormatter._read(f, parseRes.path)
66  if existingCfg == cfg:
67  cfg.dirty = False
68  return
69  except IOError as e:
70  if e.errno != errno.ENOENT: # ENOENT is 'No such file or directory'
71  raise e
72  with safeFileIo.SafeLockedFileForWrite(loc) as f:
73  existingCfg = RepositoryCfgPosixFormatter._read(f, parseRes.path)
74  if existingCfg is None:
75  cfgToWrite = setRoot(cfg, loc)
76  else:
77  if existingCfg == cfg:
78  cfg.dirty = False
79  return
80  try:
81  existingCfg.extend(cfg)
82  cfgToWrite = setRoot(existingCfg, loc)
83  except ParentsMismatch as e:
84  raise RuntimeError("Can not extend existing repository cfg because: {}".format(e))
85  yaml.dump(cfgToWrite, f)
86  cfg.dirty = False
87 
88  @classmethod
89  def _read(cls, fileObject, uri):
90  """Get a persisted RepositoryCfg from an open file object.
91 
92  Parameters
93  ----------
94  fileObject : an open file object
95  the file that contains the RepositoryCfg.
96 
97  Returns
98  -------
99  A RepositoryCfg instance or None
100  """
101  repositoryCfg = yaml.load(fileObject)
102  if repositoryCfg is not None:
103  if repositoryCfg.root is None:
104  repositoryCfg.root = uri
105  return repositoryCfg
106 
107  @classmethod
108  def read(cls, butlerLocation):
109  repositoryCfg = None
110  loc = butlerLocation.storage.root
111  fileLoc = os.path.join(loc, butlerLocation.getLocations()[0])
112  try:
113  with safeFileIo.SafeLockedFileForRead(fileLoc) as f:
114  repositoryCfg = RepositoryCfgPosixFormatter._read(f, loc)
115  except IOError as e:
116  if e.errno != errno.ENOENT: # ENOENT is 'No such file or directory'
117  raise e
118  return repositoryCfg
119 
120 
121 PosixStorage.registerFormatter(RepositoryCfg, RepositoryCfgPosixFormatter)