59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
from pathlib import Path
|
|
from typing import NamedTuple
|
|
|
|
from loguru import logger
|
|
|
|
|
|
class EnvFile(NamedTuple):
|
|
env_path: Path
|
|
config: dict[str, str]
|
|
env_type: str
|
|
|
|
def __repr__(self) -> str:
|
|
return f"EnvFile(type={self.env_type})"
|
|
|
|
|
|
class DependencyRule(NamedTuple):
|
|
child: str
|
|
dependency: str
|
|
|
|
|
|
def _get_indices_with_string(in_list: list[EnvFile], string: str) -> list[int]:
|
|
"""returns all indices of items in in_list, where item.env_type matches string"""
|
|
return [index for index, element in enumerate(in_list) if element.env_type == string]
|
|
|
|
|
|
def _swap_item_with_previous(in_list: list[EnvFile], index: int):
|
|
"""swaps item at index N with item at index N-1"""
|
|
assert index > 0, "cannot swap with negative index"
|
|
in_list[index], in_list[index - 1] = in_list[index - 1], in_list[index]
|
|
|
|
|
|
def is_rule_satisfied(in_list: list[EnvFile], rule: DependencyRule, swap=False) -> bool:
|
|
"""returns if the ordering in in_list is compliant with the given rule
|
|
|
|
if swap=True, some reordering will happen in case of a violated rule"""
|
|
|
|
child_indices = _get_indices_with_string(in_list, rule.child)
|
|
parent_indices = _get_indices_with_string(in_list, rule.dependency)
|
|
for child_index in child_indices:
|
|
for parent_index in parent_indices:
|
|
if not parent_index < child_index:
|
|
if swap:
|
|
_swap_item_with_previous(in_list, parent_index)
|
|
return False
|
|
return True
|
|
|
|
|
|
def sort_env_files_by_rule(env_list: list[EnvFile], rules: list[DependencyRule]) -> list[EnvFile]:
|
|
in_list = env_list.copy()
|
|
|
|
for _ in range(10_000):
|
|
rule_satisfied: list[bool] = []
|
|
for rule in rules:
|
|
rule_satisfied.append(is_rule_satisfied(in_list, rule, swap=True))
|
|
|
|
if all(rule_satisfied):
|
|
return in_list
|
|
logger.error("could not find order that satisfys all rules")
|
|
raise ValueError
|