feat: add merge for repository configuration

Signed-off-by: Konstantin Fickel <mail@konstantinfickel.de>
This commit is contained in:
Konstantin Fickel 2026-01-31 19:50:36 +01:00
parent 4dbd142c74
commit 1040c060f6
Signed by: kfickel
GPG key ID: A793722F9933C1A5
6 changed files with 477 additions and 33 deletions

View file

@ -1,6 +1,6 @@
from .localize import localize_stream_file
from .repostory_configuration import RepositoryConfiguration
from .localized_shard import LocalizedShard
from .repository_configuration import RepositoryConfiguration
__all__ = [
"RepositoryConfiguration",

View file

@ -7,7 +7,7 @@ from .extract_datetime import (
extract_datetime_from_marker_list,
)
from .localized_shard import LocalizedShard
from .repostory_configuration import RepositoryConfiguration
from .repository_configuration import RepositoryConfiguration
def localize_shard(
@ -25,7 +25,7 @@ def localize_shard(
if marker in config.markers:
marker_definition = config.markers[marker]
for placement in marker_definition.placements:
if set(placement.if_with) <= set(shard.markers):
if placement.if_with <= set(shard.markers):
dimension = config.dimensions[placement.dimension]
value = placement.value or marker

View file

@ -0,0 +1,107 @@
from __future__ import annotations
from typing import Optional
from pydantic import BaseModel
class Dimension(BaseModel):
display_name: str
comment: Optional[str] = None
propagate: bool = False
class MarkerPlacement(BaseModel):
if_with: set[str] = set()
dimension: str
value: str | None = None
class Marker(BaseModel):
display_name: str
placements: list[MarkerPlacement] = []
class RepositoryConfiguration(BaseModel):
dimensions: dict[str, Dimension]
markers: dict[str, Marker]
def merge_single_dimension(base: Dimension, second: Dimension) -> Dimension:
second_fields_set = getattr(second, "model_fields_set", set())
return Dimension(
display_name=second.display_name or base.display_name,
comment=base.comment if second.comment is None else second.comment,
propagate=second.propagate
if "propagate" in second_fields_set
else base.propagate,
)
def merge_dimensions(
base: dict[str, Dimension], second: dict[str, Dimension]
) -> dict[str, Dimension]:
merged: dict[str, Dimension] = dict(base)
for key, second_dimension in second.items():
if key in merged:
merged[key] = merge_single_dimension(merged[key], second_dimension)
else:
merged[key] = second_dimension
return merged
def _placement_identity(p: MarkerPlacement) -> tuple[frozenset[str], str]:
return (frozenset(p.if_with), p.dimension)
def merge_single_marker(base: Marker, second: Marker) -> Marker:
merged_display_name = second.display_name or base.display_name
merged_placements: list[MarkerPlacement] = []
seen: dict[tuple[frozenset[str], str], int] = {}
for placement in base.placements:
ident = _placement_identity(placement)
seen[ident] = len(merged_placements)
merged_placements.append(placement)
for placement in second.placements:
ident = _placement_identity(placement)
if ident in seen:
merged_placements[seen[ident]] = placement
else:
seen[ident] = len(merged_placements)
merged_placements.append(placement)
return Marker(display_name=merged_display_name, placements=merged_placements)
def merge_markers(
base: dict[str, Marker], second: dict[str, Marker]
) -> dict[str, Marker]:
merged: dict[str, Marker] = dict(base)
for key, second_marker in second.items():
if key in merged:
merged[key] = merge_single_marker(merged[key], second_marker)
else:
merged[key] = second_marker
return merged
def merge_repository_configuration(
base: RepositoryConfiguration, second: RepositoryConfiguration
) -> RepositoryConfiguration:
return RepositoryConfiguration(
dimensions=merge_dimensions(base.dimensions, second.dimensions),
markers=merge_markers(base.markers, second.markers),
)
__all__ = [
"Dimension",
"Marker",
"MarkerPlacement",
"RepositoryConfiguration",
"merge_repository_configuration",
]

View file

@ -1,28 +0,0 @@
from typing import Optional
from pydantic import BaseModel
class Dimension(BaseModel):
display_name: str
comment: Optional[str] = None
propagate: bool = False
class MarkerPlacement(BaseModel):
if_with: list[str] = []
dimension: str
value: str | None = None
class Marker(BaseModel):
display_name: str
placements: list[MarkerPlacement]
class RepositoryConfiguration(BaseModel):
dimensions: dict[str, Dimension]
markers: dict[str, Marker]
__all__ = ["Dimension", "Marker", "MarkerPlacement", "RepositoryConfiguration"]