extended-data 8.4.1__tar.gz → 8.4.2__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.4.1 → extended_data-8.4.2}/CHANGELOG.md +7 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/PKG-INFO +1 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/conf.py +1 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/operations/inputs.rst +1 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/pyproject.toml +1 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/inputs/__init__.py +1 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/inputs/decorators.py +1 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/types.py +0 -1
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_containers.py +89 -0
- extended_data-8.4.2/tests/core/test_decode_errors.py +76 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_file_data_type.py +32 -0
- extended_data-8.4.2/tests/core/test_normalization.py +50 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_package_cli.py +192 -0
- extended_data-8.4.1/tests/inputs/test_main.py → extended_data-8.4.2/tests/inputs/test_providers.py +15 -2
- {extended_data-8.4.1 → extended_data-8.4.2}/.gitignore +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/README.md +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/CNAME +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/PUBLISHING_CHECKLIST.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/_static/.gitkeep +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/_static/extended-data.css +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/api/index.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/architecture.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/core/containers.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/core/primitives.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/core/workflows.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/examples/core.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/examples/index.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/examples/inputs.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/examples/logging.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/getting-started.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/index.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/operations/logging.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/ownership-map.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/package-surface.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/pillars.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/docs/publishing.rst +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/core/README.md +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/core/basic_usage.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/core/composed_workflows.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/core/file_operations.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/core/serialization.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/core/string_transformations.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/inputs/README.md +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/inputs/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/inputs/basic_usage.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/inputs/decorator_api.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/inputs/encoding_decoding.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/logging/README.md +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/logging/basic_logging.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/logging/exit_run_formatting.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/logging/markers_and_storage.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/examples/logging/verbosity_control.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/_version.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/cli.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/containers/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/containers/data.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/containers/factory.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/containers/mappings.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/containers/sequences.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/containers/strings.py +0 -0
- /extended_data-8.4.1/src/extended_data/inputs/__main__.py → /extended_data-8.4.2/src/extended_data/inputs/providers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/inputs/py.typed +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/io/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/io/base64.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/io/exporters.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/io/files.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/io/importers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/const.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/handlers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/log_types.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/logging.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/py.typed +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/logging/utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/_normalization.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/errors.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/hcl.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/json.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/toml.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/constructors.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/dumpers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/loaders.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/representers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/tag_classes.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/introspection.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/mappings.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/matching.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/numbers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/redaction.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/sequences.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/serialization.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/splitting.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/state.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/string_transforms.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/strings.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/numbers/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/numbers/notation.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/numbers/words.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/strings/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/strings/inflection.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/py.typed +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/workflows/__init__.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/workflows/sync.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_base64_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_export_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_hcl2_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_import_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_integration_workflows.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_json_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_list_data_type.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_map_data_type.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_matcher_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_number_transformations.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_package_surface.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_redaction.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_release_hygiene.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_serialization_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_splitter_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_stack_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_state_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_string_data_type.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_string_transformations.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_toml_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_type_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_workflows.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/test_yaml_utils.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/transformations/numbers/test_notation.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/transformations/numbers/test_words.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/core/transformations/strings/test_inflection.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/examples/test_safe_examples.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/inputs/test_decorators.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/conftest.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/integration/test_lifecycle_logging.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/test_exit_run.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/test_handlers.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/test_logging.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/test_properties.py +0 -0
- {extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/test_utils.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [8.4.2](https://github.com/jbcom/extended-data/compare/extended-data-v8.4.1...extended-data-v8.4.2) (2026-06-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* close doc, autodoc2, and test coverage gaps ([#30](https://github.com/jbcom/extended-data/issues/30)) ([9c577df](https://github.com/jbcom/extended-data/commit/9c577df4e68c0ace888566a981f6054806b0da75))
|
|
9
|
+
|
|
3
10
|
## [8.4.1](https://github.com/jbcom/extended-data/compare/extended-data-v8.4.0...extended-data-v8.4.1) (2026-06-27)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: extended-data
|
|
3
|
-
Version: 8.4.
|
|
3
|
+
Version: 8.4.2
|
|
4
4
|
Summary: Comprehensive Python data utilities for serialization, inputs, logging, and workflows
|
|
5
5
|
Project-URL: Documentation, https://extended-data.dev
|
|
6
6
|
Project-URL: Issues, https://github.com/jbcom/extended-data/issues
|
|
@@ -63,6 +63,6 @@ autodoc2_packages = [
|
|
|
63
63
|
]
|
|
64
64
|
autodoc2_render_plugin = "rst"
|
|
65
65
|
autodoc2_docstring_parser_regexes = [(r".*", "myst")]
|
|
66
|
-
autodoc2_hidden_objects = ["inherited", "dunder"]
|
|
66
|
+
autodoc2_hidden_objects = ["inherited", "dunder", "private"]
|
|
67
67
|
autodoc2_class_docstring = "merge"
|
|
68
68
|
autodoc2_module_summary = True
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "extended-data"
|
|
7
|
-
version = "8.4.
|
|
7
|
+
version = "8.4.2"
|
|
8
8
|
description = "Comprehensive Python data utilities for serialization, inputs, logging, and workflows"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -7,8 +7,8 @@ various sources like environment variables, stdin, and predefined dictionaries.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
from extended_data._version import __version__
|
|
10
|
-
from extended_data.inputs.__main__ import InputProvider
|
|
11
10
|
from extended_data.inputs.decorators import directed_inputs, input_config
|
|
11
|
+
from extended_data.inputs.providers import InputProvider
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
__all__ = ["InputProvider", "__version__", "directed_inputs", "input_config"]
|
|
@@ -25,7 +25,7 @@ from dataclasses import dataclass, field
|
|
|
25
25
|
from typing import TYPE_CHECKING, Any
|
|
26
26
|
|
|
27
27
|
from extended_data.containers import ExtendedDict, to_builtin
|
|
28
|
-
from extended_data.inputs.
|
|
28
|
+
from extended_data.inputs.providers import InputProvider
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
if TYPE_CHECKING:
|
|
@@ -770,3 +770,92 @@ def test_container_classes_are_root_exports() -> None:
|
|
|
770
770
|
assert extended_data.ExtendedTuple is ExtendedTuple
|
|
771
771
|
assert extended_data.extend_data is extend_data
|
|
772
772
|
assert extended_data.to_builtin is to_builtin
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
def test_extended_string_transform_methods_round_trip() -> None:
|
|
776
|
+
"""ExtendedString transform bound methods should delegate to Tier 1 primitives."""
|
|
777
|
+
assert ExtendedString("camelCase").lower_first() == "camelCase"
|
|
778
|
+
assert ExtendedString("CamelCase").lower_first() == "camelCase"
|
|
779
|
+
assert ExtendedString("API Response").sanitize() == "API_Response"
|
|
780
|
+
assert ExtendedString("API Response").sanitize("-") == "API-Response"
|
|
781
|
+
assert ExtendedString("abcdefghijklmnop").truncate(5) == "ab..."
|
|
782
|
+
assert ExtendedString("abcdefghijklmnop").truncate(5, ender="!") == "abcd!"
|
|
783
|
+
assert ExtendedString("api_service").titleize_name() == "Api Service"
|
|
784
|
+
assert ExtendedString("api response").to_camel_case() == "apiResponse"
|
|
785
|
+
assert ExtendedString("api response").to_camel_case(uppercase_first=True) == "ApiResponse"
|
|
786
|
+
assert ExtendedString("api response").to_pascal_case() == "ApiResponse"
|
|
787
|
+
assert ExtendedString("API Response").pluralize() == "API Responses"
|
|
788
|
+
assert ExtendedString("API Responses").singularize() == "API Response"
|
|
789
|
+
assert ExtendedString("api_response").humanize() == "API response"
|
|
790
|
+
assert ExtendedString("api_response").titleize() == "Api Response"
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
def test_extended_string_is_url_bound_method() -> None:
|
|
794
|
+
"""ExtendedString.is_url should delegate to the Tier 1 url detector."""
|
|
795
|
+
assert ExtendedString("https://example.com").is_url() is True
|
|
796
|
+
assert ExtendedString("not a url").is_url() is False
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
def test_extended_dict_unhump_bound_method() -> None:
|
|
800
|
+
"""ExtendedDict.unhump should delegate to unhump_map with prefix option."""
|
|
801
|
+
value = ExtendedDict({"serviceName": "api", "HTTPResponse": 200})
|
|
802
|
+
unhumped = value.unhump()
|
|
803
|
+
assert unhumped == {"service_name": "api", "http_response": 200}
|
|
804
|
+
assert isinstance(unhumped, ExtendedDict)
|
|
805
|
+
|
|
806
|
+
prefixed = ExtendedDict({"v1Service": "api", "v2Other": "x"}).unhump(drop_without_prefix="v1")
|
|
807
|
+
assert prefixed == {"v1_service": "api"}
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
def test_extended_dict_delitem_succeeds_on_mappings() -> None:
|
|
811
|
+
"""ExtendedData.__delitem__ should delete keys on mutable mappings."""
|
|
812
|
+
value = ExtendedDict({"service": "api", "region": "us-east-1"})
|
|
813
|
+
del value["region"]
|
|
814
|
+
assert "region" not in value
|
|
815
|
+
assert value == {"service": "api"}
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
def test_reconstruct_special_types_fail_silently_branches() -> None:
|
|
819
|
+
"""reconstruct_special_types(fail_silently=True) should swallow, False should raise."""
|
|
820
|
+
from extended_data.primitives.types import ConversionError
|
|
821
|
+
|
|
822
|
+
bad_yaml = "---\ninvalid: [unclosed"
|
|
823
|
+
bad = ExtendedList([bad_yaml])
|
|
824
|
+
|
|
825
|
+
with pytest.raises(ConversionError):
|
|
826
|
+
bad.reconstruct_special_types(fail_silently=False)
|
|
827
|
+
|
|
828
|
+
silent = bad.reconstruct_special_types(fail_silently=True)
|
|
829
|
+
assert isinstance(silent, ExtendedList)
|
|
830
|
+
|
|
831
|
+
bad_tuple = ExtendedTuple((bad_yaml,))
|
|
832
|
+
with pytest.raises(ConversionError):
|
|
833
|
+
bad_tuple.reconstruct_special_types(fail_silently=False)
|
|
834
|
+
silent_tuple = bad_tuple.reconstruct_special_types(fail_silently=True)
|
|
835
|
+
assert isinstance(silent_tuple, ExtendedTuple)
|
|
836
|
+
|
|
837
|
+
bad_set = ExtendedSet({bad_yaml})
|
|
838
|
+
with pytest.raises(ConversionError):
|
|
839
|
+
bad_set.reconstruct_special_types(fail_silently=False)
|
|
840
|
+
silent_set = bad_set.reconstruct_special_types(fail_silently=True)
|
|
841
|
+
assert isinstance(silent_set, ExtendedSet)
|
|
842
|
+
|
|
843
|
+
bad_dict = ExtendedDict({"key": bad_yaml})
|
|
844
|
+
with pytest.raises(ConversionError):
|
|
845
|
+
bad_dict.reconstruct_special_types(fail_silently=False)
|
|
846
|
+
silent_dict = bad_dict.reconstruct_special_types(fail_silently=True)
|
|
847
|
+
assert isinstance(silent_dict, ExtendedDict)
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
def test_extended_set_discard_and_copy() -> None:
|
|
851
|
+
"""ExtendedSet.discard and copy should mutate / duplicate as expected."""
|
|
852
|
+
value = ExtendedSet({"api", "worker", "gateway"})
|
|
853
|
+
discarded = value.discard("worker")
|
|
854
|
+
assert discarded is value
|
|
855
|
+
assert "worker" not in value
|
|
856
|
+
assert value == {"api", "gateway"}
|
|
857
|
+
|
|
858
|
+
copied = value.copy()
|
|
859
|
+
assert copied == value
|
|
860
|
+
assert copied is not value
|
|
861
|
+
assert isinstance(copied, ExtendedSet)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Direct tests for the shared decode-error helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from extended_data.primitives.formats.errors import DataDecodeError, invalid_utf8_error
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_from_exception_builds_sanitized_error() -> None:
|
|
9
|
+
"""DataDecodeError.from_exception should translate parser attributes without source snippets."""
|
|
10
|
+
|
|
11
|
+
class FakeParserError(Exception):
|
|
12
|
+
msg = "unexpected token"
|
|
13
|
+
lineno = 3
|
|
14
|
+
colno = 12
|
|
15
|
+
|
|
16
|
+
err = DataDecodeError.from_exception("YAML", FakeParserError("whatever source text"))
|
|
17
|
+
|
|
18
|
+
assert err.format_name == "YAML"
|
|
19
|
+
assert err.reason == "unexpected token"
|
|
20
|
+
assert err.line == 3
|
|
21
|
+
assert err.column == 12
|
|
22
|
+
message = str(err)
|
|
23
|
+
assert "Failed to decode YAML data" in message
|
|
24
|
+
assert "unexpected token" in message
|
|
25
|
+
assert "line 3" in message
|
|
26
|
+
assert "column 12" in message
|
|
27
|
+
assert "whatever source text" not in message
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_from_exception_falls_back_to_type_name_when_no_msg() -> None:
|
|
31
|
+
"""When a parser exposes no msg/problem attr, the reason should be the exception type name."""
|
|
32
|
+
|
|
33
|
+
class BareError(Exception):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
err = DataDecodeError.from_exception("JSON", BareError())
|
|
37
|
+
|
|
38
|
+
assert err.reason == "BareError"
|
|
39
|
+
assert err.line is None
|
|
40
|
+
assert err.column is None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_from_exception_extracts_yaml_problem_mark() -> None:
|
|
44
|
+
"""The YAML parser exposes problem_mark; from_exception should honor it."""
|
|
45
|
+
|
|
46
|
+
class Mark:
|
|
47
|
+
line = 5
|
|
48
|
+
column = 9
|
|
49
|
+
|
|
50
|
+
class YamlishError(Exception):
|
|
51
|
+
problem_mark = Mark()
|
|
52
|
+
|
|
53
|
+
err = DataDecodeError.from_exception("YAML", YamlishError())
|
|
54
|
+
|
|
55
|
+
assert err.line == 6
|
|
56
|
+
assert err.column == 10
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_invalid_utf8_error_returns_data_decode_error() -> None:
|
|
60
|
+
"""invalid_utf8_error should return a DataDecodeError with the canonical reason text."""
|
|
61
|
+
err = invalid_utf8_error("TOML")
|
|
62
|
+
|
|
63
|
+
assert isinstance(err, DataDecodeError)
|
|
64
|
+
assert err.format_name == "TOML"
|
|
65
|
+
assert err.reason == "input bytes are not valid UTF-8"
|
|
66
|
+
assert "input bytes are not valid UTF-8" in str(err)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_data_decode_error_message_without_reason_or_position() -> None:
|
|
70
|
+
"""A bare DataDecodeError should still render a valid message."""
|
|
71
|
+
err = DataDecodeError("HCL")
|
|
72
|
+
|
|
73
|
+
assert str(err) == "Failed to decode HCL data."
|
|
74
|
+
assert err.reason is None
|
|
75
|
+
assert err.line is None
|
|
76
|
+
assert err.column is None
|
|
@@ -739,6 +739,38 @@ def test_write_file_tfvars_infers_hcl(tmp_path: Path) -> None:
|
|
|
739
739
|
assert decode_file(content, file_path=test_file) == data
|
|
740
740
|
|
|
741
741
|
|
|
742
|
+
def test_write_file_toml(tmp_path: Path) -> None:
|
|
743
|
+
"""TOML encoding should round-trip through write_file and decode_file."""
|
|
744
|
+
test_file = tmp_path / "config.toml"
|
|
745
|
+
data = {"service": "api", "replicas": 3, "enabled": True}
|
|
746
|
+
|
|
747
|
+
result = write_file(test_file, data, tld=tmp_path)
|
|
748
|
+
|
|
749
|
+
assert result == test_file.resolve()
|
|
750
|
+
assert test_file.exists()
|
|
751
|
+
content = test_file.read_text()
|
|
752
|
+
assert 'service = "api"' in content
|
|
753
|
+
assert "replicas = 3" in content
|
|
754
|
+
assert decode_file(content, file_path=test_file) == data
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
def test_data_file_toml_round_trip(tmp_path: Path) -> None:
|
|
758
|
+
"""DataFile should preserve TOML data across write then read."""
|
|
759
|
+
source = tmp_path / "source.toml"
|
|
760
|
+
source.write_text('service = "api"\nreplicas = 3\n', encoding="utf-8")
|
|
761
|
+
|
|
762
|
+
artifact = DataFile.read(source)
|
|
763
|
+
assert artifact.data == {"service": "api", "replicas": 3}
|
|
764
|
+
assert artifact.encoding == "toml"
|
|
765
|
+
|
|
766
|
+
target = tmp_path / "build" / "out.toml"
|
|
767
|
+
artifact.write(target, tld=tmp_path)
|
|
768
|
+
|
|
769
|
+
reread = DataFile.read(target)
|
|
770
|
+
assert reread.data == artifact.data
|
|
771
|
+
assert reread.encoding == "toml"
|
|
772
|
+
|
|
773
|
+
|
|
742
774
|
def test_write_file_bytes(tmp_path: Path) -> None:
|
|
743
775
|
"""Write raw bytes without re-encoding."""
|
|
744
776
|
test_file = tmp_path / "payload.bin"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Tests for the internal data normalization helper."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from extended_data.containers import ExtendedDict, ExtendedList, ExtendedSet, ExtendedString, ExtendedTuple
|
|
6
|
+
from extended_data.primitives.formats._normalization import lower_extended_data
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_lower_extended_data_unwraps_containers() -> None:
|
|
10
|
+
"""lower_extended_data should lower Tier 2 containers to plain Python values."""
|
|
11
|
+
value = ExtendedDict(
|
|
12
|
+
{
|
|
13
|
+
"service": ExtendedString("api"),
|
|
14
|
+
"ports": ExtendedList([80, 443]),
|
|
15
|
+
"tags": ExtendedSet({"prod", "api"}),
|
|
16
|
+
"aliases": ExtendedTuple(("api", "gateway")),
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
lowered = lower_extended_data(value)
|
|
21
|
+
|
|
22
|
+
assert lowered == {
|
|
23
|
+
"service": "api",
|
|
24
|
+
"ports": [80, 443],
|
|
25
|
+
"tags": {"prod", "api"},
|
|
26
|
+
"aliases": ("api", "gateway"),
|
|
27
|
+
}
|
|
28
|
+
assert type(lowered) is dict
|
|
29
|
+
assert type(lowered["ports"]) is list
|
|
30
|
+
assert type(lowered["tags"]) is set
|
|
31
|
+
assert type(lowered["aliases"]) is tuple
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_lower_extended_data_passes_through_plain_values() -> None:
|
|
35
|
+
"""lower_extended_data should leave plain Python values untouched."""
|
|
36
|
+
assert lower_extended_data(None) is None
|
|
37
|
+
assert lower_extended_data(42) == 42
|
|
38
|
+
assert lower_extended_data("api") == "api"
|
|
39
|
+
assert lower_extended_data({"service": "api"}) == {"service": "api"}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_lower_extended_data_unwraps_nested_extended_containers() -> None:
|
|
43
|
+
"""lower_extended_data should recursively lower nested Tier 2 containers."""
|
|
44
|
+
value = ExtendedDict({"outer": ExtendedDict({"inner": ExtendedList([ExtendedString("api")])})})
|
|
45
|
+
|
|
46
|
+
lowered = lower_extended_data(value)
|
|
47
|
+
|
|
48
|
+
assert lowered == {"outer": {"inner": ["api"]}}
|
|
49
|
+
assert type(lowered["outer"]) is dict
|
|
50
|
+
assert type(lowered["outer"]["inner"]) is list
|
|
@@ -269,3 +269,195 @@ def test_transform_can_write_output_artifact(tmp_path) -> None:
|
|
|
269
269
|
output_text = output.read_text(encoding="utf-8")
|
|
270
270
|
assert _stdout_text(mock_write) == f"{output_text}\n"
|
|
271
271
|
assert "http_response_code: 200" in output_text
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def test_decode_compact_json_drops_indent() -> None:
|
|
275
|
+
"""--compact should produce single-line JSON without indent."""
|
|
276
|
+
with patch("sys.stdout.write") as mock_write:
|
|
277
|
+
exit_code = cli_module.main(["decode", '{"service": "api"}', "--suffix", "json", "--compact"])
|
|
278
|
+
|
|
279
|
+
assert exit_code == 0
|
|
280
|
+
output = _stdout_text(mock_write)
|
|
281
|
+
assert json.loads(output) == {"service": "api"}
|
|
282
|
+
assert "\n" not in output.strip()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def test_decode_non_json_output_ignores_compact() -> None:
|
|
286
|
+
"""--compact only affects JSON; YAML output should remain unchanged."""
|
|
287
|
+
with patch("sys.stdout.write") as mock_write:
|
|
288
|
+
exit_code = cli_module.main(["decode", '{"service": "api"}', "--suffix", "json", "--output", "yaml", "--compact"])
|
|
289
|
+
|
|
290
|
+
assert exit_code == 0
|
|
291
|
+
output = _stdout_text(mock_write)
|
|
292
|
+
assert "service:" in output
|
|
293
|
+
assert "api" in output
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def test_decode_toml_output() -> None:
|
|
297
|
+
"""decode should emit TOML when --output toml is requested."""
|
|
298
|
+
with patch("sys.stdout.write") as mock_write:
|
|
299
|
+
exit_code = cli_module.main(["decode", '{"service": "api", "replicas": 3}', "--suffix", "json", "--output", "toml"])
|
|
300
|
+
|
|
301
|
+
assert exit_code == 0
|
|
302
|
+
output = _stdout_text(mock_write)
|
|
303
|
+
assert 'service = "api"' in output
|
|
304
|
+
assert "replicas = 3" in output
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def test_decode_hcl_output() -> None:
|
|
308
|
+
"""decode should emit HCL when --output hcl is requested."""
|
|
309
|
+
with patch("sys.stdout.write") as mock_write:
|
|
310
|
+
exit_code = cli_module.main(["decode", '{"locals": [{"region": "us-east-1"}]}', "--suffix", "json", "--output", "hcl"])
|
|
311
|
+
|
|
312
|
+
assert exit_code == 0
|
|
313
|
+
output = _stdout_text(mock_write)
|
|
314
|
+
assert "locals {" in output
|
|
315
|
+
assert 'region = "us-east-1"' in output
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def test_inspect_toml_output(tmp_path) -> None:
|
|
319
|
+
"""inspect should emit TOML metadata when --output toml is requested."""
|
|
320
|
+
config = tmp_path / "service.json"
|
|
321
|
+
config.write_text('{"service": "api"}', encoding="utf-8")
|
|
322
|
+
|
|
323
|
+
with patch("sys.stdout.write") as mock_write:
|
|
324
|
+
exit_code = cli_module.main(["inspect", "--file", str(config), "--output", "toml"])
|
|
325
|
+
|
|
326
|
+
assert exit_code == 0
|
|
327
|
+
output = _stdout_text(mock_write)
|
|
328
|
+
assert "source" in output
|
|
329
|
+
assert "json" in output
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def test_inspect_hcl_output() -> None:
|
|
333
|
+
"""inspect should emit HCL metadata when --output hcl is requested."""
|
|
334
|
+
with patch("sys.stdout.write") as mock_write:
|
|
335
|
+
exit_code = cli_module.main(["inspect", '{"service": "api"}', "--suffix", "json", "--output", "hcl"])
|
|
336
|
+
|
|
337
|
+
assert exit_code == 0
|
|
338
|
+
output = _stdout_text(mock_write)
|
|
339
|
+
assert "source" in output
|
|
340
|
+
assert "memory" in output
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def test_merge_toml_output(tmp_path) -> None:
|
|
344
|
+
"""merge should emit TOML when --output toml is requested."""
|
|
345
|
+
base = tmp_path / "base.json"
|
|
346
|
+
env = tmp_path / "env.json"
|
|
347
|
+
base.write_text('{"service": "api", "replicas": 1}', encoding="utf-8")
|
|
348
|
+
env.write_text('{"replicas": 3}', encoding="utf-8")
|
|
349
|
+
|
|
350
|
+
with patch("sys.stdout.write") as mock_write:
|
|
351
|
+
exit_code = cli_module.main(["merge", str(base), str(env), "--output", "toml"])
|
|
352
|
+
|
|
353
|
+
assert exit_code == 0
|
|
354
|
+
output = _stdout_text(mock_write)
|
|
355
|
+
assert 'service = "api"' in output
|
|
356
|
+
assert "replicas = 3" in output
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def test_merge_hcl_output(tmp_path) -> None:
|
|
360
|
+
"""merge should emit HCL when --output hcl is requested."""
|
|
361
|
+
base = tmp_path / "base.json"
|
|
362
|
+
env = tmp_path / "env.json"
|
|
363
|
+
base.write_text('{"locals": [{"region": "us-east-1"}]}', encoding="utf-8")
|
|
364
|
+
env.write_text('{"locals": [{"zone": "a"}]}', encoding="utf-8")
|
|
365
|
+
|
|
366
|
+
with patch("sys.stdout.write") as mock_write:
|
|
367
|
+
exit_code = cli_module.main(["merge", str(base), str(env), "--output", "hcl"])
|
|
368
|
+
|
|
369
|
+
assert exit_code == 0
|
|
370
|
+
output = _stdout_text(mock_write)
|
|
371
|
+
assert "locals {" in output
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def test_transform_toml_output(tmp_path) -> None:
|
|
375
|
+
"""transform should emit TOML when --output toml is requested."""
|
|
376
|
+
payload = tmp_path / "payload.json"
|
|
377
|
+
payload.write_text('{"HTTPResponseCode": "200"}', encoding="utf-8")
|
|
378
|
+
|
|
379
|
+
with patch("sys.stdout.write") as mock_write:
|
|
380
|
+
exit_code = cli_module.main(
|
|
381
|
+
["transform", "--file", str(payload), "--step", "reconstruct", "--step", "unhump", "--output", "toml"]
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
assert exit_code == 0
|
|
385
|
+
output = _stdout_text(mock_write)
|
|
386
|
+
assert "http_response_code" in output
|
|
387
|
+
assert "200" in output
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def test_transform_hcl_output(tmp_path) -> None:
|
|
391
|
+
"""transform should emit HCL when --output hcl is requested."""
|
|
392
|
+
payload = tmp_path / "payload.json"
|
|
393
|
+
payload.write_text('{"locals": [{"region": "us-east-1"}]}', encoding="utf-8")
|
|
394
|
+
|
|
395
|
+
with patch("sys.stdout.write") as mock_write:
|
|
396
|
+
exit_code = cli_module.main(
|
|
397
|
+
["transform", "--file", str(payload), "--step", "reconstruct", "--output", "hcl"]
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
assert exit_code == 0
|
|
401
|
+
output = _stdout_text(mock_write)
|
|
402
|
+
assert "locals {" in output
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def test_merge_allow_empty_writes_empty_output(tmp_path) -> None:
|
|
406
|
+
"""--allow-empty should let merge write an empty result without error."""
|
|
407
|
+
base = tmp_path / "base.json"
|
|
408
|
+
env = tmp_path / "env.json"
|
|
409
|
+
output = tmp_path / "out.json"
|
|
410
|
+
base.write_text("{}", encoding="utf-8")
|
|
411
|
+
env.write_text("{}", encoding="utf-8")
|
|
412
|
+
|
|
413
|
+
with patch("sys.stdout.write"):
|
|
414
|
+
exit_code = cli_module.main(
|
|
415
|
+
["merge", str(base), str(env), "--output", "json", "--write", str(output), "--allow-empty"]
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
assert exit_code == 0
|
|
419
|
+
assert output.exists()
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def test_transform_allow_empty_writes_empty_output(tmp_path) -> None:
|
|
423
|
+
"""--allow-empty should let transform write an empty result without error."""
|
|
424
|
+
payload = tmp_path / "payload.json"
|
|
425
|
+
output = tmp_path / "out.json"
|
|
426
|
+
payload.write_text("{}", encoding="utf-8")
|
|
427
|
+
|
|
428
|
+
with patch("sys.stdout.write"):
|
|
429
|
+
exit_code = cli_module.main(
|
|
430
|
+
["transform", "--file", str(payload), "--step", "compact", "--output", "json", "--write", str(output), "--allow-empty"]
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
assert exit_code == 0
|
|
434
|
+
assert output.exists()
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def test_no_command_prints_help_and_returns_zero() -> None:
|
|
438
|
+
"""Calling the CLI with no command should print help and exit 0."""
|
|
439
|
+
with patch("sys.stdout.write") as mock_write:
|
|
440
|
+
exit_code = cli_module.main([])
|
|
441
|
+
|
|
442
|
+
assert exit_code == 0
|
|
443
|
+
output = _stdout_text(mock_write)
|
|
444
|
+
assert "CLI for Extended Data" in output or "usage:" in output.lower()
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def test_keyboard_interrupt_returns_130() -> None:
|
|
448
|
+
"""KeyboardInterrupt during a command should return exit code 130."""
|
|
449
|
+
with patch("extended_data.cli.cmd_decode", side_effect=KeyboardInterrupt):
|
|
450
|
+
exit_code = cli_module.main(["decode", '{"service": "api"}', "--suffix", "json"])
|
|
451
|
+
|
|
452
|
+
assert exit_code == 130
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
def test_main_argv_none_reads_sys_argv(monkeypatch) -> None:
|
|
456
|
+
"""main(argv=None) should fall back to sys.argv[1:]."""
|
|
457
|
+
monkeypatch.setattr("sys.argv", ["extended-data", "decode", '{"x": 1}', "--suffix", "json"])
|
|
458
|
+
|
|
459
|
+
with patch("sys.stdout.write") as mock_write:
|
|
460
|
+
exit_code = cli_module.main()
|
|
461
|
+
|
|
462
|
+
assert exit_code == 0
|
|
463
|
+
assert json.loads(_stdout_text(mock_write)) == {"x": 1}
|
extended_data-8.4.1/tests/inputs/test_main.py → extended_data-8.4.2/tests/inputs/test_providers.py
RENAMED
|
@@ -38,8 +38,8 @@ import pytest
|
|
|
38
38
|
|
|
39
39
|
from extended_data import base64_encode
|
|
40
40
|
from extended_data.containers import ExtendedDict, ExtendedString
|
|
41
|
-
from extended_data.inputs import
|
|
42
|
-
from extended_data.inputs.
|
|
41
|
+
from extended_data.inputs import providers as inputs_module
|
|
42
|
+
from extended_data.inputs.providers import InputProvider
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
@pytest.fixture
|
|
@@ -288,6 +288,19 @@ def test_decode_input_base64():
|
|
|
288
288
|
assert decoded == {"name": "test"}
|
|
289
289
|
|
|
290
290
|
|
|
291
|
+
def test_decode_input_base64_then_yaml():
|
|
292
|
+
"""Base64 payload decoded then re-decoded as YAML should produce a mapping."""
|
|
293
|
+
import yaml
|
|
294
|
+
|
|
295
|
+
yaml_payload = yaml.safe_dump({"name": "test", "replicas": 3})
|
|
296
|
+
encoded_value = base64_encode(yaml_payload.encode())
|
|
297
|
+
dic = InputProvider(inputs={"base64_key": encoded_value})
|
|
298
|
+
|
|
299
|
+
decoded = dic.decode_input("base64_key", decode_from_base64=True, decode_from_yaml=True)
|
|
300
|
+
|
|
301
|
+
assert decoded == {"name": "test", "replicas": 3}
|
|
302
|
+
|
|
303
|
+
|
|
291
304
|
def test_decode_input_base64_from_bytes():
|
|
292
305
|
"""Base64 encoded bytes can be decoded and parsed."""
|
|
293
306
|
encoded_value = base64_encode(json.dumps({"name": "test"}).encode())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/__init__.py
RENAMED
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/_normalization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/dumpers.py
RENAMED
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/loaders.py
RENAMED
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/tag_classes.py
RENAMED
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/formats/yaml/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/string_transforms.py
RENAMED
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/src/extended_data/primitives/transformations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/tests/core/transformations/numbers/test_notation.py
RENAMED
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/tests/core/transformations/numbers/test_words.py
RENAMED
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/tests/core/transformations/strings/test_inflection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{extended_data-8.4.1 → extended_data-8.4.2}/tests/logging/integration/test_lifecycle_logging.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|