Skip to content

Commit

Permalink
V2 (#82)
Browse files Browse the repository at this point in the history
* remove DI framework (GSI-536) (#78)

- removes the DI framework.
- removes  dependency_injector from dependencies
- example app shown DI without dedicated framework
- added tests for the CLI of the example app

This is a breaking change.

Bumps version to 2.0.0.

* Tools for Structured Logging (GSI 510) (#77)

* Add basic logging tools

* Use configurable class rather than instance

* Add service name and instance id to config

* Explicitly get service/instance from log record

* Use capitalized LogLevel literal for log_level arg

* Add __all__ and rename Adapter to StructuredLogger

* Add RecordCompiler handler

* Add log_format config option

* Bump version from 1.2.0 -> 2.0.0

* Add tests

* remove DI framework (GSI-536) (#78)

- removes the DI framework.
- removes  dependency_injector from dependencies
- example app shown DI without dedicated framework
- added tests for the CLI of the example app

This is a breaking change.

Bumps version to 2.0.0.

* Rename function and remove second config in fixture

* Integrate Kersten's suggestions for simpler config

---------

Co-authored-by: TheByronHimes <TheByronHimes@gmail.com>
Co-authored-by: Kersten Breuer <kersten-breuer@outlook.com>

* Upgrade pytest-asyncio (GSI-534) (#80)

* Remove cap on pytest-asyncio and update lock files

* Use module-scoped kafka fixture in correlation tests

Place the publishing tests at the end of the module, rather than in the middle.

* Specify minimum ver so lower version doesn't get installed

---------

Co-authored-by: TheByronHimes <TheByronHimes@gmail.com>

* Log all config (GSI-546) (#81)

* Log complete config when configuring logging

* Make no-secrets log test more robust

* Add suggested changes

---------

Co-authored-by: TheByronHimes <TheByronHimes@gmail.com>

---------

Co-authored-by: Kersten Breuer <kersten-breuer@outlook.com>
Co-authored-by: TheByronHimes <TheByronHimes@gmail.com>
  • Loading branch information
3 people authored Dec 19, 2023
1 parent 412568e commit 5c619ef
Show file tree
Hide file tree
Showing 23 changed files with 970 additions and 1,434 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ repos:
- id: debug-statements
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.7
rev: v0.1.8
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
57 changes: 57 additions & 0 deletions examples/stream_calc/sc_tests/integration/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Test the stream_calc app via the CLI."""

import os
import subprocess
import sys
from pathlib import Path

from func_timeout import func_timeout

from hexkit.providers.akafka.testutils import KafkaFixture, kafka_fixture # noqa:F401
from sc_tests.integration.test_event_api import (
CASES,
check_problem_outcomes,
submit_test_problems,
)

APP_DIR = Path(__file__).parent.parent.parent.absolute()


def test_cli(kafka_fixture: KafkaFixture, monkeypatch): # noqa:F811
"""Test the stream_calc app via the CLI."""
os.chdir(APP_DIR)
monkeypatch.setenv(
name="STREAM_CALC_KAFKA_SERVERS", value=f'["{kafka_fixture.kafka_servers[0]}"]'
)
monkeypatch.setenv(
name="PYTHONPATH", value=(os.environ.get("PYTHONPATH", "") + f":{APP_DIR}")
)

submit_test_problems(CASES, kafka_server=kafka_fixture.kafka_servers[0])

with subprocess.Popen(
args=["-m", "stream_calc"],
executable=sys.executable,
) as process:
func_timeout(
10,
check_problem_outcomes,
kwargs={"cases": CASES, "kafka_server": kafka_fixture.kafka_servers[0]},
)
process.terminate()
9 changes: 4 additions & 5 deletions examples/stream_calc/sc_tests/integration/test_event_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"""

import json
from copy import deepcopy
from typing import NamedTuple

import pytest
Expand Down Expand Up @@ -203,7 +202,7 @@ def check_problem_outcomes(


@pytest.mark.asyncio
async def test_receive_calc_publish(cases: list[Case] = deepcopy(CASES)):
async def test_receive_calc_publish():
"""
Test the receipt of new arithmetic problems, the calculation, and the publication of
the results.
Expand All @@ -212,12 +211,12 @@ async def test_receive_calc_publish(cases: list[Case] = deepcopy(CASES)):
with KafkaContainer(image=KAFKA_IMAGE) as kafka:
kafka_server = kafka.get_bootstrap_server()

submit_test_problems(cases, kafka_server=kafka_server)
submit_test_problems(CASES, kafka_server=kafka_server)

# run the stream_calc app:
# (for each problem separately to avoid running forever)
config = Config(kafka_servers=[kafka_server])
for _ in cases:
for _ in CASES:
await main(config=config, run_forever=False)

check_problem_outcomes(cases, kafka_server=kafka_server)
check_problem_outcomes(CASES, kafka_server=kafka_server)
2 changes: 2 additions & 0 deletions examples/stream_calc/stream_calc/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@

from typing import Literal

from hexkit.config import config_from_yaml
from hexkit.providers.akafka.provider import KafkaConfig
from stream_calc.translators.eventpub import EventResultEmitterConfig
from stream_calc.translators.eventsub import EventProblemReceiverConfig

LOGLEVEL = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]


@config_from_yaml(prefix="stream_calc")
class Config(KafkaConfig, EventProblemReceiverConfig, EventResultEmitterConfig):
"""Config parameters and their defaults."""

Expand Down
67 changes: 0 additions & 67 deletions examples/stream_calc/stream_calc/container.py

This file was deleted.

58 changes: 58 additions & 0 deletions examples/stream_calc/stream_calc/inject.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright 2021 - 2023 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
# for the German Human Genome-Phenome Archive (GHGA)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module hosting the dependency injection container."""

from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager

from hexkit.providers.akafka import KafkaEventPublisher, KafkaEventSubscriber
from stream_calc.config import Config
from stream_calc.core.calc import StreamCalculator
from stream_calc.ports.problem_receiver import ArithProblemHandlerPort
from stream_calc.translators.eventpub import EventResultEmitter
from stream_calc.translators.eventsub import EventProblemReceiver


@asynccontextmanager
async def prepare_core(
*,
config: Config,
) -> AsyncGenerator[ArithProblemHandlerPort, None]:
"""Constructs and initializes all core components and their outbound dependencies."""

async with KafkaEventPublisher.construct(config=config) as event_pub_provider:
result_emitter = EventResultEmitter(
config=config, event_publisher=event_pub_provider
)

yield StreamCalculator(result_emitter=result_emitter)


@asynccontextmanager
async def prepare_event_subscriber(
*,
config: Config,
) -> AsyncGenerator[KafkaEventSubscriber, None]:
"""Construct and initialize an event subscriber with all its dependencies."""
async with prepare_core(config=config) as stream_calculator:
event_problem_receiver = EventProblemReceiver(
config=config, problem_handler=stream_calculator
)

async with KafkaEventSubscriber.construct(
config=config, translator=event_problem_receiver
) as event_subscriber:
yield event_subscriber
22 changes: 4 additions & 18 deletions examples/stream_calc/stream_calc/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,7 @@
import logging

from stream_calc.config import Config
from stream_calc.container import Container # type: ignore


def get_container(config: Config) -> Container:
"""
Get a pre-configures container for the stream calc app.
Args:
config: App config object.
"""
logging.basicConfig(level=config.log_level)

container = Container()
container.config.load_config(config)

return container
from stream_calc.inject import prepare_event_subscriber


async def main(
Expand All @@ -52,8 +37,9 @@ async def main(
run_forever:
If set too `False`, will exit after handling one arithmetic problem.
"""
async with get_container(config) as container:
event_subscriber = await container.event_subscriber()
logging.basicConfig(level=config.log_level)

async with prepare_event_subscriber(config=config) as event_subscriber:
await event_subscriber.run(forever=run_forever)


Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "hexkit"
version = "1.2.0"
version = "2.0.0"
description = "A Toolkit for Building Microservices using the Hexagonal Architecture"
readme = "README.md"
authors = [
Expand All @@ -27,7 +27,6 @@ dependencies = [
"pydantic >=2, <3",
"pydantic_settings >=2, <3",
"PyYAML >=6.0, <7",
"dependency-injector >=4.41.0, <5",
]

[project.optional-dependencies]
Expand Down
3 changes: 2 additions & 1 deletion requirements-dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

# additional requirements can be listed her
cryptography >= 41
pytest-asyncio < 0.23.0
func-timeout >= 4.3.5
pytest-asyncio >= 0.23.0
Loading

0 comments on commit 5c619ef

Please sign in to comment.