Skip to content

Commit

Permalink
GET with '?data_source=<name>' works.
Browse files Browse the repository at this point in the history
  • Loading branch information
danielballan committed Feb 25, 2024
1 parent 0b4a4b4 commit d5ac0a8
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 81 deletions.
45 changes: 23 additions & 22 deletions tiled/catalog/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,18 @@ def __init__(
self.ancestors = node.ancestors
self.key = node.key
self.access_policy = access_policy
self.data_source_name = data_source_name
self.startup_tasks = [self.startup]
self.shutdown_tasks = [self.shutdown]
if data_source_name is not None:
for data_source in self.data_sources:
if data_source_name == data_source.name:
self.data_source_structure_family = data_source.structure_family
break
else:
raise ValueError(f"No DataSource named {data_source_name} on this node")
self.data_source = data_source
elif len(self.data_sources) == 1:
(self.data_source,) = self.data_sources

def metadata(self):
return self.node.metadata_
Expand Down Expand Up @@ -443,30 +452,20 @@ async def lookup_adapter(
)

async def get_adapter(self):
num_data_sources = len(self.data_sources)
if self.data_source_name is not None:
for data_source in self.data_sources:
if self.data_source_name == data_source.name:
break
else:
raise ValueError(
f"No DataSource named {self.data_source_name} on this node"
)
elif num_data_sources > 1:
raise ValueError(
"A data_source_name is required because this node "
f"has {num_data_sources} data sources"
if (self.structure_family == StructureFamily.union) and not self.data_source:
raise RuntimeError(
"A data_source_name must be specified at construction time."
)
else:
(data_source,) = self.data_sources
try:
adapter_factory = self.context.adapters_by_mimetype[data_source.mimetype]
adapter_factory = self.context.adapters_by_mimetype[
self.data_source.mimetype
]
except KeyError:
raise RuntimeError(
f"Server configuration has no adapter for mimetype {data_source.mimetype!r}"
f"Server configuration has no adapter for mimetype {self.data_source.mimetype!r}"
)
parameters = collections.defaultdict(list)
for asset in data_source.assets:
for asset in self.data_source.assets:
if asset.parameter is None:
continue
scheme = urlparse(asset.data_uri).scheme
Expand Down Expand Up @@ -495,10 +494,10 @@ async def get_adapter(self):
else:
parameters[asset.parameter].append(asset.data_uri)
adapter_kwargs = dict(parameters)
adapter_kwargs.update(data_source.parameters)
adapter_kwargs.update(self.data_source.parameters)
adapter_kwargs["specs"] = self.node.specs
adapter_kwargs["metadata"] = self.node.metadata_
adapter_kwargs["structure"] = data_source.structure
adapter_kwargs["structure"] = self.data_source.structure
adapter_kwargs["access_policy"] = self.access_policy
adapter = await anyio.to_thread.run_sync(
partial(adapter_factory, **adapter_kwargs)
Expand Down Expand Up @@ -1007,7 +1006,9 @@ async def write_partition(self, *args, **kwargs):


class CatalogUnionAdapter(CatalogNodeAdapter):
# This does not support direct reading or writing.
# def get(self, key):
# for data_source in data_sources:
# if data_source.name ==

async def read(self, *args, **kwargs):
return await ensure_awaitable((await self.get_adapter()).read, *args, **kwargs)
Expand Down
34 changes: 32 additions & 2 deletions tiled/server/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
serialization_registry as default_serialization_registry,
)
from ..query_registration import query_registry as default_query_registry
from ..structures.core import StructureFamily
from ..validation_registration import validation_registry as default_validation_registry
from .authentication import get_current_principal, get_session_state
from .core import NoEntry
Expand Down Expand Up @@ -48,7 +49,7 @@ def get_root_tree():
)


def SecureEntry(scopes):
def SecureEntry(scopes, structure_families=None):
async def inner(
path: str,
request: Request,
Expand Down Expand Up @@ -119,7 +120,36 @@ async def inner(
)
except NoEntry:
raise HTTPException(status_code=404, detail=f"No such entry: {path_parts}")
return entry
# Fast path for the common successful case
if (structure_families is None) or (
entry.structure_family in structure_families
):
return entry
# Handle union structure_family
if entry.structure_family == StructureFamily.union:
if not data_source:
raise HTTPException(
status_code=400, detail="A data_source query parameter is required."
)
if entry.data_source.structure_family in structure_families:
return entry
raise HTTPException(
status_code=404,
detail=(
f"The data source named {data_source} backing the node "
f"at {path} has structure family {entry.data_source.structure_family} "
"and this endpoint is compatible with structure families "
f"{structure_families}"
),
)
raise HTTPException(
status_code=404,
detail=(
f"The node at {path} has structure family {entry.structure_family} "
"and this endpoint is compatible with structure families "
f"{structure_families}"
),
)

return Security(inner, scopes=scopes)

Expand Down
Loading

0 comments on commit d5ac0a8

Please sign in to comment.