lsst-resources 29.2025.1300__py3-none-any.whl → 29.2025.1500__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/_resourceHandles/_httpResourceHandle.py +13 -2
- lsst/resources/_resourcePath.py +13 -26
- lsst/resources/http.py +21 -21
- lsst/resources/utils.py +31 -1
- lsst/resources/version.py +1 -1
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/METADATA +1 -1
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/RECORD +12 -12
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/WHEEL +0 -0
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/licenses/COPYRIGHT +0 -0
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/licenses/LICENSE +0 -0
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/top_level.txt +0 -0
- {lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/zip-safe +0 -0
|
@@ -29,6 +29,15 @@ if TYPE_CHECKING:
|
|
|
29
29
|
from ..http import HttpResourcePath
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
# Prevent circular import by copying this code. Can be removed as soon
|
|
33
|
+
# as separate dav implementation is implemented.
|
|
34
|
+
def _dav_to_http(url: str) -> str:
|
|
35
|
+
"""Convert dav scheme in URL to http scheme."""
|
|
36
|
+
if url.startswith("dav"):
|
|
37
|
+
url = "http" + url.removeprefix("dav")
|
|
38
|
+
return url
|
|
39
|
+
|
|
40
|
+
|
|
32
41
|
class HttpReadResourceHandle(BaseResourceHandle[bytes]):
|
|
33
42
|
"""HTTP-based specialization of `.BaseResourceHandle`.
|
|
34
43
|
|
|
@@ -159,7 +168,7 @@ class HttpReadResourceHandle(BaseResourceHandle[bytes]):
|
|
|
159
168
|
# return the result
|
|
160
169
|
self._completeBuffer = io.BytesIO()
|
|
161
170
|
with time_this(self._log, msg="Read from remote resource %s", args=(self._url,)):
|
|
162
|
-
resp = self._session.get(self._url, stream=False, timeout=self._timeout)
|
|
171
|
+
resp = self._session.get(_dav_to_http(self._url), stream=False, timeout=self._timeout)
|
|
163
172
|
if (code := resp.status_code) not in (requests.codes.ok, requests.codes.partial):
|
|
164
173
|
raise FileNotFoundError(f"Unable to read resource {self._url}; status code: {code}")
|
|
165
174
|
self._completeBuffer.write(resp.content)
|
|
@@ -181,7 +190,9 @@ class HttpReadResourceHandle(BaseResourceHandle[bytes]):
|
|
|
181
190
|
with time_this(
|
|
182
191
|
self._log, msg="Read from remote resource %s using headers %s", args=(self._url, headers)
|
|
183
192
|
):
|
|
184
|
-
resp = self._session.get(
|
|
193
|
+
resp = self._session.get(
|
|
194
|
+
_dav_to_http(self._url), stream=False, timeout=self._timeout, headers=headers
|
|
195
|
+
)
|
|
185
196
|
|
|
186
197
|
if resp.status_code == requests.codes.range_not_satisfiable:
|
|
187
198
|
# Must have run off the end of the file. A standard file handle
|
lsst/resources/_resourcePath.py
CHANGED
|
@@ -23,8 +23,6 @@ import multiprocessing
|
|
|
23
23
|
import os
|
|
24
24
|
import posixpath
|
|
25
25
|
import re
|
|
26
|
-
import shutil
|
|
27
|
-
import tempfile
|
|
28
26
|
import urllib.parse
|
|
29
27
|
from functools import cache
|
|
30
28
|
from pathlib import Path, PurePath, PurePosixPath
|
|
@@ -41,7 +39,7 @@ from collections.abc import Iterable, Iterator
|
|
|
41
39
|
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, overload
|
|
42
40
|
|
|
43
41
|
from ._resourceHandles._baseResourceHandle import ResourceHandleProtocol
|
|
44
|
-
from .utils import
|
|
42
|
+
from .utils import get_tempdir
|
|
45
43
|
|
|
46
44
|
if TYPE_CHECKING:
|
|
47
45
|
from .utils import TransactionProtocol
|
|
@@ -336,6 +334,10 @@ class ResourcePath: # numpydoc ignore=PR02
|
|
|
336
334
|
elif parsed.scheme.startswith("http"):
|
|
337
335
|
from .http import HttpResourcePath
|
|
338
336
|
|
|
337
|
+
subclass = HttpResourcePath
|
|
338
|
+
elif parsed.scheme in {"dav", "davs"}:
|
|
339
|
+
from .http import HttpResourcePath
|
|
340
|
+
|
|
339
341
|
subclass = HttpResourcePath
|
|
340
342
|
elif parsed.scheme == "gs":
|
|
341
343
|
from .gs import GSResourcePath
|
|
@@ -1136,35 +1138,23 @@ class ResourcePath: # numpydoc ignore=PR02
|
|
|
1136
1138
|
prefix : `ResourcePath`, optional
|
|
1137
1139
|
Temporary directory to use (can be any scheme). Without this the
|
|
1138
1140
|
path will be formed as a local file URI in a temporary directory
|
|
1139
|
-
|
|
1140
|
-
location exists is the responsibility of the caller.
|
|
1141
|
+
obtained from `lsst.resources.utils.get_tempdir`. Ensuring that the
|
|
1142
|
+
prefix location exists is the responsibility of the caller.
|
|
1141
1143
|
suffix : `str`, optional
|
|
1142
1144
|
A file suffix to be used. The ``.`` should be included in this
|
|
1143
1145
|
suffix.
|
|
1144
1146
|
delete : `bool`, optional
|
|
1145
1147
|
By default the resource will be deleted when the context manager
|
|
1146
1148
|
is exited. Setting this flag to `False` will leave the resource
|
|
1147
|
-
alone.
|
|
1148
|
-
been created.
|
|
1149
|
+
alone.
|
|
1149
1150
|
|
|
1150
1151
|
Yields
|
|
1151
1152
|
------
|
|
1152
1153
|
uri : `ResourcePath`
|
|
1153
1154
|
The temporary URI. Will be removed when the context is completed.
|
|
1154
1155
|
"""
|
|
1155
|
-
use_tempdir = False
|
|
1156
1156
|
if prefix is None:
|
|
1157
|
-
|
|
1158
|
-
# If the user has set a umask that restricts the owner-write bit,
|
|
1159
|
-
# the directory returned from mkdtemp may not initially be
|
|
1160
|
-
# writeable by us
|
|
1161
|
-
ensure_directory_is_writeable(directory)
|
|
1162
|
-
|
|
1163
|
-
prefix = ResourcePath(directory, forceDirectory=True, isTemporary=True)
|
|
1164
|
-
# Record that we need to delete this directory. Can not rely
|
|
1165
|
-
# on isTemporary flag since an external prefix may have that
|
|
1166
|
-
# set as well.
|
|
1167
|
-
use_tempdir = True
|
|
1157
|
+
prefix = ResourcePath(get_tempdir(), forceDirectory=True)
|
|
1168
1158
|
|
|
1169
1159
|
# Need to create a randomized file name. For consistency do not
|
|
1170
1160
|
# use mkstemp for local and something else for remote. Additionally
|
|
@@ -1183,13 +1173,10 @@ class ResourcePath: # numpydoc ignore=PR02
|
|
|
1183
1173
|
yield temporary_uri
|
|
1184
1174
|
finally:
|
|
1185
1175
|
if delete:
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
# It's okay if this does not work because the user
|
|
1191
|
-
# removed the file.
|
|
1192
|
-
temporary_uri.remove()
|
|
1176
|
+
with contextlib.suppress(FileNotFoundError):
|
|
1177
|
+
# It's okay if this does not work because the user
|
|
1178
|
+
# removed the file.
|
|
1179
|
+
temporary_uri.remove()
|
|
1193
1180
|
|
|
1194
1181
|
def read(self, size: int = -1) -> bytes:
|
|
1195
1182
|
"""Open the resource and return the contents in bytes.
|
lsst/resources/http.py
CHANGED
|
@@ -26,7 +26,6 @@ import random
|
|
|
26
26
|
import re
|
|
27
27
|
import ssl
|
|
28
28
|
import stat
|
|
29
|
-
import tempfile
|
|
30
29
|
from collections.abc import Iterator
|
|
31
30
|
from typing import TYPE_CHECKING, Any, BinaryIO, cast
|
|
32
31
|
|
|
@@ -60,6 +59,7 @@ from lsst.utils.timer import time_this
|
|
|
60
59
|
from ._resourceHandles import ResourceHandleProtocol
|
|
61
60
|
from ._resourceHandles._httpResourceHandle import HttpReadResourceHandle, parse_content_range_header
|
|
62
61
|
from ._resourcePath import ResourcePath
|
|
62
|
+
from .utils import get_tempdir
|
|
63
63
|
|
|
64
64
|
if TYPE_CHECKING:
|
|
65
65
|
from .utils import TransactionProtocol
|
|
@@ -112,6 +112,13 @@ def _calc_tmpdir_buffer_size(tmpdir: str) -> int:
|
|
|
112
112
|
return max(10 * fsstats.f_bsize, 256 * 4096)
|
|
113
113
|
|
|
114
114
|
|
|
115
|
+
def _dav_to_http(url: str) -> str:
|
|
116
|
+
"""Convert dav scheme in URL to http scheme."""
|
|
117
|
+
if url.startswith("dav"):
|
|
118
|
+
url = "http" + url.removeprefix("dav")
|
|
119
|
+
return url
|
|
120
|
+
|
|
121
|
+
|
|
115
122
|
class HttpResourcePathConfig:
|
|
116
123
|
"""Configuration class to encapsulate the configurable items used by class
|
|
117
124
|
HttpResourcePath.
|
|
@@ -377,18 +384,7 @@ class HttpResourcePathConfig:
|
|
|
377
384
|
if self._tmpdir_buffersize is not None:
|
|
378
385
|
return self._tmpdir_buffersize
|
|
379
386
|
|
|
380
|
-
|
|
381
|
-
# 'TMPDIR', if defined. Otherwise use the system temporary directory,
|
|
382
|
-
# with a last-resort fallback to the current working directory if
|
|
383
|
-
# nothing else is available.
|
|
384
|
-
tmpdir = None
|
|
385
|
-
for dir in (os.getenv(v) for v in ("LSST_RESOURCES_TMPDIR", "TMPDIR")):
|
|
386
|
-
if dir and os.path.isdir(dir):
|
|
387
|
-
tmpdir = dir
|
|
388
|
-
break
|
|
389
|
-
|
|
390
|
-
if tmpdir is None:
|
|
391
|
-
tmpdir = tempfile.gettempdir()
|
|
387
|
+
tmpdir = get_tempdir()
|
|
392
388
|
|
|
393
389
|
# Compute the block size as 256 blocks of typical size
|
|
394
390
|
# (i.e. 4096 bytes) or 10 times the file system block size,
|
|
@@ -441,7 +437,7 @@ def _get_dav_and_server_headers(path: ResourcePath | str) -> tuple[str | None, s
|
|
|
441
437
|
config = HttpResourcePathConfig()
|
|
442
438
|
with SessionStore(config=config).get(path) as session:
|
|
443
439
|
resp = session.options(
|
|
444
|
-
str(path),
|
|
440
|
+
_dav_to_http(str(path)),
|
|
445
441
|
stream=False,
|
|
446
442
|
timeout=config.timeout,
|
|
447
443
|
)
|
|
@@ -601,7 +597,7 @@ class SessionStore:
|
|
|
601
597
|
def _make_session(self, rpath: ResourcePath) -> requests.Session:
|
|
602
598
|
"""Make a new session configured from values from the environment."""
|
|
603
599
|
session = requests.Session()
|
|
604
|
-
root_uri = str(rpath.root_uri())
|
|
600
|
+
root_uri = _dav_to_http(str(rpath.root_uri()))
|
|
605
601
|
log.debug("Creating new HTTP session for endpoint %s ...", root_uri)
|
|
606
602
|
retries = Retry(
|
|
607
603
|
# Total number of retries to allow. Takes precedence over other
|
|
@@ -661,8 +657,9 @@ class SessionStore:
|
|
|
661
657
|
# from request to request. Systematically persisting connections to
|
|
662
658
|
# those servers may exhaust their capabilities when there are thousands
|
|
663
659
|
# of simultaneous clients.
|
|
660
|
+
scheme = _dav_to_http(rpath.scheme)
|
|
664
661
|
session.mount(
|
|
665
|
-
f"{
|
|
662
|
+
f"{scheme}://",
|
|
666
663
|
HTTPAdapter(
|
|
667
664
|
pool_connections=self._num_pools,
|
|
668
665
|
pool_maxsize=0,
|
|
@@ -1130,7 +1127,7 @@ class HttpResourcePath(ResourcePath):
|
|
|
1130
1127
|
stream = size > 0
|
|
1131
1128
|
with self.data_session as session:
|
|
1132
1129
|
with time_this(log, msg="GET %s", args=(self,)):
|
|
1133
|
-
resp = session.get(self.geturl(), stream=stream, timeout=self._config.timeout)
|
|
1130
|
+
resp = session.get(_dav_to_http(self.geturl()), stream=stream, timeout=self._config.timeout)
|
|
1134
1131
|
|
|
1135
1132
|
if resp.status_code != requests.codes.ok: # 200
|
|
1136
1133
|
raise FileNotFoundError(
|
|
@@ -1351,6 +1348,9 @@ class HttpResourcePath(ResourcePath):
|
|
|
1351
1348
|
or not self.is_webdav_endpoint
|
|
1352
1349
|
or self.server not in HttpResourcePath.SUPPORTED_URL_SIGNERS
|
|
1353
1350
|
):
|
|
1351
|
+
if self.scheme.startswith("dav") and fsspec:
|
|
1352
|
+
# Not webdav so convert to http.
|
|
1353
|
+
return fsspec.url_to_fs(_dav_to_http(self.geturl()))
|
|
1354
1354
|
return super().to_fsspec()
|
|
1355
1355
|
|
|
1356
1356
|
if self.isdir():
|
|
@@ -1520,7 +1520,7 @@ class HttpResourcePath(ResourcePath):
|
|
|
1520
1520
|
# to both the front end and back end servers are closed after the
|
|
1521
1521
|
# download operation is finished.
|
|
1522
1522
|
with self.data_session as session:
|
|
1523
|
-
resp = session.get(self.geturl(), stream=True, timeout=self._config.timeout)
|
|
1523
|
+
resp = session.get(_dav_to_http(self.geturl()), stream=True, timeout=self._config.timeout)
|
|
1524
1524
|
if resp.status_code != requests.codes.ok:
|
|
1525
1525
|
raise FileNotFoundError(
|
|
1526
1526
|
f"Unable to download resource {self}; status: {resp.status_code} {resp.reason}"
|
|
@@ -1633,7 +1633,7 @@ class HttpResourcePath(ResourcePath):
|
|
|
1633
1633
|
for _ in range(max_redirects := 5):
|
|
1634
1634
|
resp = session.request(
|
|
1635
1635
|
method,
|
|
1636
|
-
url,
|
|
1636
|
+
_dav_to_http(url),
|
|
1637
1637
|
data=body,
|
|
1638
1638
|
headers=headers,
|
|
1639
1639
|
stream=False,
|
|
@@ -1791,7 +1791,7 @@ class HttpResourcePath(ResourcePath):
|
|
|
1791
1791
|
src : `HttpResourcePath`
|
|
1792
1792
|
The source of the contents to move to `self`.
|
|
1793
1793
|
"""
|
|
1794
|
-
headers = {"Destination": self.geturl()}
|
|
1794
|
+
headers = {"Destination": _dav_to_http(self.geturl())}
|
|
1795
1795
|
resp = self._send_webdav_request(method, url=src.geturl(), headers=headers, session=self.data_session)
|
|
1796
1796
|
if resp.status_code in (requests.codes.created, requests.codes.no_content):
|
|
1797
1797
|
return
|
|
@@ -1898,7 +1898,7 @@ class HttpResourcePath(ResourcePath):
|
|
|
1898
1898
|
if self._config.send_expect_on_put or self.server == "dcache":
|
|
1899
1899
|
headers["Expect"] = "100-continue"
|
|
1900
1900
|
|
|
1901
|
-
url = self.geturl()
|
|
1901
|
+
url = _dav_to_http(self.geturl())
|
|
1902
1902
|
|
|
1903
1903
|
# Use the session as a context manager to ensure the underlying
|
|
1904
1904
|
# connections are closed after finishing uploading the data.
|
lsst/resources/utils.py
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
-
__all__ = ("NoTransaction", "TransactionProtocol", "os2posix", "posix2os")
|
|
14
|
+
__all__ = ("NoTransaction", "TransactionProtocol", "get_tempdir", "os2posix", "posix2os")
|
|
15
15
|
|
|
16
16
|
import contextlib
|
|
17
17
|
import logging
|
|
@@ -21,6 +21,7 @@ import shutil
|
|
|
21
21
|
import stat
|
|
22
22
|
import tempfile
|
|
23
23
|
from collections.abc import Callable, Iterator
|
|
24
|
+
from functools import cache
|
|
24
25
|
from pathlib import Path, PurePath, PurePosixPath
|
|
25
26
|
from typing import Any, Protocol
|
|
26
27
|
|
|
@@ -93,6 +94,35 @@ def posix2os(posix: PurePath | str) -> str:
|
|
|
93
94
|
return os.path.join(*paths)
|
|
94
95
|
|
|
95
96
|
|
|
97
|
+
@cache
|
|
98
|
+
def get_tempdir() -> str:
|
|
99
|
+
"""Get POSIX path to temporary directory.
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
tmpdir : `str`
|
|
104
|
+
Path to the default temporary directory location.
|
|
105
|
+
|
|
106
|
+
Notes
|
|
107
|
+
-----
|
|
108
|
+
Uses the value of environment variables ``LSST_RESOURCES_TMPDIR`` or
|
|
109
|
+
``TMPDIR``, if defined. Otherwise use the system temporary directory,
|
|
110
|
+
with a last-resort fallback to the current working directory if
|
|
111
|
+
nothing else is available.
|
|
112
|
+
"""
|
|
113
|
+
tmpdir = None
|
|
114
|
+
# $TMPDIR is also checked with getttempdir() below.
|
|
115
|
+
for dir in (os.getenv(v) for v in ("LSST_RESOURCES_TMPDIR", "TMPDIR")):
|
|
116
|
+
if dir and os.path.isdir(dir):
|
|
117
|
+
tmpdir = dir
|
|
118
|
+
break
|
|
119
|
+
|
|
120
|
+
if tmpdir is None:
|
|
121
|
+
tmpdir = tempfile.gettempdir()
|
|
122
|
+
|
|
123
|
+
return tmpdir
|
|
124
|
+
|
|
125
|
+
|
|
96
126
|
class NoTransaction:
|
|
97
127
|
"""A simple emulation of the
|
|
98
128
|
`~lsst.daf.butler.core.datastore.DatastoreTransaction` class.
|
lsst/resources/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = ["__version__"]
|
|
2
|
-
__version__ = "29.2025.
|
|
2
|
+
__version__ = "29.2025.1500"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lsst-resources
|
|
3
|
-
Version: 29.2025.
|
|
3
|
+
Version: 29.2025.1500
|
|
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: BSD 3-Clause License
|
|
@@ -1,9 +1,9 @@
|
|
|
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=xTVyDHD-UHlF5FeDvSXXnsmOuoSFnORZD_wMksxiFfA,64926
|
|
4
4
|
lsst/resources/file.py,sha256=-jPuoHvTEtx5tnDyNkfwhWAyX0cTwkuMd-JvJn9EGdE,23226
|
|
5
5
|
lsst/resources/gs.py,sha256=Lpo5GAzH7R7HG8E5RMGOdP4j4hjWJn-k6M3OXj0nHQM,12783
|
|
6
|
-
lsst/resources/http.py,sha256=
|
|
6
|
+
lsst/resources/http.py,sha256=JW3cBe4MERyjopFKkELui1BRr4b4Mkgp0Iqt9YFIxuc,88227
|
|
7
7
|
lsst/resources/location.py,sha256=x3Tq0x5o1OXYmZDxYBenUG1N71wtDhnjVAr3s2ZEiu8,7937
|
|
8
8
|
lsst/resources/mem.py,sha256=VOWh7XxJPfqKcFdLZSjKEAfORQ2AHZHpxmjT8LniV60,1008
|
|
9
9
|
lsst/resources/packageresource.py,sha256=vnfeRlpVwpC5cDQZE6Lnh8EH6oZy1sH2vLz9ONYjJ4k,6817
|
|
@@ -12,17 +12,17 @@ lsst/resources/s3.py,sha256=wrOMdFWltxpGEWeL--kPCbk5Le_viCIsEn4lOPZbXhM,24124
|
|
|
12
12
|
lsst/resources/s3utils.py,sha256=cKJ9GWHETHhn1djezyikWwAaw4k1B3hFvfif96THHDQ,14355
|
|
13
13
|
lsst/resources/schemeless.py,sha256=GfJcKzZ0XIeepfQdW4HPZWiZlSp_ej0SEtSiJTrDUQs,10666
|
|
14
14
|
lsst/resources/tests.py,sha256=MLB8hERKuNredzzg3Qq9M_U7IesV3xrbcjFwKuMp3Ok,43513
|
|
15
|
-
lsst/resources/utils.py,sha256=
|
|
16
|
-
lsst/resources/version.py,sha256=
|
|
15
|
+
lsst/resources/utils.py,sha256=IHVrOdj0szNWxiXk-jbZu1RhTR8WXks1vI9JCpBxeBA,6706
|
|
16
|
+
lsst/resources/version.py,sha256=altncYankWkwG1F2OVHhPl0np72lUhdVRAOSqBtd-kc,55
|
|
17
17
|
lsst/resources/_resourceHandles/__init__.py,sha256=zOcZ8gVEBdAWcHJaZabA8Vdq-wAVcxjbmA_1b1IWM6M,76
|
|
18
18
|
lsst/resources/_resourceHandles/_baseResourceHandle.py,sha256=lQwxDOmFUNJndTxsjpz-HxrQBL0L-z4aXQocHdOEI7c,4676
|
|
19
19
|
lsst/resources/_resourceHandles/_fileResourceHandle.py,sha256=A7_WQPzD0ZlOzNmaI_TPdZybrNxrXPkNHWVla3UFxfs,3676
|
|
20
|
-
lsst/resources/_resourceHandles/_httpResourceHandle.py,sha256=
|
|
20
|
+
lsst/resources/_resourceHandles/_httpResourceHandle.py,sha256=JRjpE-ZQfgKX5OyVLulIbzW38FdhovcoOd1D4rhb5vk,10900
|
|
21
21
|
lsst/resources/_resourceHandles/_s3ResourceHandle.py,sha256=NkDmPb9bm_zMvr6mMnb-tBmqJDt0yUJrt2gZXR8l7ok,12923
|
|
22
|
-
lsst_resources-29.2025.
|
|
23
|
-
lsst_resources-29.2025.
|
|
24
|
-
lsst_resources-29.2025.
|
|
25
|
-
lsst_resources-29.2025.
|
|
26
|
-
lsst_resources-29.2025.
|
|
27
|
-
lsst_resources-29.2025.
|
|
28
|
-
lsst_resources-29.2025.
|
|
22
|
+
lsst_resources-29.2025.1500.dist-info/licenses/COPYRIGHT,sha256=yazVsoMmFwhiw5itGrdT4YPmXbpsQyUFjlpOyZIa77M,148
|
|
23
|
+
lsst_resources-29.2025.1500.dist-info/licenses/LICENSE,sha256=7wrtgl8meQ0_RIuv2TjIKpAnNrl-ODH-QLwyHe9citI,1516
|
|
24
|
+
lsst_resources-29.2025.1500.dist-info/METADATA,sha256=8tmxas_i8S1F0lwXkFr7MwlERU1h1TArUW-xUqp4FwE,2237
|
|
25
|
+
lsst_resources-29.2025.1500.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
26
|
+
lsst_resources-29.2025.1500.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
|
|
27
|
+
lsst_resources-29.2025.1500.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
28
|
+
lsst_resources-29.2025.1500.dist-info/RECORD,,
|
|
File without changes
|
{lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/licenses/COPYRIGHT
RENAMED
|
File without changes
|
{lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{lsst_resources-29.2025.1300.dist-info → lsst_resources-29.2025.1500.dist-info}/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|