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
storage.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 from future import standard_library
25 standard_library.install_aliases()
26 from builtins import object
27 
28 import urllib.parse
29 
30 
31 class Storage(object):
32  """Base class for storages"""
33 
34  storages = {}
35 
36  @staticmethod
37  def registerStorageClass(scheme, cls):
38  """Register derived classes for lookup by URI scheme.
39 
40  A scheme is a name that describes the form a resource at the beginning of a URI
41  e.g. 'http' indicates HTML and related code, such as is found in http://www.lsst.org
42 
43  The only currently supported schemes are:
44  * 'file' where the portion of the URI after the // indicates an absolute locaiton on disk.
45  for example: file:/my_repository_folder/
46  * '' (no scheme) where the entire string is a relative path on the local system
47  for example "my_repository_folder" will indicate a folder in the current working directory with the
48  same name.
49 
50  See documentation for the urlparse python library for more information.
51 
52  .. warning::
53 
54  Storage is 'wet paint' and very likely to change during factorization of Butler back end and
55  storage formats (DM-6225). Use of it in production code other than via the 'old butler' API is
56  strongly discouraged.
57 
58  Parameters
59  ----------
60  scheme : str
61  Name of the `scheme` the class is being registered for, which appears at the beginning of a URI.
62  cls : class object
63  A class object that should be used for a given scheme.
64  """
65  if scheme in Storage.storages:
66  raise RuntimeError("Scheme '%s' already registered:%s" % (scheme, Storage.storages[scheme]))
67  Storage.storages[scheme] = cls
68 
69  @staticmethod
70  def getRepositoryCfg(uri):
71  """Get a RepositoryCfg from a location specified by uri."""
72  ret = None
73  parseRes = urllib.parse.urlparse(uri)
74  if parseRes.scheme in Storage.storages:
75  ret = Storage.storages[parseRes.scheme].getRepositoryCfg(uri)
76  else:
77  raise RuntimeError("No storage registered for scheme %s" % parseRes.scheme)
78  return ret
79 
80  @staticmethod
81  def putRepositoryCfg(cfg, uri):
82  """Write a RepositoryCfg object to a location described by uri"""
83  ret = None
84  parseRes = urllib.parse.urlparse(uri)
85  if parseRes.scheme in Storage.storages:
86  ret = Storage.storages[parseRes.scheme].putRepositoryCfg(cfg, uri)
87  else:
88  raise RuntimeError("No storage registered for scheme %s" % parseRes.scheme)
89  return ret
90 
91  @staticmethod
92  def getMapperClass(uri):
93  """Get a mapper class cfg value from location described by uri.
94 
95  Note that in legacy repositories the mapper may be specified by a file called _mapper at the uri
96  location, and in newer repositories the mapper would be specified by a RepositoryCfg stored at the uri
97  location.
98 
99  .. warning::
100 
101  Storage is 'wet paint' and very likely to change during factorization of Butler back end and
102  storage formats (DM-6225). Use of it in production code other than via the 'old butler' API is
103  strongly discouraged.
104 
105  """
106  ret = None
107  parseRes = urllib.parse.urlparse(uri)
108  if parseRes.scheme in Storage.storages:
109  ret = Storage.storages[parseRes.scheme].getMapperClass(uri)
110  else:
111  raise RuntimeError("No storage registered for scheme %s" % parseRes.scheme)
112  return ret
113 
114  @staticmethod
115  def makeFromURI(uri):
116  '''Instantiate a storage sublcass from a URI.
117 
118  .. warning::
119 
120  Storage is 'wet paint' and very likely to change during factorization of Butler back end and
121  storage formats (DM-6225). Use of it in production code other than via the 'old butler' API is
122  strongly discouraged.
123 
124  :param uri: the uri to a locaiton that contains a repositoryCfg.
125  :return: a Storage subclass instance.
126  '''
127  ret = None
128  parseRes = urllib.parse.urlparse(uri)
129  if parseRes.scheme in Storage.storages:
130  theClass = Storage.storages[parseRes.scheme]
131  ret = theClass(uri)
132  else:
133  raise RuntimeError("No storage registered for scheme %s" % parseRes.scheme)
134  return ret
135 
136  @staticmethod
137  def isPosix(uri):
138  """Test if a URI is for a local filesystem storage.
139 
140  This is mostly for backward compatibility; Butler V1 repositories were only ever on the local
141  filesystem. They may exist but not have a RepositoryCfg class. This enables conditional checking for a
142  V1 Repository.
143 
144  This function treats 'file' and '' (no scheme) as posix storages, see
145  the class docstring for more details.
146 
147  Parameters
148  ----------
149  uri : string
150  URI to the root of a Repository.
151 
152  Returns
153  -------
154  Bool
155  True if the URI is associated with a posix storage, else false.
156  """
157  parseRes = urllib.parse.urlparse(uri)
158  if parseRes.scheme in ('file', ''):
159  return True
160  return False
161