26 from . 
import NoRepositroyAtRoot
 
   30     """Base class for storages""" 
   39         """Register derived classes for lookup by URI scheme. 
   41         A scheme is a name that describes the form a resource at the beginning of a URI 
   42         e.g. 'http' indicates HTML and related code, such as is found in http://www.lsst.org 
   44         The only currently supported schemes are: 
   45         * 'file' where the portion of the URI after the // indicates an absolute locaiton on disk. 
   46           for example: file:/my_repository_folder/ 
   47         * '' (no scheme) where the entire string is a relative path on the local system 
   48           for example "my_repository_folder" will indicate a folder in the current working directory with the 
   51         See documentation for the urlparse python library for more information. 
   55             Storage is 'wet paint' and very likely to change during factorization of Butler back end and 
   56             storage formats (DM-6225). Use of it in production code other than via the 'old butler' API is 
   62             Name of the `scheme` the class is being registered for, which appears at the beginning of a URI. 
   64             A class object that should be used for a given scheme. 
   66         if scheme 
in Storage.storages:
 
   67             raise RuntimeError(
"Scheme '%s' already registered:%s" % (scheme, Storage.storages[scheme]))
 
   68         Storage.storages[scheme] = cls
 
   71         """Get a RepositoryCfg from a location specified by uri. 
   73         If a cfg is found then it is cached by the uri, so that multiple lookups 
   74         are not performed on storages that might be remote. 
   76         RepositoryCfgs are not supposed to change once they are created so this 
   77         should not lead to stale data. 
   82         parseRes = urllib.parse.urlparse(uri)
 
   83         if parseRes.scheme 
in Storage.storages:
 
   88             raise RuntimeError(
"No storage registered for scheme %s" % parseRes.scheme)
 
   93         """Write a RepositoryCfg object to a location described by uri""" 
   95         parseRes = urllib.parse.urlparse(uri)
 
   96         if parseRes.scheme 
in Storage.storages:
 
   99             raise RuntimeError(
"No storage registered for scheme %s" % parseRes.scheme)
 
  104         """Get a mapper class cfg value from location described by uri. 
  106         Note that in legacy repositories the mapper may be specified by a file called _mapper at the uri 
  107         location, and in newer repositories the mapper would be specified by a RepositoryCfg stored at the uri 
  112             Storage is 'wet paint' and very likely to change during factorization of Butler back end and 
  113             storage formats (DM-6225). Use of it in production code other than via the 'old butler' API is 
  114             strongly discouraged. 
  118         parseRes = urllib.parse.urlparse(uri)
 
  119         if parseRes.scheme 
in Storage.storages:
 
  122             raise RuntimeError(
"No storage registered for scheme %s" % parseRes.scheme)
 
  127         '''Instantiate a StorageInterface sublcass from a URI. 
  131             Storage is 'wet paint' and very likely to change during factorization of Butler back end and 
  132             storage formats (DM-6225). Use of it in production code other than via the 'old butler' API is 
  133             strongly discouraged. 
  138             The uri to the root location of a repository. 
  139         create : bool, optional 
  140             If True The StorageInterface subclass should create a new 
  141             repository at the root location. If False then a new repository 
  146         A Storage subclass instance, or if create is False and a repository 
  147         does not exist at the root location then returns None. 
  152             When a StorageInterface subclass does not exist for the scheme 
  153             indicated by the uri. 
  156         parseRes = urllib.parse.urlparse(uri)
 
  157         if parseRes.scheme 
in Storage.storages:
 
  158             theClass = Storage.storages[parseRes.scheme]
 
  160                 ret = theClass(uri=uri, create=create)
 
  161             except NoRepositroyAtRoot:
 
  164             raise RuntimeError(
"No storage registered for scheme %s" % parseRes.scheme)
 
  169         """Test if a URI is for a local filesystem storage. 
  171         This is mostly for backward compatibility; Butler V1 repositories were only ever on the local 
  172         filesystem. They may exist but not have a RepositoryCfg class. This enables conditional checking for a 
  175         This function treats 'file' and '' (no scheme) as posix storages, see 
  176         the class docstring for more details. 
  181             URI to the root of a Repository. 
  186             True if the URI is associated with a posix storage, else false. 
  188         parseRes = urllib.parse.urlparse(uri)
 
  189         if parseRes.scheme 
in (
'file', 
''):
 
  195         """Get a relative path from a location to a location, if a relative path for these 2 locations exists. 
  200             A URI that describes a location at which to start. 
  202             A URI that describes a target location. 
  207             A relative path that describes the path from fromUri to toUri, provided one exists. If a relative 
  208             path between the two URIs does not exist then the entire toUri path is returned. 
  210         fromUriParseRes = urllib.parse.urlparse(fromUri)
 
  211         toUriParseRes = urllib.parse.urlparse(toUri)
 
  212         if fromUriParseRes.scheme != toUriParseRes.scheme:
 
  214         storage = Storage.storages.get(fromUriParseRes.scheme, 
None)
 
  217         return storage.relativePath(fromUri, toUri)
 
  221         """Get an absolute path for the path from fromUri to toUri 
  225         fromUri : the starting location 
  227         toUri : the location relative to fromUri 
  233             URI that is absolutepath fromUri + toUri, if one exists. If toUri is absolute or if fromUri is not 
  234             related to toUri (e.g. are of different storage types) then toUri will be returned. 
  236         fromUriParseRes = urllib.parse.urlparse(fromUri)
 
  237         toUriParseRes = urllib.parse.urlparse(toUri)
 
  238         if fromUriParseRes.scheme != toUriParseRes.scheme:
 
  240         storage = Storage.storages.get(fromUriParseRes.scheme, 
None)
 
  243         return storage.absolutePath(fromUri, toUri)
 
  247         """Look for the given path in a storage root at URI; return None if it can't be found. 
  249         If the path contains an HDU indicator (a number in brackets before the 
  250         dot, e.g. 'foo.fits[1]', this will be stripped when searching and so 
  251         will match filenames without the HDU indicator, e.g. 'foo.fits'. The 
  252         path returned WILL contain the indicator though, e.g. ['foo.fits[1]']. 
  258             URI to the the root location to search 
  260             A filename (and optionally prefix path) to search for within root. 
  265             The location that was found, or None if no location was found. 
  267         parseRes = urllib.parse.urlparse(uri)
 
  268         storage = Storage.storages.get(parseRes.scheme, 
None)
 
  270             return storage.search(uri, path)
 
  275         """Ask if a storage at the location described by uri exists 
  280             URI to the the root location of the storage 
  285             True if the storage exists, false if not 
  287         parseRes = urllib.parse.urlparse(uri)
 
  288         storage = Storage.storages.get(parseRes.scheme, 
None)
 
  290             return storage.storageExists(uri)