geoservercloud 0.7.2.dev1__tar.gz → 0.7.2.dev10__tar.gz
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.
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/PKG-INFO +1 -1
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/geoservercloud.py +3 -0
- geoservercloud-0.7.2.dev10/geoservercloud/models/common.py +376 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/featuretype.py +22 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/pyproject.toml +1 -1
- geoservercloud-0.7.2.dev1/geoservercloud/models/common.py +0 -208
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/LICENSE +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/README.md +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/.gitignore +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/README.md +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/cli.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/compose/example.compose.yaml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/compose/geodatabase/001_create_schemas.sql +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/config.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/data/sampledata.tgz +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/example.config.yaml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/conftest.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_None_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language__expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_de_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_fr_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/default_value/language_it_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language_None_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language__expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/default_locale/no_default_value/language_it_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_None_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language__expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_de_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_fr_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/default_value/language_it_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language_None_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language__expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/labels/no_default_locale/no_default_value/language_it_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/localized_labels.sld +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/localized_no_default.sld +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/i18n/localized_with_default.sld +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/wfs/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/wfs/wfs_delete_payload.xml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/wfs/wfs_insert_payload.xml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/wms/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/resources/wms/getmap_expected.png +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_cascaded_stores.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_cog.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_datastore.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_gwc.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_i18n.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_imagemosaic.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_imagemosaic_cog.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_wfs.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_wms.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/test_workspace.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/utils.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/geoservercloudsync.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/gridsets/2056.xml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/gridsets/21781.xml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/gridsets/3857.xml +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/abstractlayer.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/coverage.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/coverages.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/coveragestore.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/datastore.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/datastores.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/featuretypes.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/layer.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/layergroup.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/layergroups.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/resourcedirectory.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/style.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/styles.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/wmslayer.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/wmssettings.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/wmsstore.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/workspace.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/workspaces.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/__init__.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/owsservice.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/restclient.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/restlogger.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/restservice.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/templates.py +0 -0
- {geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/utils.py +0 -0
|
@@ -7,6 +7,7 @@ from owslib.wmts import WebMapTileService
|
|
|
7
7
|
from requests import Response
|
|
8
8
|
|
|
9
9
|
from geoservercloud import utils
|
|
10
|
+
from geoservercloud.models.common import TimeDimensionInfo
|
|
10
11
|
from geoservercloud.models.coverage import Coverage
|
|
11
12
|
from geoservercloud.models.coveragestore import CoverageStore
|
|
12
13
|
from geoservercloud.models.datastore import PostGisDataStore
|
|
@@ -639,6 +640,7 @@ class GeoServerCloud:
|
|
|
639
640
|
attributes: dict | None = None,
|
|
640
641
|
epsg: int = 4326,
|
|
641
642
|
keywords: list[str] = [],
|
|
643
|
+
time_dimension_info: TimeDimensionInfo | None = None,
|
|
642
644
|
) -> tuple[str, int]:
|
|
643
645
|
"""
|
|
644
646
|
Create a feature type or update it if it already exist.
|
|
@@ -660,6 +662,7 @@ class GeoServerCloud:
|
|
|
660
662
|
attributes=utils.convert_attributes(attributes) if attributes else None,
|
|
661
663
|
epsg_code=epsg,
|
|
662
664
|
keywords=keywords,
|
|
665
|
+
time_dimension_info=time_dimension_info,
|
|
663
666
|
)
|
|
664
667
|
return self.rest_service.create_feature_type(feature_type=feature_type)
|
|
665
668
|
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, Generic, TypeVar
|
|
4
|
+
|
|
5
|
+
T = TypeVar("T")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseModel:
|
|
9
|
+
@classmethod
|
|
10
|
+
def from_get_response_payload(cls, content: dict):
|
|
11
|
+
raise NotImplementedError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EntityModel(BaseModel):
|
|
15
|
+
def asdict(self) -> dict[str, Any]:
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
|
|
18
|
+
def post_payload(self) -> dict[str, Any]:
|
|
19
|
+
raise NotImplementedError
|
|
20
|
+
|
|
21
|
+
def put_payload(self) -> dict[str, Any]:
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def add_items_to_dict(content: dict, items: dict[str, Any]) -> dict[Any, Any]:
|
|
26
|
+
for key, value in items.items():
|
|
27
|
+
content = EntityModel.add_item_to_dict(content, key, value)
|
|
28
|
+
return content
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def add_item_to_dict(content: dict, key: str, value: Any) -> dict[Any, Any]:
|
|
32
|
+
if value is not None:
|
|
33
|
+
content[key] = value
|
|
34
|
+
return content
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ListModel(BaseModel, Generic[T]):
|
|
38
|
+
"""Base class for list-based models with configurable list and item names."""
|
|
39
|
+
|
|
40
|
+
# These should be overridden in subclasses
|
|
41
|
+
_list_key: str = "" # e.g., "workspaces", "dataStores"
|
|
42
|
+
_item_key: str = "" # e.g., "workspace", "dataStore"
|
|
43
|
+
|
|
44
|
+
def __init__(self, items: list[T] | None = None) -> None:
|
|
45
|
+
self._items: list[T] = items or []
|
|
46
|
+
|
|
47
|
+
def aslist(self) -> list[T]:
|
|
48
|
+
"""Return the list of items."""
|
|
49
|
+
return self._items
|
|
50
|
+
|
|
51
|
+
def find(self, name: str) -> T | None:
|
|
52
|
+
"""Find an item by name (assumes items are dicts with 'name' key)."""
|
|
53
|
+
for item in self._items:
|
|
54
|
+
if isinstance(item, dict) and item.get("name") == name:
|
|
55
|
+
return item
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def from_get_response_payload(cls, content: dict):
|
|
60
|
+
"""Create instance from API response payload."""
|
|
61
|
+
if not cls._list_key or not cls._item_key:
|
|
62
|
+
raise NotImplementedError("Subclasses must define _list_key and _item_key")
|
|
63
|
+
|
|
64
|
+
data = content.get(cls._list_key)
|
|
65
|
+
if not data:
|
|
66
|
+
return cls()
|
|
67
|
+
|
|
68
|
+
items = data[cls._item_key]
|
|
69
|
+
return cls(items)
|
|
70
|
+
|
|
71
|
+
def __repr__(self) -> str:
|
|
72
|
+
"""String representation of the list."""
|
|
73
|
+
return json.dumps(self._items, indent=4)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ReferencedObjectModel(BaseModel):
|
|
77
|
+
def __init__(self, name: str, href: str | None = None):
|
|
78
|
+
self.name: str = name
|
|
79
|
+
self.href: str | None = href
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def from_get_response_payload(cls, content: dict):
|
|
83
|
+
cls.name = content["name"]
|
|
84
|
+
cls.href = content["href"]
|
|
85
|
+
|
|
86
|
+
def asdict(self) -> dict[str, str]:
|
|
87
|
+
return EntityModel.add_item_to_dict({"name": self.name}, "href", self.href)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class KeyDollarListDict(dict):
|
|
91
|
+
|
|
92
|
+
key_prefix: str = "@key"
|
|
93
|
+
value_prefix: str = "$"
|
|
94
|
+
|
|
95
|
+
def __init__(
|
|
96
|
+
self,
|
|
97
|
+
input_list: list | None = None,
|
|
98
|
+
input_dict: dict | None = None,
|
|
99
|
+
*args,
|
|
100
|
+
**kwargs
|
|
101
|
+
):
|
|
102
|
+
super().__init__(*args, **kwargs)
|
|
103
|
+
if input_list:
|
|
104
|
+
self.deserialize(input_list)
|
|
105
|
+
if input_dict:
|
|
106
|
+
self.update(input_dict)
|
|
107
|
+
|
|
108
|
+
def deserialize(self, input_list: list):
|
|
109
|
+
for item in input_list:
|
|
110
|
+
key = item[self.key_prefix]
|
|
111
|
+
if self.value_prefix in item:
|
|
112
|
+
value = item[self.value_prefix]
|
|
113
|
+
else:
|
|
114
|
+
value = None
|
|
115
|
+
super().__setitem__(key, value)
|
|
116
|
+
|
|
117
|
+
def serialize(self):
|
|
118
|
+
return [
|
|
119
|
+
{self.key_prefix: key, self.value_prefix: value}
|
|
120
|
+
for key, value in self.items()
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
def __repr__(self) -> str:
|
|
124
|
+
return str(self.serialize())
|
|
125
|
+
|
|
126
|
+
def __str__(self):
|
|
127
|
+
return json.dumps(self.serialize())
|
|
128
|
+
|
|
129
|
+
def update(self, other: dict): # type: ignore
|
|
130
|
+
for key, value in other.items():
|
|
131
|
+
super().__setitem__(key, value)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class I18N:
|
|
135
|
+
"""
|
|
136
|
+
Geoserver handles internationalization with 2 possible (mutually exclusive) keys in the rest payload:
|
|
137
|
+
either:
|
|
138
|
+
- [key: string]
|
|
139
|
+
or
|
|
140
|
+
- [internationalKey: dictionary]
|
|
141
|
+
|
|
142
|
+
example:
|
|
143
|
+
a) as key: string we get {"title": "Test Title"}
|
|
144
|
+
b) as key: dict we get {"internationalTitle": {"en": "Test Title", "es": "Título de Prueba"}}
|
|
145
|
+
|
|
146
|
+
This class gives a layer of abstraction to handle both cases.
|
|
147
|
+
|
|
148
|
+
Usage:
|
|
149
|
+
Call the class by adding both possible keys in a tuple and the value.
|
|
150
|
+
|
|
151
|
+
Parameters:
|
|
152
|
+
keys: tuple[str, str] example : ("title", "internationalTitle")
|
|
153
|
+
value: str | dict example: "Test Title" | {"en": "Test Title", "es": "Título de Prueba"}
|
|
154
|
+
|
|
155
|
+
Example:
|
|
156
|
+
|
|
157
|
+
my_i18n = I18N(("title", "internationalTitle"), "Test Title")
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def __init__(self, keys: tuple[str, Any], value: str | dict) -> None:
|
|
161
|
+
self._str_key = keys[0]
|
|
162
|
+
self._i18n_key = keys[1]
|
|
163
|
+
self._value = value
|
|
164
|
+
if isinstance(value, str):
|
|
165
|
+
self._content = {self.str_key: self._value}
|
|
166
|
+
elif isinstance(value, dict):
|
|
167
|
+
self._content = {self._i18n_key: self._value}
|
|
168
|
+
else:
|
|
169
|
+
raise ValueError("Invalid value type")
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def str_key(self):
|
|
173
|
+
return self._str_key
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def i18n_key(self):
|
|
177
|
+
return self._i18n_key
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def value(self):
|
|
181
|
+
return self._value
|
|
182
|
+
|
|
183
|
+
def asdict(self):
|
|
184
|
+
return self._content
|
|
185
|
+
|
|
186
|
+
def __repr__(self):
|
|
187
|
+
return json.dumps(self._content, indent=4)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class MetadataLink:
|
|
191
|
+
def __init__(self, url: str, metadata_type="TC211", mime_type: str = "text/xml"):
|
|
192
|
+
self.url: str = url
|
|
193
|
+
self.metadata_type: str = metadata_type
|
|
194
|
+
self.type: str = mime_type
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def from_get_response_payload(cls, content: dict):
|
|
198
|
+
return cls(
|
|
199
|
+
url=content["content"],
|
|
200
|
+
metadata_type=content["metadataType"],
|
|
201
|
+
mime_type=content["type"],
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
def asdict(self) -> dict[str, str]:
|
|
205
|
+
return {
|
|
206
|
+
"content": self.url,
|
|
207
|
+
"metadataType": self.metadata_type,
|
|
208
|
+
"type": self.type,
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class TimeDimensionInfo(BaseModel):
|
|
213
|
+
"""
|
|
214
|
+
This class represents the required configuration needed for the dimension "time" to create a
|
|
215
|
+
time enabled :py:class:`geoservercloud.models.FeatureType`
|
|
216
|
+
|
|
217
|
+
Parameters
|
|
218
|
+
----------
|
|
219
|
+
attribute: str
|
|
220
|
+
Name of the attribute that will be used for the temporal dimension
|
|
221
|
+
presentation: str
|
|
222
|
+
How the time dimension will be represented in the capabilities document
|
|
223
|
+
Possible values are: LIST, DISCRETE_INTERVAL, CONTINUOUS_INTERVAL
|
|
224
|
+
This property will be resolved as a :py:class:`geoservercloud.models.common.Presentation` enum.
|
|
225
|
+
end_attribute: str | None, optional
|
|
226
|
+
Defines the attribute that will be used to define the end of the temporal interval.
|
|
227
|
+
start_value: str | None, optional
|
|
228
|
+
If presentation is DISCRETE_INTERVAL or CONTINUOUS_INTERVAL, this attribute will be used to define the start of the temporal interval.
|
|
229
|
+
end_value: str | None, optional
|
|
230
|
+
If presentation is DISCRETE_INTERVAL or CONTINUOUS_INTERVAL, this attribute will be used to define the end of the temporal interval.
|
|
231
|
+
resolution: int | None, optional
|
|
232
|
+
If presentation is DISCRETE_INTERVAL, this attribute will be used to define the resolution of the temporal interval.
|
|
233
|
+
default_value_strategy: str | None, optional
|
|
234
|
+
Defines which value of the attribute will be used as a default
|
|
235
|
+
Possible values are: MAXIMUM, MINIMUM, NEAREST, FIXED, EMPTY
|
|
236
|
+
This property will be resolved as a :py:class:`geoservercloud.models.common.DefaultValueStrategy` enum.
|
|
237
|
+
reference_value: str | None, optional
|
|
238
|
+
This value will be used as the reference value for the :py:class:`geoservercloud.models.common.DefaultValueStrategy`
|
|
239
|
+
NEAREST and FIXED strategy.
|
|
240
|
+
nearest_match_enabled: bool | None, optional
|
|
241
|
+
Defines whether the nearest match should be used for the attribute values.
|
|
242
|
+
nearest_fail_behavior: str | None, optional
|
|
243
|
+
Fail behavior for the nearest match.
|
|
244
|
+
Possible values are: IGNORE, EXCEPTION.
|
|
245
|
+
This property will be resolved as a :py:class:`geoservercloud.models.common.NearestFailBehavior` enum.
|
|
246
|
+
acceptable_interval: str | None, optional
|
|
247
|
+
Defines the acceptable interval for the nearest match behavior.
|
|
248
|
+
A single value, or two values separated by slash. Time values must use the ISO period syntax (e.g., PT1H)
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
def __init__(
|
|
252
|
+
self,
|
|
253
|
+
attribute: str,
|
|
254
|
+
presentation: str,
|
|
255
|
+
end_attribute: str | None = None,
|
|
256
|
+
start_value: str | None = None,
|
|
257
|
+
end_value: str | None = None,
|
|
258
|
+
resolution: int | None = None,
|
|
259
|
+
default_value_strategy: str | None = None,
|
|
260
|
+
reference_value: str | None = None,
|
|
261
|
+
nearest_match_enabled: bool | None = None,
|
|
262
|
+
nearest_fail_behavior: str | None = None,
|
|
263
|
+
acceptable_interval: str | None = None,
|
|
264
|
+
):
|
|
265
|
+
self.dimension: str = "time"
|
|
266
|
+
self.enabled: bool = True
|
|
267
|
+
self.attribute: str = attribute
|
|
268
|
+
self.end_attribute: str | None = end_attribute
|
|
269
|
+
self.presentation: Presentation = Presentation(presentation)
|
|
270
|
+
self.start_value: str | None = start_value
|
|
271
|
+
self.end_value: str | None = end_value
|
|
272
|
+
self.resolution: int | None = resolution
|
|
273
|
+
self.units: str | None = "ISO8601"
|
|
274
|
+
self.default_value_strategy: DefaultValueStrategy | None = DefaultValueStrategy(
|
|
275
|
+
default_value_strategy
|
|
276
|
+
)
|
|
277
|
+
self.reference_value: str | None = reference_value
|
|
278
|
+
self.nearest_match_enabled: bool | None = nearest_match_enabled
|
|
279
|
+
self.nearest_fail_behavior: NearestFailBehavior | None = (
|
|
280
|
+
NearestFailBehavior(nearest_fail_behavior)
|
|
281
|
+
if nearest_fail_behavior
|
|
282
|
+
else None
|
|
283
|
+
)
|
|
284
|
+
self.acceptable_interval: str | None = acceptable_interval
|
|
285
|
+
|
|
286
|
+
@classmethod
|
|
287
|
+
def from_get_response_payload(cls, content: dict):
|
|
288
|
+
time_dimension_info: dict[str, Any] = content["dimensionInfo"]
|
|
289
|
+
return cls(
|
|
290
|
+
attribute=time_dimension_info["attribute"],
|
|
291
|
+
presentation=time_dimension_info["presentation"],
|
|
292
|
+
end_attribute=time_dimension_info.get("endAttribute"),
|
|
293
|
+
start_value=time_dimension_info.get("startValue"),
|
|
294
|
+
end_value=time_dimension_info.get("endValue"),
|
|
295
|
+
resolution=time_dimension_info.get("resolution"),
|
|
296
|
+
default_value_strategy=time_dimension_info.get("defaultValue", {}).get(
|
|
297
|
+
"strategy"
|
|
298
|
+
),
|
|
299
|
+
reference_value=time_dimension_info.get("defaultValue", {}).get(
|
|
300
|
+
"referenceValue"
|
|
301
|
+
),
|
|
302
|
+
nearest_match_enabled=time_dimension_info.get("nearestMatchEnabled"),
|
|
303
|
+
nearest_fail_behavior=time_dimension_info.get(
|
|
304
|
+
"nearestFailBehavior", {}
|
|
305
|
+
).get("value"),
|
|
306
|
+
acceptable_interval=time_dimension_info.get("acceptableInterval"),
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def asdict(self) -> dict[str, Any]:
|
|
310
|
+
content: dict[str, Any] = {
|
|
311
|
+
"@key": self.dimension,
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
dimension_info: dict[str, Any] = {
|
|
315
|
+
"enabled": self.enabled,
|
|
316
|
+
"attribute": self.attribute,
|
|
317
|
+
"presentation": self.presentation.value,
|
|
318
|
+
"units": self.units,
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
optional_items: dict[str, Any] = {
|
|
322
|
+
"endAttribute": self.end_attribute,
|
|
323
|
+
"nearestMatchEnabled": self.nearest_match_enabled,
|
|
324
|
+
"nearestFailBehavior": (
|
|
325
|
+
self.nearest_fail_behavior.value if self.nearest_fail_behavior else None
|
|
326
|
+
),
|
|
327
|
+
"acceptableInterval": self.acceptable_interval,
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (
|
|
331
|
+
self.presentation == Presentation.DISCRETE_INTERVAL
|
|
332
|
+
or self.presentation == Presentation.CONTINUOUS_INTERVAL
|
|
333
|
+
):
|
|
334
|
+
EntityModel.add_item_to_dict(optional_items, "startValue", self.start_value)
|
|
335
|
+
EntityModel.add_item_to_dict(optional_items, "endValue", self.end_value)
|
|
336
|
+
if self.presentation == Presentation.DISCRETE_INTERVAL:
|
|
337
|
+
EntityModel.add_item_to_dict(
|
|
338
|
+
optional_items, "resolution", self.resolution
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
if self.default_value_strategy:
|
|
342
|
+
default_value_strategy: dict[str, str] = {
|
|
343
|
+
"strategy": self.default_value_strategy.value,
|
|
344
|
+
}
|
|
345
|
+
if (
|
|
346
|
+
self.default_value_strategy == DefaultValueStrategy.FIXED
|
|
347
|
+
or self.default_value_strategy == DefaultValueStrategy.NEAREST
|
|
348
|
+
):
|
|
349
|
+
EntityModel.add_item_to_dict(
|
|
350
|
+
default_value_strategy, "referenceValue", self.reference_value
|
|
351
|
+
)
|
|
352
|
+
EntityModel.add_item_to_dict(
|
|
353
|
+
dimension_info, "defaultValue", default_value_strategy
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
EntityModel.add_items_to_dict(dimension_info, optional_items)
|
|
357
|
+
EntityModel.add_item_to_dict(content, "dimensionInfo", dimension_info)
|
|
358
|
+
return content
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class DefaultValueStrategy(Enum):
|
|
362
|
+
MAXIMUM = "MAXIMUM"
|
|
363
|
+
MINIMUM = "MINIMUM"
|
|
364
|
+
NEAREST = "NEAREST"
|
|
365
|
+
FIXED = "FIXED"
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class Presentation(Enum):
|
|
369
|
+
LIST = "LIST"
|
|
370
|
+
DISCRETE_INTERVAL = "DISCRETE_INTERVAL"
|
|
371
|
+
CONTINUOUS_INTERVAL = "CONTINUOUS_INTERVAL"
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class NearestFailBehavior(Enum):
|
|
375
|
+
IGNORE = "IGNORE"
|
|
376
|
+
EXCEPTION = "EXCEPTION"
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/featuretype.py
RENAMED
|
@@ -5,10 +5,14 @@ from geoservercloud.models.abstractlayer import AbstractLayer
|
|
|
5
5
|
from geoservercloud.models.common import (
|
|
6
6
|
EntityModel,
|
|
7
7
|
MetadataLink,
|
|
8
|
+
TimeDimensionInfo,
|
|
8
9
|
)
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class FeatureType(AbstractLayer):
|
|
13
|
+
|
|
14
|
+
TIME_DIMENSION_KEY: str = "time"
|
|
15
|
+
|
|
12
16
|
def __init__(
|
|
13
17
|
self,
|
|
14
18
|
# Mandatory fields
|
|
@@ -40,6 +44,7 @@ class FeatureType(AbstractLayer):
|
|
|
40
44
|
circular_arc_present: bool | None = None,
|
|
41
45
|
encode_measures: bool | None = None,
|
|
42
46
|
metadata_links: list[MetadataLink] | None = None,
|
|
47
|
+
time_dimension_info: TimeDimensionInfo | None = None,
|
|
43
48
|
) -> None:
|
|
44
49
|
super().__init__(
|
|
45
50
|
name=name,
|
|
@@ -70,6 +75,7 @@ class FeatureType(AbstractLayer):
|
|
|
70
75
|
self.circular_arc_present: bool | None = circular_arc_present
|
|
71
76
|
self.encode_measures: bool | None = encode_measures
|
|
72
77
|
self.metadata_links: list[MetadataLink] | None = metadata_links
|
|
78
|
+
self.time_dimension_info: TimeDimensionInfo | None = time_dimension_info
|
|
73
79
|
|
|
74
80
|
@classmethod
|
|
75
81
|
def from_get_response_payload(cls, content: dict):
|
|
@@ -89,6 +95,16 @@ class FeatureType(AbstractLayer):
|
|
|
89
95
|
else:
|
|
90
96
|
metadata_links = None
|
|
91
97
|
|
|
98
|
+
# Check if the feature type contains information about the dimensions "time"
|
|
99
|
+
time_dimension_info: TimeDimensionInfo | None = None
|
|
100
|
+
if feature_type.get("metadata"):
|
|
101
|
+
metadata: list[Any] = feature_type["metadata"]["entry"]
|
|
102
|
+
for metadata_entry in metadata:
|
|
103
|
+
if metadata_entry["@key"] == FeatureType.TIME_DIMENSION_KEY:
|
|
104
|
+
time_dimension_info = TimeDimensionInfo.from_get_response_payload(
|
|
105
|
+
metadata_entry
|
|
106
|
+
)
|
|
107
|
+
|
|
92
108
|
return cls(
|
|
93
109
|
namespace_name=feature_type["namespace"]["name"],
|
|
94
110
|
name=feature_type["name"],
|
|
@@ -114,6 +130,7 @@ class FeatureType(AbstractLayer):
|
|
|
114
130
|
forced_decimals=feature_type.get("forcedDecimals"),
|
|
115
131
|
simple_conversion_enabled=feature_type.get("simpleConversionEnabled"),
|
|
116
132
|
skip_number_match=feature_type.get("skipNumberMatch"),
|
|
133
|
+
time_dimension_info=time_dimension_info,
|
|
117
134
|
)
|
|
118
135
|
|
|
119
136
|
def asdict(self) -> dict[str, Any]:
|
|
@@ -132,6 +149,11 @@ class FeatureType(AbstractLayer):
|
|
|
132
149
|
"circularArcPresent": self.circular_arc_present,
|
|
133
150
|
"encodeMeasures": self.encode_measures,
|
|
134
151
|
}
|
|
152
|
+
|
|
153
|
+
if self.time_dimension_info:
|
|
154
|
+
metadata = {"entry": [self.time_dimension_info.asdict()]}
|
|
155
|
+
EntityModel.add_item_to_dict(optional_items, "metadata", metadata)
|
|
156
|
+
|
|
135
157
|
return EntityModel.add_items_to_dict(content, optional_items)
|
|
136
158
|
|
|
137
159
|
def post_payload(self) -> dict[str, Any]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "geoservercloud"
|
|
3
|
-
version = "0.7.2.
|
|
3
|
+
version = "0.7.2.dev10"
|
|
4
4
|
description = "Lightweight Python client to interact with GeoServer Cloud REST API, GeoServer ACL and OGC services"
|
|
5
5
|
authors = ["Camptocamp <info@camptocamp.com>"]
|
|
6
6
|
license = "BSD-2-Clause"
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Any, Generic, TypeVar
|
|
3
|
-
|
|
4
|
-
T = TypeVar("T")
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class BaseModel:
|
|
8
|
-
@classmethod
|
|
9
|
-
def from_get_response_payload(cls, content: dict):
|
|
10
|
-
raise NotImplementedError
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class EntityModel(BaseModel):
|
|
14
|
-
def asdict(self) -> dict[str, Any]:
|
|
15
|
-
raise NotImplementedError
|
|
16
|
-
|
|
17
|
-
def post_payload(self) -> dict[str, Any]:
|
|
18
|
-
raise NotImplementedError
|
|
19
|
-
|
|
20
|
-
def put_payload(self) -> dict[str, Any]:
|
|
21
|
-
raise NotImplementedError
|
|
22
|
-
|
|
23
|
-
@staticmethod
|
|
24
|
-
def add_items_to_dict(content: dict, items: dict[str, Any]) -> dict[Any, Any]:
|
|
25
|
-
for key, value in items.items():
|
|
26
|
-
content = EntityModel.add_item_to_dict(content, key, value)
|
|
27
|
-
return content
|
|
28
|
-
|
|
29
|
-
@staticmethod
|
|
30
|
-
def add_item_to_dict(content: dict, key: str, value: Any) -> dict[Any, Any]:
|
|
31
|
-
if value is not None:
|
|
32
|
-
content[key] = value
|
|
33
|
-
return content
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class ListModel(BaseModel, Generic[T]):
|
|
37
|
-
"""Base class for list-based models with configurable list and item names."""
|
|
38
|
-
|
|
39
|
-
# These should be overridden in subclasses
|
|
40
|
-
_list_key: str = "" # e.g., "workspaces", "dataStores"
|
|
41
|
-
_item_key: str = "" # e.g., "workspace", "dataStore"
|
|
42
|
-
|
|
43
|
-
def __init__(self, items: list[T] | None = None) -> None:
|
|
44
|
-
self._items: list[T] = items or []
|
|
45
|
-
|
|
46
|
-
def aslist(self) -> list[T]:
|
|
47
|
-
"""Return the list of items."""
|
|
48
|
-
return self._items
|
|
49
|
-
|
|
50
|
-
def find(self, name: str) -> T | None:
|
|
51
|
-
"""Find an item by name (assumes items are dicts with 'name' key)."""
|
|
52
|
-
for item in self._items:
|
|
53
|
-
if isinstance(item, dict) and item.get("name") == name:
|
|
54
|
-
return item
|
|
55
|
-
return None
|
|
56
|
-
|
|
57
|
-
@classmethod
|
|
58
|
-
def from_get_response_payload(cls, content: dict):
|
|
59
|
-
"""Create instance from API response payload."""
|
|
60
|
-
if not cls._list_key or not cls._item_key:
|
|
61
|
-
raise NotImplementedError("Subclasses must define _list_key and _item_key")
|
|
62
|
-
|
|
63
|
-
data = content.get(cls._list_key)
|
|
64
|
-
if not data:
|
|
65
|
-
return cls()
|
|
66
|
-
|
|
67
|
-
items = data[cls._item_key]
|
|
68
|
-
return cls(items)
|
|
69
|
-
|
|
70
|
-
def __repr__(self) -> str:
|
|
71
|
-
"""String representation of the list."""
|
|
72
|
-
return json.dumps(self._items, indent=4)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class ReferencedObjectModel(BaseModel):
|
|
76
|
-
def __init__(self, name: str, href: str | None = None):
|
|
77
|
-
self.name: str = name
|
|
78
|
-
self.href: str | None = href
|
|
79
|
-
|
|
80
|
-
@classmethod
|
|
81
|
-
def from_get_response_payload(cls, content: dict):
|
|
82
|
-
cls.name = content["name"]
|
|
83
|
-
cls.href = content["href"]
|
|
84
|
-
|
|
85
|
-
def asdict(self) -> dict[str, str]:
|
|
86
|
-
return EntityModel.add_item_to_dict({"name": self.name}, "href", self.href)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
class KeyDollarListDict(dict):
|
|
90
|
-
|
|
91
|
-
key_prefix: str = "@key"
|
|
92
|
-
value_prefix: str = "$"
|
|
93
|
-
|
|
94
|
-
def __init__(
|
|
95
|
-
self,
|
|
96
|
-
input_list: list | None = None,
|
|
97
|
-
input_dict: dict | None = None,
|
|
98
|
-
*args,
|
|
99
|
-
**kwargs
|
|
100
|
-
):
|
|
101
|
-
super().__init__(*args, **kwargs)
|
|
102
|
-
if input_list:
|
|
103
|
-
self.deserialize(input_list)
|
|
104
|
-
if input_dict:
|
|
105
|
-
self.update(input_dict)
|
|
106
|
-
|
|
107
|
-
def deserialize(self, input_list: list):
|
|
108
|
-
for item in input_list:
|
|
109
|
-
key = item[self.key_prefix]
|
|
110
|
-
if self.value_prefix in item:
|
|
111
|
-
value = item[self.value_prefix]
|
|
112
|
-
else:
|
|
113
|
-
value = None
|
|
114
|
-
super().__setitem__(key, value)
|
|
115
|
-
|
|
116
|
-
def serialize(self):
|
|
117
|
-
return [
|
|
118
|
-
{self.key_prefix: key, self.value_prefix: value}
|
|
119
|
-
for key, value in self.items()
|
|
120
|
-
]
|
|
121
|
-
|
|
122
|
-
def __repr__(self) -> str:
|
|
123
|
-
return str(self.serialize())
|
|
124
|
-
|
|
125
|
-
def __str__(self):
|
|
126
|
-
return json.dumps(self.serialize())
|
|
127
|
-
|
|
128
|
-
def update(self, other: dict): # type: ignore
|
|
129
|
-
for key, value in other.items():
|
|
130
|
-
super().__setitem__(key, value)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
class I18N:
|
|
134
|
-
"""
|
|
135
|
-
Geoserver handles internationalization with 2 possible (mutually exclusive) keys in the rest payload:
|
|
136
|
-
either:
|
|
137
|
-
- [key: string]
|
|
138
|
-
or
|
|
139
|
-
- [internationalKey: dictionary]
|
|
140
|
-
|
|
141
|
-
example:
|
|
142
|
-
a) as key: string we get {"title": "Test Title"}
|
|
143
|
-
b) as key: dict we get {"internationalTitle": {"en": "Test Title", "es": "Título de Prueba"}}
|
|
144
|
-
|
|
145
|
-
This class gives a layer of abstraction to handle both cases.
|
|
146
|
-
|
|
147
|
-
Usage:
|
|
148
|
-
Call the class by adding both possible keys in a tuple and the value.
|
|
149
|
-
|
|
150
|
-
Parameters:
|
|
151
|
-
keys: tuple[str, str] example : ("title", "internationalTitle")
|
|
152
|
-
value: str | dict example: "Test Title" | {"en": "Test Title", "es": "Título de Prueba"}
|
|
153
|
-
|
|
154
|
-
Example:
|
|
155
|
-
|
|
156
|
-
my_i18n = I18N(("title", "internationalTitle"), "Test Title")
|
|
157
|
-
"""
|
|
158
|
-
|
|
159
|
-
def __init__(self, keys: tuple[str, Any], value: str | dict) -> None:
|
|
160
|
-
self._str_key = keys[0]
|
|
161
|
-
self._i18n_key = keys[1]
|
|
162
|
-
self._value = value
|
|
163
|
-
if isinstance(value, str):
|
|
164
|
-
self._content = {self.str_key: self._value}
|
|
165
|
-
elif isinstance(value, dict):
|
|
166
|
-
self._content = {self._i18n_key: self._value}
|
|
167
|
-
else:
|
|
168
|
-
raise ValueError("Invalid value type")
|
|
169
|
-
|
|
170
|
-
@property
|
|
171
|
-
def str_key(self):
|
|
172
|
-
return self._str_key
|
|
173
|
-
|
|
174
|
-
@property
|
|
175
|
-
def i18n_key(self):
|
|
176
|
-
return self._i18n_key
|
|
177
|
-
|
|
178
|
-
@property
|
|
179
|
-
def value(self):
|
|
180
|
-
return self._value
|
|
181
|
-
|
|
182
|
-
def asdict(self):
|
|
183
|
-
return self._content
|
|
184
|
-
|
|
185
|
-
def __repr__(self):
|
|
186
|
-
return json.dumps(self._content, indent=4)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
class MetadataLink:
|
|
190
|
-
def __init__(self, url: str, metadata_type="TC211", mime_type: str = "text/xml"):
|
|
191
|
-
self.url: str = url
|
|
192
|
-
self.metadata_type: str = metadata_type
|
|
193
|
-
self.type: str = mime_type
|
|
194
|
-
|
|
195
|
-
@classmethod
|
|
196
|
-
def from_get_response_payload(cls, content: dict):
|
|
197
|
-
return cls(
|
|
198
|
-
url=content["content"],
|
|
199
|
-
metadata_type=content["metadataType"],
|
|
200
|
-
mime_type=content["type"],
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
def asdict(self) -> dict[str, str]:
|
|
204
|
-
return {
|
|
205
|
-
"content": self.url,
|
|
206
|
-
"metadataType": self.metadata_type,
|
|
207
|
-
"type": self.type,
|
|
208
|
-
}
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/.gitignore
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/README.md
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoserver_acceptance_tests/tests/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/geoservercloudsync.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/abstractlayer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/coveragestore.py
RENAMED
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/datastores.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/featuretypes.py
RENAMED
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/layergroup.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/layergroups.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/resourcedirectory.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/wmssettings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/models/workspaces.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/__init__.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/owsservice.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/restclient.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/restlogger.py
RENAMED
|
File without changes
|
{geoservercloud-0.7.2.dev1 → geoservercloud-0.7.2.dev10}/geoservercloud/services/restservice.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|