Skip to content

Commit a102cce

Browse files
committed
Implement configuration classes
1 parent d6d6095 commit a102cce

File tree

7 files changed

+141
-34
lines changed

7 files changed

+141
-34
lines changed

.pre-commit-config.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ repos:
1212
rev: v1.11.2
1313
hooks:
1414
- id: mypy
15+
additional_dependencies: ["types-PyYAML"]
1516
- repo: https://github.com/astral-sh/ruff-pre-commit
1617
rev: v0.6.5
1718
hooks:

arho_feature_template/core/feature_template.py

-31
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
from dataclasses import dataclass
5+
from typing import TYPE_CHECKING
6+
7+
import yaml
8+
9+
if TYPE_CHECKING:
10+
from pathlib import Path
11+
12+
logger = logging.getLogger(__name__)
13+
14+
SUPPORTED_TEMPLATE_VERSION = 1
15+
16+
17+
class TemplateLibraryVersionError(Exception):
18+
def __init__(self, version: str):
19+
super().__init__(f"Template library version {version} is not supported")
20+
21+
22+
class TemplateSyntaxError(Exception):
23+
def __init__(self, message: str):
24+
super().__init__(f"Invalid template syntax: {message}")
25+
26+
27+
@dataclass
28+
class TemplateLibraryConfig:
29+
"""Describes the configuration of a template library"""
30+
31+
version: str
32+
meta: TemplateLibraryMeta
33+
templates: list[FeatureTemplate]
34+
35+
@classmethod
36+
def from_dict(cls, data: dict) -> TemplateLibraryConfig:
37+
file_version = data["version"]
38+
if file_version != SUPPORTED_TEMPLATE_VERSION:
39+
raise TemplateLibraryVersionError(file_version)
40+
41+
try:
42+
return cls(
43+
version=file_version,
44+
meta=TemplateLibraryMeta.from_dict(data["meta"]),
45+
templates=[FeatureTemplate.from_dict(template) for template in data["templates"]],
46+
)
47+
except KeyError as e:
48+
raise TemplateSyntaxError(str(e)) from e
49+
50+
51+
@dataclass
52+
class TemplateLibraryMeta:
53+
"""Describes the metadata of a template library"""
54+
55+
name: str
56+
description: str | None
57+
version: str | None
58+
59+
@classmethod
60+
def from_dict(cls, data: dict) -> TemplateLibraryMeta:
61+
return cls(
62+
name=data["name"],
63+
description=data.get("description"),
64+
version=data.get("version"),
65+
)
66+
67+
68+
@dataclass
69+
class FeatureTemplate:
70+
"""Describes a feature template that can include nested features"""
71+
72+
name: str
73+
description: str | None
74+
feature: Feature
75+
76+
@classmethod
77+
def from_dict(cls, data: dict) -> FeatureTemplate:
78+
return cls(
79+
name=data["name"],
80+
description=data.get("description"),
81+
feature=Feature.from_dict(data["feature"]),
82+
)
83+
84+
85+
@dataclass
86+
class Feature:
87+
"""Describes a feature to be inserted into a Vector layer"""
88+
89+
layer: str
90+
attributes: list[Attribute]
91+
child_features: list[Feature] | None
92+
93+
@classmethod
94+
def from_dict(cls, data: dict) -> Feature:
95+
return cls(
96+
layer=data["layer"],
97+
attributes=[Attribute.from_dict(attribute) for attribute in data["attributes"]],
98+
child_features=[Feature.from_dict(feature) for feature in data.get("child_features", [])],
99+
)
100+
101+
102+
@dataclass
103+
class Attribute:
104+
"""Describes an attribute to be set on a feature"""
105+
106+
attribute: str
107+
default: str | None
108+
109+
@classmethod
110+
def from_dict(cls, data: dict) -> Attribute:
111+
return cls(attribute=data["attribute"], default=data.get("default"))
112+
113+
114+
def parse_template_library_config(template_library_config: Path) -> TemplateLibraryConfig:
115+
with template_library_config.open(encoding="utf-8") as f:
116+
data = yaml.safe_load(f)
117+
return TemplateLibraryConfig.from_dict(data)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from __future__ import annotations
2+
3+
from importlib import resources
4+
from typing import TYPE_CHECKING
5+
6+
if TYPE_CHECKING:
7+
from collections.abc import Iterator
8+
from pathlib import Path
9+
10+
11+
def library_config_files() -> Iterator[Path]:
12+
"""Get all template library configuration files."""
13+
14+
for resource in resources.files(__package__).iterdir():
15+
with resources.as_file(resource) as resource_path:
16+
if resource_path.suffix == ".yaml":
17+
yield resource_path

arho_feature_template/resources/template_libraries/asemakaava-sample.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
version: 1
22
meta:
3-
name: Asemakaava-kaavamääräyskirjasto
3+
name: Asemakaavan kaavamääräykset
44
version: "1.0"
55
templates:
66
- name: Simppeli kaavakohde

requirements-dev.in

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ debugpy
66

77
# Linting and formatting
88
pre-commit
9-
mypy
109
ruff
1110
flake8
1211
flake8-qgis
1312

14-
# Stubs
13+
# Types
14+
mypy
1515
PyQt5-stubs
16+
types-PyYAML
1617

1718
# repo itself
1819
-e file:.

requirements-dev.txt

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ tomli==2.0.1 ; python_full_version < '3.11'
4646
# via
4747
# -c requirements-test.txt
4848
# mypy
49+
types-pyyaml==6.0.12.20240917
50+
# via -r requirements-dev.in
4951
typing-extensions==4.12.2
5052
# via mypy
5153
virtualenv==20.26.5

0 commit comments

Comments
 (0)