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.
Files changed (148) hide show
  1. extended_data-8.0.0/.github/workflows/cd.yml +111 -0
  2. extended_data-8.0.0/.github/workflows/ci.yml +52 -0
  3. extended_data-8.0.0/.github/workflows/release.yml +29 -0
  4. extended_data-8.0.0/.gitignore +16 -0
  5. extended_data-8.0.0/.python-version +1 -0
  6. extended_data-8.0.0/.release-please-manifest.json +3 -0
  7. extended_data-8.0.0/CHANGELOG.md +29 -0
  8. extended_data-8.0.0/LICENSE +21 -0
  9. extended_data-8.0.0/PKG-INFO +189 -0
  10. extended_data-8.0.0/README.md +117 -0
  11. extended_data-8.0.0/docs/CNAME +1 -0
  12. extended_data-8.0.0/docs/PUBLISHING_CHECKLIST.md +82 -0
  13. extended_data-8.0.0/docs/__init__.py +1 -0
  14. extended_data-8.0.0/docs/_static/.gitkeep +1 -0
  15. extended_data-8.0.0/docs/_static/extended-data.css +22 -0
  16. extended_data-8.0.0/docs/api/index.rst +9 -0
  17. extended_data-8.0.0/docs/conf.py +76 -0
  18. extended_data-8.0.0/docs/core/containers.md +31 -0
  19. extended_data-8.0.0/docs/core/primitives.md +52 -0
  20. extended_data-8.0.0/docs/core/workflows.md +46 -0
  21. extended_data-8.0.0/docs/examples/core.md +36 -0
  22. extended_data-8.0.0/docs/examples/index.md +13 -0
  23. extended_data-8.0.0/docs/examples/inputs.md +22 -0
  24. extended_data-8.0.0/docs/examples/logging.md +29 -0
  25. extended_data-8.0.0/docs/getting-started.md +52 -0
  26. extended_data-8.0.0/docs/index.md +53 -0
  27. extended_data-8.0.0/docs/operations/inputs.md +34 -0
  28. extended_data-8.0.0/docs/operations/logging.md +25 -0
  29. extended_data-8.0.0/docs/ownership-map.md +48 -0
  30. extended_data-8.0.0/docs/package-surface.md +93 -0
  31. extended_data-8.0.0/docs/publishing.md +22 -0
  32. extended_data-8.0.0/examples/core/README.md +39 -0
  33. extended_data-8.0.0/examples/core/basic_usage.py +70 -0
  34. extended_data-8.0.0/examples/core/composed_workflows.py +142 -0
  35. extended_data-8.0.0/examples/core/file_operations.py +123 -0
  36. extended_data-8.0.0/examples/core/serialization.py +139 -0
  37. extended_data-8.0.0/examples/core/string_transformations.py +109 -0
  38. extended_data-8.0.0/examples/inputs/README.md +52 -0
  39. extended_data-8.0.0/examples/inputs/__init__.py +3 -0
  40. extended_data-8.0.0/examples/inputs/basic_usage.py +60 -0
  41. extended_data-8.0.0/examples/inputs/decorator_api.py +96 -0
  42. extended_data-8.0.0/examples/inputs/encoding_decoding.py +80 -0
  43. extended_data-8.0.0/examples/logging/README.md +73 -0
  44. extended_data-8.0.0/examples/logging/basic_logging.py +52 -0
  45. extended_data-8.0.0/examples/logging/exit_run_formatting.py +56 -0
  46. extended_data-8.0.0/examples/logging/markers_and_storage.py +63 -0
  47. extended_data-8.0.0/examples/logging/verbosity_control.py +63 -0
  48. extended_data-8.0.0/pyproject.toml +177 -0
  49. extended_data-8.0.0/release-please-config.json +22 -0
  50. extended_data-8.0.0/src/extended_data/__init__.py +105 -0
  51. extended_data-8.0.0/src/extended_data/_version.py +16 -0
  52. extended_data-8.0.0/src/extended_data/cli.py +204 -0
  53. extended_data-8.0.0/src/extended_data/containers/__init__.py +17 -0
  54. extended_data-8.0.0/src/extended_data/containers/factory.py +57 -0
  55. extended_data-8.0.0/src/extended_data/containers/mappings.py +181 -0
  56. extended_data-8.0.0/src/extended_data/containers/sequences.py +403 -0
  57. extended_data-8.0.0/src/extended_data/containers/strings.py +276 -0
  58. extended_data-8.0.0/src/extended_data/inputs/__init__.py +14 -0
  59. extended_data-8.0.0/src/extended_data/inputs/__main__.py +412 -0
  60. extended_data-8.0.0/src/extended_data/inputs/decorators.py +346 -0
  61. extended_data-8.0.0/src/extended_data/inputs/py.typed +0 -0
  62. extended_data-8.0.0/src/extended_data/io/__init__.py +50 -0
  63. extended_data-8.0.0/src/extended_data/io/base64.py +65 -0
  64. extended_data-8.0.0/src/extended_data/io/exporters.py +151 -0
  65. extended_data-8.0.0/src/extended_data/io/files.py +619 -0
  66. extended_data-8.0.0/src/extended_data/io/importers.py +53 -0
  67. extended_data-8.0.0/src/extended_data/logging/__init__.py +13 -0
  68. extended_data-8.0.0/src/extended_data/logging/const.py +15 -0
  69. extended_data-8.0.0/src/extended_data/logging/handlers.py +61 -0
  70. extended_data-8.0.0/src/extended_data/logging/log_types.py +18 -0
  71. extended_data-8.0.0/src/extended_data/logging/logging.py +663 -0
  72. extended_data-8.0.0/src/extended_data/logging/py.typed +0 -0
  73. extended_data-8.0.0/src/extended_data/logging/utils.py +167 -0
  74. extended_data-8.0.0/src/extended_data/primitives/__init__.py +172 -0
  75. extended_data-8.0.0/src/extended_data/primitives/formats/__init__.py +47 -0
  76. extended_data-8.0.0/src/extended_data/primitives/formats/_normalization.py +15 -0
  77. extended_data-8.0.0/src/extended_data/primitives/formats/errors.py +72 -0
  78. extended_data-8.0.0/src/extended_data/primitives/formats/hcl.py +264 -0
  79. extended_data-8.0.0/src/extended_data/primitives/formats/json.py +100 -0
  80. extended_data-8.0.0/src/extended_data/primitives/formats/toml.py +48 -0
  81. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/__init__.py +43 -0
  82. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/constructors.py +58 -0
  83. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/dumpers.py +75 -0
  84. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/loaders.py +31 -0
  85. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/representers.py +82 -0
  86. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/tag_classes.py +79 -0
  87. extended_data-8.0.0/src/extended_data/primitives/formats/yaml/utils.py +75 -0
  88. extended_data-8.0.0/src/extended_data/primitives/introspection.py +168 -0
  89. extended_data-8.0.0/src/extended_data/primitives/mappings.py +399 -0
  90. extended_data-8.0.0/src/extended_data/primitives/matching.py +82 -0
  91. extended_data-8.0.0/src/extended_data/primitives/numbers.py +236 -0
  92. extended_data-8.0.0/src/extended_data/primitives/redaction.py +126 -0
  93. extended_data-8.0.0/src/extended_data/primitives/sequences.py +85 -0
  94. extended_data-8.0.0/src/extended_data/primitives/serialization.py +37 -0
  95. extended_data-8.0.0/src/extended_data/primitives/splitting.py +56 -0
  96. extended_data-8.0.0/src/extended_data/primitives/state.py +162 -0
  97. extended_data-8.0.0/src/extended_data/primitives/string_transforms.py +74 -0
  98. extended_data-8.0.0/src/extended_data/primitives/strings.py +127 -0
  99. extended_data-8.0.0/src/extended_data/primitives/transformations/__init__.py +13 -0
  100. extended_data-8.0.0/src/extended_data/primitives/transformations/numbers/__init__.py +40 -0
  101. extended_data-8.0.0/src/extended_data/primitives/transformations/numbers/notation.py +181 -0
  102. extended_data-8.0.0/src/extended_data/primitives/transformations/numbers/words.py +403 -0
  103. extended_data-8.0.0/src/extended_data/primitives/transformations/strings/__init__.py +26 -0
  104. extended_data-8.0.0/src/extended_data/primitives/transformations/strings/inflection.py +95 -0
  105. extended_data-8.0.0/src/extended_data/primitives/types.py +532 -0
  106. extended_data-8.0.0/src/extended_data/py.typed +0 -0
  107. extended_data-8.0.0/src/extended_data/workflows/__init__.py +394 -0
  108. extended_data-8.0.0/tests/core/test_base64_utils.py +207 -0
  109. extended_data-8.0.0/tests/core/test_containers.py +486 -0
  110. extended_data-8.0.0/tests/core/test_export_utils.py +419 -0
  111. extended_data-8.0.0/tests/core/test_file_data_type.py +842 -0
  112. extended_data-8.0.0/tests/core/test_hcl2_utils.py +310 -0
  113. extended_data-8.0.0/tests/core/test_import_utils.py +67 -0
  114. extended_data-8.0.0/tests/core/test_integration_workflows.py +89 -0
  115. extended_data-8.0.0/tests/core/test_json_utils.py +217 -0
  116. extended_data-8.0.0/tests/core/test_list_data_type.py +179 -0
  117. extended_data-8.0.0/tests/core/test_map_data_type.py +537 -0
  118. extended_data-8.0.0/tests/core/test_matcher_utils.py +100 -0
  119. extended_data-8.0.0/tests/core/test_number_transformations.py +137 -0
  120. extended_data-8.0.0/tests/core/test_package_cli.py +271 -0
  121. extended_data-8.0.0/tests/core/test_package_surface.py +194 -0
  122. extended_data-8.0.0/tests/core/test_redaction.py +85 -0
  123. extended_data-8.0.0/tests/core/test_release_hygiene.py +462 -0
  124. extended_data-8.0.0/tests/core/test_serialization_utils.py +19 -0
  125. extended_data-8.0.0/tests/core/test_splitter_utils.py +112 -0
  126. extended_data-8.0.0/tests/core/test_stack_utils.py +251 -0
  127. extended_data-8.0.0/tests/core/test_state_utils.py +214 -0
  128. extended_data-8.0.0/tests/core/test_string_data_type.py +268 -0
  129. extended_data-8.0.0/tests/core/test_string_transformations.py +111 -0
  130. extended_data-8.0.0/tests/core/test_toml_utils.py +86 -0
  131. extended_data-8.0.0/tests/core/test_type_utils.py +805 -0
  132. extended_data-8.0.0/tests/core/test_workflows.py +462 -0
  133. extended_data-8.0.0/tests/core/test_yaml_utils.py +334 -0
  134. extended_data-8.0.0/tests/core/transformations/numbers/test_notation.py +210 -0
  135. extended_data-8.0.0/tests/core/transformations/numbers/test_words.py +226 -0
  136. extended_data-8.0.0/tests/core/transformations/strings/test_inflection.py +156 -0
  137. extended_data-8.0.0/tests/examples/test_safe_examples.py +224 -0
  138. extended_data-8.0.0/tests/inputs/test_decorators.py +125 -0
  139. extended_data-8.0.0/tests/inputs/test_main.py +552 -0
  140. extended_data-8.0.0/tests/logging/conftest.py +20 -0
  141. extended_data-8.0.0/tests/logging/integration/test_lifecycle_logging.py +129 -0
  142. extended_data-8.0.0/tests/logging/test_exit_run.py +384 -0
  143. extended_data-8.0.0/tests/logging/test_handlers.py +36 -0
  144. extended_data-8.0.0/tests/logging/test_logging.py +289 -0
  145. extended_data-8.0.0/tests/logging/test_properties.py +155 -0
  146. extended_data-8.0.0/tests/logging/test_utils.py +85 -0
  147. extended_data-8.0.0/tox.ini +75 -0
  148. 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,16 @@
1
+ .venv/
2
+ .pytest_cache/
3
+ .ruff_cache/
4
+ .mypy_cache/
5
+ .hypothesis/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ __pycache__/
10
+ *.py[cod]
11
+ *.log
12
+ coverage.xml
13
+ .coverage
14
+ .tox/
15
+ docs/apidocs/
16
+ docs/_build/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "8.0.0"
3
+ }
@@ -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
+