processcube-etw-library 2026.1.19.145934__tar.gz → 2026.1.21.174504b0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {processcube_etw_library-2026.1.19.145934/src/processcube_etw_library.egg-info → processcube_etw_library-2026.1.21.174504b0}/PKG-INFO +1 -1
  2. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/create_external_task_client.py +9 -20
  3. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/etw_app.py +3 -17
  4. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/built_in.py +6 -4
  5. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/server_config.py +5 -2
  6. processcube_etw_library-2026.1.21.174504b0/src/processcube_etw_library/settings.py +117 -0
  7. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0/src/processcube_etw_library.egg-info}/PKG-INFO +1 -1
  8. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library.egg-info/SOURCES.txt +1 -0
  9. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/.github/workflows/build_and_publish.yml +0 -0
  10. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/.gitignore +0 -0
  11. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/.python-version +0 -0
  12. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/README.md +0 -0
  13. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/pyproject.toml +0 -0
  14. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/setup.cfg +0 -0
  15. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/__init__.py +0 -0
  16. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/__init__.py +0 -0
  17. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/check.py +0 -0
  18. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/handlers.py +0 -0
  19. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/models.py +0 -0
  20. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/registry.py +0 -0
  21. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/health/routes.py +0 -0
  22. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/identity_provider.py +0 -0
  23. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library/typed_handler.py +0 -0
  24. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library.egg-info/dependency_links.txt +0 -0
  25. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library.egg-info/requires.txt +0 -0
  26. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/src/processcube_etw_library.egg-info/top_level.txt +0 -0
  27. {processcube_etw_library-2026.1.19.145934 → processcube_etw_library-2026.1.21.174504b0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: processcube-etw-library
3
- Version: 2026.1.19.145934
3
+ Version: 2026.1.21.174504b0
4
4
  Summary: A library to create ETW apps with the ProcessCube platform.
5
5
  Author-email: Jeremy Hill <jeremy.hill@profection.de>
6
6
  License: MIT
@@ -1,32 +1,21 @@
1
- from os import getenv
2
-
3
1
  # Prevent nest_asyncio from patching asyncio.run() in processcube_client - it breaks uvicorn's loop_factory
4
2
  import nest_asyncio
5
3
  nest_asyncio.apply = lambda *args, **kwargs: None
6
4
 
7
5
  from processcube_client.external_task import ExternalTaskClient
8
- from processcube_client.app_info import AppInfoClient
9
6
 
10
7
  from .identity_provider import IdentityProvider
8
+ from .settings import get_settings
11
9
 
12
10
 
13
- def _determine_authority_url(engine_url: str) -> str:
14
- if authority := getenv("PROCESSCUBE_AUTHORITY_URL"):
15
- return authority
16
-
17
- app_info_client = AppInfoClient(engine_url)
18
- authority_url = app_info_client.get_authority()
19
- return authority_url # type: ignore
20
-
21
-
22
- def create_external_task_client(
23
- engine_url: str,
24
- client_name: str,
25
- client_secret: str,
26
- client_scopes: str,
27
- max_get_oauth_access_token_retries: int,
28
- ) -> ExternalTaskClient:
29
- authority_url = _determine_authority_url(engine_url)
11
+ def create_external_task_client() -> ExternalTaskClient:
12
+ settings = get_settings()
13
+ authority_url = settings.processcube_authority_url
14
+ engine_url = settings.processcube_engine_url
15
+ client_name = settings.processcube_etw_client_id
16
+ client_secret = settings.processcube_etw_client_secret
17
+ client_scopes = settings.processcube_etw_client_scopes
18
+ max_get_oauth_access_token_retries = settings.max_get_oauth_access_token_retries
30
19
 
31
20
  identity_provider = IdentityProvider(
32
21
  authority_url,
@@ -1,7 +1,6 @@
1
1
  import asyncio
2
2
  from concurrent.futures import ThreadPoolExecutor
3
3
  from contextlib import asynccontextmanager
4
- import os
5
4
  from typing import Callable, Optional
6
5
 
7
6
  from fastapi import FastAPI
@@ -16,6 +15,7 @@ from .health import (
16
15
  from .create_external_task_client import create_external_task_client
17
16
  from .server_config import get_server_config
18
17
  from .typed_handler import create_typed_handler_wrapper
18
+ from .settings import get_settings
19
19
  from processcube_client.external_task import ExternalTaskClient
20
20
 
21
21
 
@@ -92,23 +92,9 @@ class ExternalTaskWorkerApp:
92
92
  def new_external_task_worker_app(
93
93
  built_in_health_checks: bool = True,
94
94
  ) -> ExternalTaskWorkerApp:
95
- engine_url = os.getenv("PROCESSCUBE_ENGINE_URL", "http://localhost:56000")
96
- etw_client_name = os.getenv("PROCESSCUBE_ETW_CLIENT_ID", "test_etw")
97
- etw_client_secret = os.getenv(
98
- "PROCESSCUBE_ETW_CLIENT_SECRET", "3ef62eb3-fe49-4c2c-ba6f-73e4d234321b"
99
- )
100
- etw_client_scopes = os.getenv("PROCESSCUBE_ETW_CLIENT_SCOPES", "engine_etw")
101
- max_get_oauth_access_token_retries = int(
102
- os.getenv("MAX_GET_OAUTH_ACCESS_TOKEN_RETRIES", 10)
103
- )
95
+ settings = get_settings()
104
96
 
105
- external_task_client = create_external_task_client(
106
- engine_url,
107
- etw_client_name,
108
- etw_client_secret,
109
- etw_client_scopes,
110
- max_get_oauth_access_token_retries,
111
- )
97
+ external_task_client = create_external_task_client()
112
98
 
113
99
  return ExternalTaskWorkerApp(
114
100
  external_task_client, built_in_health_checks=built_in_health_checks
@@ -1,16 +1,18 @@
1
- import os
2
-
1
+ from ..settings import get_settings
3
2
  from .check import HealthCheck, create_url_health_check
4
3
  from .registry import HealthCheckRegistry
5
4
 
6
5
 
7
6
  def add_built_in_health_checks(registry: HealthCheckRegistry) -> None:
7
+ settings = get_settings()
8
+
8
9
  engine_url = (
9
- os.getenv("PROCESSCUBE_ENGINE_URL", "http://localhost:56000").strip("/")
10
+ settings.processcube_engine_url.strip("/")
10
11
  + "/atlas_engine/api/v1/info"
11
12
  )
13
+
12
14
  authority_url = (
13
- os.getenv("PROCESSCUBE_AUTHORITY_URL", "http://localhost:56020").strip("/")
15
+ settings.processcube_authority_url.strip("/")
14
16
  + "/.well-known/openid-configuration"
15
17
  )
16
18
 
@@ -1,6 +1,7 @@
1
- from os import getenv
2
1
  from typing import TypedDict
3
2
 
3
+ from .settings import get_settings
4
+
4
5
 
5
6
  class ServerConfig(TypedDict, total=False):
6
7
  host: str
@@ -11,7 +12,9 @@ class ServerConfig(TypedDict, total=False):
11
12
 
12
13
 
13
14
  def get_server_config() -> ServerConfig:
14
- if getenv("ENVIRONMENT") == "production":
15
+ settings = get_settings()
16
+
17
+ if settings.environment == "production":
15
18
  return ServerConfig(
16
19
  host="0.0.0.0",
17
20
  port=8000,
@@ -0,0 +1,117 @@
1
+ import logging
2
+ from os import getenv
3
+ from typing import Optional, Type, TypeVar
4
+
5
+ from pydantic import Field, model_validator
6
+ from pydantic_settings import BaseSettings, SettingsConfigDict
7
+
8
+ from processcube_client.app_info import AppInfoClient
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ T = TypeVar("T", bound="ETWSettings")
13
+
14
+ DEFAULTS = {
15
+ "PROCESSCUBE_ENGINE_URL": "http://localhost:56000",
16
+ "PROCESSCUBE_ETW_CLIENT_ID": "test_etw",
17
+ "PROCESSCUBE_ETW_CLIENT_SECRET": "3ef62eb3-fe49-4c2c-ba6f-73e4d234321b",
18
+ "PROCESSCUBE_ETW_CLIENT_SCOPES": "engine_etw",
19
+ "MAX_GET_OAUTH_ACCESS_TOKEN_RETRIES": 10,
20
+ "ENVIRONMENT": "development",
21
+ }
22
+
23
+
24
+ def _determine_authority_url(engine_url: str) -> str:
25
+ if authority_url := getenv("PROCESSCUBE_AUTHORITY_URL"):
26
+ logger.info("Using authority URL from environment variable PROCESSCUBE_AUTHORITY_URL")
27
+ return authority_url
28
+
29
+ app_info_client = AppInfoClient(engine_url)
30
+ authority_url = app_info_client.get_authority()
31
+ logger.debug(f"Determined authority URL from AppInfoClient: {authority_url}")
32
+ if type(authority_url) is not str:
33
+ raise ValueError("Could not determine authority URL from AppInfoClient")
34
+
35
+ return authority_url
36
+
37
+
38
+ class ETWSettings(BaseSettings):
39
+ """
40
+ Base settings for the External Task Worker library.
41
+
42
+ Users can extend this class to add their own settings:
43
+
44
+ class MySettings(ETWSettings):
45
+ my_custom_var: str = Field(default="default_value")
46
+
47
+ # Initialize with custom settings class
48
+ init_settings(MySettings)
49
+ """
50
+
51
+ model_config = SettingsConfigDict(
52
+ env_file=".env",
53
+ env_file_encoding="utf-8",
54
+ extra="ignore",
55
+ )
56
+
57
+ processcube_engine_url: str = Field(default=DEFAULTS["PROCESSCUBE_ENGINE_URL"])
58
+ processcube_authority_url: str = Field(default="")
59
+ processcube_etw_client_id: str = Field(default=DEFAULTS["PROCESSCUBE_ETW_CLIENT_ID"])
60
+ processcube_etw_client_secret: str = Field(default=DEFAULTS["PROCESSCUBE_ETW_CLIENT_SECRET"])
61
+ processcube_etw_client_scopes: str = Field(default=DEFAULTS["PROCESSCUBE_ETW_CLIENT_SCOPES"])
62
+ max_get_oauth_access_token_retries: int = Field(default=DEFAULTS["MAX_GET_OAUTH_ACCESS_TOKEN_RETRIES"])
63
+ environment: str = Field(default=DEFAULTS["ENVIRONMENT"])
64
+
65
+ @model_validator(mode="before")
66
+ @classmethod
67
+ def warn_missing_values(cls, values: dict) -> dict:
68
+ for env_name, default_value in DEFAULTS.items():
69
+ field_name = env_name.lower()
70
+ if field_name not in values or values.get(field_name) is None:
71
+ if default_value is not None:
72
+ logger.warning(
73
+ f"Environment variable '{env_name}' not set, using default: {default_value}"
74
+ )
75
+ return values
76
+
77
+ @model_validator(mode="after")
78
+ def resolve_authority_url(self) -> "ETWSettings":
79
+ if not self.processcube_authority_url.strip():
80
+ self.processcube_authority_url = _determine_authority_url(
81
+ self.processcube_engine_url
82
+ )
83
+ logger.info(
84
+ f"Authority URL resolved from AppInfoClient: {self.processcube_authority_url}"
85
+ )
86
+ return self
87
+
88
+
89
+ _settings: Optional[ETWSettings] = None
90
+
91
+
92
+ def init_settings(settings_class: Type[T] = ETWSettings) -> T:
93
+ """
94
+ Initialize the global settings instance.
95
+
96
+ Call this with a custom settings class to extend the base settings:
97
+
98
+ class MySettings(ETWSettings):
99
+ my_var: str = Field(default="value")
100
+
101
+ init_settings(MySettings)
102
+ """
103
+ global _settings
104
+ _settings = settings_class()
105
+ return _settings
106
+
107
+
108
+ def get_settings() -> ETWSettings:
109
+ """
110
+ Get the global settings instance.
111
+
112
+ If settings haven't been initialized, creates a default ETWSettings instance.
113
+ """
114
+ global _settings
115
+ if _settings is None:
116
+ _settings = ETWSettings()
117
+ return _settings
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: processcube-etw-library
3
- Version: 2026.1.19.145934
3
+ Version: 2026.1.21.174504b0
4
4
  Summary: A library to create ETW apps with the ProcessCube platform.
5
5
  Author-email: Jeremy Hill <jeremy.hill@profection.de>
6
6
  License: MIT
@@ -9,6 +9,7 @@ src/processcube_etw_library/create_external_task_client.py
9
9
  src/processcube_etw_library/etw_app.py
10
10
  src/processcube_etw_library/identity_provider.py
11
11
  src/processcube_etw_library/server_config.py
12
+ src/processcube_etw_library/settings.py
12
13
  src/processcube_etw_library/typed_handler.py
13
14
  src/processcube_etw_library.egg-info/PKG-INFO
14
15
  src/processcube_etw_library.egg-info/SOURCES.txt