Coverage for python/lsst/daf/butler/remote_butler/_get.py: 0%
29 statements
« prev ^ index » next coverage.py v7.15.3, created at 2026-08-07 09:51 +0000
« prev ^ index » next coverage.py v7.15.3, created at 2026-08-07 09:51 +0000
1from typing import Any
3from pydantic import AnyHttpUrl
5from lsst.resources import ResourcePath
6from lsst.resources.http import HttpResourcePath
8from .._dataset_ref import DatasetRef
9from .._location import Location
10from ..datastore.cache_manager import AbstractDatastoreCacheManager, DatastoreDisabledCacheManager
11from ..datastore.stored_file_info import StoredFileInfo
12from ..datastores.file_datastore.get import (
13 DatasetLocationInformation,
14 Mapping,
15 generate_datastore_get_information,
16 get_dataset_as_python_object_from_get_info,
17)
18from .authentication.interface import RemoteButlerAuthenticationProvider
19from .server_models import FileAuthenticationMode, FileInfoPayload, FileInfoRecord
22def get_dataset_as_python_object(
23 written_ref: DatasetRef,
24 read_ref: DatasetRef,
25 payload: FileInfoPayload,
26 *,
27 auth: RemoteButlerAuthenticationProvider,
28 parameters: Mapping[str, Any] | None,
29 cache_manager: AbstractDatastoreCacheManager | None = None,
30) -> Any:
31 """Retrieve an artifact from storage and return it as a Python object.
33 Parameters
34 ----------
35 written_ref : `DatasetRef`
36 Metadata about this artifact using the `StorageClass` that the file
37 was written with. This is the ref given to the `Formatter`, so that
38 it always sees the write `StorageClass` regardless of any read-time
39 override, matching the behavior of `DirectButler`.
40 read_ref : `DatasetRef`
41 Metadata about this artifact using the `StorageClass` that the caller
42 wants returned. This differs from ``written_ref`` only in its
43 `StorageClass` when a read-time override has been requested. The two
44 refs always share the same dataset type name, so they either both
45 refer to a component or both refer to a composite; any component
46 override requested by the caller is applied before the read
47 `StorageClass` override is derived.
48 payload : `FileInfoPayload`
49 Pre-processed information about each file associated with this
50 artifact.
51 auth : `RemoteButlerAuthenticationProvider`
52 Provides authentication headers for HTTP service hosting the artifact
53 files.
54 parameters : `~collections.abc.Mapping` [`str`, `typing.Any`]
55 `StorageClass` and `Formatter` parameters to be used when converting
56 the artifact to a Python object.
57 cache_manager : `AbstractDatastoreCacheManager` or `None`, optional
58 Cache manager to use. If `None` the cache is disabled.
60 Returns
61 -------
62 python_object : `typing.Any`
63 The retrieved artifact, converted to a Python object.
64 """
65 fileLocations = [_to_dataset_location_information(file_info, auth) for file_info in payload.file_info]
67 # The Formatter is constructed with the written ref, while the read
68 # StorageClass override travels separately. DirectButler does the same in
69 # ``FileDatastore._prepare_for_direct_get``.
70 datastore_file_info = generate_datastore_get_information(
71 fileLocations,
72 ref=written_ref,
73 readStorageClass=read_ref.datasetType.storageClass,
74 parameters=parameters,
75 )
76 if cache_manager is None:
77 cache_manager = DatastoreDisabledCacheManager()
78 return get_dataset_as_python_object_from_get_info(
79 datastore_file_info, ref=read_ref, parameters=parameters, cache_manager=cache_manager
80 )
83def convert_http_url_to_resource_path(
84 url: AnyHttpUrl, auth: RemoteButlerAuthenticationProvider, auth_mode: FileAuthenticationMode
85) -> ResourcePath:
86 """Convert an HTTP URL to a ResourcePath instance with authentication
87 headers attached.
89 Parameters
90 ----------
91 url : `AnyHttpUrl`
92 URL to convert.
93 auth : `RemoteButlerAuthenticationProvider`
94 Provides authentication headers for the URL.
95 auth_mode : `FileAuthenticationMode`
96 Specifies which authentication headers to use.
97 """
98 if auth_mode == "none":
99 headers = None
100 elif auth_mode == "gafaelfawr":
101 headers = auth.get_server_headers()
102 elif auth_mode == "datastore":
103 headers = auth.get_datastore_headers()
104 else:
105 raise ValueError(f"Unknown authentication type: '{auth_mode}'")
107 return HttpResourcePath.create_http_resource_path(str(url), extra_headers=headers)
110def _to_dataset_location_information(
111 file_info: FileInfoRecord, auth: RemoteButlerAuthenticationProvider
112) -> DatasetLocationInformation:
113 path = convert_http_url_to_resource_path(file_info.url, auth, auth_mode=file_info.auth)
114 return (Location(None, path), StoredFileInfo.from_simple(file_info.datastoreRecords))