ahbicht.expressions package
Submodules
ahbicht.expressions.ahb_expression_evaluation module
This module evaluates the parsed ahb expression tree. The AhbExpressionTransformer defines the rules how the different parts of the parsed tree are handled.
The used terms are defined in the README.md.
- class ahbicht.expressions.ahb_expression_evaluation.AhbExpressionTransformer(ahb_context: AhbContext)[source]
Bases:
TransformerTransformer, that evaluates the trees built from the ahb expressions. The input are the conditions as defined in the AHBs in the form of ConditionNodes. It returns a list of the separated requirement indicators with their respective condition expressions already evaluated to booleans.
- PREFIX_OPERATOR(prefix_operator: Token) PrefixOperator[source]
Returns the prefix operator.
- ahb_expression(list_of_single_requirement_indicator_expressions: list[AhbExpressionEvaluationResult | Awaitable[AhbExpressionEvaluationResult]]) Awaitable[AhbExpressionEvaluationResult][source]
Returns the requirement indicator with its condition expressions already evaluated to booleans. If there are more than one modal mark the first whose conditions are fulfilled is returned or the last of the list if they are all unfulfilled.
- requirement_indicator(requirement_indicator: PrefixOperator | ModalMark) AhbExpressionEvaluationResult[source]
If there is no condition expression but only a requirement indicator, all evaluations are automatically set to True.
- single_requirement_indicator_expression(requirement_indicator: PrefixOperator | ModalMark, condition_expression: str) Awaitable[AhbExpressionEvaluationResult][source]
Evaluates the condition expression of the respective requirement indicator expression and returns a list of the separated requirement indicators with their results of the condition check.
- async ahbicht.expressions.ahb_expression_evaluation.evaluate_ahb_expression_tree(parsed_tree: Tree[Token], ahb_context: AhbContext) AhbExpressionEvaluationResult[source]
Evaluates the tree built from the ahb expressions with the help of the AhbExpressionTransformer.
- Parameters:
parsed_tree – Tree
ahb_context – AhbContext providing all evaluators and data
- Returns:
the result of the overall condition check (including requirement constraints, format constraints, several modal marks)
ahbicht.expressions.ahb_expression_parser module
This module parses a given ahb expression like “Muss [59]U([123]O[456]) Soll [53]” or “X [59]U[53]” using the parsing library lark: https://lark-parser.readthedocs.io/en/latest/ The goal is to separate the requirement indicator (i.e. Muss, Soll, Kann, X, O, U) from the condition expression and also several modal marks expressions if there are more than one.
ahbicht.expressions.base_transformer module
This module implements the base class for the condition check Transformers that evaluate trees build from the condition_expression_parser.
- class ahbicht.expressions.base_transformer.BaseTransformer(input_values: Mapping[str, SupportedArgumentNode])[source]
Bases:
Transformer,ABC,Generic[SupportedArgumentNode,SupportedReturn]Transformer that evaluates the trees built from the format constraint expressions. The input are the evaluated format constraint conditions in the form of ConditionNodes.
After two nodes are evaluated in a composition, the resulting node has the node type EvalutatedComposition. The return value is a ConditionNode whose attribute format_constraint_fulfilled describes whether the format constraint expression is fulfilled or not.
- abstract and_composition(left: SupportedArgumentNode, right: SupportedArgumentNode) SupportedReturn[source]
Evaluates logical and_composition
ahbicht.expressions.condition_expression_parser module
This module parses a condition expression like “[59] U ([123] O [456])” into a tree structure using the parsing library lark: https://lark-parser.readthedocs.io/en/latest/
The used terms are defined in the README_conditions.md.
- async ahbicht.expressions.condition_expression_parser.extract_categorized_keys(condition_expression: str, resolve_packages: bool = False, resolve_time_conditions: bool = False, replace_time_conditions: bool = False, ahb_context: AhbContext | None = None) CategorizedKeyExtract[source]
Parses the given condition expression and returns CategorizedKeyExtract as a template for content evaluation. :param ahb_context: required when resolve_packages=True; provides the package resolver
- ahbicht.expressions.condition_expression_parser.extract_categorized_keys_from_tree(tree_or_list: Tree[Token] | list[str], sanitize: bool = False) CategorizedKeyExtract[source]
find different types of condition nodes inside the given tree or list of keys. The types are differentiated by their number range. See ‘Allgemeine Festlegungen’ from EDI@Energy.
ahbicht.expressions.expression_builder module
Module to create expressions from scratch.
- class ahbicht.expressions.expression_builder.ExpressionBuilder[source]
Bases:
Generic[SupportedNodes],ABCClass that helps to create expression strings. It separates the logical operation (connect two conditions with a logical operator) from the implementation which might differ depending on the condition type and other circumstances.
- abstract get_expression() str | None[source]
Returns the expression string or none if there is no expression. :return:
- abstract land(other: SupportedNodes) ExpressionBuilder[SupportedNodes][source]
connects the expression with a logical and (LAND) :param other: condition or expression to be connected to the expression :return:
- abstract lor(other: SupportedNodes) ExpressionBuilder[SupportedNodes][source]
connects the expression with a logical or (LOR) :param other: condition or expression to be connected to the expression :return:
- abstract xor(other: SupportedNodes) ExpressionBuilder[SupportedNodes][source]
connects the expression with an exclusive or (XOR) :param other: condition or expression to be connected to the expression :return:
- class ahbicht.expressions.expression_builder.FormatConstraintExpressionBuilder(init_condition_or_expression: EvaluatedComposition | UnevaluatedFormatConstraint | str | None | RequirementConstraint | Hint | Type[ConditionNode])[source]
Bases:
ExpressionBuilder[EvaluatedComposition|UnevaluatedFormatConstraint|str|None|RequirementConstraint|Hint|Type[ConditionNode]]Class to create expressions that consist of FormatConstraints
- get_expression() str | None[source]
Returns the expression string or none if there is no expression. :return:
- land(other: EvaluatedComposition | UnevaluatedFormatConstraint | str | None | RequirementConstraint | Hint | Type[ConditionNode]) FormatConstraintExpressionBuilder[source]
connects the expression with a logical and (LAND) :param other: condition or expression to be connected to the expression :return:
- lor(other: EvaluatedComposition | UnevaluatedFormatConstraint | str | None | RequirementConstraint | Hint | Type[ConditionNode]) FormatConstraintExpressionBuilder[source]
connects the expression with a logical or (LOR) :param other: condition or expression to be connected to the expression :return:
- xor(other: EvaluatedComposition | UnevaluatedFormatConstraint | str | None | RequirementConstraint | Hint | Type[ConditionNode]) FormatConstraintExpressionBuilder[source]
connects the expression with an exclusive or (XOR) :param other: condition or expression to be connected to the expression :return:
- class ahbicht.expressions.expression_builder.FormatErrorMessageExpressionBuilder(init_condition: EvaluatedFormatConstraint)[source]
Bases:
ExpressionBuilder[EvaluatedFormatConstraint]Class to build the error messages for the format constraint evaluation.
- get_expression() str | None[source]
Returns the expression string or none if there is no expression. :return:
- land(other: EvaluatedFormatConstraint) FormatErrorMessageExpressionBuilder[source]
connects the expression with a logical and (LAND) :param other: condition or expression to be connected to the expression :return:
- lor(other: EvaluatedFormatConstraint) FormatErrorMessageExpressionBuilder[source]
connects the expression with a logical or (LOR) :param other: condition or expression to be connected to the expression :return:
- xor(other: EvaluatedFormatConstraint) FormatErrorMessageExpressionBuilder[source]
connects the expression with an exclusive or (XOR) :param other: condition or expression to be connected to the expression :return:
- class ahbicht.expressions.expression_builder.HintExpressionBuilder(init_condition: _ClassesWithHintAttribute | None)[source]
Bases:
ExpressionBuilder[ClassesWithHintAttribute]Allows connecting hints with logical operations.
- get_expression() str | None[source]
Returns the expression string or none if there is no expression. :return:
- static get_hint_text(hinty_object: _ClassesWithHintAttribute | None) str | None[source]
get the hint from a Hint instance or plain string :param hinty_object: :return: hint if there is any, None otherwise
- land(other: _ClassesWithHintAttribute | None) HintExpressionBuilder[ClassesWithHintAttribute][source]
connects the expression with a logical and (LAND) :param other: condition or expression to be connected to the expression :return:
- lor(other: _ClassesWithHintAttribute | None) HintExpressionBuilder[ClassesWithHintAttribute][source]
connects the expression with a logical or (LOR) :param other: condition or expression to be connected to the expression :return:
- xor(other: _ClassesWithHintAttribute | None) HintExpressionBuilder[ClassesWithHintAttribute][source]
connects the expression with an exclusive or (XOR) :param other: condition or expression to be connected to the expression :return:
ahbicht.expressions.expression_resolver module
This module makes it possible to parse expressions including all their subexpressions, if present. for example ahb_expressions which contain condition_expressions or condition_expressions which contain packages. Parsing expressions that are nested into other expressions is referred to as “resolving”.
- class ahbicht.expressions.expression_resolver.AhbExpressionResolverTransformer(visit_tokens: bool = True)[source]
Bases:
TransformerResolves the condition_expressions inside an ahb_expression.
- class ahbicht.expressions.expression_resolver.PackageExpansionTransformer(include_package_repeatabilities: bool = False, ahb_context: AhbContext | None = None)[source]
Bases:
TransformerThe PackageExpansionTransformer expands packages inside a tree to condition expressions by using a PackageResolver. :param include_package_repeatabilities: Flag to include the repeatabilities of the packages.
At this point, we implemented this flag to include a workaround for the repeatability of packages. We will convert the package repeatability to a condition expression and add it to the condition expression of the package (e.g. [2P1..2] -> [2P]U[1..2]). Thus, we can evaluate the repeatability of the package as a condition expression by injecting a suitable condition expression evaluator. Caution: we losen the constraints on condition keys to be able to that. This is a workaround and should be replaced by a more sophisticated solution which truly deals with package repetitions in the future (cf. https://github.com/Hochfrequenz/ahbicht/pull/565).
- class ahbicht.expressions.expression_resolver.TimeConditionTransformer(replace_time_conditions: bool = True)[source]
Bases:
TransformerThere are two options which are chosen by the boolean replace_time_conditions: i: The time conditions are resolved as provided in the “Allgemeine Festlegungen”. ii: The TimeConditionEvaluator replaces “time conditions” (aka “UB1”, “UB2”, “UB3”) with evaluatable format constraints. This is not what BDEW suggests us to do in the “Allgemeine Festlegungen”. BDEW says that “UBx” conditions have to be expanded just like packages: For example “UB1” shall be expanded to “([931] ∧ [932] [490]) ⊻ ([931] ∧ [933] [491])”.
This just doesn’t work out for multiple reasons:
1. Other than _all_ the other requirement constraints RC 490, 491, 492 and 493 are self-referencing. While “normal” RCs act like “You have to provide this (“Foo”) if the other thing (“Bar”) meets a requirement”, the 49x RCs are of kind “This (“Foo”) has to meet certain requirements (e.g. the end of a German day), regardless of the other things (“Bar”). So the usual requirement constraint evaluation approach (“Search for Bar and derive from there what it means for this (Foo)”) won’t work and is overly complicated, too. Also, if the pseudo requirement constraint 490-493 is UNFULFILLED, this does _not_ mean that the data must not be provided which is also a different behaviour compared to usual requirement constraints.
2. No one who understands the concept of datetime+offset and is able to parse datetime+offset nowadays cares, if you use (“x datetime” with an “0 offset”) or (“x+z datetime” that has a “z offset”) instead. It’s just BDEWs home-brewed EDIFACT serialization rule that, for no real reason, restricts us to set the offset z to “+00:00” always. https://imgflip.com/i/65giq5
AHBicht won’t restrict you to use datetime offset==”+00:00”. Because we don’t care and you should not care. The scope of AHBicht is to evaluate expressions and data, not to obey pointless BDEW EDIFACT rules. Also this default transformer won’t expand the UBx conditions into something which is overly complicated and in the end does really fit (for above reasons).
That being said… the thing that actually happens is: UBx will be replaced with a format constraint (plus a requirement constraint in case of UB3) that is fulfilled, if and only if the value provided obeys the original meaning of UBx. So the data provided will be evaluated just as you’d expect them to be evaluated but without all the bureaucracy.
Condition UB1 checks if the datetime provided is the (inclusive) start / (exclusive) end of a German “Stromtag”. Condition UB1 will be replaced with the format constraint 932.
Condition UB2 checks if the datetime provided is the (inclusive) start / (exclusive) end of a German “Gastag”. Condition UB2 will be replaced with the format constraint 934.
Condition UB3 checks if the datetime provided is the (inclusive) start / (exclusive) end of a German “Stromtag” if the receiver is from division electricity (RC 492) or a “Gastag” if a receiver is from division gas (RC 493). Condition UB3 will be replaced with two XOR connected format constraints, each of them coupled to a requirement constraint for the respective division.
- async ahbicht.expressions.expression_resolver.expand_packages(parsed_tree: Tree[Token], include_package_repeatabilities: bool = False, ahb_context: AhbContext | None = None) Tree[Token][source]
Replaces all the “short” packages in parser_tree with the respective “long” condition expressions
- ahbicht.expressions.expression_resolver.expand_time_conditions(parsed_tree: Tree[Token], replace_time_conditions: bool = True) Tree[Token][source]
Replaces either all the “short” time conditions in parser_tree with the respective “long” condition expressions or replaces all the time conditions “UBx” with format constraints (and requirements constraints for UB3)
- async ahbicht.expressions.expression_resolver.parse_expression_including_unresolved_subexpressions(expression: str, resolve_packages: bool = False, resolve_time_conditions: bool = True, replace_time_conditions: bool = True, include_package_repeatabilities: bool = False, ahb_context: AhbContext | None = None) Tree[Token][source]
Parses expressions and resolves its subexpressions, for example condition_expressions in ahb_expressions or packages in condition_expressions. :param expression: a syntactically valid ahb_expression or condition_expression :param resolve_packages: if true resolves also the packages in the condition_expressions :param resolve_time_conditions: if true resolves also the time conditions in the condition_expressions :param replace_time_conditions: if true the time conditions “UBx” are replaced with format constraints :param include_package_repeatabilities: if true we include the repeatabilities of the packages take a look at PackageExpansionTransformer for a better understanding why we included this flag. :param ahb_context: required when resolve_packages=True; provides the package resolver
ahbicht.expressions.format_constraint_expression_evaluation module
This module evaluates the format constraint expression tree using EvaluatedFormatConstraints. The FormatConstraintTransformer defines the rules how the different parts and nodes of the format constraint expression tree are handled.
The used terms are defined in the README_conditions.md.
- class ahbicht.expressions.format_constraint_expression_evaluation.FormatConstraintTransformer(input_values: Mapping[str, SupportedArgumentNode])[source]
Bases:
BaseTransformerTransformer that evaluates the trees built from the format constraint expressions. The input are the evaluated format constraint conditions in the form of EvaluatedFormatConstraints. The return value is an EvaluatedFormatConstraint whose attribute format_constraint_fulfilled describes whether the format constraint expression is fulfilled or not.
- and_composition(left: EvaluatedFormatConstraint, right: EvaluatedFormatConstraint) EvaluatedFormatConstraint[source]
Evaluates logical and_composition
- or_composition(left: EvaluatedFormatConstraint, right: EvaluatedFormatConstraint) EvaluatedFormatConstraint[source]
Evaluates logical (inclusive) or_composition
- xor_composition(left: EvaluatedFormatConstraint, right: EvaluatedFormatConstraint) EvaluatedFormatConstraint[source]
Evaluates exclusive xor_composition
- ahbicht.expressions.format_constraint_expression_evaluation.evaluate_format_constraint_tree(parsed_tree: Tree[Token], input_values: Mapping[str, EvaluatedFormatConstraint]) EvaluatedFormatConstraint[source]
Evaluates the tree built from the format constraint expressions with the help of the FormatConstraintTransformer.
- Parameters:
parsed_tree – Tree
input_values – dict(condition_key, EvaluatedFormatConstraint) :return: EvaluatedFormatConstraint
- async ahbicht.expressions.format_constraint_expression_evaluation.format_constraint_evaluation(format_constraints_expression: str | None, ahb_context: AhbContext) FormatConstraintEvaluationResult[source]
Evaluation of the format constraint expression.
ahbicht.expressions.hints_provider module
Module to provide the condition hints from their respective json file as dictionary with the condition keys as keys and the hint texts as values.
- class ahbicht.expressions.hints_provider.ContentEvaluationResultBasedHintsProvider(evaluatable_data: EvaluatableData[Any] | None = None)[source]
Bases:
HintsProviderA hints provider that expects the evaluatable data to contain a ContentEvalutionResult as edifact seed. Other than the DictBasedHintsProvider the outcome is not dependent on the initialization but on the evaluatable data.
- class ahbicht.expressions.hints_provider.DictBasedHintsProvider(results: Mapping[str, str | None])[source]
Bases:
HintsProviderA Hints Provider that is based on hardcoded values from a dictionary
- class ahbicht.expressions.hints_provider.HintsProvider[source]
Bases:
ABCA Hints Provider provides plain text hints for a given condition number. This class provides the hints from the respective json file (defined by EdifactFormatVersion and EdifactFormat) as dictionary with the condition keys as keys and the hint texts as values.
- edifact_format: EdifactFormat = NotImplementedError('The inheriting class needs to define a format to which it is applicable.')
- edifact_format_version: EdifactFormatVersion = NotImplementedError('The inheriting class needs to define a format version.')
- class ahbicht.expressions.hints_provider.JsonFileHintsProvider(edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, file_path: Path)[source]
Bases:
DictBasedHintsProviderThe JsonFileHintsProvider loads hints from a JSON file.
- ahbicht.expressions.hints_provider.PACKAGE_1P_HINT_TEXT: str = 'Hinweis: Das ist das Standardpaket, wenn keine Bedingung zum Tragen kommt, z.B. im COM-Segment.'
The hardcoded hint text for package ‘1P’.
Package ‘1P’ is resolved to a synthetic hint with condition key PACKAGE_1P_HINT_KEY (9999). This hint text is returned for that key, regardless of any configuration.
See PACKAGE_1P_HINT_KEY in condition_node_distinction.py for the full explanation of why we use a synthetic hint key for package ‘1P’.
ahbicht.expressions.package_expansion module
Package Expansion is the process of finding the condition expression which was abbreviated by using a package. e.g. if inside a tree “[123P]” is replaced by “[1] U ([2] O [3])”.
- class ahbicht.expressions.package_expansion.ContentEvaluationResultBasedPackageResolver(evaluatable_data: EvaluatableData[Any] | None = None)[source]
Bases:
PackageResolverA package resolver that expects the evaluatable data to contain a ContentEvalutionResult as edifact seed. Other than the DictBasedPackageResolver the outcome is not dependent on the initialization but on the evaluatable data.
- async get_condition_expression(package_key: str) PackageKeyConditionExpressionMapping[source]
Returns a condition expression (e.g. “[1] U ([2] O [3])”) for the given package_key (e.g. “123P”) Returns None in the package_expression if the package is unresolvable (see ‘has_been_resolved_successfully’). :param package_key: The unique (integer) key of the package. The ‘P’ suffix is required. :return:
- class ahbicht.expressions.package_expansion.DictBasedPackageResolver(results: Mapping[str, str | None])[source]
Bases:
PackageResolverA Package Resolver that is based on hardcoded values from a dictionary
- async get_condition_expression(package_key: str) PackageKeyConditionExpressionMapping[source]
Returns a condition expression (e.g. “[1] U ([2] O [3])”) for the given package_key (e.g. “123P”) Returns None in the package_expression if the package is unresolvable (see ‘has_been_resolved_successfully’). :param package_key: The unique (integer) key of the package. The ‘P’ suffix is required. :return:
- class ahbicht.expressions.package_expansion.JsonFilePackageResolver(edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, file_path: Path)[source]
Bases:
DictBasedPackageResolverThe JsonFilePackageResolver loads package keys/expressions from a JSON file.
- class ahbicht.expressions.package_expansion.PackageResolver[source]
Bases:
ABCA package resolver provides condition expressions for given package keys.
- edifact_format: EdifactFormat = NotImplementedError('The inheriting package resolver needs to define a format to which it is applicable.')
the format for which the resolver may be used
- edifact_format_version: EdifactFormatVersion = NotImplementedError('The inheriting package resolver needs to define a format version.')
the format version for which the resolver may be used
- abstract async get_condition_expression(package_key: str) PackageKeyConditionExpressionMapping[source]
Returns a condition expression (e.g. “[1] U ([2] O [3])”) for the given package_key (e.g. “123P”) Returns None in the package_expression if the package is unresolvable (see ‘has_been_resolved_successfully’). :param package_key: The unique (integer) key of the package. The ‘P’ suffix is required. :return:
ahbicht.expressions.requirement_constraint_expression_evaluation module
This module evaluates the parsed condition expression tree regarding the requirement constraints using ConditionNodes. The RequirementConstraintTransformer defines the rules how the different parts and nodes of the condition expression tree are handled.
The used terms are defined in the README_conditions.md.
- class ahbicht.expressions.requirement_constraint_expression_evaluation.RequirementConstraintTransformer(input_values: Mapping[str, SupportedArgumentNode])[source]
Bases:
BaseTransformerTransformer that evaluates the trees built from the condition expressions regarding the requirement constraints. The input are the conditions as defined in the AHBs in the form of ConditionNodes. In the case of a Bedingung/RequirementConstraint already evaluated for the single condition. Hints are evaluated as neutral element in the boolean logic: and_composition: True, or_composition: False.
After two nodes are evaluated in a composition, the resulting node has the node type EvalutatedComposition. The return value is a ConditionNode whose attribute conditions_fulfilled describes whether it is a required field, its hints are the gathered hints and its format_constraint_expression contains the gathered format constraints for the field in a newly built expression.
- and_composition(left: RequirementConstraint | UnevaluatedFormatConstraint | Hint, right: RequirementConstraint | UnevaluatedFormatConstraint | Hint) EvaluatedComposition[source]
Evaluates logical and_composition
- or_composition(left: ConditionNode, right: ConditionNode) EvaluatedComposition[source]
Evaluates logical (inclusive) or_composition
- then_also_composition(left: Type[ConditionNode], right: Type[ConditionNode]) EvaluatedComposition[source]
A “then also” composition is typically used for format constraints. It connects an evaluable expression with a format constraint. If the conditions_fulfilled attribute evaluates to true, then also the attached format constraint has to be fulfilled.
- xor_composition(left: ConditionNode, right: ConditionNode) EvaluatedComposition[source]
Evaluates exclusive xor_composition
- ahbicht.expressions.requirement_constraint_expression_evaluation.evaluate_requirement_constraint_tree(parsed_tree: Tree[Token], input_values: Mapping[str, RequirementConstraint | UnevaluatedFormatConstraint | Hint]) EvaluatedComposition[source]
Evaluates the tree built from the expressions with the help of the ConditionsTransformer.
- Parameters:
parsed_tree – Tree
input_values – dict(condition_key, ConditionNode) :return: EvaluatedComposition
- async ahbicht.expressions.requirement_constraint_expression_evaluation.requirement_constraint_evaluation(condition_expression: str | Tree[Token], ahb_context: AhbContext) RequirementConstraintEvaluationResult[source]
Evaluation of the condition expression in regard to the requirement conditions (rc). The condition expression can either be a string that still needs to be parsed as condition expression or a tree that has already been parsed. :param ahb_context: AhbContext providing all evaluators and data
ahbicht.expressions.sanitizer module
contains a function to sanitize user input/expressions from the AHBs
Module contents
instantiates a “global” logger for all parsing related stuff
- exception ahbicht.expressions.InvalidExpressionError(error_message: str, invalid_expression: str | None = None)[source]
Bases:
BaseExceptionIs raised when an expression is well-formed but invalid. A syntactical error leads to a SyntaxError during parsing with lark whereas this exception occurs during evaluation.