aboutsummaryrefslogtreecommitdiff
path: root/tools/cru-py/cru/attr.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/cru-py/cru/attr.py')
-rw-r--r--tools/cru-py/cru/attr.py364
1 files changed, 0 insertions, 364 deletions
diff --git a/tools/cru-py/cru/attr.py b/tools/cru-py/cru/attr.py
deleted file mode 100644
index d4cc86a..0000000
--- a/tools/cru-py/cru/attr.py
+++ /dev/null
@@ -1,364 +0,0 @@
-from __future__ import annotations
-
-import copy
-from collections.abc import Callable, Iterable
-from dataclasses import dataclass, field
-from typing import Any
-
-from .list import CruUniqueKeyList
-from ._type import CruTypeSet
-from ._const import CruNotFound, CruUseDefault, CruDontChange
-from ._iter import CruIterator
-
-
-@dataclass
-class CruAttr:
-
- name: str
- value: Any
- description: str | None
-
- @staticmethod
- def make(
- name: str, value: Any = CruUseDefault.VALUE, description: str | None = None
- ) -> CruAttr:
- return CruAttr(name, value, description)
-
-
-CruAttrDefaultFactory = Callable[["CruAttrDef"], Any]
-CruAttrTransformer = Callable[[Any, "CruAttrDef"], Any]
-CruAttrValidator = Callable[[Any, "CruAttrDef"], None]
-
-
-@dataclass
-class CruAttrDef:
- name: str
- description: str
- default_factory: CruAttrDefaultFactory
- transformer: CruAttrTransformer
- validator: CruAttrValidator
-
- def __init__(
- self,
- name: str,
- description: str,
- default_factory: CruAttrDefaultFactory,
- transformer: CruAttrTransformer,
- validator: CruAttrValidator,
- ) -> None:
- self.name = name
- self.description = description
- self.default_factory = default_factory
- self.transformer = transformer
- self.validator = validator
-
- def transform(self, value: Any) -> Any:
- if self.transformer is not None:
- return self.transformer(value, self)
- return value
-
- def validate(self, value: Any, /, force_allow_none: bool = False) -> None:
- if force_allow_none is value is None:
- return
- if self.validator is not None:
- self.validator(value, self)
-
- def transform_and_validate(
- self, value: Any, /, force_allow_none: bool = False
- ) -> Any:
- value = self.transform(value)
- self.validate(value, force_allow_none)
- return value
-
- def make_default_value(self) -> Any:
- return self.transform_and_validate(self.default_factory(self))
-
- def adopt(self, attr: CruAttr) -> CruAttr:
- attr = copy.deepcopy(attr)
-
- if attr.name is None:
- attr.name = self.name
- elif attr.name != self.name:
- raise ValueError(f"Attr name is not match: {attr.name} != {self.name}")
-
- if attr.value is CruUseDefault.VALUE:
- attr.value = self.make_default_value()
- else:
- attr.value = self.transform_and_validate(attr.value)
-
- if attr.description is None:
- attr.description = self.description
-
- return attr
-
- def make(
- self, value: Any = CruUseDefault.VALUE, description: None | str = None
- ) -> CruAttr:
- value = self.make_default_value() if value is CruUseDefault.VALUE else value
- value = self.transform_and_validate(value)
- return CruAttr(
- self.name,
- value,
- description if description is not None else self.description,
- )
-
-
-@dataclass
-class CruAttrDefBuilder:
-
- name: str
- description: str
- types: list[type] | None = field(default=None)
- allow_none: bool = field(default=False)
- default: Any = field(default=CruUseDefault.VALUE)
- default_factory: CruAttrDefaultFactory | None = field(default=None)
- auto_list: bool = field(default=False)
- transformers: list[CruAttrTransformer] = field(default_factory=list)
- validators: list[CruAttrValidator] = field(default_factory=list)
- override_transformer: CruAttrTransformer | None = field(default=None)
- override_validator: CruAttrValidator | None = field(default=None)
-
- build_hook: Callable[[CruAttrDef], None] | None = field(default=None)
-
- def __init__(self, name: str, description: str) -> None:
- super().__init__()
- self.name = name
- self.description = description
-
- def auto_adjust_default(self) -> None:
- if self.default is not CruUseDefault.VALUE and self.default is not None:
- return
- if self.allow_none and self.default is CruUseDefault.VALUE:
- self.default = None
- if not self.allow_none and self.default is None:
- self.default = CruUseDefault.VALUE
- if self.auto_list and not self.allow_none:
- self.default = []
-
- def with_name(self, name: str | CruDontChange) -> CruAttrDefBuilder:
- if name is not CruDontChange.VALUE:
- self.name = name
- return self
-
- def with_description(
- self, default_description: str | CruDontChange
- ) -> CruAttrDefBuilder:
- if default_description is not CruDontChange.VALUE:
- self.description = default_description
- return self
-
- def with_default(self, default: Any) -> CruAttrDefBuilder:
- if default is not CruDontChange.VALUE:
- self.default = default
- return self
-
- def with_default_factory(
- self,
- default_factory: CruAttrDefaultFactory | CruDontChange,
- ) -> CruAttrDefBuilder:
- if default_factory is not CruDontChange.VALUE:
- self.default_factory = default_factory
- return self
-
- def with_types(
- self,
- types: Iterable[type] | None | CruDontChange,
- ) -> CruAttrDefBuilder:
- if types is not CruDontChange.VALUE:
- self.types = None if types is None else list(types)
- return self
-
- def with_allow_none(self, allow_none: bool | CruDontChange) -> CruAttrDefBuilder:
- if allow_none is not CruDontChange.VALUE:
- self.allow_none = allow_none
- return self
-
- def with_auto_list(
- self, auto_list: bool | CruDontChange = True
- ) -> CruAttrDefBuilder:
- if auto_list is not CruDontChange.VALUE:
- self.auto_list = auto_list
- return self
-
- def with_constraint(
- self,
- /,
- allow_none: bool | CruDontChange = CruDontChange.VALUE,
- types: Iterable[type] | None | CruDontChange = CruDontChange.VALUE,
- default: Any = CruDontChange.VALUE,
- default_factory: CruAttrDefaultFactory | CruDontChange = CruDontChange.VALUE,
- auto_list: bool | CruDontChange = CruDontChange.VALUE,
- ) -> CruAttrDefBuilder:
- return (
- self.with_allow_none(allow_none)
- .with_types(types)
- .with_default(default)
- .with_default_factory(default_factory)
- .with_auto_list(auto_list)
- )
-
- def add_transformer(self, transformer: CruAttrTransformer) -> CruAttrDefBuilder:
- self.transformers.append(transformer)
- return self
-
- def clear_transformers(self) -> CruAttrDefBuilder:
- self.transformers.clear()
- return self
-
- def add_validator(self, validator: CruAttrValidator) -> CruAttrDefBuilder:
- self.validators.append(validator)
- return self
-
- def clear_validators(self) -> CruAttrDefBuilder:
- self.validators.clear()
- return self
-
- def with_override_transformer(
- self, override_transformer: CruAttrTransformer | None | CruDontChange
- ) -> CruAttrDefBuilder:
- if override_transformer is not CruDontChange.VALUE:
- self.override_transformer = override_transformer
- return self
-
- def with_override_validator(
- self, override_validator: CruAttrValidator | None | CruDontChange
- ) -> CruAttrDefBuilder:
- if override_validator is not CruDontChange.VALUE:
- self.override_validator = override_validator
- return self
-
- def is_valid(self) -> tuple[bool, str]:
- if not isinstance(self.name, str):
- return False, "Name must be a string!"
- if not isinstance(self.description, str):
- return False, "Default description must be a string!"
- if (
- not self.allow_none
- and self.default is None
- and self.default_factory is None
- ):
- return False, "Default must be set if allow_none is False!"
- return True, ""
-
- @staticmethod
- def _build(
- builder: CruAttrDefBuilder, auto_adjust_default: bool = True
- ) -> CruAttrDef:
- if auto_adjust_default:
- builder.auto_adjust_default()
-
- valid, err = builder.is_valid()
- if not valid:
- raise ValueError(err)
-
- def composed_transformer(value: Any, attr_def: CruAttrDef) -> Any:
- def transform_value(single_value: Any) -> Any:
- for transformer in builder.transformers:
- single_value = transformer(single_value, attr_def)
- return single_value
-
- if builder.auto_list:
- if not isinstance(value, list):
- value = [value]
- value = CruIterator(value).transform(transform_value).to_list()
-
- else:
- value = transform_value(value)
- return value
-
- type_set = None if builder.types is None else CruTypeSet(*builder.types)
-
- def composed_validator(value: Any, attr_def: CruAttrDef):
- def validate_value(single_value: Any) -> None:
- if type_set is not None:
- type_set.check_value(single_value, allow_none=builder.allow_none)
- for validator in builder.validators:
- validator(single_value, attr_def)
-
- if builder.auto_list:
- CruIterator(value).foreach(validate_value)
- else:
- validate_value(value)
-
- real_transformer = builder.override_transformer or composed_transformer
- real_validator = builder.override_validator or composed_validator
-
- default_factory = builder.default_factory
- if default_factory is None:
-
- def default_factory(_d):
- return copy.deepcopy(builder.default)
-
- d = CruAttrDef(
- builder.name,
- builder.description,
- default_factory,
- real_transformer,
- real_validator,
- )
- if builder.build_hook:
- builder.build_hook(d)
- return d
-
- def build(self, auto_adjust_default=True) -> CruAttrDef:
- c = copy.deepcopy(self)
- self.build_hook = None
- return CruAttrDefBuilder._build(c, auto_adjust_default)
-
-
-class CruAttrDefRegistry(CruUniqueKeyList[CruAttrDef, str]):
-
- def __init__(self) -> None:
- super().__init__(lambda d: d.name)
-
- def make_builder(self, name: str, default_description: str) -> CruAttrDefBuilder:
- b = CruAttrDefBuilder(name, default_description)
- b.build_hook = lambda a: self.add(a)
- return b
-
- def adopt(self, attr: CruAttr) -> CruAttr:
- d = self.get(attr.name)
- return d.adopt(attr)
-
-
-class CruAttrTable(CruUniqueKeyList[CruAttr, str]):
- def __init__(self, registry: CruAttrDefRegistry) -> None:
- self._registry: CruAttrDefRegistry = registry
- super().__init__(lambda a: a.name, before_add=registry.adopt)
-
- @property
- def registry(self) -> CruAttrDefRegistry:
- return self._registry
-
- def get_value_or(self, name: str, fallback: Any = CruNotFound.VALUE) -> Any:
- a = self.get_or(name, CruNotFound.VALUE)
- if a is CruNotFound.VALUE:
- return fallback
- return a.value
-
- def get_value(self, name: str) -> Any:
- a = self.get(name)
- return a.value
-
- def make_attr(
- self,
- name: str,
- value: Any = CruUseDefault.VALUE,
- /,
- description: str | None = None,
- ) -> CruAttr:
- d = self._registry.get(name)
- return d.make(value, description or d.description)
-
- def add_value(
- self,
- name: str,
- value: Any = CruUseDefault.VALUE,
- /,
- description: str | None = None,
- *,
- replace: bool = False,
- ) -> CruAttr:
- attr = self.make_attr(name, value, description)
- self.add(attr, replace)
- return attr