maus package

Subpackages

Submodules

maus.cli module

the maus cli tool

maus.division_helper module

division helper is a module that allow to distinguish electricity (“Strom”) and gas (“Gas”)

class maus.division_helper.Division(value)[source]

Bases: str, Enum

the possibility to distinguish between electricity and gas

ELECTRICITY = 'ELECTRICITY'

strom

GAS = 'GAS'

gas

maus.division_helper.get_division(field_name: str | None) Division | None[source]

returns a division if the field name is definitly from that division, None otherwise

maus.division_helper.is_electricity_name(field_name: str, _is_recursive: bool = False) bool | None[source]

returns true iff the field name is definitely a strom field

maus.division_helper.is_gas_name(field_name: str, _is_recursive: bool = False) bool | None[source]

returns true iff the field name is definitely a gas field

maus.edifact module

This module manages EDIFACT related stuff. It’s basically a helper module to avoid stringly typed parameters.

class maus.edifact.EdiMetaData(*, pruefidentifikator: str, edifact_format: EdifactFormat = _Nothing.NOTHING, edifact_format_version: EdifactFormatVersion)[source]

Bases: object

a container that contains edifact-related metadata

edifact_format: EdifactFormat

The Edifact Format, e.g. ‘UTILMD’

edifact_format_version: EdifactFormatVersion

The Edifact Format Version, e.g. ‘FV2210’

pruefidentifikator: str

The pruefidentifikator, e.g. ‘11042’

class maus.edifact.EdifactFormat(value)[source]

Bases: str, Enum

existing EDIFACT formats

APERAK = 'APERAK'
COMDIS = 'COMDIS'

communication dispute

CONTRL = 'CONTRL'

control messages

IFTSTA = 'IFTSTA'

Multimodaler Statusbericht

INSRPT = 'INSRPT'

Prüfbericht

INVOIC = 'INVOIC'

invoice

MSCONS = 'MSCONS'

meter readings

ORDCHG = 'ORDCHG'

changing an order

ORDERS = 'ORDERS'

orders

ORDRSP = 'ORDRSP'

orders response

PARTIN = 'PARTIN'

market partner data

PRICAT = 'PRICAT'

price catalogue

QUOTES = 'QUOTES'

quotes

REMADV = 'REMADV'

zahlungsavis

REQOTE = 'REQOTE'

request quote

UTILMD = 'UTILMD'

utilities master data

UTILTS = 'UTILTS'

formula

class maus.edifact.EdifactFormatVersion(value)[source]

Bases: str, Enum

One format version refers to the period in which an AHB is valid.

FV2104 = 'FV2104'

valid from 2021-04-01 until 2021-10-01

FV2110 = 'FV2110'

valid from 2021-10-01 until 2022-04-01

FV2210 = 'FV2210'

valid from 2022-10-01 onwards (“MaKo 2022”, was 2204 previously)

FV2304 = 'FV2304'

valid from 2023-04-01 onwards

FV2310 = 'FV2310'

valid from 2023-10-01 onwards

FV2404 = 'FV2404'

valid from 2024-04-01 onwards

maus.edifact.get_current_edifact_format_version() EdifactFormatVersion[source]

returns the edifact_format_version that is valid as of now

maus.edifact.get_edifact_format_version(key_date: datetime) EdifactFormatVersion[source]
Returns:

the edifact format version that is valid on the specified key date

maus.edifact.get_format_of_pruefidentifikator(pruefidentifikator: str) EdifactFormat[source]

returns the format corresponding to a given pruefi

maus.edifact.is_edifact_boilerplate(segment_code: str | None) bool[source]

returns true iff this segment is not relevant in a sense that it has to be validated or merged with the AHB

maus.maus_provider module

MAUS s (plural of MAUS) are data structures which are structurally equivalent to the maus.DeepAnwendungshandbuch. For more information see the MAUS repo and its documentation: https://github.com/Hochfrequenz/mig_ahb_utility_stack/ A MAUS Provider is a class that returns MAUS s’ from what ever data source the implementation prefers. The MAUS provider is supposed to be used with dependency injection.

class maus.maus_provider.FileBasedMausProvider(base_path: Path, encoding: str = 'utf-8')[source]

Bases: MausProvider

A MAUS provider that uses the file system to retrieve MAUS s.

get_maus(edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str) DeepAnwendungshandbuch | None[source]

Return a MAUS for the given parameters. returns None if the requested MAUS is not available.

abstract to_path(edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str) Path[source]

returns the path of the maus file relative to the given parameters.

class maus.maus_provider.MausProvider[source]

Bases: ABC

A MausProvider is a class that provides MAUS’ (Deep Anwendungshandbuch) to calling code.

abstract get_maus(edifact_format: EdifactFormat, edifact_format_version: EdifactFormatVersion, pruefidentifikator: str) DeepAnwendungshandbuch | None[source]

Return a MAUS for the given parameters. returns None if the requested MAUS is not available.

maus.mig_ahb_matching module

MAUS is the MIG AHB Utility stack. This module contains methods to merge data from Message Implementation Guide and Anwendungshandbuch

maus.mig_ahb_matching.merge_lines_with_same_data_element(ahb_lines: Sequence[AhbLine], first_stack: EdifactStack | None) DataElement[source]

Merges lines that have the same data element into a single data element instance which is returned

maus.mig_ahb_matching.to_deep_ahb(flat_ahb: FlatAnwendungshandbuch, segment_group_hierarchy: SegmentGroupHierarchy, mig_reader: MigReader) DeepAnwendungshandbuch[source]

Converts a flat ahb into a nested ahb using the provided segment hierarchy

maus.navigation module

the navigation module is contains models and code that allow to “navigate” through the AHB and MIG structure. I.e. it allows to loop over an Anwendungshandbuch and “remember” which turns we took in the MIG structure (each turn is a AhbLocationLayer) in order to arrive at a certain line of the AHB. This information is stored in an AhbLocation.

class maus.navigation.AhbLocation(*, layers: List[AhbLocationLayer], segment_code: str | None = None, data_element_id: str | None = None, qualifier: str | None = None)[source]

Bases: object

An ahb location describes where in a SegmentGroupHierarchy an AhbLine is located. The position is determined by the opening segments and qualifiers that have “passed by” while iterating over the lines inside an AHB from top to bottom. The location is initialized when you start iterating over the AHB by providing the relevant SegmentGroupHierarchy. Example: Consider the line: “SG10, CAV, 7111, Wertegranularität” from FV2210 UTILMD AHBs. It is located in * root (None, UNH, None) * “Vorgang” (SG4, IDE, 24) * “OBIS-Daten der Marktlokation” (SG8, SEQ, Z02) * “Wertegranularität” (SG10, CCI, ZE4)

The AhbLocation relates to the AHB just as the EdifactStack relates to the MIG.

data_element_id: str | None

the ID of th data element (inside the segment group described by layers), e.g. “0062”

is_parent_of(other: AhbLocation) bool[source]

Returns true iff this other stack is a sub position of self.

is_sub_location_of(other: AhbLocation) bool[source]

Returns true iff this (self) location is a sub position of the other provided location. ([Foo][0][Bar]).is_sub_position_of([Foo][0]) is true.

layers: List[AhbLocationLayer]

the single layers that define the segment groups involved in the location

qualifier: str | None

qualifier to identify the matching data element if the data_element id is not unique

segment_code: str | None

The segment code of an element. None for groups only.

class maus.navigation.AhbLocationLayer(*, segment_group_key: str | None, opening_segment_code: str, opening_qualifier: str | None)[source]

Bases: object

The AhbLocation consists of multiple layers of information about the nesting of a line in the SegmentGroupHierarchy. one _AhbLocationLayer models exactly one of these nesting layers. It is used only internally in the AhbLocation.

The AhbLocationLayer relates to the AhbLocation just as the EdifactStackLevel relates to the EdifactStack.

opening_qualifier: str | None

” The opening_qualifier is the qualifier used in the opening_segment of this segment group. It is used to distinguish this segment group from other segment groups with the same key. (e.g. to distinguish between different SG8 for different purposes but the same internal structure). Example: “24”

opening_segment_code: str

The opening_segment_code is the first segment code of the respective SegmentGroupHierarchy. Example: “IDE”

segment_group_key: str | None

The key of the segment group in which the line is located; use None for the root. Example: “SG4”

maus.navigation.calculate_distance(location_x: AhbLocation, location_y: AhbLocation) _AhbLocationDistance[source]

Calculate the “distance” between two locations. The distance is measured in how many layers you have to go up and how many down reach location_y from location_y. For more information see the docstring of _AhbLocationDistance :param location_x: the start location :param location_y: the target location :return: the number of layers between location_x and location_y via their common ancestor.

maus.navigation.determine_hierarchy_changes(ahb_lines: List[AhbLine], segment_group_hierarchy: SegmentGroupHierarchy) List[Tuple[AhbLine, _DifferentialAhbLineHierarchyChange]][source]

Determine the differential hierarchy changes between neighbouring ahb lines. The returned tuple at index n is the line n itself + the change in hierarchy necessary to get from line n-1 to n.

maus.navigation.determine_locations(segment_group_hierarchy: SegmentGroupHierarchy, ahb_lines: List[AhbLine]) List[Tuple[AhbLine, AhbLocation]][source]

If you provide _all_ lines of an AHB from top to bottom, this function will enrich the list of ahb_lines with the respective locations of the single AHBLines. These locations can then be used to find/match the lines with the MIG. :param segment_group_hierarchy: the general structure of the MIG :param ahb_lines: all lines of an AHB :return: the same lines that have been entered but together with their location which is derived from the segment group hierarchy.

maus.navigation.find_common_ancestor(location_x: _PseudoAhbLocation, location_y: _PseudoAhbLocation) _PseudoAhbLocation[source]
maus.navigation.find_common_ancestor(location_x: _PseudoAhbLocation, location_y: AhbLocation | _PseudoAhbLocation) _PseudoAhbLocation
maus.navigation.find_common_ancestor(location_x: AhbLocation | _PseudoAhbLocation, location_y: _PseudoAhbLocation) _PseudoAhbLocation
maus.navigation.find_common_ancestor(location_x: AhbLocation, location_y: AhbLocation) AhbLocation

Finds the last common ancestor of location_x and location_y. If the layers of location X are: [A,B,C,F,G,H] And the layers of location Y are: [A,B,C,D,E,F] then the last common ancestor is: [A,B,C] :param location_x: :param location_y: :return: the location that is the last common ancestor of x and y

maus.transformation module

The transformation module is useful when you handle edifact transactions in both a domain/data model similar to edifact (the “edifact domain”) and a domain/data model which is used by your application (we simply call it the “non-edifact” or “application domain”).

Usually the data model similar to EDIFACT is something structurally equivalent to EDIFACT, think e.g. of a JSON or XML. Wherever there is the possibility to group something in the form of repeated segment groups, you usually have something like an array in your edifact-equivalent data structure. We call this structure an “EdiSeed”, because it is what you “seed” into your EdifactBuilder to generate EDIFACT. The transformation from an EdiSeed to EDIFACT is quite simple. It’s a plain mapping logic that doesn’t care about cardinalities and more complicated stuff than simple replacements and loops. Neighbouring segments in EDIFACT are transformed into neighbouring fields in the EdiSeed structure. Think of the EdiSeed as an intermediate data structure.

MAUS is agnostic regarding your EdiSeed. It doesn’t care about how your EdiSeed looks like exactly. It just needs to be accessible somehow.

In your application you might use a different data model which is de-coupled from EDIFACT and thus also de-coupled from the EdiSeed. This is generally a good idea, because it spares your application from the never-ending pain introduced by BDEW and edi@energy every 6 months. However, this comes with the price of having to write a more complex transformation.

This module contains methods that are relevant when transforming data between your edi-similar structure (“EdiSeed”) and the application domain (“non-edifact”).

class maus.transformation.Accessor(*args, **kwargs)[source]

Bases: Protocol[DataModel_contra]

description of a class that allows to get and set values from a generic data model

get_value(data: DataModel_contra, discriminator: str) Any | None[source]

Gets the value described by the discriminator from the given data :param data: the data to be read :param discriminator: describes _which_ value should be read and returned :return: the value or None

set_value(data: DataModel_contra, discriminator: str, value: Any) None[source]

Sets the value that is described by the disciminator in the given data instance. :param value: the value to be set :param data: the data to be modified :param discriminator: describes _which_ value should be set :return: nothing; it modifies the instance of data

maus.transformation.ApplicationAccessor

a class that allows to access (read/write) in the application data

alias of Accessor[ApplicationData]

class maus.transformation.ApplicationData

the type which you use to model the data in your application (e.g. the type of your BO4E, BOneyComb)

alias of TypeVar(‘ApplicationData’)

class maus.transformation.ApplicationEdifactConverter(*args, **kwargs)[source]

Bases: Protocol[EdifactData, ApplicationData]

this class describes a converter from the Application Domain to the EDIFACT Domain

async transform_application_to_edi_domain(application_data: ApplicationData) EdifactData[source]

Transforms the given application data (e.g. bo4e/boneycomb) into the edifact domain (e.g. ediseed) :param application_data: :return: the converted data

async transform_edi_to_application_domain(edifact_data: EdifactData) ApplicationData[source]

Transforms the given edifact data (e.g. ediseed) into the application domain (e.g. bo4e/boneycomb) :param edifact_data: :return: the converted data

maus.transformation.EdifactAccessor

a class that allows to access (read/write) in the edifact data model

alias of Accessor[EdifactData]

class maus.transformation.EdifactData

the type which you use to model the edifact side of things (e.g. the type of the EdiSeed)

alias of TypeVar(‘EdifactData’)

async maus.transformation.generate_value_pool_replacement(application_data_model: ApplicationData, data_element: DataElementValuePool, converter: ApplicationEdifactConverter, edifact_accessor: Accessor[EdifactData], application_accessor: Accessor[ApplicationData], edifact_to_non_edifact_path_mapping: Mapping[str, str]) Dict[str, str][source]

generate the value pool replacement dict for the given data_element :param application_data_model: the application representation of the data :param data_element: the data_element for which the replacement shall be computed :param converter: a converter between application and edifact domain :param application_accessor: Allows to modify and access a given application data model :param edifact_accessor: Allows to modify and access a given edifact data model :param edifact_to_non_edifact_path_mapping: maps application domain (keys) to edifact domain (values) discriminators :return: a edifact (key) to non-edifact (value) mapping of values from the given data element value pool

async maus.transformation.transform_all_value_pools(application_data_model: ApplicationData, deep_ahb: DeepAnwendungshandbuch, converter: ApplicationEdifactConverter, edifact_accessor: Accessor[EdifactData], application_accessor: Accessor[ApplicationData], edifact_to_non_edifact_path_mapping: Mapping[str, str]) None[source]

transforms all value pools in the given deep ahb

Module contents

maus is the MIG AHB Utility Stack