<commit_before>from collections import namedtuple

from siebenapp.goaltree import Goals
from siebenapp.domain import EdgeType

selected = "select"
previous = "previous"
allowed_selects = {selected, previous, None}
GoalPrototype = namedtuple("GoalPrototype", "id name open children blockers select")


def _build_goal_prototype(
    goal_id, name, is_open, children, blockers, select
):  # pylint: disable=too-many-arguments
    children = [] if children is None else children
    blockers = [] if blockers is None else blockers
    assert isinstance(children, list)
    assert select in allowed_selects
    return GoalPrototype(goal_id, name, is_open, children, blockers, select)


def open_(goal_id, name, children=None, blockers=None, select=None):
    return _build_goal_prototype(goal_id, name, True, children, blockers, select)


def clos_(goal_id, name, children=None, blockers=None, select=None):
    return _build_goal_prototype(goal_id, name, False, children, blockers, select)


def build_goaltree(*goal_prototypes, message_fn=None):
    goals = [(g.id, g.name, g.open) for g in goal_prototypes]
    edges = [
        (g.id, e, EdgeType.PARENT) for g in goal_prototypes for e in g.children
    ] + [(g.id, e, EdgeType.BLOCKER) for g in goal_prototypes for e in g.blockers]
    selection = {g.id for g in goal_prototypes if g.select == selected}
    prev_selection = {g.id for g in goal_prototypes if g.select == previous}
    assert len(selection) == 1
    assert len(prev_selection) <= 1
    selection_id = selection.pop()
    return Goals.build(
        goals,
        edges,
        [
            ("selection", selection_id),
            (
                "previous_selection",
                prev_selection.pop() if prev_selection else selection_id,
            ),
        ],
        message_fn,
    )
<commit_msg>Test DSL: use dataclass instead of namedtuple<commit_after>from dataclasses import dataclass
from typing import List, Optional

from siebenapp.domain import EdgeType
from siebenapp.goaltree import Goals

selected = "select"
previous = "previous"
allowed_selects = {selected, previous, None}


@dataclass(frozen=True)
class GoalPrototype:
    id: int
    name: str
    open: bool
    children: List[int]
    blockers: List[int]
    select: Optional[str]


def _build_goal_prototype(
    goal_id, name, is_open, children, blockers, select
):  # pylint: disable=too-many-arguments
    children = [] if children is None else children
    blockers = [] if blockers is None else blockers
    assert isinstance(children, list)
    assert select in allowed_selects
    return GoalPrototype(goal_id, name, is_open, children, blockers, select)


def open_(goal_id, name, children=None, blockers=None, select=None):
    return _build_goal_prototype(goal_id, name, True, children, blockers, select)


def clos_(goal_id, name, children=None, blockers=None, select=None):
    return _build_goal_prototype(goal_id, name, False, children, blockers, select)


def build_goaltree(*goal_prototypes, message_fn=None):
    goals = [(g.id, g.name, g.open) for g in goal_prototypes]
    edges = [
        (g.id, e, EdgeType.PARENT) for g in goal_prototypes for e in g.children
    ] + [(g.id, e, EdgeType.BLOCKER) for g in goal_prototypes for e in g.blockers]
    selection = {g.id for g in goal_prototypes if g.select == selected}
    prev_selection = {g.id for g in goal_prototypes if g.select == previous}
    assert len(selection) == 1
    assert len(prev_selection) <= 1
    selection_id = selection.pop()
    return Goals.build(
        goals,
        edges,
        [
            ("selection", selection_id),
            (
                "previous_selection",
                prev_selection.pop() if prev_selection else selection_id,
            ),
        ],
        message_fn,
    )

{'fraction_non_alphanumeric': 0.09447368421052632, 'fraction_numerical': 0.0010526315789473684, 'mean_word_length': 3.3891454965357966, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '476982', 'n_tokens_mistral': 1210, 'n_tokens_neox': 1143, 'n_words': 348}