openframe-core 1.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.
- openframe_core-1.0.0/.github/CHANGELOG.md +91 -0
- openframe_core-1.0.0/.github/requirements/docs.txt +3 -0
- openframe_core-1.0.0/.github/requirements/test.txt +18 -0
- openframe_core-1.0.0/.github/workflows/app-test.yml +41 -0
- openframe_core-1.0.0/.github/workflows/auto-docs.yml +74 -0
- openframe_core-1.0.0/.github/workflows/python-build.yml +84 -0
- openframe_core-1.0.0/.gitignore +218 -0
- openframe_core-1.0.0/LICENSE +21 -0
- openframe_core-1.0.0/PKG-INFO +219 -0
- openframe_core-1.0.0/README.md +198 -0
- openframe_core-1.0.0/openframe/__init__.py +1 -0
- openframe_core-1.0.0/openframe/core/__init__.py +1 -0
- openframe_core-1.0.0/openframe/core/config/__init__.py +17 -0
- openframe_core-1.0.0/openframe/core/config/settings.py +70 -0
- openframe_core-1.0.0/openframe/core/exceptions/__init__.py +39 -0
- openframe_core-1.0.0/openframe/core/exceptions/errors.py +189 -0
- openframe_core-1.0.0/openframe/core/health/__init__.py +19 -0
- openframe_core-1.0.0/openframe/core/health/protocol.py +94 -0
- openframe_core-1.0.0/openframe/core/middleware/__init__.py +55 -0
- openframe_core-1.0.0/openframe/core/middleware/telemetry.py +315 -0
- openframe_core-1.0.0/openframe/core/middleware/types.py +56 -0
- openframe_core-1.0.0/openframe/core/ports/__init__.py +29 -0
- openframe_core-1.0.0/openframe/core/ports/consumer.py +125 -0
- openframe_core-1.0.0/openframe/core/ports/producer.py +94 -0
- openframe_core-1.0.0/openframe/core/ports/repository.py +143 -0
- openframe_core-1.0.0/openframe/core/telemetry/__init__.py +43 -0
- openframe_core-1.0.0/openframe/core/telemetry/setup.py +230 -0
- openframe_core-1.0.0/openframe/core/tracing/__init__.py +24 -0
- openframe_core-1.0.0/openframe/core/tracing/proxy.py +135 -0
- openframe_core-1.0.0/pyproject.toml +35 -0
- openframe_core-1.0.0/pytest.ini +4 -0
- openframe_core-1.0.0/tests/conftest.py +135 -0
- openframe_core-1.0.0/tests/test_config.py +148 -0
- openframe_core-1.0.0/tests/test_exceptions.py +218 -0
- openframe_core-1.0.0/tests/test_health.py +118 -0
- openframe_core-1.0.0/tests/test_middleware.py +321 -0
- openframe_core-1.0.0/tests/test_middleware_types.py +147 -0
- openframe_core-1.0.0/tests/test_ports.py +240 -0
- openframe_core-1.0.0/tests/test_tracing.py +190 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## [1.0.0] — 2026-06-13
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
#### `openframe.core.exceptions`
|
|
19
|
+
- `AdapterError` — base exception class for all OpenFrame adapter packages. Carries `message`, `adapter`, `operation`, and `cause` fields. Implements `__str__` to produce `[adapter.operation] message — caused by: <cause>` rather than a raw tuple repr.
|
|
20
|
+
- `AdapterConnectionError` — raised when an adapter cannot establish a connection to its backend.
|
|
21
|
+
- `AdapterQueryError` — raised when an operation fails after a connection is established.
|
|
22
|
+
- `AdapterNotFoundError` — raised when a requested entity does not exist in the backend.
|
|
23
|
+
- `AdapterConfigurationError` — raised when required configuration (env vars, settings) is missing or invalid.
|
|
24
|
+
- `AdapterTimeoutError` — raised when an operation exceeds its configured timeout.
|
|
25
|
+
|
|
26
|
+
#### `openframe.core.config`
|
|
27
|
+
- `BaseAdapterSettings` — Pydantic `BaseSettings` subclass that all adapter config classes inherit from. Reads fields from environment variables automatically (case-insensitive, no prefix). Ships with four common fields: `adapter_name`, `connection_timeout` (30 s), `operation_timeout` (10 s), and `max_retries` (3). Missing required fields raise `ValidationError` at instantiation time.
|
|
28
|
+
|
|
29
|
+
#### `openframe.core.ports`
|
|
30
|
+
- `BaseRepository[T]` — generic `runtime_checkable` Protocol for persistence adapters. Methods: `get`, `list`, `create`, `update`, `delete`.
|
|
31
|
+
- `BaseProducer[T]` — generic `runtime_checkable` Protocol for message producers. Methods: `publish`, `publish_batch`, `close`.
|
|
32
|
+
- `BaseConsumer[T]` — generic `runtime_checkable` Protocol for message consumers. Methods: `subscribe`, `ack`, `nack`, `close`. Uses a push-based handler model via `Callable[[T], Awaitable[None]]`.
|
|
33
|
+
|
|
34
|
+
#### `openframe.core.health`
|
|
35
|
+
- `HealthCheck` — `runtime_checkable` Protocol with two async methods: `ping()` (low-cost liveness, e.g. `SELECT 1`) and `is_ready()` (full readiness — schema migrations, pool health).
|
|
36
|
+
|
|
37
|
+
#### `openframe.core.telemetry`
|
|
38
|
+
- `setup_telemetry()` — idempotent OTel SDK bootstrap. Configures OTLP trace and metric exporters when `OTEL_EXPORTER_OTLP_ENDPOINT` is set; falls back to no-op providers otherwise. Applies `LoggingInstrumentor` for automatic trace-id injection into log records.
|
|
39
|
+
- `get_tracer(name)` — `@lru_cache` accessor for the globally-configured `Tracer`.
|
|
40
|
+
- `get_meter(name)` — `@lru_cache` accessor for the globally-configured `Meter`.
|
|
41
|
+
- `record_lifecycle_event(event_name, attributes)` — platform-agnostic lifecycle counter. Replaces the template's `record_cold_start()`; callers pass `event_name="cold_start"`. Core remains platform-agnostic.
|
|
42
|
+
- Reads environment variables: `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_HEADERS`, `OTEL_SERVICE_NAME`, `OTEL_SERVICE_VERSION`, `OTEL_METRIC_EXPORT_INTERVAL_MS`, `OPENFRAME_ENV`.
|
|
43
|
+
|
|
44
|
+
#### `openframe.core.tracing`
|
|
45
|
+
- `TracingProxy` — zero-code async telemetry sidecar. Wraps any object and intercepts every async method call with an OTel child span. Span name: `{prefix}.{method_name}`. Sync methods pass through unwrapped. Uses an explicit `_cache` dict for closure reuse without method snapshotting — safe for reconnecting adapters (Postgres pools, Redis clients) that replace their own methods after reconnect.
|
|
46
|
+
|
|
47
|
+
#### `openframe.core.middleware`
|
|
48
|
+
- `TelemetryMiddleware` — pure ASGI telemetry middleware, compatible with FastAPI, Starlette, Litestar, and bare ASGI. Records one OTel span and five HTTP metric instruments per request. Injects `x-session-id` response header. Sets `StatusCode.ERROR` for HTTP ≥ 400, `StatusCode.OK` otherwise. Emits a structured log line per request.
|
|
49
|
+
- Metric instruments: `http.server.request.count` (`1`), `http.server.request.duration` (`s`), `http.server.active_requests` (`1`), `http.server.error.count` (`1`), `http.server.response.size` (`By`). Duration uses unit `"s"` per OTel HTTP semantic conventions.
|
|
50
|
+
- Span attributes: `http.method`, `http.target`, `http.route`, `http.scheme`, `http.status_code`, `http.user_agent`, `net.host.name`, `http.client_ip`, `app.session_id`.
|
|
51
|
+
- Route template extraction: raw ASGI uses `scope["path"]`; Starlette/FastAPI users get template grouping automatically via `scope["route"].path`.
|
|
52
|
+
|
|
53
|
+
#### `openframe.core.middleware.types`
|
|
54
|
+
- `ASGIScope`, `ASGIMessage`, `Receive`, `Send`, `ASGIApp` — stdlib-only ASGI type aliases shared across the OpenFrame ecosystem. No framework imports required.
|
|
55
|
+
|
|
56
|
+
#### Tests
|
|
57
|
+
- 112 tests across 8 test modules: `test_exceptions`, `test_config`, `test_ports`, `test_health`, `test_tracing`, `test_middleware`, `test_middleware_types`, `test_config`.
|
|
58
|
+
- `conftest.py` resets all OTel SDK global state between tests (the `Once._done` guard on `set_tracer_provider` / `set_meter_provider`, `lru_cache` entries, and the `_INITIALISED` flag) so every test receives a clean, isolated tracer and meter.
|
|
59
|
+
|
|
60
|
+
#### Package
|
|
61
|
+
- `pyproject.toml` with `hatchling` build backend, `requires-python = ">=3.11"`.
|
|
62
|
+
- `pytest.ini` with `asyncio_mode = auto` for `pytest-asyncio`.
|
|
63
|
+
- Namespace package declaration in `openframe/__init__.py` via `pkgutil.extend_path`.
|
|
64
|
+
|
|
65
|
+
### Design decisions
|
|
66
|
+
|
|
67
|
+
- **Exception naming** — all exception subclasses carry the `Adapter` prefix (`AdapterConnectionError`, `AdapterTimeoutError`) to avoid shadowing the Python stdlib built-ins `ConnectionError` and `TimeoutError`.
|
|
68
|
+
- **No Grafana-specific auth** — `_grafana_headers()` from the production template is removed. The OTel SDK handles authentication natively via `OTEL_EXPORTER_OTLP_HEADERS`.
|
|
69
|
+
- **`OPENFRAME_ENV` replaces `MODAL_ENV`** — the environment tag is platform-agnostic. Modal users map `MODAL_ENV → OPENFRAME_ENV` in their `configure_env_vars()`.
|
|
70
|
+
- **Middleware does not call `setup_telemetry()`** — it calls `get_tracer()` and `get_meter()` directly. `setup_telemetry()` is an application startup concern (called once in a `lifespan` handler). This design makes the middleware safely composable with test fixtures that install their own providers.
|
|
71
|
+
- **`TracingProxy` closure safety** — the original template captured the resolved method in the closure at first access (a snapshot). This implementation resolves the method fresh on every invocation inside `_traced`, making the proxy safe for adapters that replace their own methods after reconnect.
|
|
72
|
+
- **Pure ASGI middleware** — uses `__call__(scope, receive, send)` rather than Starlette's `BaseHTTPMiddleware`, which has documented streaming and buffering limitations.
|
|
73
|
+
|
|
74
|
+
### Dependencies
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
opentelemetry-api>=1.24
|
|
78
|
+
opentelemetry-sdk>=1.24
|
|
79
|
+
opentelemetry-exporter-otlp-proto-http>=1.24
|
|
80
|
+
opentelemetry-semantic-conventions>=0.45b0
|
|
81
|
+
opentelemetry-instrumentation-logging>=0.45b0
|
|
82
|
+
pydantic>=2.0
|
|
83
|
+
pydantic-settings>=2.0
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Dev dependencies: `pytest>=8.0`, `pytest-asyncio>=0.23`, `httpx>=0.27`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
[Unreleased]: https://github.com/openframe-org/openframe-core/compare/v1.0.0...HEAD
|
|
91
|
+
[1.0.0]: https://github.com/openframe-org/openframe-core/releases/tag/v1.0.0
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Test dependencies for openframe-core CI
|
|
2
|
+
# Install the package first: pip install -e .
|
|
3
|
+
# Then: pip install -r .github/requirements/test.txt
|
|
4
|
+
|
|
5
|
+
pytest>=8.0
|
|
6
|
+
pytest-asyncio>=0.23
|
|
7
|
+
httpx>=0.27
|
|
8
|
+
|
|
9
|
+
# Core runtime deps — pinned here to lock CI against minimum supported versions.
|
|
10
|
+
# The package's own pyproject.toml declares the same floors; these are explicit
|
|
11
|
+
# to catch regressions when upstream releases a new major.
|
|
12
|
+
pydantic>=2.0
|
|
13
|
+
pydantic-settings>=2.0
|
|
14
|
+
opentelemetry-api>=1.24
|
|
15
|
+
opentelemetry-sdk>=1.24
|
|
16
|
+
opentelemetry-exporter-otlp-proto-http>=1.24
|
|
17
|
+
opentelemetry-semantic-conventions>=0.45b0
|
|
18
|
+
opentelemetry-instrumentation-logging>=0.45b0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: App Testing
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches:
|
|
6
|
+
- dev
|
|
7
|
+
- production
|
|
8
|
+
|
|
9
|
+
# Callable from other workflows (e.g. python-build.yml runs tests before publish).
|
|
10
|
+
workflow_call:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Pytest — Python ${{ matrix.python-version }}
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: true
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.11", "3.12"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Setup Python ${{ matrix.python-version }}
|
|
27
|
+
uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python-version }}
|
|
30
|
+
cache: pip
|
|
31
|
+
|
|
32
|
+
- name: Install package in editable mode
|
|
33
|
+
run: |
|
|
34
|
+
python -m pip install --upgrade pip
|
|
35
|
+
pip install -e .
|
|
36
|
+
|
|
37
|
+
- name: Install test dependencies
|
|
38
|
+
run: pip install -r .github/requirements/test.txt
|
|
39
|
+
|
|
40
|
+
- name: Run tests
|
|
41
|
+
run: python -m pytest tests/ -v --tb=short
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Auto Docs
|
|
2
|
+
|
|
3
|
+
# Deploy docs to GitHub Pages on every push to production.
|
|
4
|
+
# On PRs to dev or production, only build (validate) — do not deploy.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- production
|
|
9
|
+
|
|
10
|
+
pull_request:
|
|
11
|
+
branches:
|
|
12
|
+
- dev
|
|
13
|
+
- production
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
# ── 1. Build docs (runs on every PR to validate the docs compile) ────────
|
|
17
|
+
build-docs:
|
|
18
|
+
name: Build Documentation
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Setup Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.11"
|
|
29
|
+
cache: pip
|
|
30
|
+
|
|
31
|
+
- name: Install docs dependencies
|
|
32
|
+
run: |
|
|
33
|
+
python -m pip install --upgrade pip
|
|
34
|
+
pip install -r .github/requirements/docs.txt
|
|
35
|
+
|
|
36
|
+
- name: Build docs (validate only)
|
|
37
|
+
run: mkdocs build --strict
|
|
38
|
+
|
|
39
|
+
# ── 2. Deploy docs to GitHub Pages (production merges only) ─────────────
|
|
40
|
+
deploy-docs:
|
|
41
|
+
name: Deploy Documentation
|
|
42
|
+
needs: build-docs
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
|
|
45
|
+
# Only deploy when a commit lands on production, not on PRs.
|
|
46
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/production'
|
|
47
|
+
|
|
48
|
+
permissions:
|
|
49
|
+
contents: write # required for gh-deploy to push to gh-pages branch
|
|
50
|
+
|
|
51
|
+
steps:
|
|
52
|
+
- name: Checkout
|
|
53
|
+
uses: actions/checkout@v4
|
|
54
|
+
with:
|
|
55
|
+
fetch-depth: 0 # full history needed for mkdocs git-revision-date plugins
|
|
56
|
+
|
|
57
|
+
- name: Setup Python
|
|
58
|
+
uses: actions/setup-python@v5
|
|
59
|
+
with:
|
|
60
|
+
python-version: "3.11"
|
|
61
|
+
cache: pip
|
|
62
|
+
|
|
63
|
+
- name: Install docs dependencies
|
|
64
|
+
run: |
|
|
65
|
+
python -m pip install --upgrade pip
|
|
66
|
+
pip install -r .github/requirements/docs.txt
|
|
67
|
+
|
|
68
|
+
- name: Configure Git for gh-deploy
|
|
69
|
+
run: |
|
|
70
|
+
git config user.name "github-actions[bot]"
|
|
71
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
72
|
+
|
|
73
|
+
- name: Deploy docs to GitHub Pages
|
|
74
|
+
run: mkdocs gh-deploy --force
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: Build & Publish Python Package
|
|
2
|
+
|
|
3
|
+
# Triggers on every push to production (i.e. after a PR is merged).
|
|
4
|
+
# Runs the full test suite first; publish is blocked until all tests pass.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- production
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
# ── 1. Gate: full test suite must pass before anything is published ──────
|
|
12
|
+
test:
|
|
13
|
+
name: Run Test Suite
|
|
14
|
+
uses: ./.github/workflows/app-test.yml
|
|
15
|
+
|
|
16
|
+
# ── 2. Build the wheel and sdist ────────────────────────────────────────
|
|
17
|
+
build:
|
|
18
|
+
name: Build Distribution
|
|
19
|
+
needs: test
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Setup Python
|
|
27
|
+
uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.11"
|
|
30
|
+
cache: pip
|
|
31
|
+
|
|
32
|
+
- name: Install build tools
|
|
33
|
+
run: |
|
|
34
|
+
python -m pip install --upgrade pip
|
|
35
|
+
pip install build
|
|
36
|
+
|
|
37
|
+
- name: Build wheel and sdist
|
|
38
|
+
run: python -m build
|
|
39
|
+
|
|
40
|
+
- name: Upload distribution artifacts
|
|
41
|
+
uses: actions/upload-artifact@v4
|
|
42
|
+
with:
|
|
43
|
+
name: dist
|
|
44
|
+
path: dist/
|
|
45
|
+
retention-days: 7
|
|
46
|
+
|
|
47
|
+
# ── 3. Publish to PyPI ──────────────────────────────────────────────────
|
|
48
|
+
publish:
|
|
49
|
+
name: Publish to PyPI
|
|
50
|
+
needs: build
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
|
|
53
|
+
# Restrict to the production branch only — belt-and-suspenders guard
|
|
54
|
+
# so an accidental workflow_dispatch on dev cannot publish.
|
|
55
|
+
if: github.ref == 'refs/heads/production'
|
|
56
|
+
|
|
57
|
+
# PyPI Trusted Publishing (OIDC) — no long-lived API token required.
|
|
58
|
+
# Configure at: https://pypi.org/manage/project/openframe-core/settings/publishing/
|
|
59
|
+
# Add a publisher with:
|
|
60
|
+
# Owner: <your GitHub org/user>
|
|
61
|
+
# Repo: openframe-core
|
|
62
|
+
# Workflow: python-build.yml
|
|
63
|
+
# Env: pypi
|
|
64
|
+
environment:
|
|
65
|
+
name: pypi
|
|
66
|
+
url: https://pypi.org/p/openframe-core
|
|
67
|
+
|
|
68
|
+
permissions:
|
|
69
|
+
id-token: write # required for OIDC trusted publishing
|
|
70
|
+
|
|
71
|
+
steps:
|
|
72
|
+
- name: Download distribution artifacts
|
|
73
|
+
uses: actions/download-artifact@v4
|
|
74
|
+
with:
|
|
75
|
+
name: dist
|
|
76
|
+
path: dist/
|
|
77
|
+
|
|
78
|
+
- name: Publish to PyPI
|
|
79
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
80
|
+
# No password needed when using OIDC trusted publishing.
|
|
81
|
+
# If you prefer an API token, uncomment the line below and set the
|
|
82
|
+
# PYPI_API_TOKEN secret in repo Settings → Secrets → Actions:
|
|
83
|
+
# with:
|
|
84
|
+
# password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenFrame
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|