Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

32 katja asetuksen kaavamääräysryhmät yml kirjastoksi tärkeimmät #69

Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add config classes for plan regulation groups, add PlanRegulationDefi…
…nition for plan regulations with additional data and defaults
nmaarnio committed Nov 21, 2024
commit 3566ddc9e2fa48cc9f1bee4091daaaded1a41a44
61 changes: 53 additions & 8 deletions arho_feature_template/core/plan_regulation_config.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

import logging
import os
from dataclasses import dataclass
from dataclasses import dataclass, field
from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING, cast
@@ -14,6 +14,7 @@
from arho_feature_template.qgis_plugin_tools.tools.resources import resources_path

if TYPE_CHECKING:
from numbers import Number
from typing import Literal

from qgis.core import QgsMapLayer
@@ -34,10 +35,11 @@ def __init__(self, message: str):

class UninitializedError(Exception):
def __init__(self):
super().__init__("PlanRegulationsSet is not initialized. Call 'load_config' first")
super().__init__("PlanRegulationsSet is not initialized. Call 'initialize' first")


class ValueType(Enum):
DECIMAL = "desimaali"
POSITIVE_DECIMAL = "positiivinen desimaali"
POSITIVE_INTEGER = "positiivinen kokonaisluku"
POSITIVE_INTEGER_RANGE = "positiivinen kokonaisluku arvoväli"
@@ -50,6 +52,8 @@ class Unit(Enum):
EFFICIENCY_RATIO = "k-m2/m2"
PERCENTAGE = "prosentti"
AREA_RATIO = "m2/k-m2"
DEGREES = "°"
DECIBEL = "dB"


# TODO: Same as in PlanManager, should refactor
@@ -75,6 +79,7 @@ class PlanRegulationsSet:

version: str
regulations: list[PlanRegulationConfig]
regulations_dict: dict[str, PlanRegulationConfig] = field(default_factory=dict)

_instance: PlanRegulationsSet | None = None

@@ -87,9 +92,18 @@ def get_instance(cls) -> PlanRegulationsSet:

@classmethod
def get_regulations(cls) -> list[PlanRegulationConfig]:
"""Get the list of regulation configs, if instance is initialized."""
instance = cls.get_instance()
return instance.regulations
"""Get the list of top-level regulation configs, if instance is initialized."""
return cls.get_instance().regulations

@classmethod
def get_regulations_dict(cls) -> dict[str, PlanRegulationConfig]:
"""Get all regulations in a dictionary where keys are regulations codes and values PlanRegulationConfigs."""
return cls.get_instance().regulations_dict

@classmethod
def get_regulation_by_code(cls, regulation_code: str) -> PlanRegulationConfig | None:
"""Get a regulation by it's regulation code (if exists)."""
return cls.get_instance().regulations_dict.get(regulation_code)

@classmethod
def initialize(
@@ -103,12 +117,17 @@ def initialize(
data = yaml.safe_load(f)
cls._instance = cls.from_dict(data)

# Add names from plan regulation layer
regulations = cls.get_regulations()
regulations_dict: dict[str, PlanRegulationConfig] = {}
mapping = get_name_mapping_for_plan_regulations(type_of_plan_regulations_layer_name)
if mapping:
for regulation in cls.get_regulations():

# Add names to dictionary, add names to regulations
for regulation in regulations:
regulation.add_to_dictionary(regulations_dict)
if mapping:
regulation.add_name(mapping, language)

cls._instance.regulations_dict = regulations_dict
logger.info("PlanRegulationsSet initialized successfully.")
return cls._instance

@@ -156,3 +175,29 @@ def add_name(self, code_to_name_mapping: dict[str, dict[str, str]], language: Li
self.name = language_to_name_dict[language] if language_to_name_dict else self.regulation_code
for regulation in self.child_regulations:
regulation.add_name(code_to_name_mapping, language)

def add_to_dictionary(self, dictionary: dict[str, PlanRegulationConfig]):
dictionary[self.regulation_code] = self
for regulation in self.child_regulations:
regulation.add_to_dictionary(dictionary)


@dataclass
class PlanRegulationDefinition:
"""Associates a PlanRegulationConfig with an optional default value and additional data."""

regulation_config: PlanRegulationConfig
default_value: str | Number | None
additional_info: dict[str, str | Number | None] # NOTE: Correct typing for additional information values?
regulation_number: int | None
attached_files: list[Path]

@classmethod
def from_dict(cls, data: dict) -> PlanRegulationDefinition:
return cls(
regulation_config=data["config"],
default_value=data.get("default_value"),
additional_info=data.get("additional_info", {}),
regulation_number=data.get("regulation_number"),
attached_files=data.get("attached_files", []),
)
118 changes: 118 additions & 0 deletions arho_feature_template/core/plan_regulation_group_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import TYPE_CHECKING, cast

import yaml
from qgis.utils import iface

from arho_feature_template.core.plan_regulation_config import PlanRegulationDefinition, PlanRegulationsSet

if TYPE_CHECKING:
from pathlib import Path

from qgis.gui import QgisInterface

iface: QgisInterface = cast("QgisInterface", iface) # type: ignore[no-redef]

logger = logging.getLogger(__name__)


class ConfigSyntaxError(Exception):
def __init__(self, message: str):
super().__init__(f"Invalid config syntax: {message}")


@dataclass
class PlanRegulationGroupLibrary:
"""Describes the configuration of a plan regulation group library"""

meta: PlanRegulationGroupLibraryMeta
plan_regulation_group_categories: list[PlanRegulationGroupCategory]

@classmethod
def from_dict(cls, data: dict) -> PlanRegulationGroupLibrary:
try:
return cls(
meta=PlanRegulationGroupLibraryMeta.from_dict(data["meta"]),
plan_regulation_group_categories=[
PlanRegulationGroupCategory.from_dict(category) for category in data["categories"]
],
)
except KeyError as e:
raise ConfigSyntaxError(str(e)) from e

@classmethod
def new_from_file(cls, fp: Path) -> PlanRegulationGroupLibrary:
with fp.open(encoding="utf-8") as f:
data = yaml.safe_load(f)
return PlanRegulationGroupLibrary.from_dict(data)


@dataclass
class PlanRegulationGroupLibraryMeta:
"""Describes the metadata of a plan regulation group library"""

name: str
version: int | None
group: str | None
sub_group: str | None
description: str | None

@classmethod
def from_dict(cls, data: dict) -> PlanRegulationGroupLibraryMeta:
return cls(
name=data["name"],
version=data.get("version"),
group=data.get("group"),
sub_group=data.get("sub_group"),
description=data.get("description"),
)


@dataclass
class PlanRegulationGroupCategory:
category_code: str
name: str | None
plan_regulation_groups: list[PlanRegulationGroupDefinition]

@classmethod
def from_dict(cls, data: dict) -> PlanRegulationGroupCategory:
return cls(
category_code=data["category_code"],
name=data.get("name"),
plan_regulation_groups=[
PlanRegulationGroupDefinition.from_dict(group) for group in data["plan_regulation_groups"]
],
)


@dataclass
class PlanRegulationGroupDefinition:
"""Describes a plan regulation group"""

name: str
geometry: str
color_code: str | None
letter_code: str | None
plan_regulations: list[PlanRegulationDefinition]

@classmethod
def from_dict(cls, data: dict) -> PlanRegulationGroupDefinition:
regulations = []
for reg_data in data["plan_regulations"]:
reg_code = reg_data["regulation_code"]
config = PlanRegulationsSet.get_regulation_by_code(reg_code)
if config:
reg_data["config"] = config
regulations.append(PlanRegulationDefinition.from_dict(reg_data))
else:
iface.messageBar().pushWarning("", f"Could not find config for {reg_code} plan regulation!")
return cls(
name=data["name"],
geometry=data["geometry"],
color_code=data.get("color_code"),
letter_code=data.get("letter_code"),
plan_regulations=regulations,
)