finanzonline-uid 2.0.0__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.
- finanzonline_uid-2.0.0/.devcontainer/devcontainer.json +22 -0
- finanzonline_uid-2.0.0/.devcontainer/settings.json +6 -0
- finanzonline_uid-2.0.0/.env.example +131 -0
- finanzonline_uid-2.0.0/.github/dependabot.yml +22 -0
- finanzonline_uid-2.0.0/.github/workflows/ci.yml +205 -0
- finanzonline_uid-2.0.0/.github/workflows/codeql.yml +39 -0
- finanzonline_uid-2.0.0/.github/workflows/release.yml +50 -0
- finanzonline_uid-2.0.0/.gitignore +180 -0
- finanzonline_uid-2.0.0/.qlty/qlty.toml +2 -0
- finanzonline_uid-2.0.0/.snyk +5 -0
- finanzonline_uid-2.0.0/API_REFERENCE_de.md +428 -0
- finanzonline_uid-2.0.0/API_REFERENCE_en.md +428 -0
- finanzonline_uid-2.0.0/CHANGELOG.md +30 -0
- finanzonline_uid-2.0.0/CLAUDE.md +172 -0
- finanzonline_uid-2.0.0/CLI_REFERENCE_de.md +171 -0
- finanzonline_uid-2.0.0/CLI_REFERENCE_en.md +171 -0
- finanzonline_uid-2.0.0/CONFIGURATION_de.md +252 -0
- finanzonline_uid-2.0.0/CONFIGURATION_en.md +252 -0
- finanzonline_uid-2.0.0/CONTRIBUTING.md +48 -0
- finanzonline_uid-2.0.0/DEVELOPMENT.md +134 -0
- finanzonline_uid-2.0.0/INSTALL_de.md +266 -0
- finanzonline_uid-2.0.0/INSTALL_en.md +266 -0
- finanzonline_uid-2.0.0/LICENSE +22 -0
- finanzonline_uid-2.0.0/Makefile +68 -0
- finanzonline_uid-2.0.0/PKG-INFO +232 -0
- finanzonline_uid-2.0.0/README.md +187 -0
- finanzonline_uid-2.0.0/README_en.md +187 -0
- finanzonline_uid-2.0.0/RETURNCODES_de.md +91 -0
- finanzonline_uid-2.0.0/RETURNCODES_en.md +91 -0
- finanzonline_uid-2.0.0/babel.cfg +5 -0
- finanzonline_uid-2.0.0/codecov.yml +28 -0
- finanzonline_uid-2.0.0/docs/prd/BMF_DataBox_Download_Webservice_2.pdf +0 -0
- finanzonline_uid-2.0.0/docs/prd/BMF_DataBox_Download_Webservice_Dokumentenversion.pdf +0 -0
- finanzonline_uid-2.0.0/docs/prd/BMF_Session_Webservice_Englisch.pdf +0 -0
- finanzonline_uid-2.0.0/docs/prd/BMF_UID_Abfrage_Webservice_2.pdf +0 -0
- finanzonline_uid-2.0.0/docs/prd/databox.xsd +105 -0
- finanzonline_uid-2.0.0/docs/prd/databoxService.wsdl +55 -0
- finanzonline_uid-2.0.0/docs/prd/login.wdsl +55 -0
- finanzonline_uid-2.0.0/docs/prd/login.xsd +82 -0
- finanzonline_uid-2.0.0/docs/prd/prd.md +344 -0
- finanzonline_uid-2.0.0/docs/prd/uidAbfrageService.wsdl +36 -0
- finanzonline_uid-2.0.0/docs/systemdesign/module_reference.md +273 -0
- finanzonline_uid-2.0.0/notebooks/Quickstart.ipynb +165 -0
- finanzonline_uid-2.0.0/pyproject.toml +174 -0
- finanzonline_uid-2.0.0/reset_git_history.sh +54 -0
- finanzonline_uid-2.0.0/scripts/__init__.py +9 -0
- finanzonline_uid-2.0.0/scripts/__main__.py +9 -0
- finanzonline_uid-2.0.0/scripts/_utils.py +768 -0
- finanzonline_uid-2.0.0/scripts/build.py +53 -0
- finanzonline_uid-2.0.0/scripts/bump.py +33 -0
- finanzonline_uid-2.0.0/scripts/bump_major.py +21 -0
- finanzonline_uid-2.0.0/scripts/bump_minor.py +21 -0
- finanzonline_uid-2.0.0/scripts/bump_patch.py +21 -0
- finanzonline_uid-2.0.0/scripts/bump_version.py +122 -0
- finanzonline_uid-2.0.0/scripts/clean.py +75 -0
- finanzonline_uid-2.0.0/scripts/cli.py +229 -0
- finanzonline_uid-2.0.0/scripts/dependencies.py +590 -0
- finanzonline_uid-2.0.0/scripts/dev.py +20 -0
- finanzonline_uid-2.0.0/scripts/help.py +38 -0
- finanzonline_uid-2.0.0/scripts/install.py +20 -0
- finanzonline_uid-2.0.0/scripts/menu.py +640 -0
- finanzonline_uid-2.0.0/scripts/push.py +310 -0
- finanzonline_uid-2.0.0/scripts/release.py +95 -0
- finanzonline_uid-2.0.0/scripts/run_cli.py +147 -0
- finanzonline_uid-2.0.0/scripts/target_metadata.py +198 -0
- finanzonline_uid-2.0.0/scripts/test.py +1004 -0
- finanzonline_uid-2.0.0/scripts/toml_config.py +433 -0
- finanzonline_uid-2.0.0/scripts/version_current.py +21 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/__init__.py +29 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/__init__conf__.py +74 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/__main__.py +114 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/_datetime_utils.py +53 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/__init__.py +20 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/cache/__init__.py +14 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/cache/file_cache.py +285 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/finanzonline/__init__.py +26 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/finanzonline/session_client.py +268 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/finanzonline/uid_query_client.py +318 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/notification/__init__.py +23 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/notification/email_adapter.py +614 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/output/__init__.py +25 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/output/formatters.py +181 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/ratelimit/__init__.py +15 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/adapters/ratelimit/rate_limit_tracker.py +320 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/application/__init__.py +38 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/application/ports.py +138 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/application/use_cases.py +193 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/behaviors.py +133 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/cli.py +817 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/config.py +440 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/config_deploy.py +139 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/config_show.py +124 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/defaultconfig.d/20-email.toml +95 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/defaultconfig.d/30-logging.toml +420 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/defaultconfig.toml +192 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/domain/__init__.py +61 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/domain/errors.py +203 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/domain/models.py +370 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/domain/return_codes.py +249 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/enums.py +91 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/i18n.py +156 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/de/LC_MESSAGES/messages.mo +0 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/de/LC_MESSAGES/messages.po +339 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/es/LC_MESSAGES/messages.mo +0 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/es/LC_MESSAGES/messages.po +339 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/fr/LC_MESSAGES/messages.mo +0 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/fr/LC_MESSAGES/messages.po +339 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/messages.pot +19 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/ru/LC_MESSAGES/messages.mo +0 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/locales/ru/LC_MESSAGES/messages.po +339 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/logging_setup.py +107 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/mail.py +391 -0
- finanzonline_uid-2.0.0/src/finanzonline_uid/py.typed +0 -0
- finanzonline_uid-2.0.0/tests/adapters/__init__.py +1 -0
- finanzonline_uid-2.0.0/tests/adapters/test_email_adapter.py +586 -0
- finanzonline_uid-2.0.0/tests/adapters/test_file_cache.py +381 -0
- finanzonline_uid-2.0.0/tests/adapters/test_formatters.py +182 -0
- finanzonline_uid-2.0.0/tests/adapters/test_rate_limit_tracker.py +396 -0
- finanzonline_uid-2.0.0/tests/adapters/test_session_client.py +435 -0
- finanzonline_uid-2.0.0/tests/adapters/test_uid_query_client.py +391 -0
- finanzonline_uid-2.0.0/tests/application/__init__.py +1 -0
- finanzonline_uid-2.0.0/tests/application/test_use_cases.py +187 -0
- finanzonline_uid-2.0.0/tests/conftest.py +456 -0
- finanzonline_uid-2.0.0/tests/domain/__init__.py +1 -0
- finanzonline_uid-2.0.0/tests/domain/test_errors.py +139 -0
- finanzonline_uid-2.0.0/tests/domain/test_models.py +278 -0
- finanzonline_uid-2.0.0/tests/domain/test_return_codes.py +200 -0
- finanzonline_uid-2.0.0/tests/test_behaviors.py +67 -0
- finanzonline_uid-2.0.0/tests/test_cli.py +1223 -0
- finanzonline_uid-2.0.0/tests/test_config_finanzonline.py +474 -0
- finanzonline_uid-2.0.0/tests/test_i18n.py +202 -0
- finanzonline_uid-2.0.0/tests/test_mail.py +560 -0
- finanzonline_uid-2.0.0/tests/test_metadata.py +106 -0
- finanzonline_uid-2.0.0/tests/test_module_entry.py +161 -0
- finanzonline_uid-2.0.0/tests/test_scripts.py +270 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"image": "mcr.microsoft.com/devcontainers/python:3.13",
|
|
3
|
+
|
|
4
|
+
"postCreateCommand": "bash -lc '\nPY=/usr/local/bin/python;\n$PY -m pip install -U pip && \\\n$PY -m pip install ipykernel && \\\n$PY -m pip install -e . && \\\n# register kernel using this exact interpreter\n$PY -m ipykernel install --name=python3 --display-name=\"Python 3 (3.13)\" --user && \\\n# patch the notebook to point to the python3 kernelspec (VS Code will bind to /usr/local/bin/python)\n$PY - <<\"PY\"\nimport json, pathlib\np = pathlib.Path(\"notebooks/Quickstart.ipynb\")\nif p.exists():\n nb = json.loads(p.read_text(encoding=\"utf-8\"))\n md = nb.setdefault(\"metadata\", {})\n md[\"kernelspec\"] = {\n \"name\": \"python3\",\n \"display_name\": \"Python 3 (3.13)\",\n \"language\": \"python\"\n }\n md[\"language_info\"] = {\"name\": \"python\"}\n p.write_text(json.dumps(nb, ensure_ascii=False, indent=1), encoding=\"utf-8\")\n print(\"Pinned kernelspec to python3 in\", p)\nelse:\n print(\"Notebook not found:\", p)\nPY'\n",
|
|
5
|
+
|
|
6
|
+
"customizations": {
|
|
7
|
+
"vscode": {
|
|
8
|
+
"extensions": ["ms-toolsai.jupyter", "ms-python.python"],
|
|
9
|
+
"settings": {
|
|
10
|
+
"workbench.startupEditor": "none",
|
|
11
|
+
"jupyter.alwaysTrustNotebooks": true,
|
|
12
|
+
"jupyter.kernelPickerType": "OnlyRecommended",
|
|
13
|
+
"python.defaultInterpreterPath": "/usr/local/bin/python"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"codespaces": {
|
|
17
|
+
"openFiles": ["README.md"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
"postAttachCommand": "bash -lc 'if [ -f notebooks/Quickstart.ipynb ]; then code -r notebooks/Quickstart.ipynb; fi'"
|
|
22
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Copy to .env and fill values as needed.
|
|
2
|
+
#
|
|
3
|
+
# .env file format (no prefix needed):
|
|
4
|
+
# SECTION__KEY=value
|
|
5
|
+
#
|
|
6
|
+
# Environment variable format (requires prefix):
|
|
7
|
+
# FINANZONLINE_UID___SECTION__KEY=value
|
|
8
|
+
|
|
9
|
+
# =============================================================================
|
|
10
|
+
# CI/CD Tokens
|
|
11
|
+
# =============================================================================
|
|
12
|
+
|
|
13
|
+
# Codecov upload token (required for private repos; optional for public repos)
|
|
14
|
+
CODECOV_TOKEN=
|
|
15
|
+
|
|
16
|
+
# PyPI API token for release workflow (.github/workflows/release.yml)
|
|
17
|
+
# Format: pypi-AgENdGVzdC5weXBpLm9yZwIk...
|
|
18
|
+
PYPI_API_TOKEN=
|
|
19
|
+
|
|
20
|
+
# Optional: GitHub token for API-limited tasks
|
|
21
|
+
GITHUB_TOKEN=
|
|
22
|
+
|
|
23
|
+
# =============================================================================
|
|
24
|
+
# Application Settings
|
|
25
|
+
# =============================================================================
|
|
26
|
+
|
|
27
|
+
# Language for user-facing messages and email notifications
|
|
28
|
+
# Supported: en (English), de (German), es (Spanish), fr (French), ru (Russian)
|
|
29
|
+
APP__LANGUAGE=en
|
|
30
|
+
|
|
31
|
+
# =============================================================================
|
|
32
|
+
# FinanzOnline Configuration (required for UID checks)
|
|
33
|
+
# =============================================================================
|
|
34
|
+
#
|
|
35
|
+
# IMPORTANT: The user (BENID) must have webservice permissions enabled!
|
|
36
|
+
# Check FinanzOnline user administration to ensure the user is configured
|
|
37
|
+
# as a webservice user, not just a regular FinanzOnline user.
|
|
38
|
+
#
|
|
39
|
+
# Return code -7 means "The user is not a web service user"
|
|
40
|
+
# Return code -4 means "The access codes are not valid"
|
|
41
|
+
#
|
|
42
|
+
|
|
43
|
+
# Participant ID (Teilnehmer-ID) - 8-12 alphanumeric characters
|
|
44
|
+
FINANZONLINE__TID=123456789
|
|
45
|
+
|
|
46
|
+
# User ID (Benutzer-ID) - 5-12 characters
|
|
47
|
+
# IMPORTANT: Must be a WEBSERVICE user created in FinanzOnline user admin!
|
|
48
|
+
FINANZONLINE__BENID=MYUSER
|
|
49
|
+
|
|
50
|
+
# Password/PIN - 5-128 characters
|
|
51
|
+
FINANZONLINE__PIN=secret
|
|
52
|
+
|
|
53
|
+
# Your Austrian UID (must start with ATU)
|
|
54
|
+
FINANZONLINE__UID_TN=ATU12345678
|
|
55
|
+
|
|
56
|
+
# Software Producer VAT-ID - 10-24 alphanumeric characters
|
|
57
|
+
# This is the VAT-ID of the company that produced the software - put Your own ATU Number there
|
|
58
|
+
FINANZONLINE__HERSTELLERID=ATU12345678
|
|
59
|
+
|
|
60
|
+
# Optional: Session and query timeouts
|
|
61
|
+
# FINANZONLINE__SESSION_TIMEOUT=60.0
|
|
62
|
+
# FINANZONLINE__QUERY_TIMEOUT=60.0
|
|
63
|
+
|
|
64
|
+
# Default email recipients for UID check results (JSON array format)
|
|
65
|
+
# Note: EMAIL__DEFAULT_RECIPIENTS is preferred as it works even when FO config fails
|
|
66
|
+
# FINANZONLINE__DEFAULT_RECIPIENTS=["admin@example.com"]
|
|
67
|
+
|
|
68
|
+
# Email format for notifications (default: both)
|
|
69
|
+
# Options: html, plain, both
|
|
70
|
+
# - html: Send HTML-only emails (rich formatting)
|
|
71
|
+
# - plain: Send plain text-only emails
|
|
72
|
+
# - both: Send multipart/alternative with both formats
|
|
73
|
+
FINANZONLINE__EMAIL_FORMAT=both
|
|
74
|
+
|
|
75
|
+
# Cache valid UID results for this many hours (0 = disabled, default: 48)
|
|
76
|
+
# Only valid results are cached. Email notifications include cache timestamp.
|
|
77
|
+
FINANZONLINE__CACHE_RESULTS_HOURS=48
|
|
78
|
+
|
|
79
|
+
# Path to cache file (default: platform-specific cache directory)
|
|
80
|
+
# Uses file locking for safe concurrent access on network drives
|
|
81
|
+
# FINANZONLINE__CACHE_FILE=/shared/network/uid_cache.json
|
|
82
|
+
|
|
83
|
+
# Rate limiting: Maximum API queries allowed within the time window (0 = disabled)
|
|
84
|
+
# When exceeded: logs warning, sends email, but query still proceeds (BMF handles actual limit)
|
|
85
|
+
# Note: Cache hits don't count toward rate limit - only actual API calls are tracked
|
|
86
|
+
FINANZONLINE__RATELIMIT_QUERIES=50
|
|
87
|
+
|
|
88
|
+
# Rate limiting: Sliding window duration in hours (default: 24)
|
|
89
|
+
FINANZONLINE__RATELIMIT_HOURS=24.0
|
|
90
|
+
|
|
91
|
+
# Path to rate limit tracking file (default: platform-specific cache directory)
|
|
92
|
+
# Uses file locking for safe concurrent access
|
|
93
|
+
# FINANZONLINE__RATELIMIT_FILE=/shared/network/rate_limits.json
|
|
94
|
+
|
|
95
|
+
# Default email recipients for ALL notifications (including config errors)
|
|
96
|
+
# This is the PRIMARY recipient setting - used even when FinanzOnline config fails
|
|
97
|
+
FINANZONLINE__DEFAULT_RECIPIENTS=["admin@example.com"]
|
|
98
|
+
|
|
99
|
+
# =============================================================================
|
|
100
|
+
# Email Configuration (for sending notifications)
|
|
101
|
+
# =============================================================================
|
|
102
|
+
|
|
103
|
+
# SMTP servers in JSON array format (tried in order)
|
|
104
|
+
EMAIL__SMTP_HOSTS=["smtp.example.com:587"]
|
|
105
|
+
|
|
106
|
+
# Default sender address
|
|
107
|
+
EMAIL__FROM_ADDRESS=alerts@example.com
|
|
108
|
+
|
|
109
|
+
# SMTP authentication (optional, both needed for auth)
|
|
110
|
+
# EMAIL__SMTP_USERNAME=your-email@example.com
|
|
111
|
+
# EMAIL__SMTP_PASSWORD=your-app-password
|
|
112
|
+
|
|
113
|
+
# SMTP connection settings
|
|
114
|
+
# EMAIL__USE_STARTTLS=true
|
|
115
|
+
# EMAIL__TIMEOUT=30.0
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# =============================================================================
|
|
119
|
+
# Testing (for local development)
|
|
120
|
+
# =============================================================================
|
|
121
|
+
|
|
122
|
+
# Test SMTP server configuration
|
|
123
|
+
TEST_SMTP_SERVER=
|
|
124
|
+
TEST_EMAIL_ADDRESS=
|
|
125
|
+
|
|
126
|
+
# =============================================================================
|
|
127
|
+
# Logging Configuration
|
|
128
|
+
# =============================================================================
|
|
129
|
+
# Uses same SECTION__KEY format as other settings (via lib_layered_config)
|
|
130
|
+
# LIB_LOG_RICH__CONSOLE_LEVEL=DEBUG
|
|
131
|
+
# LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=short
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
allow:
|
|
8
|
+
- dependency-type: "direct"
|
|
9
|
+
labels:
|
|
10
|
+
- "dependencies"
|
|
11
|
+
commit-message:
|
|
12
|
+
prefix: "deps"
|
|
13
|
+
include: "scope"
|
|
14
|
+
- package-ecosystem: "github-actions"
|
|
15
|
+
directory: "/"
|
|
16
|
+
schedule:
|
|
17
|
+
interval: "weekly"
|
|
18
|
+
labels:
|
|
19
|
+
- "dependencies"
|
|
20
|
+
commit-message:
|
|
21
|
+
prefix: "deps"
|
|
22
|
+
include: "scope"
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, master ]
|
|
8
|
+
schedule:
|
|
9
|
+
# Run daily at 3:17 AM UTC (off-peak hours, odd minute to avoid congestion)
|
|
10
|
+
- cron: '17 3 * * *'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Tests (Python ${{ matrix.python }}, ${{ matrix.os }})
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
20
|
+
# Test against Python 3.10, 3.11, 3.12, and 3.13
|
|
21
|
+
python: ["3.10", "3.11", "3.12", "3.13"]
|
|
22
|
+
env:
|
|
23
|
+
PYO3_USE_ABI3_FORWARD_COMPATIBILITY: "1"
|
|
24
|
+
PYTHONIOENCODING: "utf-8"
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v6
|
|
27
|
+
- uses: actions/setup-python@v6
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python }}
|
|
30
|
+
cache: 'pip'
|
|
31
|
+
cache-dependency-path: 'pyproject.toml'
|
|
32
|
+
- name: Install uv
|
|
33
|
+
uses: astral-sh/setup-uv@v7
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
- name: Install rtoml for metadata extraction
|
|
37
|
+
shell: bash
|
|
38
|
+
run: python -m pip install rtoml
|
|
39
|
+
- name: Extract project metadata
|
|
40
|
+
shell: python
|
|
41
|
+
run: |
|
|
42
|
+
import os
|
|
43
|
+
import rtoml
|
|
44
|
+
from pathlib import Path
|
|
45
|
+
|
|
46
|
+
data = rtoml.loads(Path('pyproject.toml').read_text('utf-8'))
|
|
47
|
+
project = data['project']['name']
|
|
48
|
+
module = project.replace('-', '_')
|
|
49
|
+
dash = project.replace('_', '-')
|
|
50
|
+
scripts = list(data['project'].get('scripts', {}).keys())
|
|
51
|
+
cli_bin = scripts[0] if scripts else dash
|
|
52
|
+
|
|
53
|
+
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
54
|
+
env.write(f"PROJECT_NAME={project}\n")
|
|
55
|
+
env.write(f"PACKAGE_MODULE={module}\n")
|
|
56
|
+
env.write(f"CLI_BIN={cli_bin}\n")
|
|
57
|
+
- name: Install make on Windows
|
|
58
|
+
if: runner.os == 'Windows'
|
|
59
|
+
shell: pwsh
|
|
60
|
+
run: |
|
|
61
|
+
choco install -y make
|
|
62
|
+
echo "C:\\ProgramData\\chocolatey\\bin" >> $env:GITHUB_PATH
|
|
63
|
+
- name: Install journald prerequisites
|
|
64
|
+
if: runner.os == 'Linux'
|
|
65
|
+
shell: bash
|
|
66
|
+
run: |
|
|
67
|
+
sudo apt-get update
|
|
68
|
+
sudo apt-get install -y python3-systemd
|
|
69
|
+
|
|
70
|
+
- name: Upgrade pip
|
|
71
|
+
shell: bash
|
|
72
|
+
run: python -m pip install --upgrade pip
|
|
73
|
+
|
|
74
|
+
- name: Install dev deps
|
|
75
|
+
shell: bash
|
|
76
|
+
run: |
|
|
77
|
+
uv pip install -e .[dev] --system
|
|
78
|
+
|
|
79
|
+
- name: Install Windows Event Log prerequisites
|
|
80
|
+
if: runner.os == 'Windows'
|
|
81
|
+
shell: bash
|
|
82
|
+
run: |
|
|
83
|
+
uv pip install pywin32 --system
|
|
84
|
+
- name: Cache ruff
|
|
85
|
+
uses: actions/cache@v5
|
|
86
|
+
with:
|
|
87
|
+
path: .ruff_cache
|
|
88
|
+
key: ruff-${{ runner.os }}-${{ github.sha }}
|
|
89
|
+
restore-keys: |
|
|
90
|
+
ruff-${{ runner.os }}-
|
|
91
|
+
- name: Cache pyright
|
|
92
|
+
uses: actions/cache@v5
|
|
93
|
+
with:
|
|
94
|
+
path: .pyright
|
|
95
|
+
key: pyright-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
|
|
96
|
+
restore-keys: |
|
|
97
|
+
pyright-${{ runner.os }}-py${{ matrix.python }}-
|
|
98
|
+
pyright-${{ runner.os }}-
|
|
99
|
+
- name: Run full test suite (lint, types, tests, coverage, codecov)
|
|
100
|
+
shell: bash
|
|
101
|
+
env:
|
|
102
|
+
TEST_VERBOSE: "1"
|
|
103
|
+
run: make test
|
|
104
|
+
- name: Build wheel/sdist
|
|
105
|
+
shell: bash
|
|
106
|
+
run: python -m build
|
|
107
|
+
- name: Verify wheel install in clean env
|
|
108
|
+
shell: bash
|
|
109
|
+
run: |
|
|
110
|
+
python -m venv .venv_wheel
|
|
111
|
+
. .venv_wheel/bin/activate 2>/dev/null || . .venv_wheel/Scripts/activate 2>/dev/null
|
|
112
|
+
pip install dist/*.whl
|
|
113
|
+
"$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
|
|
114
|
+
|
|
115
|
+
pipx-uv:
|
|
116
|
+
name: pipx/uv verification (ubuntu)
|
|
117
|
+
runs-on: ubuntu-latest
|
|
118
|
+
steps:
|
|
119
|
+
- uses: actions/checkout@v6
|
|
120
|
+
- uses: actions/setup-python@v6
|
|
121
|
+
with:
|
|
122
|
+
python-version: "3.13"
|
|
123
|
+
cache: 'pip'
|
|
124
|
+
cache-dependency-path: 'pyproject.toml'
|
|
125
|
+
- name: Install rtoml for metadata extraction
|
|
126
|
+
run: python -m pip install rtoml
|
|
127
|
+
- name: Extract project metadata
|
|
128
|
+
shell: python
|
|
129
|
+
run: |
|
|
130
|
+
import os
|
|
131
|
+
import rtoml
|
|
132
|
+
from pathlib import Path
|
|
133
|
+
|
|
134
|
+
data = rtoml.loads(Path('pyproject.toml').read_text('utf-8'))
|
|
135
|
+
project = data['project']['name']
|
|
136
|
+
module = project.replace('-', '_')
|
|
137
|
+
dash = project.replace('_', '-')
|
|
138
|
+
scripts = list(data['project'].get('scripts', {}).keys())
|
|
139
|
+
cli_bin = scripts[0] if scripts else dash
|
|
140
|
+
|
|
141
|
+
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
142
|
+
env.write(f"PROJECT_NAME={project}\n")
|
|
143
|
+
env.write(f"PACKAGE_MODULE={module}\n")
|
|
144
|
+
env.write(f"CLI_BIN={cli_bin}\n")
|
|
145
|
+
- name: Build wheel
|
|
146
|
+
run: |
|
|
147
|
+
python -m pip install --upgrade pip build
|
|
148
|
+
python -m build
|
|
149
|
+
- name: pipx install from wheel
|
|
150
|
+
run: |
|
|
151
|
+
python -m pip install pipx
|
|
152
|
+
pipx install dist/*.whl
|
|
153
|
+
"$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
|
|
154
|
+
- name: Install uv
|
|
155
|
+
uses: astral-sh/setup-uv@v7
|
|
156
|
+
with:
|
|
157
|
+
enable-cache: true
|
|
158
|
+
- name: uv tool install
|
|
159
|
+
run: |
|
|
160
|
+
uv tool install .
|
|
161
|
+
"$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
|
|
162
|
+
|
|
163
|
+
notebooks:
|
|
164
|
+
name: Execute notebooks (ubuntu, Python 3.13)
|
|
165
|
+
runs-on: ubuntu-latest
|
|
166
|
+
steps:
|
|
167
|
+
- uses: actions/checkout@v6
|
|
168
|
+
- uses: actions/setup-python@v6
|
|
169
|
+
with:
|
|
170
|
+
python-version: "3.13"
|
|
171
|
+
cache: 'pip'
|
|
172
|
+
cache-dependency-path: 'pyproject.toml'
|
|
173
|
+
- name: Install notebook runner deps
|
|
174
|
+
run: |
|
|
175
|
+
python -m pip install --upgrade pip
|
|
176
|
+
pip install nbclient nbformat ipykernel jupyter_client
|
|
177
|
+
python -m ipykernel install --user --name python3 --display-name "Python 3"
|
|
178
|
+
- name: Execute Quickstart notebook
|
|
179
|
+
env:
|
|
180
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
|
181
|
+
PIP_NO_INPUT: "1"
|
|
182
|
+
run: |
|
|
183
|
+
python - << 'PY'
|
|
184
|
+
from pathlib import Path
|
|
185
|
+
|
|
186
|
+
import nbformat
|
|
187
|
+
from nbclient import NotebookClient
|
|
188
|
+
|
|
189
|
+
nb_path = Path('notebooks/Quickstart.ipynb')
|
|
190
|
+
if not nb_path.exists():
|
|
191
|
+
raise SystemExit(f"Notebook not found: {nb_path}")
|
|
192
|
+
|
|
193
|
+
notebook = nbformat.read(nb_path, as_version=4)
|
|
194
|
+
client = NotebookClient(
|
|
195
|
+
notebook,
|
|
196
|
+
timeout=900,
|
|
197
|
+
kernel_name='python3',
|
|
198
|
+
allow_errors=False,
|
|
199
|
+
)
|
|
200
|
+
client.execute()
|
|
201
|
+
|
|
202
|
+
out_path = Path('notebooks/Quickstart-executed.ipynb')
|
|
203
|
+
nbformat.write(notebook, out_path)
|
|
204
|
+
print(f"Executed notebook written to: {out_path}")
|
|
205
|
+
PY
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, master ]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 8 * * 1'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
analyze:
|
|
13
|
+
name: CodeQL Analyze
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
actions: read
|
|
17
|
+
contents: read
|
|
18
|
+
security-events: write
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
language: [ 'python' ]
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- name: Checkout repository
|
|
26
|
+
uses: actions/checkout@v6
|
|
27
|
+
|
|
28
|
+
- name: Initialize CodeQL
|
|
29
|
+
uses: github/codeql-action/init@v4
|
|
30
|
+
with:
|
|
31
|
+
languages: ${{ matrix.language }}
|
|
32
|
+
|
|
33
|
+
- name: Autobuild
|
|
34
|
+
uses: github/codeql-action/autobuild@v4
|
|
35
|
+
|
|
36
|
+
- name: Perform CodeQL Analysis
|
|
37
|
+
uses: github/codeql-action/analyze@v4
|
|
38
|
+
with:
|
|
39
|
+
category: "/language:${{ matrix.language }}"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
push:
|
|
7
|
+
tags:
|
|
8
|
+
- 'v*'
|
|
9
|
+
workflow_dispatch: {}
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build-and-publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
- name: Verify PyPI token is set
|
|
19
|
+
run: |
|
|
20
|
+
if [ -z "${{ secrets.PYPI_API_TOKEN }}" ]; then
|
|
21
|
+
echo "::error title=Missing PyPI token::Set the PYPI_API_TOKEN secret in GitHub repository settings to enable PyPI publishing on releases."
|
|
22
|
+
echo "See: https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
- uses: actions/setup-python@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: '3.13'
|
|
28
|
+
cache: 'pip'
|
|
29
|
+
cache-dependency-path: 'pyproject.toml'
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@v7
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
- name: Build artifacts
|
|
35
|
+
run: |
|
|
36
|
+
python -m pip install --upgrade pip
|
|
37
|
+
uv pip install build --system
|
|
38
|
+
python -m build
|
|
39
|
+
- name: Publish to PyPI
|
|
40
|
+
# Use the rolling major tag to get latest Twine/standards support (e.g., Core Metadata 2.4)
|
|
41
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
42
|
+
with:
|
|
43
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
44
|
+
attestations: false
|
|
45
|
+
skip-existing: true
|
|
46
|
+
- name: Upload artifacts
|
|
47
|
+
uses: actions/upload-artifact@v6
|
|
48
|
+
with:
|
|
49
|
+
name: dist
|
|
50
|
+
path: dist/*
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# ====================================
|
|
2
|
+
# ROTEK SPEZIFISCH: Git commands you might run once
|
|
3
|
+
# git add .gitignore && git commit -m "Ignore IDE settings"
|
|
4
|
+
# git push
|
|
5
|
+
# git rm -r --cached .idea
|
|
6
|
+
# git commit -m "Remove .idea and add to .gitignore"
|
|
7
|
+
# git push
|
|
8
|
+
# alternative : BE CAREFUL: overwrites remote history
|
|
9
|
+
# git push origin master --force
|
|
10
|
+
|
|
11
|
+
# ====================================
|
|
12
|
+
# APP
|
|
13
|
+
# ====================================
|
|
14
|
+
website/build/
|
|
15
|
+
website/.docusaurus/
|
|
16
|
+
website/node_modules/
|
|
17
|
+
node_modules/
|
|
18
|
+
web-local-preview/
|
|
19
|
+
translation_app*.log
|
|
20
|
+
translation_web*.log
|
|
21
|
+
tmp_github_web_pages/
|
|
22
|
+
tmp_linkcheck_web_pages/
|
|
23
|
+
.eslintcache
|
|
24
|
+
.vitest/
|
|
25
|
+
npm-debug.log*
|
|
26
|
+
yarn-error.log*
|
|
27
|
+
pnpm-debug.log*
|
|
28
|
+
.env.*
|
|
29
|
+
!.env.example
|
|
30
|
+
todo.md
|
|
31
|
+
tmp_*
|
|
32
|
+
|
|
33
|
+
# ====================================
|
|
34
|
+
# IDEs & Editors
|
|
35
|
+
# ====================================
|
|
36
|
+
# IntelliJ, PyCharm, etc.
|
|
37
|
+
.idea/
|
|
38
|
+
# VS Code workspace settings
|
|
39
|
+
.vscode/
|
|
40
|
+
*.code-workspace
|
|
41
|
+
|
|
42
|
+
# ====================================
|
|
43
|
+
# Python bytecode & caches
|
|
44
|
+
# ====================================
|
|
45
|
+
# __pycache__: compiled .pyc files at any depth
|
|
46
|
+
# *.py[cod]: catches .pyc, .pyo, .pyd
|
|
47
|
+
__pycache__/
|
|
48
|
+
*.py[cod]
|
|
49
|
+
*$py.class # other compiled artifacts
|
|
50
|
+
|
|
51
|
+
# pytest, coverage, MyPy, Hypothesis
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
.mypy_cache/
|
|
54
|
+
.pyright/
|
|
55
|
+
.coverage*
|
|
56
|
+
htmlcov/
|
|
57
|
+
nosetests.xml
|
|
58
|
+
coverage.xml
|
|
59
|
+
*.cover
|
|
60
|
+
.hypothesis/
|
|
61
|
+
.tox/
|
|
62
|
+
.nox/
|
|
63
|
+
|
|
64
|
+
# general cache directories (any project-level caching)
|
|
65
|
+
.cache/
|
|
66
|
+
.run/
|
|
67
|
+
.import_linter_cache/
|
|
68
|
+
|
|
69
|
+
# ====================================
|
|
70
|
+
# Build & distribution artifacts
|
|
71
|
+
# ====================================
|
|
72
|
+
# source/package builds
|
|
73
|
+
build/
|
|
74
|
+
dist/
|
|
75
|
+
*.egg-info/ # metadata for pip installs
|
|
76
|
+
*.egg
|
|
77
|
+
*.whl
|
|
78
|
+
pip-wheel-metadata/
|
|
79
|
+
*.manifest # PyInstaller metadata
|
|
80
|
+
*.spec # PyInstaller spec files
|
|
81
|
+
|
|
82
|
+
# Eggs, parts, wheels, sdist, etc.
|
|
83
|
+
develop-eggs/
|
|
84
|
+
.eggs/
|
|
85
|
+
parts/
|
|
86
|
+
sdist/
|
|
87
|
+
wheels/
|
|
88
|
+
downloads/
|
|
89
|
+
var/
|
|
90
|
+
|
|
91
|
+
# pip logs & installer leftovers
|
|
92
|
+
pip-log.txt
|
|
93
|
+
pip-delete-this-directory.txt
|
|
94
|
+
.installed.cfg
|
|
95
|
+
|
|
96
|
+
# ====================================
|
|
97
|
+
# Virtual environments & secrets
|
|
98
|
+
# ====================================
|
|
99
|
+
# common venv folder names
|
|
100
|
+
env/
|
|
101
|
+
venv/
|
|
102
|
+
ENV/
|
|
103
|
+
.venv/
|
|
104
|
+
# backups, alternate names
|
|
105
|
+
env.bak/
|
|
106
|
+
venv.bak/
|
|
107
|
+
# dotenv files with credentials
|
|
108
|
+
.env
|
|
109
|
+
|
|
110
|
+
# ====================================
|
|
111
|
+
# Project-specific & framework files
|
|
112
|
+
# ====================================
|
|
113
|
+
# Django logs & local overrides
|
|
114
|
+
*.log
|
|
115
|
+
local_settings.py
|
|
116
|
+
|
|
117
|
+
# Flask instance folder
|
|
118
|
+
instance/
|
|
119
|
+
.webassets-cache
|
|
120
|
+
|
|
121
|
+
# Scrapy cache
|
|
122
|
+
.scrapy
|
|
123
|
+
|
|
124
|
+
# Sphinx docs
|
|
125
|
+
docs/_build/
|
|
126
|
+
|
|
127
|
+
# PyBuilder output
|
|
128
|
+
target/
|
|
129
|
+
|
|
130
|
+
# Jupyter notebooks checkpoints
|
|
131
|
+
.ipynb_checkpoints
|
|
132
|
+
|
|
133
|
+
# pyenv Python version file
|
|
134
|
+
.python-version
|
|
135
|
+
|
|
136
|
+
# Celery beat schedule
|
|
137
|
+
celerybeat-schedule
|
|
138
|
+
|
|
139
|
+
# SageMath parsed files
|
|
140
|
+
*.sage.py
|
|
141
|
+
|
|
142
|
+
# Spyder IDE
|
|
143
|
+
.spyderproject
|
|
144
|
+
.spyproject
|
|
145
|
+
|
|
146
|
+
# Rope IDE
|
|
147
|
+
.ropeproject
|
|
148
|
+
|
|
149
|
+
# MkDocs static site folder
|
|
150
|
+
/site
|
|
151
|
+
|
|
152
|
+
# ====================================
|
|
153
|
+
# OS-specific files
|
|
154
|
+
# ====================================
|
|
155
|
+
# macOS
|
|
156
|
+
.DS_Store
|
|
157
|
+
# Windows
|
|
158
|
+
Thumbs.db
|
|
159
|
+
ehthumbs.db
|
|
160
|
+
|
|
161
|
+
# Archives
|
|
162
|
+
*.zip
|
|
163
|
+
|
|
164
|
+
# Thunderbird build artifact (created temporarily by pack script)
|
|
165
|
+
sources/manifest.json
|
|
166
|
+
|
|
167
|
+
# ====================================
|
|
168
|
+
# Tool-specific extras
|
|
169
|
+
# ====================================
|
|
170
|
+
# Codecov uploader script (downloaded during local uploads)
|
|
171
|
+
codecov.sh
|
|
172
|
+
codecov.xml
|
|
173
|
+
|
|
174
|
+
# Nix build result symlink
|
|
175
|
+
result
|
|
176
|
+
|
|
177
|
+
# Optional lockfiles (for alternative managers)
|
|
178
|
+
poetry.lock
|
|
179
|
+
pdm.lock
|
|
180
|
+
uv.lock
|