Skip to content

Commit

Permalink
resolve dependency circle, add method to get dataset info from server
Browse files Browse the repository at this point in the history
  • Loading branch information
jdroenner committed Dec 11, 2024
1 parent 27d1cfb commit c70d325
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 122 deletions.
5 changes: 3 additions & 2 deletions geoengine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@
SpatialReferenceMismatchException, check_response_for_error, ModificationNotOnLayerDbException, \
InvalidUrlException, MissingFieldInResponseException
from .layers import Layer, LayerCollection, LayerListing, LayerCollectionListing, \
LayerId, LayerCollectionId, LayerProviderId, \
layer_collection, layer
from .ml import register_ml_model, MlModelConfig
from .permissions import add_permission, remove_permission, add_role, remove_role, assign_role, revoke_role, \
ADMIN_ROLE_ID, REGISTERED_USER_ROLE_ID, ANONYMOUS_USER_ROLE_ID, Permission, Resource, UserId, RoleId
ADMIN_ROLE_ID, REGISTERED_USER_ROLE_ID, ANONYMOUS_USER_ROLE_ID, Permission, UserId, RoleId
from .tasks import Task, TaskId
from .types import QueryRectangle, GeoTransform, \
RasterResultDescriptor, Provenance, UnitlessMeasurement, ContinuousMeasurement, \
ClassificationMeasurement, BoundingBox2D, TimeInterval, SpatialResolution, SpatialPartition2D, \
RasterSymbology, VectorSymbology, VectorDataType, VectorResultDescriptor, VectorColumnInfo, \
FeatureDataType, RasterBandDescriptor, DEFAULT_ISO_TIME_FORMAT, RasterColorizer, SingleBandRasterColorizer, \
MultiBandRasterColorizer
from .resource_identifier import LAYER_DB_PROVIDER_ID, LAYER_DB_ROOT_COLLECTION_ID, DatasetName, UploadId, \
LayerId, LayerCollectionId, LayerProviderId, Resource

from .util import clamp_datetime_ms_ns
from .workflow import WorkflowId, Workflow, workflow_by_id, register_workflow, get_quota, update_quota
Expand Down
77 changes: 12 additions & 65 deletions geoengine/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from uuid import UUID
import tempfile
from attr import dataclass
import geoengine_openapi_client.models
import numpy as np
import geopandas as gpd
import geoengine_openapi_client
Expand All @@ -19,6 +20,7 @@
from geoengine.types import Provenance, RasterSymbology, TimeStep, \
TimeStepGranularity, VectorDataType, VectorResultDescriptor, VectorColumnInfo, \
UnitlessMeasurement, FeatureDataType
from geoengine.resource_identifier import Resource, UploadId, DatasetName


class UnixTimeStampType(Enum):
Expand Down Expand Up @@ -256,71 +258,6 @@ def to_api_enum(self) -> geoengine_openapi_client.OgrSourceErrorSpec:
return geoengine_openapi_client.OgrSourceErrorSpec(self.value)


class DatasetName:
'''A wrapper for a dataset id'''

__dataset_name: str

def __init__(self, dataset_name: str) -> None:
self.__dataset_name = dataset_name

@classmethod
def from_response(cls, response: geoengine_openapi_client.CreateDatasetHandler200Response) -> DatasetName:
'''Parse a http response to an `DatasetId`'''
return DatasetName(response.dataset_name)

def __str__(self) -> str:
return self.__dataset_name

def __repr__(self) -> str:
return str(self)

def __eq__(self, other) -> bool:
'''Checks if two dataset ids are equal'''
if not isinstance(other, self.__class__):
return False

return self.__dataset_name == other.__dataset_name # pylint: disable=protected-access

def to_api_dict(self) -> geoengine_openapi_client.CreateDatasetHandler200Response:
return geoengine_openapi_client.CreateDatasetHandler200Response(
dataset_name=str(self.__dataset_name)
)


class UploadId:
'''A wrapper for an upload id'''

__upload_id: UUID

def __init__(self, upload_id: UUID) -> None:
self.__upload_id = upload_id

@classmethod
def from_response(cls, response: geoengine_openapi_client.AddCollection200Response) -> UploadId:
'''Parse a http response to an `UploadId`'''
return UploadId(UUID(response.id))

def __str__(self) -> str:
return str(self.__upload_id)

def __repr__(self) -> str:
return str(self)

def __eq__(self, other) -> bool:
'''Checks if two upload ids are equal'''
if not isinstance(other, self.__class__):
return False

return self.__upload_id == other.__upload_id # pylint: disable=protected-access

def to_api_dict(self) -> geoengine_openapi_client.AddCollection200Response:
'''Converts the upload id to a dict for the api'''
return geoengine_openapi_client.AddCollection200Response(
id=str(self.__upload_id)
)


class AddDatasetProperties():
'''The properties for adding a dataset'''
name: Optional[str]
Expand Down Expand Up @@ -630,3 +567,13 @@ def list_datasets(offset: int = 0,
)

return response


def dataset_info_by_name(dataset_name: DatasetName, timeout: int = 60) -> geoengine_openapi_client.models.Dataset:
'''Delete a dataset. The dataset must be owned by the caller.'''

session = get_session()

with geoengine_openapi_client.ApiClient(session.configuration) as api_client:
datasets_api = geoengine_openapi_client.DatasetsApi(api_client)
return datasets_api.get_dataset_handler(str(dataset_name), _request_timeout=timeout)
19 changes: 7 additions & 12 deletions geoengine/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from enum import auto
from io import StringIO
import os
from typing import Any, Dict, Generic, List, Literal, NewType, Optional, TypeVar, Union, cast, Tuple
from typing import Any, Dict, Generic, List, Literal, Optional, TypeVar, Union, cast, Tuple
from uuid import UUID
import json
from strenum import LowercaseStrEnum
Expand All @@ -16,16 +16,11 @@
from geoengine.error import ModificationNotOnLayerDbException, InputException
from geoengine.tasks import Task, TaskId
from geoengine.types import Symbology
import geoengine.permissions as ge_permissions
from geoengine.permissions import RoleId, Permission, add_permission
from geoengine.workflow import Workflow, WorkflowId
from geoengine.workflow_builder.operators import Operator as WorkflowBuilderOperator

LayerId = NewType('LayerId', str)
LayerCollectionId = NewType('LayerCollectionId', str)
LayerProviderId = NewType('LayerProviderId', UUID)

LAYER_DB_PROVIDER_ID = LayerProviderId(UUID('ce5e84db-cbf9-48a2-9a32-d4b7cc56ea74'))
LAYER_DB_ROOT_COLLECTION_ID = LayerCollectionId('05102bb3-a855-4a37-8a8a-30026a91fef1')
from geoengine.resource_identifier import LayerCollectionId, LayerId, LayerProviderId, \
LAYER_DB_PROVIDER_ID, Resource


class LayerCollectionListingType(LowercaseStrEnum):
Expand Down Expand Up @@ -462,7 +457,7 @@ def get_or_create_unique_collection(
collection_name: str,
create_collection_description: Optional[str] = None,
delete_existing_with_same_name: bool = False,
create_permissions_tuples: Optional[List[Tuple[ge_permissions.RoleId, ge_permissions.Permission]]] = None
create_permissions_tuples: Optional[List[Tuple[RoleId, Permission]]] = None
) -> LayerCollection:
'''
Get a unique child by name OR if it does not exist create it.
Expand All @@ -483,11 +478,11 @@ def get_or_create_unique_collection(
if len(existing_collections) == 0:
new_desc = create_collection_description if create_collection_description is not None else collection_name
new_collection = parent_collection.add_collection(collection_name, new_desc)
new_ressource = ge_permissions.Resource.from_layer_collection_id(new_collection)
new_ressource = Resource.from_layer_collection_id(new_collection)

if create_permissions_tuples is not None:
for (role, perm) in create_permissions_tuples:
ge_permissions.add_permission(role, new_ressource, perm)
add_permission(role, new_ressource, perm)
parent_collection = parent_collection.reload()
existing_collections = parent_collection.get_items_by_name(collection_name)

Expand Down
45 changes: 2 additions & 43 deletions geoengine/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
from enum import Enum

import ast
from typing import Dict, Literal, Any
from typing import Dict
from uuid import UUID

import geoengine_openapi_client

from geoengine.auth import get_session
from geoengine.datasets import DatasetName
from geoengine.resource_identifier import Resource
from geoengine.error import GeoEngineException
import geoengine.layers as ge_layers


class RoleId:
Expand Down Expand Up @@ -79,46 +78,6 @@ def __repr__(self) -> str:
return repr(self.__user_id)


class Resource:
'''A wrapper for a resource id'''

def __init__(self, resource_type: Literal['dataset', 'layer', 'layerCollection'],
resource_id: str) -> None:
'''Create a resource id'''
self.__type = resource_type
self.__id = resource_id

@classmethod
def from_layer_id(cls, layer_id: ge_layers.LayerId) -> Resource:
'''Create a resource id from a layer id'''
return Resource('layer', str(layer_id))

@classmethod
def from_layer_collection_id(cls, layer_collection_id: ge_layers.LayerCollectionId) -> Resource:
'''Create a resource id from a layer collection id'''
return Resource('layerCollection', str(layer_collection_id))

@classmethod
def from_dataset_name(cls, dataset_name: DatasetName) -> Resource:
'''Create a resource id from a dataset id'''
return Resource('dataset', str(dataset_name))

def to_api_dict(self) -> geoengine_openapi_client.Resource:
'''Convert to a dict for the API'''
inner: Any = None

if self.__type == "layer":
inner = geoengine_openapi_client.LayerResource(type="layer", id=self.__id)
elif self.__type == "layerCollection":
inner = geoengine_openapi_client.LayerCollectionResource(type="layerCollection", id=self.__id)
elif self.__type == "project":
inner = geoengine_openapi_client.ProjectResource(type="project", id=self.__id)
elif self.__type == "dataset":
inner = geoengine_openapi_client.DatasetResource(type="dataset", id=self.__id)

return geoengine_openapi_client.Resource(inner)


class Permission(str, Enum):
'''A permission'''
READ = 'Read'
Expand Down
118 changes: 118 additions & 0 deletions geoengine/resource_identifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
''' Types that identify a ressource in the Geo Engine'''

from __future__ import annotations
from typing import Any, Literal, NewType
from uuid import UUID
import geoengine_openapi_client

LayerId = NewType('LayerId', str)
LayerCollectionId = NewType('LayerCollectionId', str)
LayerProviderId = NewType('LayerProviderId', UUID)

LAYER_DB_PROVIDER_ID = LayerProviderId(UUID('ce5e84db-cbf9-48a2-9a32-d4b7cc56ea74'))
LAYER_DB_ROOT_COLLECTION_ID = LayerCollectionId('05102bb3-a855-4a37-8a8a-30026a91fef1')


class DatasetName:
'''A wrapper for a dataset id'''

__dataset_name: str

def __init__(self, dataset_name: str) -> None:
self.__dataset_name = dataset_name

@classmethod
def from_response(cls, response: geoengine_openapi_client.CreateDatasetHandler200Response) -> DatasetName:
'''Parse a http response to an `DatasetId`'''
return DatasetName(response.dataset_name)

def __str__(self) -> str:
return self.__dataset_name

def __repr__(self) -> str:
return str(self)

def __eq__(self, other) -> bool:
'''Checks if two dataset ids are equal'''
if not isinstance(other, self.__class__):
return False

return self.__dataset_name == other.__dataset_name # pylint: disable=protected-access

def to_api_dict(self) -> geoengine_openapi_client.CreateDatasetHandler200Response:
return geoengine_openapi_client.CreateDatasetHandler200Response(
dataset_name=str(self.__dataset_name)
)


class UploadId:
'''A wrapper for an upload id'''

__upload_id: UUID

def __init__(self, upload_id: UUID) -> None:
self.__upload_id = upload_id

@classmethod
def from_response(cls, response: geoengine_openapi_client.AddCollection200Response) -> UploadId:
'''Parse a http response to an `UploadId`'''
return UploadId(UUID(response.id))

def __str__(self) -> str:
return str(self.__upload_id)

def __repr__(self) -> str:
return str(self)

def __eq__(self, other) -> bool:
'''Checks if two upload ids are equal'''
if not isinstance(other, self.__class__):
return False

return self.__upload_id == other.__upload_id # pylint: disable=protected-access

def to_api_dict(self) -> geoengine_openapi_client.AddCollection200Response:
'''Converts the upload id to a dict for the api'''
return geoengine_openapi_client.AddCollection200Response(
id=str(self.__upload_id)
)


class Resource:
'''A wrapper for a resource id'''

def __init__(self, resource_type: Literal['dataset', 'layer', 'layerCollection'],
resource_id: str) -> None:
'''Create a resource id'''
self.__type = resource_type
self.__id = resource_id

@classmethod
def from_layer_id(cls, layer_id: LayerId) -> Resource:
'''Create a resource id from a layer id'''
return Resource('layer', str(layer_id))

@classmethod
def from_layer_collection_id(cls, layer_collection_id: LayerCollectionId) -> Resource:
'''Create a resource id from a layer collection id'''
return Resource('layerCollection', str(layer_collection_id))

@classmethod
def from_dataset_name(cls, dataset_name: DatasetName) -> Resource:
'''Create a resource id from a dataset id'''
return Resource('dataset', str(dataset_name))

def to_api_dict(self) -> geoengine_openapi_client.Resource:
'''Convert to a dict for the API'''
inner: Any = None

if self.__type == "layer":
inner = geoengine_openapi_client.LayerResource(type="layer", id=self.__id)
elif self.__type == "layerCollection":
inner = geoengine_openapi_client.LayerCollectionResource(type="layerCollection", id=self.__id)
elif self.__type == "project":
inner = geoengine_openapi_client.ProjectResource(type="project", id=self.__id)
elif self.__type == "dataset":
inner = geoengine_openapi_client.DatasetResource(type="dataset", id=self.__id)

return geoengine_openapi_client.Resource(inner)

0 comments on commit c70d325

Please sign in to comment.