Skip to content

Commit b7706ad

Browse files
metadata and resource mandatory fields check and other details
1 parent 7d8f6cc commit b7706ad

File tree

12 files changed

+160
-160
lines changed

12 files changed

+160
-160
lines changed

models/ConfigData.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def set_data_from_yaml(self, dict_content: dict):
7676
if resource_data.get("type") in [e.value for e in ResourceTypesEnum]:
7777

7878
# Create a new ResourceConfigTemplate instance and update with available values
79-
new_resource_item = ResourceConfigTemplate(
79+
new_resource_item = ResourceConfigTemplate.init_with_name(
8080
instance_name=resource_instance_name
8181
)
8282
(
@@ -170,7 +170,9 @@ def asdict_enum_safe(self, obj):
170170
def add_new_resource(self) -> str:
171171
"""Add a placeholder resource."""
172172
new_name = "new_resource"
173-
self.resources[new_name] = ResourceConfigTemplate(instance_name=new_name)
173+
self.resources[new_name] = ResourceConfigTemplate.init_with_name(
174+
instance_name=new_name
175+
)
174176
return new_name
175177

176178
def delete_resource(self, dialog):

models/top_level/MetadataConfig.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
# records
77
class MetadataKeywordTypeEnum(Enum):
8+
NONE = ""
89
DISCIPLINE = "discipline"
910
TEMPORAL = "temporal"
1011
PLACE = "place"
@@ -42,43 +43,39 @@ class MetadataIdentificationConfig:
4243
title: str | dict = field(default_factory=lambda: "")
4344
description: str | dict = field(default_factory=lambda: "")
4445
keywords: list | dict = field(default_factory=lambda: [])
45-
keywords_type: MetadataKeywordTypeEnum = field(
46-
default_factory=lambda: MetadataKeywordTypeEnum.THEME
47-
)
48-
terms_of_service: str = field(
49-
default="https://creativecommons.org/licenses/by/4.0/"
50-
)
5146
url: str = field(default="https://example.org")
47+
keywords_type: MetadataKeywordTypeEnum | None = None
48+
terms_of_service: str | None = None
5249

5350

5451
@dataclass(kw_only=True)
5552
class MetadataLicenseConfig:
5653
name: str = field(default="CC-BY 4.0 license")
57-
url: str = field(default="https://creativecommons.org/licenses/by/4.0/")
54+
url: str | None = None
5855

5956

6057
@dataclass(kw_only=True)
6158
class MetadataProviderConfig:
6259
name: str = field(default="Organization Name")
63-
url: str = field(default="https://pygeoapi.io")
60+
url: str | None = None
6461

6562

6663
@dataclass(kw_only=True)
6764
class MetadataContactConfig:
6865
name: str = field(default="Lastname, Firstname")
69-
position: str = field(default="Position Title")
70-
address: str = field(default="Mailing Address")
71-
city: str = field(default="City")
72-
stateorprovince: str = field(default="Administrative Area")
73-
postalcode: str = field(default="Zip or Postal Code")
74-
country: str = field(default="Country")
75-
phone: str = field(default="+xx-xxx-xxx-xxxx")
76-
fax: str = field(default="+xx-xxx-xxx-xxxx")
77-
email: str = field(default="you@example.org")
78-
url: str = field(default="Contact URL")
79-
hours: str = field(default="Mo-Fr 08:00-17:00")
80-
instructions: str = field(default="During hours of service. Off on weekends.")
81-
role: MetadataRoleEnum = field(default_factory=lambda: MetadataRoleEnum.NONE)
66+
position: str | None = None
67+
address: str | None = None
68+
city: str | None = None
69+
stateorprovince: str | None = None
70+
postalcode: str | None = None
71+
country: str | None = None
72+
phone: str | None = None
73+
fax: str | None = None
74+
email: str | None = None
75+
url: str | None = None
76+
hours: str | None = None
77+
instructions: str | None = None
78+
role: MetadataRoleEnum | None = None
8279

8380

8481
@dataclass(kw_only=True)
@@ -108,15 +105,17 @@ def get_invalid_properties(self):
108105
all_invalid_fields.append("metadata.identification.description")
109106
if len(self.identification.keywords) == 0:
110107
all_invalid_fields.append("metadata.identification.keywords")
108+
if len(self.identification.url) == 0:
109+
all_invalid_fields.append("metadata.identification.url")
111110
if len(self.license.name) == 0:
112111
all_invalid_fields.append("metadata.license.name")
113112
if len(self.provider.name) == 0:
114113
all_invalid_fields.append("metadata.provider.name")
115114
if len(self.contact.name) == 0:
116115
all_invalid_fields.append("metadata.contact.name")
117116

118-
parsed_url = urlparse(self.identification.url)
119-
if not all([parsed_url.scheme, parsed_url.netloc]):
120-
all_invalid_fields.append("metadata.identification.url")
117+
# parsed_url = urlparse(self.identification.url)
118+
# if not all([parsed_url.scheme, parsed_url.netloc]):
119+
# all_invalid_fields.append("metadata.identification.url")
121120

122121
return all_invalid_fields

models/top_level/ResourceConfigTemplate.py

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,15 @@ class ResourceLinkTemplate:
4343
class ResourceSpatialConfig:
4444
bbox: InlineList = field(default_factory=lambda: InlineList([-180, -90, 180, 90]))
4545

46-
# optional, but with assumed default value:
47-
crs: str = field(default="http://www.opengis.net/def/crs/OGC/1.3/CRS84")
46+
# optional
47+
crs: str | None = None
4848

4949
# we need these as separate properties so that Enum class values can be set&selected in the UI
5050
@property
5151
def crs_authority(self):
52+
if self.crs is None:
53+
return CrsAuthorities.OGC13
54+
5255
crs_auth_id = self.crs.split("http://www.opengis.net/def/crs/")[
5356
-1
5457
] # OGC/1.3/CRS84
@@ -61,6 +64,8 @@ def crs_authority(self):
6164

6265
@property
6366
def crs_id(self):
67+
if self.crs is None:
68+
return ""
6469
return self.crs.split("/")[-1]
6570

6671

@@ -109,51 +114,17 @@ class ResourceConfigTemplate:
109114
links: list[ResourceLinkTemplate] | None = None
110115
visibility: ResourceVisibilityEnum | None = None
111116
linked__data: dict | None = (
112-
None # intentionally with double undersore to not confuse with any reserved word
117+
None # intentionally with double undersore to not confuse with any reserved keyword
113118
)
114119
# limits: ignored for now
115120

116121
# Overwriding __init__ method to pass 'instance_name' as an input but not make it an instance property
117122
# This will allow to have a clean 'asdict(class)' output without 'instance_name' in it
118-
def __init__(
119-
self,
120-
*,
121-
instance_name: str,
122-
type: ResourceTypesEnum = ResourceTypesEnum.COLLECTION,
123-
title: str = "",
124-
description: str = "",
125-
keywords: dict = None,
126-
links: list[ResourceLinkTemplate] | None = None,
127-
extents: ResourceExtentsConfig = None,
128-
providers: list[
129-
ProviderPostgresql | ProviderMvtProxy | ProviderWmsFacade
130-
] = None,
131-
visibility: ResourceVisibilityEnum | None = None
132-
):
133-
self._instance_name = instance_name
134-
self.type = type
135-
self.title = title
136-
self.description = description
137-
138-
# using full class name here instead of type(self), because "type" is used here as a property name
139-
if keywords is None:
140-
keywords = ResourceConfigTemplate.__dataclass_fields__[
141-
"keywords"
142-
].default_factory()
143-
if extents is None:
144-
extents = ResourceConfigTemplate.__dataclass_fields__[
145-
"extents"
146-
].default_factory()
147-
if providers is None:
148-
providers = ResourceConfigTemplate.__dataclass_fields__[
149-
"providers"
150-
].default_factory()
151-
152-
self.keywords = keywords
153-
self.links = links
154-
self.extents = extents
155-
self.providers = providers
156-
self.visibility = visibility
123+
@classmethod
124+
def init_with_name(cls, *, instance_name: str):
125+
obj = cls()
126+
obj._instance_name = instance_name
127+
return obj
157128

158129
@property
159130
def instance_name(self):
@@ -182,9 +153,7 @@ def get_invalid_properties(self):
182153
all_invalid_fields.append("keywords")
183154
if len(self.providers) == 0:
184155
all_invalid_fields.append("providers")
185-
if not is_valid_string(self.extents.spatial.crs):
186-
all_invalid_fields.append("extents.spatial.crs")
187-
if len(self.extents.spatial.bbox) < 4:
156+
if len(self.extents.spatial.bbox) < 4 or len(self.extents.spatial.bbox) > 6:
188157
all_invalid_fields.append("extents.spatial.bbox")
189158

190159
return all_invalid_fields

models/top_level/ServerConfig.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,6 @@ class ServerConfig:
9191
locale_dir: str | None = None
9292
api_rules: dict | None = None
9393

94-
# Not currently used in the UI
95-
# api_rules: ServerApiRulesConfig | None = None
96-
9794
def get_invalid_properties(self):
9895
"""Checks the values of mandatory fields: bind (host), url, languages."""
9996
all_invalid_fields = []

models/top_level/providers/ProviderMvtProxy.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ def ui_elements_grid(cls):
6868
# Mandatory to align the fields order with data packing and assigning.
6969
# label, data_type, default, special_widget_type, placeholder
7070
return [
71-
(*cls.get_field_info(cls, "name"), "QComboBox", ["MVT-proxy"]),
72-
(*cls.get_field_info(cls, "data"), None, ""),
73-
(*cls.get_field_info(cls, "format.name"), None, ""),
74-
(*cls.get_field_info(cls, "format.mimetype"), None, ""),
71+
(*cls.get_field_info(cls, "name*"), "QComboBox", ["MVT-proxy"]),
72+
(*cls.get_field_info(cls, "data*"), None, ""),
73+
(*cls.get_field_info(cls, "format.name*"), None, ""),
74+
(*cls.get_field_info(cls, "format.mimetype*"), None, ""),
75+
# non-mandatory
7576
(*cls.get_field_info(cls, "crs"), None, ""),
7677
(*cls.get_field_info(cls, "options.zoom.min"), None, ""),
7778
(*cls.get_field_info(cls, "options.zoom.max"), None, ""),

models/top_level/providers/ProviderPostgresql.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ def ui_elements_grid(cls):
6363
# Mandatory to align the fields order with data packing and assigning.
6464
# label, data_type, default, special_widget_type, placeholder
6565
return [
66-
(*cls.get_field_info(cls, "name"), "QComboBox", ["PostgreSQL"]),
67-
(*cls.get_field_info(cls, "table"), None, ""),
68-
(*cls.get_field_info(cls, "id_field"), None, ""),
69-
(*cls.get_field_info(cls, "data.host"), None, ""),
66+
(*cls.get_field_info(cls, "name*"), "QComboBox", ["PostgreSQL"]),
67+
(*cls.get_field_info(cls, "table*"), None, ""),
68+
(*cls.get_field_info(cls, "id_field*"), None, ""),
69+
(*cls.get_field_info(cls, "data.host*"), None, ""),
7070
(
71-
*cls.get_field_info(cls, "data.dbname"),
71+
*cls.get_field_info(cls, "data.dbname*"),
7272
None,
7373
"",
7474
),
75-
(*cls.get_field_info(cls, "data.user"), None, ""),
75+
(*cls.get_field_info(cls, "data.user*"), None, ""),
7676
# non-mandatory:
7777
(*cls.get_field_info(cls, "crs"), None, ""),
7878
(

models/top_level/providers/ProviderTemplate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def get_field_info(current_cls: Type, field_path: str) -> tuple[str, Type, Any]:
3131
Inspect a (possibly nested) dataclass field on `cls` and return (type, default_value).
3232
If no default is defined, default_value is None.
3333
"""
34-
parts = field_path.split(".")
34+
parts = field_path.replace("*", "").split(".")
3535
default = None
3636
field_type = None
3737
# type_hints = get_type_hints(current_cls)

models/top_level/providers/ProviderWmsFacade.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ def ui_elements_grid(cls):
5656
# Mandatory to align the fields order with data packing and assigning.
5757
# label, data_type, default, special_widget_type, placeholder
5858
return [
59-
(*cls.get_field_info(cls, "name"), "QComboBox", ["WMSFacade"]),
60-
(*cls.get_field_info(cls, "data"), None, ""),
61-
(*cls.get_field_info(cls, "options.layer"), None, ""),
59+
(*cls.get_field_info(cls, "name*"), "QComboBox", ["WMSFacade"]),
60+
(*cls.get_field_info(cls, "data*"), None, ""),
61+
(*cls.get_field_info(cls, "options.layer*"), None, ""),
62+
# non-mandatory
6263
(*cls.get_field_info(cls, "crs"), None, ""),
6364
(*cls.get_field_info(cls, "options.style"), None, ""),
6465
(*cls.get_field_info(cls, "options.version"), None, ""),

0 commit comments

Comments
 (0)