extended-data 8.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.
- extended_data-8.0.0/.github/workflows/cd.yml +111 -0
- extended_data-8.0.0/.github/workflows/ci.yml +52 -0
- extended_data-8.0.0/.github/workflows/release.yml +29 -0
- extended_data-8.0.0/.gitignore +16 -0
- extended_data-8.0.0/.python-version +1 -0
- extended_data-8.0.0/.release-please-manifest.json +3 -0
- extended_data-8.0.0/CHANGELOG.md +29 -0
- extended_data-8.0.0/LICENSE +21 -0
- extended_data-8.0.0/PKG-INFO +189 -0
- extended_data-8.0.0/README.md +117 -0
- extended_data-8.0.0/docs/CNAME +1 -0
- extended_data-8.0.0/docs/PUBLISHING_CHECKLIST.md +82 -0
- extended_data-8.0.0/docs/__init__.py +1 -0
- extended_data-8.0.0/docs/_static/.gitkeep +1 -0
- extended_data-8.0.0/docs/_static/extended-data.css +22 -0
- extended_data-8.0.0/docs/api/index.rst +9 -0
- extended_data-8.0.0/docs/conf.py +76 -0
- extended_data-8.0.0/docs/core/containers.md +31 -0
- extended_data-8.0.0/docs/core/primitives.md +52 -0
- extended_data-8.0.0/docs/core/workflows.md +46 -0
- extended_data-8.0.0/docs/examples/core.md +36 -0
- extended_data-8.0.0/docs/examples/index.md +13 -0
- extended_data-8.0.0/docs/examples/inputs.md +22 -0
- extended_data-8.0.0/docs/examples/logging.md +29 -0
- extended_data-8.0.0/docs/getting-started.md +52 -0
- extended_data-8.0.0/docs/index.md +53 -0
- extended_data-8.0.0/docs/operations/inputs.md +34 -0
- extended_data-8.0.0/docs/operations/logging.md +25 -0
- extended_data-8.0.0/docs/ownership-map.md +48 -0
- extended_data-8.0.0/docs/package-surface.md +93 -0
- extended_data-8.0.0/docs/publishing.md +22 -0
- extended_data-8.0.0/examples/core/README.md +39 -0
- extended_data-8.0.0/examples/core/basic_usage.py +70 -0
- extended_data-8.0.0/examples/core/composed_workflows.py +142 -0
- extended_data-8.0.0/examples/core/file_operations.py +123 -0
- extended_data-8.0.0/examples/core/serialization.py +139 -0
- extended_data-8.0.0/examples/core/string_transformations.py +109 -0
- extended_data-8.0.0/examples/inputs/README.md +52 -0
- extended_data-8.0.0/examples/inputs/__init__.py +3 -0
- extended_data-8.0.0/examples/inputs/basic_usage.py +60 -0
- extended_data-8.0.0/examples/inputs/decorator_api.py +96 -0
- extended_data-8.0.0/examples/inputs/encoding_decoding.py +80 -0
- extended_data-8.0.0/examples/logging/README.md +73 -0
- extended_data-8.0.0/examples/logging/basic_logging.py +52 -0
- extended_data-8.0.0/examples/logging/exit_run_formatting.py +56 -0
- extended_data-8.0.0/examples/logging/markers_and_storage.py +63 -0
- extended_data-8.0.0/examples/logging/verbosity_control.py +63 -0
- extended_data-8.0.0/pyproject.toml +177 -0
- extended_data-8.0.0/release-please-config.json +22 -0
- extended_data-8.0.0/src/extended_data/__init__.py +105 -0
- extended_data-8.0.0/src/extended_data/_version.py +16 -0
- extended_data-8.0.0/src/extended_data/cli.py +204 -0
- extended_data-8.0.0/src/extended_data/containers/__init__.py +17 -0
- extended_data-8.0.0/src/extended_data/containers/factory.py +57 -0
- extended_data-8.0.0/src/extended_data/containers/mappings.py +181 -0
- extended_data-8.0.0/src/extended_data/containers/sequences.py +403 -0
- extended_data-8.0.0/src/extended_data/containers/strings.py +276 -0
- extended_data-8.0.0/src/extended_data/inputs/__init__.py +14 -0
- extended_data-8.0.0/src/extended_data/inputs/__main__.py +412 -0
- extended_data-8.0.0/src/extended_data/inputs/decorators.py +346 -0
- extended_data-8.0.0/src/extended_data/inputs/py.typed +0 -0
- extended_data-8.0.0/src/extended_data/io/__init__.py +50 -0
- extended_data-8.0.0/src/extended_data/io/base64.py +65 -0
- extended_data-8.0.0/src/extended_data/io/exporters.py +151 -0
- extended_data-8.0.0/src/extended_data/io/files.py +619 -0
- extended_data-8.0.0/src/extended_data/io/importers.py +53 -0
- extended_data-8.0.0/src/extended_data/logging/__init__.py +13 -0
- extended_data-8.0.0/src/extended_data/logging/const.py +15 -0
- extended_data-8.0.0/src/extended_data/logging/handlers.py +61 -0
- extended_data-8.0.0/src/extended_data/logging/log_types.py +18 -0
- extended_data-8.0.0/src/extended_data/logging/logging.py +663 -0
- extended_data-8.0.0/src/extended_data/logging/py.typed +0 -0
- extended_data-8.0.0/src/extended_data/logging/utils.py +167 -0
- extended_data-8.0.0/src/extended_data/primitives/__init__.py +172 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/__init__.py +47 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/_normalization.py +15 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/errors.py +72 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/hcl.py +264 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/json.py +100 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/toml.py +48 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/__init__.py +43 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/constructors.py +58 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/dumpers.py +75 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/loaders.py +31 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/representers.py +82 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/tag_classes.py +79 -0
- extended_data-8.0.0/src/extended_data/primitives/formats/yaml/utils.py +75 -0
- extended_data-8.0.0/src/extended_data/primitives/introspection.py +168 -0
- extended_data-8.0.0/src/extended_data/primitives/mappings.py +399 -0
- extended_data-8.0.0/src/extended_data/primitives/matching.py +82 -0
- extended_data-8.0.0/src/extended_data/primitives/numbers.py +236 -0
- extended_data-8.0.0/src/extended_data/primitives/redaction.py +126 -0
- extended_data-8.0.0/src/extended_data/primitives/sequences.py +85 -0
- extended_data-8.0.0/src/extended_data/primitives/serialization.py +37 -0
- extended_data-8.0.0/src/extended_data/primitives/splitting.py +56 -0
- extended_data-8.0.0/src/extended_data/primitives/state.py +162 -0
- extended_data-8.0.0/src/extended_data/primitives/string_transforms.py +74 -0
- extended_data-8.0.0/src/extended_data/primitives/strings.py +127 -0
- extended_data-8.0.0/src/extended_data/primitives/transformations/__init__.py +13 -0
- extended_data-8.0.0/src/extended_data/primitives/transformations/numbers/__init__.py +40 -0
- extended_data-8.0.0/src/extended_data/primitives/transformations/numbers/notation.py +181 -0
- extended_data-8.0.0/src/extended_data/primitives/transformations/numbers/words.py +403 -0
- extended_data-8.0.0/src/extended_data/primitives/transformations/strings/__init__.py +26 -0
- extended_data-8.0.0/src/extended_data/primitives/transformations/strings/inflection.py +95 -0
- extended_data-8.0.0/src/extended_data/primitives/types.py +532 -0
- extended_data-8.0.0/src/extended_data/py.typed +0 -0
- extended_data-8.0.0/src/extended_data/workflows/__init__.py +394 -0
- extended_data-8.0.0/tests/core/test_base64_utils.py +207 -0
- extended_data-8.0.0/tests/core/test_containers.py +486 -0
- extended_data-8.0.0/tests/core/test_export_utils.py +419 -0
- extended_data-8.0.0/tests/core/test_file_data_type.py +842 -0
- extended_data-8.0.0/tests/core/test_hcl2_utils.py +310 -0
- extended_data-8.0.0/tests/core/test_import_utils.py +67 -0
- extended_data-8.0.0/tests/core/test_integration_workflows.py +89 -0
- extended_data-8.0.0/tests/core/test_json_utils.py +217 -0
- extended_data-8.0.0/tests/core/test_list_data_type.py +179 -0
- extended_data-8.0.0/tests/core/test_map_data_type.py +537 -0
- extended_data-8.0.0/tests/core/test_matcher_utils.py +100 -0
- extended_data-8.0.0/tests/core/test_number_transformations.py +137 -0
- extended_data-8.0.0/tests/core/test_package_cli.py +271 -0
- extended_data-8.0.0/tests/core/test_package_surface.py +194 -0
- extended_data-8.0.0/tests/core/test_redaction.py +85 -0
- extended_data-8.0.0/tests/core/test_release_hygiene.py +462 -0
- extended_data-8.0.0/tests/core/test_serialization_utils.py +19 -0
- extended_data-8.0.0/tests/core/test_splitter_utils.py +112 -0
- extended_data-8.0.0/tests/core/test_stack_utils.py +251 -0
- extended_data-8.0.0/tests/core/test_state_utils.py +214 -0
- extended_data-8.0.0/tests/core/test_string_data_type.py +268 -0
- extended_data-8.0.0/tests/core/test_string_transformations.py +111 -0
- extended_data-8.0.0/tests/core/test_toml_utils.py +86 -0
- extended_data-8.0.0/tests/core/test_type_utils.py +805 -0
- extended_data-8.0.0/tests/core/test_workflows.py +462 -0
- extended_data-8.0.0/tests/core/test_yaml_utils.py +334 -0
- extended_data-8.0.0/tests/core/transformations/numbers/test_notation.py +210 -0
- extended_data-8.0.0/tests/core/transformations/numbers/test_words.py +226 -0
- extended_data-8.0.0/tests/core/transformations/strings/test_inflection.py +156 -0
- extended_data-8.0.0/tests/examples/test_safe_examples.py +224 -0
- extended_data-8.0.0/tests/inputs/test_decorators.py +125 -0
- extended_data-8.0.0/tests/inputs/test_main.py +552 -0
- extended_data-8.0.0/tests/logging/conftest.py +20 -0
- extended_data-8.0.0/tests/logging/integration/test_lifecycle_logging.py +129 -0
- extended_data-8.0.0/tests/logging/test_exit_run.py +384 -0
- extended_data-8.0.0/tests/logging/test_handlers.py +36 -0
- extended_data-8.0.0/tests/logging/test_logging.py +289 -0
- extended_data-8.0.0/tests/logging/test_properties.py +155 -0
- extended_data-8.0.0/tests/logging/test_utils.py +85 -0
- extended_data-8.0.0/tox.ini +75 -0
- extended_data-8.0.0/uv.lock +1539 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
name: CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
tag:
|
|
7
|
+
description: Release tag to publish and deploy
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
permissions: {}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
name: Python ${{ matrix.python-version }}
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
25
|
+
with:
|
|
26
|
+
ref: ${{ inputs.tag }}
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
29
|
+
with:
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
31
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
32
|
+
with:
|
|
33
|
+
version: "0.11.19"
|
|
34
|
+
enable-cache: true
|
|
35
|
+
- run: uv tool install tox --with tox-uv --with tox-gh
|
|
36
|
+
- run: tox -e "py$(echo '${{ matrix.python-version }}' | tr -d '.')"
|
|
37
|
+
|
|
38
|
+
quality:
|
|
39
|
+
name: Quality, docs, and build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
permissions:
|
|
42
|
+
contents: read
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
45
|
+
with:
|
|
46
|
+
ref: ${{ inputs.tag }}
|
|
47
|
+
persist-credentials: false
|
|
48
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
49
|
+
with:
|
|
50
|
+
python-version: "3.13"
|
|
51
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
52
|
+
with:
|
|
53
|
+
version: "0.11.19"
|
|
54
|
+
enable-cache: true
|
|
55
|
+
- run: uv tool install tox --with tox-uv --with tox-gh
|
|
56
|
+
- run: tox -e lint,typecheck,audit,examples,docs,build
|
|
57
|
+
|
|
58
|
+
publish-package:
|
|
59
|
+
name: Publish package to PyPI
|
|
60
|
+
needs: [test, quality]
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
permissions:
|
|
63
|
+
contents: read
|
|
64
|
+
id-token: write
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
67
|
+
with:
|
|
68
|
+
ref: ${{ inputs.tag }}
|
|
69
|
+
persist-credentials: false
|
|
70
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
71
|
+
with:
|
|
72
|
+
python-version: "3.13"
|
|
73
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
74
|
+
with:
|
|
75
|
+
version: "0.11.19"
|
|
76
|
+
enable-cache: true
|
|
77
|
+
- run: uv build
|
|
78
|
+
- run: uv publish --trusted-publishing always
|
|
79
|
+
|
|
80
|
+
publish-docs:
|
|
81
|
+
name: Publish docs to GitHub Pages
|
|
82
|
+
needs: publish-package
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
permissions:
|
|
85
|
+
contents: read
|
|
86
|
+
pages: write
|
|
87
|
+
id-token: write
|
|
88
|
+
environment:
|
|
89
|
+
name: github-pages
|
|
90
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
93
|
+
with:
|
|
94
|
+
ref: ${{ inputs.tag }}
|
|
95
|
+
persist-credentials: false
|
|
96
|
+
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
|
97
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
98
|
+
with:
|
|
99
|
+
python-version: "3.13"
|
|
100
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
101
|
+
with:
|
|
102
|
+
version: "0.11.19"
|
|
103
|
+
enable-cache: true
|
|
104
|
+
- run: uv tool install tox --with tox-uv --with tox-gh
|
|
105
|
+
- run: tox -e docs
|
|
106
|
+
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
107
|
+
with:
|
|
108
|
+
path: docs/_build/html
|
|
109
|
+
- id: deployment
|
|
110
|
+
name: Deploy docs
|
|
111
|
+
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions: {}
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Python ${{ matrix.python-version }}
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
29
|
+
with:
|
|
30
|
+
version: "0.11.19"
|
|
31
|
+
enable-cache: true
|
|
32
|
+
- run: uv tool install tox --with tox-uv --with tox-gh
|
|
33
|
+
- run: tox -e "py$(echo '${{ matrix.python-version }}' | tr -d '.')"
|
|
34
|
+
|
|
35
|
+
quality:
|
|
36
|
+
name: Quality, docs, and build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
permissions:
|
|
39
|
+
contents: read
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
42
|
+
with:
|
|
43
|
+
persist-credentials: false
|
|
44
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.13"
|
|
47
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
48
|
+
with:
|
|
49
|
+
version: "0.11.19"
|
|
50
|
+
enable-cache: true
|
|
51
|
+
- run: uv tool install tox --with tox-uv --with tox-gh
|
|
52
|
+
- run: tox -e lint,typecheck,audit,examples,docs,build
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
release-please:
|
|
12
|
+
name: Release Please
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
actions: write
|
|
16
|
+
contents: write
|
|
17
|
+
pull-requests: write
|
|
18
|
+
steps:
|
|
19
|
+
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
|
|
20
|
+
id: release
|
|
21
|
+
with:
|
|
22
|
+
config-file: release-please-config.json
|
|
23
|
+
manifest-file: .release-please-manifest.json
|
|
24
|
+
- name: Dispatch continuous delivery
|
|
25
|
+
if: steps.release.outputs.release_created == 'true'
|
|
26
|
+
env:
|
|
27
|
+
GH_TOKEN: ${{ github.token }}
|
|
28
|
+
RELEASE_TAG: ${{ steps.release.outputs.tag_name }}
|
|
29
|
+
run: gh workflow run cd.yml --ref main -f tag="$RELEASE_TAG"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [8.0.0](https://github.com/jbcom/extended-data/compare/extended-data-v7.0.0...extended-data-v8.0.0) (2026-06-26)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* extended-data now ships only the base data primitives, containers, IO, inputs, logging, and workflow surfaces. Vendor integrations move to vendor-connectors, SecretSync bridge runtime moves to secrets-sync-bridge, and agent-facing wrappers move to agentic-crew.
|
|
9
|
+
* clean integrated package surface ([#2](https://github.com/jbcom/extended-data/issues/2))
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add generic connector fabric lookup ([138ebf5](https://github.com/jbcom/extended-data/commit/138ebf5269811cda5f0109124801f85c9ae9ac18))
|
|
14
|
+
* expose integrated root API ([#4](https://github.com/jbcom/extended-data/issues/4)) ([7e5862f](https://github.com/jbcom/extended-data/commit/7e5862fa1764789c55e4062e965aa1d184470578))
|
|
15
|
+
* move connector surfaces out of extended-data ([0495d8b](https://github.com/jbcom/extended-data/commit/0495d8b1f1441b3819a77c6c2bfe2af38a78a38e))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Code Refactoring
|
|
19
|
+
|
|
20
|
+
* clean integrated package surface ([#2](https://github.com/jbcom/extended-data/issues/2)) ([76c7a3d](https://github.com/jbcom/extended-data/commit/76c7a3d594396fee9ae599e80c84e35590f5ae6a))
|
|
21
|
+
|
|
22
|
+
## 7.0.0 (2026-06-10)
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
- Consolidate the previous Extended Data Python libraries into the single
|
|
27
|
+
`extended-data` distribution and `extended_data` namespace.
|
|
28
|
+
- Promote data utilities, inputs, logging, connectors, secrets adapters, and
|
|
29
|
+
workflow placeholders as first-class package members.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Extended Data Library
|
|
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.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: extended-data
|
|
3
|
+
Version: 8.0.0
|
|
4
|
+
Summary: Comprehensive Python data utilities for serialization, inputs, logging, and workflows
|
|
5
|
+
Project-URL: Documentation, https://extended-data.dev
|
|
6
|
+
Project-URL: Issues, https://github.com/jbcom/extended-data/issues
|
|
7
|
+
Project-URL: Source, https://github.com/jbcom/extended-data
|
|
8
|
+
Project-URL: Changelog, https://github.com/jbcom/extended-data/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Jon Bogaty <jon@jonbogaty.com>
|
|
10
|
+
Maintainer-email: Jon Bogaty <jon@jonbogaty.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: configuration,data,files,inputs,logging,serialization,workflows
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: deepmerge>=2.0
|
|
25
|
+
Requires-Dist: gitpython>=3.1.0
|
|
26
|
+
Requires-Dist: inflection>=0.5.1
|
|
27
|
+
Requires-Dist: num2words>=0.5.14
|
|
28
|
+
Requires-Dist: orjson>=3.10.7
|
|
29
|
+
Requires-Dist: python-hcl2>=4.3.4
|
|
30
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
31
|
+
Requires-Dist: rich>=13.7.1
|
|
32
|
+
Requires-Dist: ruamel-yaml>=0.18.0
|
|
33
|
+
Requires-Dist: sortedcontainers>=2.4.0
|
|
34
|
+
Requires-Dist: tomlkit>=0.13.2
|
|
35
|
+
Requires-Dist: typing-extensions>=4.12.2
|
|
36
|
+
Requires-Dist: validators>=0.22.0
|
|
37
|
+
Requires-Dist: wrapt>=1.16.0
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: coverage[toml]>=7.6.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: hypothesis>=6.100.2; extra == 'dev'
|
|
42
|
+
Requires-Dist: mypy>=1.20.1; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest-mock>=3.15.1; extra == 'dev'
|
|
46
|
+
Requires-Dist: pytest-timeout>=2.4.0; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest>=9.0.3; extra == 'dev'
|
|
49
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
50
|
+
Requires-Dist: sortedcontainers-stubs>=2.4.2; extra == 'dev'
|
|
51
|
+
Requires-Dist: types-pyyaml>=6.0.12.20240724; extra == 'dev'
|
|
52
|
+
Provides-Extra: docs
|
|
53
|
+
Requires-Dist: furo>=2025.12.19; extra == 'docs'
|
|
54
|
+
Requires-Dist: myst-parser<6.0.0,>=4.0.1; extra == 'docs'
|
|
55
|
+
Requires-Dist: sphinx-autodoc2>=0.5.0; extra == 'docs'
|
|
56
|
+
Requires-Dist: sphinx-copybutton>=0.5.2; extra == 'docs'
|
|
57
|
+
Requires-Dist: sphinx<9.0.0,>=8.2.3; extra == 'docs'
|
|
58
|
+
Provides-Extra: tests
|
|
59
|
+
Requires-Dist: coverage[toml]>=7.6.0; extra == 'tests'
|
|
60
|
+
Requires-Dist: hypothesis>=6.100.2; extra == 'tests'
|
|
61
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'tests'
|
|
62
|
+
Requires-Dist: pytest-cov>=7.1.0; extra == 'tests'
|
|
63
|
+
Requires-Dist: pytest-mock>=3.15.1; extra == 'tests'
|
|
64
|
+
Requires-Dist: pytest-timeout>=2.4.0; extra == 'tests'
|
|
65
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == 'tests'
|
|
66
|
+
Requires-Dist: pytest>=9.0.3; extra == 'tests'
|
|
67
|
+
Provides-Extra: typing
|
|
68
|
+
Requires-Dist: mypy>=1.20.1; extra == 'typing'
|
|
69
|
+
Requires-Dist: sortedcontainers-stubs>=2.4.2; extra == 'typing'
|
|
70
|
+
Requires-Dist: types-pyyaml>=6.0.12.20240724; extra == 'typing'
|
|
71
|
+
Description-Content-Type: text/markdown
|
|
72
|
+
|
|
73
|
+
# Extended Data
|
|
74
|
+
|
|
75
|
+
Comprehensive Python data utilities for serialization, configuration inputs,
|
|
76
|
+
structured logging, file processing, and workflow composition.
|
|
77
|
+
|
|
78
|
+
The public API lives under one `extended_data` namespace with three deliberate
|
|
79
|
+
tiers:
|
|
80
|
+
|
|
81
|
+
- Tier 1: pure functions for codecs, string transforms, redaction, matching,
|
|
82
|
+
type coercion, mapping, sequence, and state utilities.
|
|
83
|
+
- Tier 2: `ExtendedString`, `ExtendedDict`, `ExtendedList`, `ExtendedTuple`,
|
|
84
|
+
and `ExtendedSet` containers that expose Tier 1 operations as methods.
|
|
85
|
+
- Tier 3: data processors that compose the first two tiers for files, inputs,
|
|
86
|
+
logging, export/import boundaries, and workflows.
|
|
87
|
+
|
|
88
|
+
External API clients live in the separate `vendor-connectors` distribution.
|
|
89
|
+
SecretSync's Python bridge lives in `secrets-sync-bridge`.
|
|
90
|
+
|
|
91
|
+
## Install
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install extended-data
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Development and documentation extras are available for contributors:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install "extended-data[dev]"
|
|
101
|
+
pip install "extended-data[docs]"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Usage
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from extended_data import DataFile, DataWorkflow, ExtendedDict, InputProvider, Logging, decode_file
|
|
108
|
+
from extended_data.primitives import decode_json, encode_yaml, number_to_words, redact_sensitive_text
|
|
109
|
+
|
|
110
|
+
logger = Logging(logger_name="example", enable_console=False, enable_file=False)
|
|
111
|
+
inputs = InputProvider(inputs={"SERVICE_NAME": "api"}, from_environment=False)
|
|
112
|
+
data = decode_json('{"service": {"name": "api"}}')
|
|
113
|
+
payload = ExtendedDict(data).deep_merge({"replicas": 3})
|
|
114
|
+
decoded_file = decode_file('{"service": {"name": "worker"}}', suffix="json")
|
|
115
|
+
artifact = DataFile.decode("service:\n name: api\n", suffix="yaml")
|
|
116
|
+
workflow = DataWorkflow.from_value(payload).transform("unhump").result()
|
|
117
|
+
|
|
118
|
+
logger.logged_statement("prepared workflow", json_data=workflow.as_builtin(), log_level="info")
|
|
119
|
+
|
|
120
|
+
assert inputs.inputs["SERVICE_NAME"] == "api"
|
|
121
|
+
assert decoded_file["service"]["name"].upper_first() == "Worker"
|
|
122
|
+
assert artifact.metadata["encoding"] == "yaml"
|
|
123
|
+
assert number_to_words(42) == "forty-two"
|
|
124
|
+
assert redact_sensitive_text("Authorization: Bearer raw_token") == "Authorization: [REDACTED]"
|
|
125
|
+
assert "replicas: 3" in encode_yaml(workflow.as_builtin())
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The installed CLI exposes the Tier 3 data boundary:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
extended-data decode '{"service": {"name": "api"}}' --suffix json
|
|
132
|
+
extended-data decode --file config.yaml --output json
|
|
133
|
+
extended-data inspect --file config.yaml
|
|
134
|
+
extended-data merge config/base.yaml config/dev.yaml --output yaml
|
|
135
|
+
extended-data transform --file payload.json --step reconstruct --step unhump
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Package Shape
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
extended_data/
|
|
142
|
+
containers/ Tier 2 ExtendedString/Dict/List/Tuple/Set wrappers
|
|
143
|
+
inputs/ InputProvider and decorator-based input injection
|
|
144
|
+
io/ Tier 3 file, import, export, and base64 processors
|
|
145
|
+
logging/ structured lifecycle logging
|
|
146
|
+
primitives/ Tier 1 pure functions and codecs
|
|
147
|
+
workflows/ Tier 3 higher-order workflow composition
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Tier 1 primitive names are explicit in this major version and live under
|
|
151
|
+
`extended_data.primitives`, not the package root. Use `bytes_to_string()` for
|
|
152
|
+
bytes-like coercion and `string_to_bool()`, `string_to_int()`,
|
|
153
|
+
`string_to_float()`, `string_to_path()`, `string_to_date()`,
|
|
154
|
+
`string_to_datetime()`, and `string_to_time()` for scalar string conversion.
|
|
155
|
+
Use `redact_sensitive_text()` and `redact_sensitive_data()` for diagnostic and
|
|
156
|
+
JSON-like payload redaction. Pass `values=[...]` when a caller knows specific
|
|
157
|
+
context values, such as resource IDs, emails, paths, or URLs, must be withheld
|
|
158
|
+
in addition to common secret fields.
|
|
159
|
+
|
|
160
|
+
Tier 2 containers inherit from standard Python collection primitives and expose
|
|
161
|
+
chainable data operations. For example, `ExtendedString.decode_json()` promotes
|
|
162
|
+
JSON into extended containers, `ExtendedDict.reconstruct_special_types()` turns
|
|
163
|
+
string scalars into booleans/numbers/dates where safe, and
|
|
164
|
+
`ExtendedList.first_non_empty()` returns the first meaningful value without
|
|
165
|
+
lowering the surrounding data boundary.
|
|
166
|
+
|
|
167
|
+
Tier 3 processors keep structured data moving through explicit boundaries.
|
|
168
|
+
`DataFile` reads, decodes, tracks metadata, and exports structured files.
|
|
169
|
+
`DataWorkflow` layers reads, merges, transforms, writes, and provenance into a
|
|
170
|
+
single result object. `InputProvider` loads direct inputs and environment data,
|
|
171
|
+
and `Logging` provides structured lifecycle logging with stored-message
|
|
172
|
+
snapshots returned as extended containers.
|
|
173
|
+
|
|
174
|
+
The old `extended_data_types`, `directed_inputs_class`, and `lifecyclelogging`
|
|
175
|
+
package names are not shimmed. The removed `extended_data.connectors` and
|
|
176
|
+
`extended_data.secrets` namespaces are also not preserved. Clean-break import
|
|
177
|
+
failures are intentional so stale migrations are visible.
|
|
178
|
+
|
|
179
|
+
## Local Development
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
uv sync --all-extras --dev
|
|
183
|
+
tox -e lint
|
|
184
|
+
tox -e typecheck
|
|
185
|
+
tox -e py311,py312,py313,py314
|
|
186
|
+
tox -e examples
|
|
187
|
+
tox -e docs
|
|
188
|
+
tox -e build
|
|
189
|
+
```
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Extended Data
|
|
2
|
+
|
|
3
|
+
Comprehensive Python data utilities for serialization, configuration inputs,
|
|
4
|
+
structured logging, file processing, and workflow composition.
|
|
5
|
+
|
|
6
|
+
The public API lives under one `extended_data` namespace with three deliberate
|
|
7
|
+
tiers:
|
|
8
|
+
|
|
9
|
+
- Tier 1: pure functions for codecs, string transforms, redaction, matching,
|
|
10
|
+
type coercion, mapping, sequence, and state utilities.
|
|
11
|
+
- Tier 2: `ExtendedString`, `ExtendedDict`, `ExtendedList`, `ExtendedTuple`,
|
|
12
|
+
and `ExtendedSet` containers that expose Tier 1 operations as methods.
|
|
13
|
+
- Tier 3: data processors that compose the first two tiers for files, inputs,
|
|
14
|
+
logging, export/import boundaries, and workflows.
|
|
15
|
+
|
|
16
|
+
External API clients live in the separate `vendor-connectors` distribution.
|
|
17
|
+
SecretSync's Python bridge lives in `secrets-sync-bridge`.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install extended-data
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Development and documentation extras are available for contributors:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install "extended-data[dev]"
|
|
29
|
+
pip install "extended-data[docs]"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from extended_data import DataFile, DataWorkflow, ExtendedDict, InputProvider, Logging, decode_file
|
|
36
|
+
from extended_data.primitives import decode_json, encode_yaml, number_to_words, redact_sensitive_text
|
|
37
|
+
|
|
38
|
+
logger = Logging(logger_name="example", enable_console=False, enable_file=False)
|
|
39
|
+
inputs = InputProvider(inputs={"SERVICE_NAME": "api"}, from_environment=False)
|
|
40
|
+
data = decode_json('{"service": {"name": "api"}}')
|
|
41
|
+
payload = ExtendedDict(data).deep_merge({"replicas": 3})
|
|
42
|
+
decoded_file = decode_file('{"service": {"name": "worker"}}', suffix="json")
|
|
43
|
+
artifact = DataFile.decode("service:\n name: api\n", suffix="yaml")
|
|
44
|
+
workflow = DataWorkflow.from_value(payload).transform("unhump").result()
|
|
45
|
+
|
|
46
|
+
logger.logged_statement("prepared workflow", json_data=workflow.as_builtin(), log_level="info")
|
|
47
|
+
|
|
48
|
+
assert inputs.inputs["SERVICE_NAME"] == "api"
|
|
49
|
+
assert decoded_file["service"]["name"].upper_first() == "Worker"
|
|
50
|
+
assert artifact.metadata["encoding"] == "yaml"
|
|
51
|
+
assert number_to_words(42) == "forty-two"
|
|
52
|
+
assert redact_sensitive_text("Authorization: Bearer raw_token") == "Authorization: [REDACTED]"
|
|
53
|
+
assert "replicas: 3" in encode_yaml(workflow.as_builtin())
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The installed CLI exposes the Tier 3 data boundary:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
extended-data decode '{"service": {"name": "api"}}' --suffix json
|
|
60
|
+
extended-data decode --file config.yaml --output json
|
|
61
|
+
extended-data inspect --file config.yaml
|
|
62
|
+
extended-data merge config/base.yaml config/dev.yaml --output yaml
|
|
63
|
+
extended-data transform --file payload.json --step reconstruct --step unhump
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Package Shape
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
extended_data/
|
|
70
|
+
containers/ Tier 2 ExtendedString/Dict/List/Tuple/Set wrappers
|
|
71
|
+
inputs/ InputProvider and decorator-based input injection
|
|
72
|
+
io/ Tier 3 file, import, export, and base64 processors
|
|
73
|
+
logging/ structured lifecycle logging
|
|
74
|
+
primitives/ Tier 1 pure functions and codecs
|
|
75
|
+
workflows/ Tier 3 higher-order workflow composition
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Tier 1 primitive names are explicit in this major version and live under
|
|
79
|
+
`extended_data.primitives`, not the package root. Use `bytes_to_string()` for
|
|
80
|
+
bytes-like coercion and `string_to_bool()`, `string_to_int()`,
|
|
81
|
+
`string_to_float()`, `string_to_path()`, `string_to_date()`,
|
|
82
|
+
`string_to_datetime()`, and `string_to_time()` for scalar string conversion.
|
|
83
|
+
Use `redact_sensitive_text()` and `redact_sensitive_data()` for diagnostic and
|
|
84
|
+
JSON-like payload redaction. Pass `values=[...]` when a caller knows specific
|
|
85
|
+
context values, such as resource IDs, emails, paths, or URLs, must be withheld
|
|
86
|
+
in addition to common secret fields.
|
|
87
|
+
|
|
88
|
+
Tier 2 containers inherit from standard Python collection primitives and expose
|
|
89
|
+
chainable data operations. For example, `ExtendedString.decode_json()` promotes
|
|
90
|
+
JSON into extended containers, `ExtendedDict.reconstruct_special_types()` turns
|
|
91
|
+
string scalars into booleans/numbers/dates where safe, and
|
|
92
|
+
`ExtendedList.first_non_empty()` returns the first meaningful value without
|
|
93
|
+
lowering the surrounding data boundary.
|
|
94
|
+
|
|
95
|
+
Tier 3 processors keep structured data moving through explicit boundaries.
|
|
96
|
+
`DataFile` reads, decodes, tracks metadata, and exports structured files.
|
|
97
|
+
`DataWorkflow` layers reads, merges, transforms, writes, and provenance into a
|
|
98
|
+
single result object. `InputProvider` loads direct inputs and environment data,
|
|
99
|
+
and `Logging` provides structured lifecycle logging with stored-message
|
|
100
|
+
snapshots returned as extended containers.
|
|
101
|
+
|
|
102
|
+
The old `extended_data_types`, `directed_inputs_class`, and `lifecyclelogging`
|
|
103
|
+
package names are not shimmed. The removed `extended_data.connectors` and
|
|
104
|
+
`extended_data.secrets` namespaces are also not preserved. Clean-break import
|
|
105
|
+
failures are intentional so stale migrations are visible.
|
|
106
|
+
|
|
107
|
+
## Local Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
uv sync --all-extras --dev
|
|
111
|
+
tox -e lint
|
|
112
|
+
tox -e typecheck
|
|
113
|
+
tox -e py311,py312,py313,py314
|
|
114
|
+
tox -e examples
|
|
115
|
+
tox -e docs
|
|
116
|
+
tox -e build
|
|
117
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
extended-data.dev
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Publishing Checklist
|
|
2
|
+
|
|
3
|
+
`extended-data` uses the standard `ci.yml` > `release.yml` > `cd.yml` workflow
|
|
4
|
+
shape. `release.yml` owns release-please. When a release-please PR merge creates
|
|
5
|
+
a release tag, it dispatches `cd.yml` for package publication and the
|
|
6
|
+
Sphinx/Furo documentation deploy. Do not hand-edit versions, changelog entries,
|
|
7
|
+
release tags, or GitHub releases during the normal release path.
|
|
8
|
+
|
|
9
|
+
## Release Model
|
|
10
|
+
|
|
11
|
+
- `release.yml` owns release-please version detection, changelog updates,
|
|
12
|
+
release PRs, Git tags, and dispatching `cd.yml` after a release is created.
|
|
13
|
+
- `cd.yml` owns tag-gated package verification, PyPI publication, and GitHub
|
|
14
|
+
Pages publication for `extended-data.dev`.
|
|
15
|
+
- The package name is `extended-data`; PyPI publication uses the tighter
|
|
16
|
+
`extended-data` distribution name.
|
|
17
|
+
- The CD workflow publishes only for the release tag passed by `release.yml`.
|
|
18
|
+
- The PyPI job uses OIDC trusted publishing through `uv publish`; no PyPI token
|
|
19
|
+
should be stored in repository secrets for the normal path.
|
|
20
|
+
|
|
21
|
+
## Maintainer Preflight
|
|
22
|
+
|
|
23
|
+
Run these before merging a release PR or manually dispatching release workflow
|
|
24
|
+
diagnostics:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv sync --extra tests --extra typing
|
|
28
|
+
uv run --with pip-audit==2.10.0 pip-audit --skip-editable
|
|
29
|
+
uv run ruff check .
|
|
30
|
+
uv run mypy src/extended_data
|
|
31
|
+
uv run pytest
|
|
32
|
+
uv run sphinx-build -W -E -b html docs docs/_build/html
|
|
33
|
+
uv build
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Workflow Hygiene
|
|
37
|
+
|
|
38
|
+
- Keep `.github/workflows/*.yml` actions pinned to exact commit SHAs.
|
|
39
|
+
- Update adjacent version comments when refreshing action SHAs.
|
|
40
|
+
- Use `gh` to verify latest stable action releases before changing pins.
|
|
41
|
+
- Keep top-level `permissions: {}` and grant only job-scoped permissions.
|
|
42
|
+
|
|
43
|
+
Current workflow action pins:
|
|
44
|
+
|
|
45
|
+
| Action | Stable version | Commit SHA |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `actions/checkout` | `v7.0.0` | `9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0` |
|
|
48
|
+
| `actions/configure-pages` | `v6.0.0` | `45bfe0192ca1faeb007ade9deae92b16b8254a0d` |
|
|
49
|
+
| `actions/deploy-pages` | `v5.0.0` | `cd2ce8fcbc39b97be8ca5fce6e763baed58fa128` |
|
|
50
|
+
| `actions/setup-python` | `v6.3.0` | `ece7cb06caefa5fff74198d8649806c4678c61a1` |
|
|
51
|
+
| `actions/upload-pages-artifact` | `v5.0.0` | `fc324d3547104276b827a68afc52ff2a11cc49c9` |
|
|
52
|
+
| `astral-sh/setup-uv` | `v8.2.0` | `fac544c07dec837d0ccb6301d7b5580bf5edae39` |
|
|
53
|
+
| `googleapis/release-please-action` | `v5.0.0` | `45996ed1f6d02564a971a2fa1b5860e934307cf7` |
|
|
54
|
+
|
|
55
|
+
## Publishing Flow
|
|
56
|
+
|
|
57
|
+
1. Land normal feature, fix, docs, and maintenance commits using Conventional
|
|
58
|
+
Commit prefixes.
|
|
59
|
+
2. Let `release.yml` open or update the release-please PR.
|
|
60
|
+
3. Review the release PR for the expected changelog and manifest updates.
|
|
61
|
+
4. Merge the release PR.
|
|
62
|
+
5. Confirm `release.yml` created the GitHub release and dispatched `cd.yml`.
|
|
63
|
+
6. Confirm `cd.yml` published to PyPI through trusted publishing and deployed
|
|
64
|
+
the Sphinx site to GitHub Pages for `extended-data.dev`.
|
|
65
|
+
7. Verify the package can be installed from PyPI:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python -m pip install extended-data
|
|
69
|
+
python -c "import extended_data; print(extended_data.__version__)"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Manual Repairs
|
|
73
|
+
|
|
74
|
+
Manual tags or PyPI uploads are repair paths, not the release process. If a
|
|
75
|
+
release workflow fails after release-please creates a tag:
|
|
76
|
+
|
|
77
|
+
1. Keep the failed tag intact while diagnosing unless the release is proven
|
|
78
|
+
unrecoverable.
|
|
79
|
+
2. Prefer rerunning the failed workflow job.
|
|
80
|
+
3. If a bad GitHub release was published, delete only the bad artifacts needed
|
|
81
|
+
for repair.
|
|
82
|
+
4. Document the repair in the PR or release notes.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Sphinx documentation source package."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|