Experimenting with RuleSet, future configuration merger

This commit is contained in:
MaXFeeD
2025-06-13 20:46:00 +03:00
parent 810927cf52
commit 50fd351d6a
+94
View File
@@ -0,0 +1,94 @@
from functools import lru_cache
from typing import (TYPE_CHECKING, Any, Dict, MutableSequence, MutableSet,
Optional, overload, override)
from .utils import ensure_not_whitespace
if TYPE_CHECKING:
from .config import Config
class RuleSet:
rules: Dict[str, MutableSet[str]]
rule_values: MutableSet[str]
def __init__(self, prototype_set: Optional['RuleSet'] = None) -> None:
self.rules = dict()
self.rule_values = set()
if prototype_set:
self.extend_with_rules(prototype_set)
def append_rule(self, rule: str, *values: str) -> None:
if not rule in self.rules:
self.rules[rule] = set()
rules = self.rules[rule]
for value in values:
if value in rules:
continue
if value in self.rule_values:
raise ValueError(f"Rule {rule} contains value {value!r} which is already occupied by another rule!")
rules.add(value)
def remove_rule(self, rule: str) -> None:
if not rule in self.rules:
return
for value in self.rules[rule]:
self.rule_values.remove(value)
del self.rules[rule]
def extend_with_rules(self, set: 'RuleSet') -> None:
for rule in set.rules:
self.append_rule(rule, *set.rules[rule])
def rule_of(self, value: str) -> Optional[str]:
if not value in self.rule_values:
return
for rule in self.rules:
for rule_value in self.rules[rule]:
if value == rule_value:
return rule
def bisect_values(self, properties: MutableSequence[str], *values: str) -> None:
for value in values:
rule = self.rule_of(value)
if not rule or not rule in self.rules:
continue
for rule_value in self.rules[rule]:
if rule_value in properties:
properties.remove(rule_value)
for value in values:
properties.append(value)
def remove_values(self, properties: MutableSequence[str], rule: str) -> None:
if not rule in self.rules:
return
for value in self.rules[rule]:
if value in properties:
properties.remove(value)
def is_relevant(self, properties: MutableSequence[str], value_set: str, allow_unresolved_properties: bool = True) -> bool:
if not ensure_not_whitespace(value_set) or value_set == "*":
return True
values = value_set.split("-")
for value in values:
if not value in properties:
return False
if not allow_unresolved_properties and not value in self.rule_values:
# Most likely a console property that cannot be checked here.
return False
return True
TOOLCHAIN_RULE_SET = RuleSet()
TOOLCHAIN_RULE_SET.append_rule("package_type", "develop", "release")
TOOLCHAIN_RULE_SET.append_rule("native_architecture", "arm", "arm64", "x86", "x86_64")
@lru_cache(maxsize=4096)
def get_config_rule_set(type: Optional[type['Config']]):
if not type:
if not TYPE_CHECKING:
from .config import Config
type = Config
class RuleSetConfig(type):
pass
return RuleSetConfig