Skip to content

Releases: Hochfrequenz/ahbicht

v2.1.1

12 Apr 19:54
2b73682

Choose a tag to compare

What's Changed

Full Changelog: v2.1.0...v2.1.1

v2.1.0

12 Apr 19:46
8e80321

Choose a tag to compare

What's Changed

  • feat: enable mypy --strict across entire codebase by @hf-kklein in #753

Full Changelog: v2.0.0...v2.1.0

v2.0.0

12 Apr 17:43
5856fc1

Choose a tag to compare

Breaking Changes

python-inject has been removed. All functions that previously used the global inject container now require an explicit AhbContext parameter.

Removed

  • python-inject dependency
  • EvaluatableDataProvider class (replaced by passing EvaluatableData directly via AhbContext)
  • create_and_inject_hardcoded_evaluators() function (use AhbContext.from_content_evaluation_result() instead)
  • content_evaluation_result_setter parameter on is_valid_expression() (use edifact_format + edifact_format_version params instead)
  • The inject-based binding pattern (inject.clear_and_configure, binder.bind(TokenLogicProvider, ...), etc.)

Changed to required parameters

Function Parameter
evaluate_ahb_expression_tree(tree, ahb_context) ahb_context: AhbContext (was Optional, now required)
requirement_constraint_evaluation(expr, ahb_context) ahb_context: AhbContext (was Optional, now required)
format_constraint_evaluation(expr, ahb_context) ahb_context: AhbContext (was Optional, now required)
ConditionNodeBuilder(keys, ahb_context) ahb_context: AhbContext (was Optional, now required)
is_valid_expression(expr, edifact_format, edifact_format_version) format params now required; also accepts optional ahb_context

parse_expression_including_unresolved_subexpressions and extract_categorized_keys keep ahb_context as optional — it's only needed when resolve_packages=True.

Migration Guide

Step 1: Replace inject setup with AhbContext (pre-computed results)

This is the simplest path — for consumers that already have a ContentEvaluationResult.

Before (v1.x with inject):

import inject
from ahbicht.content_evaluation.evaluationdatatypes import EvaluatableDataProvider
from ahbicht.content_evaluation.evaluator_factory import create_and_inject_hardcoded_evaluators

create_and_inject_hardcoded_evaluators(cer, evaluatable_data_provider=my_provider, ...)
tree = await parse_expression_including_unresolved_subexpressions(expr, resolve_packages=True)
result = await evaluate_ahb_expression_tree(tree)

After (v2.0):

from ahbicht.content_evaluation.ahb_context import AhbContext
from ahbicht.expressions.expression_resolver import parse_expression_including_unresolved_subexpressions
from ahbicht.expressions.ahb_expression_evaluation import evaluate_ahb_expression_tree
from efoli import EdifactFormat, EdifactFormatVersion

ctx = AhbContext.from_content_evaluation_result(cer, EdifactFormat.UTILMD, EdifactFormatVersion.FV2504)
tree = await parse_expression_including_unresolved_subexpressions(expr, resolve_packages=True, ahb_context=ctx)
result = await evaluate_ahb_expression_tree(tree, ahb_context=ctx)

Step 2: Replace is_valid_expression setter callback

Before:

await is_valid_expression(tree, lambda cer: my_context_var.set(cer))

After:

from efoli import EdifactFormat, EdifactFormatVersion

await is_valid_expression(tree, edifact_format=EdifactFormat.UTILMD, edifact_format_version=EdifactFormatVersion.FV2504)

is_valid_expression now builds a fresh AhbContext for each possible CER internally — no setter callback or inject needed.

Step 3: For custom evaluators (e.g. message validators like wanna.bee)

If you used inject.configure(... clear=True) per element to swap in different evaluators, replace it by constructing a new AhbContext for each evaluation scope.

Before:

inject.clear_and_configure(lambda binder: binder
    .bind(TokenLogicProvider, SingletonTokenLogicProvider([my_rc, my_fc, my_hints, my_pkg]))
    .bind_to_provider(EvaluatableDataProvider, my_provider)
)
result = await evaluate_ahb_expression_tree(tree)

After (option A — direct construction):

from ahbicht.content_evaluation.ahb_context import AhbContext
from ahbicht.content_evaluation.evaluationdatatypes import EvaluatableData

ctx = AhbContext(
    rc_evaluator=my_rc,
    fc_evaluator=my_fc,
    hints_provider=my_hints,
    package_resolver=my_pkg,
    evaluatable_data=EvaluatableData(body=my_data, edifact_format=my_format, edifact_format_version=my_version),
)
result = await evaluate_ahb_expression_tree(tree, ahb_context=ctx)

After (option B — bridge from existing TokenLogicProvider):

If you already have a configured TokenLogicProvider, use the bridge factory:

ctx = AhbContext.from_token_logic_provider(my_token_logic_provider, my_evaluatable_data)
result = await evaluate_ahb_expression_tree(tree, ahb_context=ctx)

Note: Create a fresh AhbContext per evaluation scope. This replaces the old inject.configure(..., clear=True) per-element pattern.

Step 4: Remove inject from your dependencies

python-inject is no longer pulled in by ahbicht. If your project only used it because of ahbicht, you can remove it.

Pinning for gradual migration

If you cannot migrate immediately, pin to the last v1.x release:

ahbicht>=1.4.0,<2.0.0

What's Changed

  • feat: refactor is_valid_expression to support AhbContext by @hf-kklein in #751
  • feat!: remove python-inject dependency by @hf-kklein in #752

Full Changelog: v1.4.0...v2.0.0

v1.4.0

12 Apr 16:34
9035b9f

Choose a tag to compare

Deprecation Warnings

All inject-based code paths now emit DeprecationWarning when used without ahb_context. This signals that the python-inject dependency will be removed in v2.0.0.

If you see warnings like:

DeprecationWarning: Calling ConditionNodeBuilder without ahb_context is deprecated
and will be removed in ahbicht v2.0. Pass an AhbContext instance explicitly.

Follow the v1.3.0 migration guide to switch to AhbContext.

Affected functions

Warning trigger Replacement
ConditionNodeBuilder(keys) without ahb_context ConditionNodeBuilder(keys, ahb_context=ctx)
PackageExpansionTransformer() without ahb_context Pass ahb_context via parse_expression_including_unresolved_subexpressions(..., ahb_context=ctx)
_build_evaluated_format_constraint_nodes() without ahb_context Pass ahb_context via evaluate_ahb_expression_tree(tree, ahb_context=ctx)
create_and_inject_hardcoded_evaluators() AhbContext.from_content_evaluation_result(cer, format, version)

Timeline

  • v1.3.0AhbContext introduced, old API unchanged
  • v1.4.0 (this release) — deprecation warnings on old API
  • v2.0.0 (upcoming) — python-inject removed, ahb_context required

What's Changed

  • feat: add deprecation warnings on inject-based code paths by @hf-kklein in #750

Full Changelog: v1.3.0...v1.4.0

v1.3.0

12 Apr 13:57
15574c7

Choose a tag to compare

Highlights

This release introduces AhbContext — a new way to use ahbicht without the global python-inject dependency injection container. All public entry points now accept an optional ahb_context parameter. The existing inject-based API is fully preserved and unchanged.

Migration Guide

Before (inject-based, still works)

import inject
from ahbicht.content_evaluation.token_logic_provider import SingletonTokenLogicProvider, TokenLogicProvider
from ahbicht.content_evaluation.evaluationdatatypes import EvaluatableDataProvider

inject.clear_and_configure(
    lambda binder: binder
        .bind(TokenLogicProvider, SingletonTokenLogicProvider([...]))
        .bind_to_provider(EvaluatableDataProvider, my_provider_func)
)
tree = await parse_expression_including_unresolved_subexpressions(expr, resolve_packages=True)
result = await evaluate_ahb_expression_tree(tree)

After (AhbContext, recommended)

from ahbicht.content_evaluation.ahb_context import AhbContext

ctx = AhbContext.from_content_evaluation_result(
    cer, EdifactFormat.UTILMD, EdifactFormatVersion.FV2210
)
tree = await parse_expression_including_unresolved_subexpressions(
    expr, resolve_packages=True, ahb_context=ctx
)
result = await evaluate_ahb_expression_tree(tree, ahb_context=ctx)

No inject, no TokenLogicProvider, no EvaluatableDataProvider, no ContextVars.

For custom evaluators (e.g. message validators)

ctx = AhbContext(
    rc_evaluator=MyRcEvaluator(),
    fc_evaluator=MyFcEvaluator(),
    hints_provider=MyHintsProvider(),
    package_resolver=MyPackageResolver(),
    evaluatable_data=my_data,
)

Functions that accept ahb_context

Function Module
parse_expression_including_unresolved_subexpressions expressions.expression_resolver
evaluate_ahb_expression_tree expressions.ahb_expression_evaluation
extract_categorized_keys expressions.condition_expression_parser
is_valid_expression content_evaluation.expression_check

What's NOT changing (yet)

  • The python-inject dependency is still included
  • The old inject-based API still works exactly as before
  • Existing consumers do not need to change anything

The inject-based API will be deprecated in a future minor release and removed in v2.0.0.


What's Changed

  • chore(deps-dev): bump coverage from 7.13.0 to 7.13.1 by @dependabot[bot] in #717
  • chore(deps-dev): bump pytest-datafiles from 3.0.0 to 3.0.1 by @dependabot[bot] in #719
  • chore(deps-dev): bump certifi from 2025.11.12 to 2026.1.4 by @dependabot[bot] in #718
  • chore(deps): bump urllib3 from 2.6.2 to 2.6.3 in /dev_requirements by @dependabot[bot] in #721
  • chore(deps-dev): bump sphinx-rtd-theme from 3.0.2 to 3.1.0 by @dependabot[bot] in #722
  • chore(deps-dev): bump build from 1.3.0 to 1.4.0 by @dependabot[bot] in #723
  • chore(deps-dev): bump packaging from 25.0 to 26.0 by @dependabot[bot] in #725
  • chore(deps-dev): bump setuptools from 80.9.0 to 80.10.2 by @dependabot[bot] in #726
  • chore(deps-dev): bump coverage from 7.13.1 to 7.13.2 by @dependabot[bot] in #727
  • chore(deps-dev): bump babel from 2.17.0 to 2.18.0 by @dependabot[bot] in #728
  • chore(deps-dev): bump setuptools from 80.10.2 to 82.0.0 by @dependabot[bot] in #729
  • chore(deps-dev): bump coverage from 7.13.2 to 7.13.4 by @dependabot[bot] in #730
  • Bump isort 7.0.0→8.0.0 and pylint 4.0.4→4.0.5 to fix dependency conflict by @Copilot in #735
  • chore(deps-dev): bump black[jupyter] from 25.12.0 to 26.1.0 by @dependabot[bot] in #724
  • chore(deps-dev): bump certifi from 2026.1.4 to 2026.2.25 by @dependabot[bot] in #738
  • chore(deps): bump requests from 2.32.5 to 2.33.0 in /dev_requirements by @dependabot[bot] in #741
  • chore(deps): bump pygments from 2.19.2 to 2.20.0 in /dev_requirements by @dependabot[bot] in #742
  • feat: add AhbContext dataclass for explicit dependency passing (w/o using it anywhere yet) by @hf-kklein in #743
  • chore(deps-dev): bump isort from 8.0.0 to 8.0.1 by @dependabot[bot] in #740
  • feat: thread AhbContext through ConditionNodeBuilder (dual-path) by @hf-kklein in #744
  • chore(deps-dev): bump charset-normalizer from 3.4.4 to 3.4.5 by @dependabot[bot] in #739
  • feat: thread AhbContext through requirement_constraint_evaluation by @hf-kklein in #745
  • feat: thread AhbContext through format_constraint_evaluation by @hf-kklein in #746
  • feat: thread AhbContext through PackageExpansionTransformer by @hf-kklein in #747
  • feat: thread AhbContext through evaluate_ahb_expression_tree (milestone) by @hf-kklein in #748
  • feat: thread AhbContext through supporting functions + update notebook by @hf-kklein in #749

Full Changelog: v1.2.0...v1.3.0

v1.2.0

17 Dec 13:04
57e6ad3

Choose a tag to compare

feat(package_expansion): resolve package '1P' to hardcoded hint node …

v1.1.0

09 Dec 19:36
69768ee

Choose a tag to compare

What's Changed

  • feat(EvaluatedFormatConstraint): prevent empty string instead of None as error message if FC is not fulfilled by @hf-kklein in #712

Full Changelog: v1.0.1...v1.1.0

v1.0.1

09 Dec 15:42
783c7e9

Choose a tag to compare

What's Changed

  • chore(deps-dev): bump coverage from 7.10.7 to 7.11.3 by @dependabot[bot] in #691
  • chore(deps-dev): bump black[jupyter] from 25.9.0 to 25.11.0 by @dependabot[bot] in #693
  • chore(deps-dev): bump isort from 6.1.0 to 7.0.0 by @dependabot[bot] in #692
  • chore(deps-dev): bump types-pytz from 2025.2.0.20250809 to 2025.2.0.20251108 by @dependabot[bot] in #694
  • chore(deps-dev): bump pytest-asyncio from 1.2.0 to 1.3.0 by @dependabot[bot] in #696
  • chore(deps-dev): bump pytest from 8.4.2 to 9.0.0 by @dependabot[bot] in #689
  • chore(deps-dev): bump pylint from 3.3.9 to 4.0.2 by @dependabot[bot] in #695
  • chore(deps-dev): bump certifi from 2025.10.5 to 2025.11.12 by @dependabot[bot] in #697
  • chore(deps-dev): bump pytest from 9.0.0 to 9.0.1 by @dependabot[bot] in #699
  • chore(deps-dev): bump pylint from 4.0.2 to 4.0.3 by @dependabot[bot] in #698
  • chore(deps-dev): bump coverage from 7.11.3 to 7.12.0 by @dependabot[bot] in #700
  • chore(deps): bump actions/checkout from 5 to 6 by @dependabot[bot] in #701
  • docs: update links and swagger of ahbicht-backend REST API by @hf-kklein in #702
  • chore(deps-dev): bump pylint from 4.0.3 to 4.0.4 by @dependabot[bot] in #703
  • chore(deps-dev): bump mypy[pydantic] from 1.18.2 to 1.19.0 by @dependabot[bot] in #705
  • chore(deps): bump pydantic from 2.12.4 to 2.12.5 by @dependabot[bot] in #704
  • chore(deps): bump urllib3 from 2.5.0 to 2.6.0 in /dev_requirements by @dependabot[bot] in #706
  • chore(deps-dev): bump coverage from 7.12.0 to 7.13.0 by @dependabot[bot] in #707
  • chore(deps-dev): bump urllib3 from 2.6.0 to 2.6.1 by @dependabot[bot] in #709
  • chore(deps-dev): bump pytest from 9.0.1 to 9.0.2 by @dependabot[bot] in #710
  • chore(deps-dev): bump black[jupyter] from 25.11.0 to 25.12.0 by @dependabot[bot] in #708
  • fix(expression_builder): use parentheses for nested XOR/OR/AND error messages by @hf-kklein in #711

Full Changelog: v1.0.0...v1.0.1

v1.0.0

06 Nov 14:13
1bdf5ee

Choose a tag to compare

In v1.0.0 we god rid of both the attrs and marshmallow dependency and use only pydantic models which makes constructing and serializing models way more consistent. Also this allows for easy integration with FastAPI backends.

The historic and hard to explain-dependency injection setup remains for now but still this is a great step forward.
The updated tests in each of the breaking change-commits are a good indicator on how you need to adapt model dumps and loads in v1.

What's Changed

  • Switch CategorizedKeyExtract from attrs+marshmallow to pydantic (breaking) by @hf-kklein in #640
  • Switch ContentEvaluationResult from attrs+marshmallow to pydantic (breaking) by @hf-kklein in #677
  • chore: fix deprecation warning about datetime.utcnow() by @hf-kklein in #678
  • Switch models from mapping_results module from attrs+marshmallow to pydantic (breaking) by @hf-kklein in #679
  • chore: fix linter warning in json schema generation by @hf-kklein in #681
  • chore(tests): fix wrong AsyncMock setup by @hf-kklein in #682
  • switch module evaluation_results from attrs+marshmallow to pydantic (breaking) by @hf-kklein in #680
  • chore(deps): drop attrs dependency by @hf-kklein in #683
  • chore(deps): drop unmaintained marshmallow_enum dependency by @hf-kklein in #684
  • chore(deps): bump lark from 1.3.0 to 1.3.1 by @dependabot[bot] in #686
  • Drop (Concise)TreeSchemas, use pydantic TypeAdapter instead; Remove marshmallow dependency; Drop Python 3.9 support (breaking) by @hf-kklein in #685
  • chore: Update Read the Docs-Requirements by @hf-kklein in #687
  • fix(docs): update minimal working example jupyter notebook; fix build errors there by @hf-kklein in #688

Full Changelog: v0.16.4...v1.0.0

v0.16.4

21 Oct 11:38
ea1a304

Choose a tag to compare

What's Changed

  • chore: officially support Python 3.14 (in pyproject.toml metadata) by @hf-kklein in #676

Full Changelog: v0.16.3...v0.16.4