lsst-resources 29.2025.4800__py3-none-any.whl → 30.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lsst/resources/_resourcePath.py +15 -1
- lsst/resources/eups.py +101 -0
- lsst/resources/packageresource.py +2 -0
- lsst/resources/proxied.py +148 -0
- lsst/resources/schemeless.py +17 -5
- lsst/resources/tests.py +14 -3
- lsst/resources/version.py +1 -1
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/METADATA +1 -1
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/RECORD +14 -12
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/WHEEL +1 -1
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/licenses/COPYRIGHT +0 -0
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/licenses/LICENSE +0 -0
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/top_level.txt +0 -0
- {lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/zip-safe +0 -0
lsst/resources/_resourcePath.py
CHANGED
|
@@ -386,6 +386,11 @@ class ResourcePath: # numpydoc ignore=PR02
|
|
|
386
386
|
from .mem import InMemoryResourcePath
|
|
387
387
|
|
|
388
388
|
subclass = InMemoryResourcePath
|
|
389
|
+
elif parsed.scheme == "eups":
|
|
390
|
+
# EUPS package root.
|
|
391
|
+
from .eups import EupsResourcePath
|
|
392
|
+
|
|
393
|
+
subclass = EupsResourcePath
|
|
389
394
|
else:
|
|
390
395
|
raise NotImplementedError(
|
|
391
396
|
f"No URI support for scheme: '{parsed.scheme}' in {parsed.geturl()}"
|
|
@@ -396,11 +401,15 @@ class ResourcePath: # numpydoc ignore=PR02
|
|
|
396
401
|
)
|
|
397
402
|
|
|
398
403
|
# It is possible for the class to change from schemeless
|
|
399
|
-
# to file so handle that
|
|
404
|
+
# to file or eups so handle that
|
|
400
405
|
if parsed.scheme == "file":
|
|
401
406
|
from .file import FileResourcePath
|
|
402
407
|
|
|
403
408
|
subclass = FileResourcePath
|
|
409
|
+
elif parsed.scheme == "eups":
|
|
410
|
+
from .eups import EupsResourcePath
|
|
411
|
+
|
|
412
|
+
subclass = EupsResourcePath
|
|
404
413
|
|
|
405
414
|
# Now create an instance of the correct subclass and set the
|
|
406
415
|
# attributes directly
|
|
@@ -410,8 +419,13 @@ class ResourcePath: # numpydoc ignore=PR02
|
|
|
410
419
|
if isTemporary is None:
|
|
411
420
|
isTemporary = False
|
|
412
421
|
self.isTemporary = isTemporary
|
|
422
|
+
self._set_proxy()
|
|
413
423
|
return self
|
|
414
424
|
|
|
425
|
+
def _set_proxy(self) -> None:
|
|
426
|
+
"""Calculate internal proxy for externally visible resource path."""
|
|
427
|
+
pass
|
|
428
|
+
|
|
415
429
|
@property
|
|
416
430
|
def scheme(self) -> str:
|
|
417
431
|
"""Return the URI scheme.
|
lsst/resources/eups.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# This file is part of lsst-resources.
|
|
2
|
+
#
|
|
3
|
+
# Developed for the LSST Data Management System.
|
|
4
|
+
# This product includes software developed by the LSST Project
|
|
5
|
+
# (https://www.lsst.org).
|
|
6
|
+
# See the COPYRIGHT file at the top-level directory of this distribution
|
|
7
|
+
# for details of code ownership.
|
|
8
|
+
#
|
|
9
|
+
# Use of this source code is governed by a 3-clause BSD-style
|
|
10
|
+
# license that can be found in the LICENSE file.
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
__all__ = ("EupsResourcePath",)
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import posixpath
|
|
18
|
+
import urllib.parse
|
|
19
|
+
|
|
20
|
+
from lsst.utils import getPackageDir
|
|
21
|
+
|
|
22
|
+
from ._resourcePath import ResourcePath
|
|
23
|
+
from .proxied import ProxiedResourcePath
|
|
24
|
+
from .utils import os2posix
|
|
25
|
+
|
|
26
|
+
log = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EupsResourcePath(ProxiedResourcePath):
|
|
30
|
+
"""URI referring to an EUPS package.
|
|
31
|
+
|
|
32
|
+
These URIs look like: ``eups://daf_butler/configs/file.yaml``
|
|
33
|
+
where the network location is the EUPS package name.
|
|
34
|
+
|
|
35
|
+
Internally they are proxied by either ``file`` URIs or ``resource`` URIs.
|
|
36
|
+
If an ``{product}_DIR`` environment variable is found it will be used
|
|
37
|
+
and internally a ``file`` URI will be created. If no environment variable
|
|
38
|
+
is found an attempt will be made to convert the EUPS product name to
|
|
39
|
+
a python package and a ``resource`` URI will be returned with
|
|
40
|
+
``/resources`` appended. The convention is that any package supporting
|
|
41
|
+
an EUPS URI outside an EUPS environment will also have made available
|
|
42
|
+
the support files as package resources.
|
|
43
|
+
|
|
44
|
+
If it is known that the package supports package resources it is always
|
|
45
|
+
better to use that URI form explicitly since it is more robust since
|
|
46
|
+
not all EUPS packages can reliably be converted to python packages
|
|
47
|
+
without EUPS.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
quotePaths = False
|
|
51
|
+
_proxy: ResourcePath | None = None
|
|
52
|
+
_default_namespace: str = "lsst"
|
|
53
|
+
|
|
54
|
+
def _set_proxy(self) -> None:
|
|
55
|
+
"""Calculate the internal `ResourcePath` corresponding to the public
|
|
56
|
+
version.
|
|
57
|
+
"""
|
|
58
|
+
# getPackageDir returns an absolute path.
|
|
59
|
+
try:
|
|
60
|
+
eups_path = getPackageDir(self.netloc)
|
|
61
|
+
log.debug("Found EUPS package %s via env var", self.netloc)
|
|
62
|
+
except LookupError:
|
|
63
|
+
eups_path = ""
|
|
64
|
+
if eups_path:
|
|
65
|
+
# Must convert this path into a file URI.
|
|
66
|
+
new_path = posixpath.join(os2posix(eups_path), os2posix(self.path.lstrip("/")))
|
|
67
|
+
parsed = self._uri._replace(path=urllib.parse.quote(new_path), scheme="file", netloc="")
|
|
68
|
+
self._proxy = ResourcePath(parsed)
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# If there is no _DIR env var we need to look for python package
|
|
72
|
+
# resource. There is no guaranteed way to generated a python package
|
|
73
|
+
# from an EUPS product name.
|
|
74
|
+
# daf_butler -> lsst.daf.butler
|
|
75
|
+
# image_cutout_backend -> lsst.image_cutout_backend
|
|
76
|
+
# astro_metadata_translator -> astro_metadata_translator
|
|
77
|
+
product = self.netloc
|
|
78
|
+
variants = (
|
|
79
|
+
product,
|
|
80
|
+
self._default_namespace + "." + product.replace("_", "."),
|
|
81
|
+
self._default_namespace + "." + product,
|
|
82
|
+
product.replace("_", "."),
|
|
83
|
+
)
|
|
84
|
+
for variant in variants:
|
|
85
|
+
proxy = ResourcePath(f"resource://{variant}/resources", forceDirectory=True)
|
|
86
|
+
# This can be slow because package imports happen but there is
|
|
87
|
+
# no other way to check that we have the correct variant.
|
|
88
|
+
log.debug("Trying variant %s", proxy)
|
|
89
|
+
if proxy.exists():
|
|
90
|
+
self._proxy = proxy
|
|
91
|
+
if self.path:
|
|
92
|
+
self._proxy = self._proxy.join(self.path.lstrip("/"))
|
|
93
|
+
log.debug(f"Found variant {variant}")
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
# Can not find an actively set up package or resources for this EUPS
|
|
97
|
+
# product. Return without setting a proxy to allow standard URI
|
|
98
|
+
# path manipulations to happen but defer failure until someone tries
|
|
99
|
+
# to use the proxy for read.
|
|
100
|
+
log.debug("Could not find any files corresponding to %s", self)
|
|
101
|
+
return
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# This file is part of lsst-resources.
|
|
2
|
+
#
|
|
3
|
+
# Developed for the LSST Data Management System.
|
|
4
|
+
# This product includes software developed by the LSST Project
|
|
5
|
+
# (https://www.lsst.org).
|
|
6
|
+
# See the COPYRIGHT file at the top-level directory of this distribution
|
|
7
|
+
# for details of code ownership.
|
|
8
|
+
#
|
|
9
|
+
# Use of this source code is governed by a 3-clause BSD-style
|
|
10
|
+
# license that can be found in the LICENSE file.
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
__all__ = ("ProxiedResourcePath",)
|
|
15
|
+
|
|
16
|
+
import contextlib
|
|
17
|
+
import logging
|
|
18
|
+
import re
|
|
19
|
+
from abc import ABC, abstractmethod
|
|
20
|
+
from collections.abc import Iterator
|
|
21
|
+
|
|
22
|
+
from ._resourcePath import ResourceHandleProtocol, ResourcePath, ResourcePathExpression
|
|
23
|
+
from .utils import TransactionProtocol
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import fsspec
|
|
27
|
+
from fsspec.spec import AbstractFileSystem
|
|
28
|
+
except ImportError:
|
|
29
|
+
fsspec = None
|
|
30
|
+
AbstractFileSystem = type
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
log = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ProxiedResourcePath(ABC, ResourcePath):
|
|
37
|
+
"""URI that is represented internally by another type of URI for file I/O.
|
|
38
|
+
|
|
39
|
+
For example ``abc://xyz/file.txt`` could be the public URI form but
|
|
40
|
+
internally all file access is forwarded to a ``file`` URI.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
_proxy: ResourcePath | None = None
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def _set_proxy(self) -> None:
|
|
47
|
+
"""Calculate the internal `ResourcePath` corresponding to the public
|
|
48
|
+
version.
|
|
49
|
+
"""
|
|
50
|
+
raise NotImplementedError("Proxy must be configured")
|
|
51
|
+
|
|
52
|
+
def _get_proxy(self) -> ResourcePath:
|
|
53
|
+
"""Retrieve the proxied ResourcePath."""
|
|
54
|
+
proxy = self._proxy
|
|
55
|
+
if proxy is None:
|
|
56
|
+
raise FileNotFoundError(f"Internal error: No proxy ResourcePath available for {self}")
|
|
57
|
+
return proxy
|
|
58
|
+
|
|
59
|
+
def to_fsspec(self) -> tuple[AbstractFileSystem, str]:
|
|
60
|
+
try:
|
|
61
|
+
proxy = self._get_proxy()
|
|
62
|
+
except FileNotFoundError:
|
|
63
|
+
raise NotImplementedError(f"No proxy registered for {self}. Resource does not exist.") from None
|
|
64
|
+
return proxy.to_fsspec()
|
|
65
|
+
|
|
66
|
+
def isdir(self) -> bool:
|
|
67
|
+
if self.dirLike is None:
|
|
68
|
+
try:
|
|
69
|
+
proxy = self._get_proxy()
|
|
70
|
+
except FileNotFoundError:
|
|
71
|
+
return False
|
|
72
|
+
self.dirLike = proxy.isdir()
|
|
73
|
+
return self.dirLike
|
|
74
|
+
|
|
75
|
+
def exists(self) -> bool:
|
|
76
|
+
try:
|
|
77
|
+
proxy = self._get_proxy()
|
|
78
|
+
except FileNotFoundError:
|
|
79
|
+
# If there is no proxy registered then the resource can not exist.
|
|
80
|
+
return False
|
|
81
|
+
return proxy.exists()
|
|
82
|
+
|
|
83
|
+
def remove(self) -> None:
|
|
84
|
+
proxy = self._get_proxy()
|
|
85
|
+
proxy.remove()
|
|
86
|
+
|
|
87
|
+
def read(self, size: int = -1) -> bytes:
|
|
88
|
+
proxy = self._get_proxy()
|
|
89
|
+
return proxy.read(size=size)
|
|
90
|
+
|
|
91
|
+
@contextlib.contextmanager
|
|
92
|
+
def as_local(
|
|
93
|
+
self, multithreaded: bool = True, tmpdir: ResourcePathExpression | None = None
|
|
94
|
+
) -> Iterator[ResourcePath]:
|
|
95
|
+
proxy = self._get_proxy()
|
|
96
|
+
with proxy.as_local(multithreaded=multithreaded, tmpdir=tmpdir) as loc:
|
|
97
|
+
yield loc
|
|
98
|
+
|
|
99
|
+
@contextlib.contextmanager
|
|
100
|
+
def open(
|
|
101
|
+
self,
|
|
102
|
+
mode: str = "r",
|
|
103
|
+
*,
|
|
104
|
+
encoding: str | None = None,
|
|
105
|
+
prefer_file_temporary: bool = False,
|
|
106
|
+
) -> Iterator[ResourceHandleProtocol]:
|
|
107
|
+
proxy = self._get_proxy()
|
|
108
|
+
with proxy.open(mode, encoding=encoding, prefer_file_temporary=prefer_file_temporary) as fh:
|
|
109
|
+
yield fh
|
|
110
|
+
|
|
111
|
+
def walk(
|
|
112
|
+
self, file_filter: str | re.Pattern | None = None
|
|
113
|
+
) -> Iterator[list | tuple[ResourcePath, list[str], list[str]]]:
|
|
114
|
+
try:
|
|
115
|
+
proxy = self._get_proxy()
|
|
116
|
+
except FileNotFoundError as e:
|
|
117
|
+
raise ValueError(str(e)) from None
|
|
118
|
+
for proxied_root, dirs, files in proxy.walk(file_filter=file_filter):
|
|
119
|
+
# Need to return the directory in the original form and not the
|
|
120
|
+
# proxy form.
|
|
121
|
+
relative_to_self = proxied_root.path.removeprefix(proxy.path)
|
|
122
|
+
root = self.replace(path=self._pathModule.join(self.path, relative_to_self))
|
|
123
|
+
yield root, dirs, files
|
|
124
|
+
|
|
125
|
+
def size(self) -> int:
|
|
126
|
+
proxy = self._get_proxy()
|
|
127
|
+
return proxy.size()
|
|
128
|
+
|
|
129
|
+
def write(self, data: bytes, overwrite: bool = True) -> None:
|
|
130
|
+
proxy = self._get_proxy()
|
|
131
|
+
proxy.write(data, overwrite=overwrite)
|
|
132
|
+
|
|
133
|
+
def mkdir(self) -> None:
|
|
134
|
+
proxy = self._get_proxy()
|
|
135
|
+
proxy.mkdir()
|
|
136
|
+
|
|
137
|
+
def transfer_from(
|
|
138
|
+
self,
|
|
139
|
+
src: ResourcePath,
|
|
140
|
+
transfer: str = "copy",
|
|
141
|
+
overwrite: bool = False,
|
|
142
|
+
transaction: TransactionProtocol | None = None,
|
|
143
|
+
multithreaded: bool = True,
|
|
144
|
+
) -> None:
|
|
145
|
+
proxy = self._get_proxy()
|
|
146
|
+
proxy.transfer_from(
|
|
147
|
+
src, transfer=transfer, overwrite=overwrite, transaction=transaction, multithreaded=multithreaded
|
|
148
|
+
)
|
lsst/resources/schemeless.py
CHANGED
|
@@ -16,6 +16,7 @@ __all__ = ("SchemelessResourcePath",)
|
|
|
16
16
|
import logging
|
|
17
17
|
import os
|
|
18
18
|
import os.path
|
|
19
|
+
import re
|
|
19
20
|
import stat
|
|
20
21
|
import urllib.parse
|
|
21
22
|
from pathlib import PurePath
|
|
@@ -211,12 +212,23 @@ class SchemelessResourcePath(FileResourcePath):
|
|
|
211
212
|
expandedPath = os.path.expanduser(urllib.parse.unquote(parsed.path))
|
|
212
213
|
|
|
213
214
|
# We might also be receiving a path containing environment variables
|
|
214
|
-
# so expand those here
|
|
215
|
+
# so expand those here, although we treat $X_DIR at the start of the
|
|
216
|
+
# path as a special EUPS URI. This allows us to handle EUPS-style
|
|
217
|
+
# env var specifications even if EUPS has not set them.
|
|
218
|
+
# Support $X_DIR and ${X_DIR} variants at the start of the path.
|
|
219
|
+
if eups := re.match(r"(\$\{?([A-Z_]+)_DIR\}?)/", expandedPath):
|
|
220
|
+
replacements["scheme"] = "eups"
|
|
221
|
+
# Two matching groups: the entire env var, and the EUPS product.
|
|
222
|
+
replacements["netloc"] = eups.group(2).lower()
|
|
223
|
+
expandedPath = expandedPath.removeprefix(eups.group(1))
|
|
224
|
+
|
|
215
225
|
expandedPath = os.path.expandvars(expandedPath)
|
|
216
226
|
|
|
217
|
-
# Ensure that this becomes a file URI if it is already absolute
|
|
227
|
+
# Ensure that this becomes a file URI if it is already absolute, unless
|
|
228
|
+
# we already overrode it above.
|
|
218
229
|
if os.path.isabs(expandedPath):
|
|
219
|
-
|
|
230
|
+
if "scheme" not in replacements:
|
|
231
|
+
replacements["scheme"] = "file"
|
|
220
232
|
# Keep in OS form for now to simplify later logic
|
|
221
233
|
replacements["path"] = os.path.normpath(expandedPath)
|
|
222
234
|
elif forceAbsolute:
|
|
@@ -265,9 +277,9 @@ class SchemelessResourcePath(FileResourcePath):
|
|
|
265
277
|
if not replacements["path"].endswith(os.sep):
|
|
266
278
|
replacements["path"] += os.sep
|
|
267
279
|
|
|
268
|
-
if "scheme" in replacements:
|
|
280
|
+
if "scheme" in replacements and replacements["scheme"] == "file":
|
|
269
281
|
# This is now meant to be a URI path so force to posix
|
|
270
|
-
# and quote
|
|
282
|
+
# and quote. EUPS URIs are not quoted.
|
|
271
283
|
replacements["path"] = urllib.parse.quote(os2posix(replacements["path"]))
|
|
272
284
|
|
|
273
285
|
# ParseResult is a NamedTuple so _replace is standard API
|
lsst/resources/tests.py
CHANGED
|
@@ -417,11 +417,19 @@ class GenericTestCase(_GenericTestCase):
|
|
|
417
417
|
def test_escapes(self) -> None:
|
|
418
418
|
"""Special characters in file paths."""
|
|
419
419
|
src = self.root_uri.join("bbb/???/test.txt")
|
|
420
|
-
|
|
420
|
+
quotes = src.quotePaths
|
|
421
|
+
|
|
422
|
+
if quotes:
|
|
423
|
+
self.assertNotIn("???", src.path)
|
|
424
|
+
else:
|
|
425
|
+
self.assertIn("???", src.path)
|
|
421
426
|
self.assertIn("???", src.unquoted_path)
|
|
422
427
|
|
|
423
428
|
file = src.updatedFile("tests??.txt")
|
|
424
|
-
|
|
429
|
+
if quotes:
|
|
430
|
+
self.assertNotIn("??.txt", file.path)
|
|
431
|
+
else:
|
|
432
|
+
self.assertIn("??.txt", file.path)
|
|
425
433
|
|
|
426
434
|
src = src.updatedFile("tests??.txt")
|
|
427
435
|
self.assertIn("??.txt", src.unquoted_path)
|
|
@@ -456,7 +464,10 @@ class GenericTestCase(_GenericTestCase):
|
|
|
456
464
|
|
|
457
465
|
fnew2 = fdir.join(new2name)
|
|
458
466
|
self.assertTrue(fnew2.unquoted_path.endswith(new2name))
|
|
459
|
-
|
|
467
|
+
if quotes:
|
|
468
|
+
self.assertNotIn("###", fnew2.path)
|
|
469
|
+
else:
|
|
470
|
+
self.assertIn("###", fnew2.path)
|
|
460
471
|
|
|
461
472
|
# Test that children relative to schemeless and file schemes
|
|
462
473
|
# still return the same unquoted name
|
lsst/resources/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "
|
|
2
|
+
__version__ = "30.0.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lsst-resources
|
|
3
|
-
Version:
|
|
3
|
+
Version: 30.0.0
|
|
4
4
|
Summary: An abstraction layer for reading and writing from URI file resources.
|
|
5
5
|
Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
lsst/__init__.py,sha256=9I6UQ9gj-ZcPlvsa0OPBo76UujxXVehVzw9yMAOQvyM,466
|
|
2
2
|
lsst/resources/__init__.py,sha256=BDj6uokvd0ZQNGl-Xgz5gZd83Z0L2gFqGSk0KJpylP8,778
|
|
3
|
-
lsst/resources/_resourcePath.py,sha256=
|
|
3
|
+
lsst/resources/_resourcePath.py,sha256=VLW9YDADwnvK2WOypmWPCstd6iTnvDns1Jtf6UAR03E,74980
|
|
4
4
|
lsst/resources/dav.py,sha256=ZYP7PnQzS7epm5woxnn1_t1XhsPQZm6_q1kv8baUfn4,32100
|
|
5
5
|
lsst/resources/davutils.py,sha256=5geEl_44lrWX-Si1VDfYJ6WP1rg22PBqlyD_v1HE4yI,100300
|
|
6
|
+
lsst/resources/eups.py,sha256=imN_qrmtHVQ0g-rCrGNYrlabWBJONRCT02hZkN7ikvc,4056
|
|
6
7
|
lsst/resources/file.py,sha256=v2XLOzflfhI6kjUGB1mE8p-1e1B2eE58PW-qsQSCqdA,24360
|
|
7
8
|
lsst/resources/gs.py,sha256=3qMEqO1wIK05BJmuUHtsEunuYWgR4-eB5Z3ffxEtb0o,12827
|
|
8
9
|
lsst/resources/http.py,sha256=WSx2VXKFd6486TytV2NMfdgLntioL6FvliZWpn9LtDE,92426
|
|
9
10
|
lsst/resources/location.py,sha256=x3Tq0x5o1OXYmZDxYBenUG1N71wtDhnjVAr3s2ZEiu8,7937
|
|
10
11
|
lsst/resources/mem.py,sha256=xCpGgvxF2gmO5gLkOikKvIet2RPvaPCiARenR9pUWCk,1115
|
|
11
|
-
lsst/resources/packageresource.py,sha256=
|
|
12
|
+
lsst/resources/packageresource.py,sha256=FJ2t7HSnAgtfLUEvg5TTEYrWEXdqVagTmWGfP0hCfC4,6841
|
|
13
|
+
lsst/resources/proxied.py,sha256=9hpfVBbzkC66QNHSKgd4lXBv3XTMzqPwXalkLZv7A34,4775
|
|
12
14
|
lsst/resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
15
|
lsst/resources/s3.py,sha256=NGJPM4BjtqFIPvg9vbp_blrIRt009NbOm06cr65Wqmw,29662
|
|
14
16
|
lsst/resources/s3utils.py,sha256=ojWf9BPrK9mhGQ8jvs4_8Nsqf9360e79U5FnPTxe24A,14576
|
|
15
|
-
lsst/resources/schemeless.py,sha256=
|
|
16
|
-
lsst/resources/tests.py,sha256=
|
|
17
|
+
lsst/resources/schemeless.py,sha256=Bhcjy-M3k7D-Kmf1ShXYaPqceGb0bOns4Rw9ecXOJjA,11658
|
|
18
|
+
lsst/resources/tests.py,sha256=0tDhVtF1euMH0Y7QR-RbQyo83GPe9baIPI6pM9VyZ-Y,46516
|
|
17
19
|
lsst/resources/utils.py,sha256=6O3Mq7JbPEtqyD2lM77pRpwcPMfV5SxiNMknw-F2vNs,8097
|
|
18
|
-
lsst/resources/version.py,sha256
|
|
20
|
+
lsst/resources/version.py,sha256=--s7nTlXrHcUGZfOJGTF8_DCdIUv7QPWWD7as9kq0iY,49
|
|
19
21
|
lsst/resources/_resourceHandles/__init__.py,sha256=zOcZ8gVEBdAWcHJaZabA8Vdq-wAVcxjbmA_1b1IWM6M,76
|
|
20
22
|
lsst/resources/_resourceHandles/_baseResourceHandle.py,sha256=lQwxDOmFUNJndTxsjpz-HxrQBL0L-z4aXQocHdOEI7c,4676
|
|
21
23
|
lsst/resources/_resourceHandles/_davResourceHandle.py,sha256=xcJNFUj8VzlPOKlHdXXoFFyiLNiSFiT-RFNqJRzKniQ,6799
|
|
22
24
|
lsst/resources/_resourceHandles/_fileResourceHandle.py,sha256=2nC8tfP_ynAfjpzrtkw_1ahx1CuMEFpZ5mLmofSShUk,3676
|
|
23
25
|
lsst/resources/_resourceHandles/_httpResourceHandle.py,sha256=Yami8IVGeru4bLQCag-OvGG0ltz1qyEg57FY4IEB87Y,10995
|
|
24
26
|
lsst/resources/_resourceHandles/_s3ResourceHandle.py,sha256=Cp-eBtptskbmthy3DwLKPpYPLvU_lrqtK10X37inHt0,12406
|
|
25
|
-
lsst_resources-
|
|
26
|
-
lsst_resources-
|
|
27
|
-
lsst_resources-
|
|
28
|
-
lsst_resources-
|
|
29
|
-
lsst_resources-
|
|
30
|
-
lsst_resources-
|
|
31
|
-
lsst_resources-
|
|
27
|
+
lsst_resources-30.0.0.dist-info/licenses/COPYRIGHT,sha256=yazVsoMmFwhiw5itGrdT4YPmXbpsQyUFjlpOyZIa77M,148
|
|
28
|
+
lsst_resources-30.0.0.dist-info/licenses/LICENSE,sha256=7wrtgl8meQ0_RIuv2TjIKpAnNrl-ODH-QLwyHe9citI,1516
|
|
29
|
+
lsst_resources-30.0.0.dist-info/METADATA,sha256=PZ5Hwf2mllBMrwywfPFpfy8x88GolYt8W2f0YkEs1UI,2234
|
|
30
|
+
lsst_resources-30.0.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
31
|
+
lsst_resources-30.0.0.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
|
|
32
|
+
lsst_resources-30.0.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
33
|
+
lsst_resources-30.0.0.dist-info/RECORD,,
|
{lsst_resources-29.2025.4800.dist-info → lsst_resources-30.0.0.dist-info}/licenses/COPYRIGHT
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|