LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
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