etlplus 0.17.3__tar.gz → 0.17.4__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.
- {etlplus-0.17.3/etlplus.egg-info → etlplus-0.17.4}/PKG-INFO +1 -1
- {etlplus-0.17.3 → etlplus-0.17.4/etlplus.egg-info}/PKG-INFO +1 -1
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus.egg-info/SOURCES.txt +1 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/conftest.py +2 -1
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/conftest.py +6 -1
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/conftest.py +3 -3
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/cli/conftest.py +2 -2
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/conftest.py +2 -1
- etlplus-0.17.4/tests/unit/file/conftest.py +112 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/file/test_u_file_core.py +165 -90
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/file/test_u_file_yaml.py +1 -1
- {etlplus-0.17.3 → etlplus-0.17.4}/.coveragerc +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.editorconfig +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.gitattributes +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.github/actions/python-bootstrap/action.yml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.github/workflows/ci.yml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.gitignore +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.pre-commit-config.yaml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/.ruff.toml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/CODE_OF_CONDUCT.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/CONTRIBUTING.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/DEMO.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/LICENSE +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/MANIFEST.in +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/Makefile +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/REFERENCES.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/SECURITY.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/SUPPORT.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/docs/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/docs/pipeline-guide.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/docs/snippets/installation_version.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/__main__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/__version__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/auth.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/endpoint_client.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/errors.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/pagination/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/pagination/client.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/pagination/config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/pagination/paginator.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/rate_limiting/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/rate_limiting/config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/rate_limiting/rate_limiter.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/request_manager.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/retry_manager.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/transport.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/api/utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/commands.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/constants.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/handlers.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/io.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/main.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/options.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/state.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/cli/types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/api.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/connector.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/core.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/database.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/file.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/connector/utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/ddl.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/engine.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/orm.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/schema.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/database/types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/_imports.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/_io.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/_r.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/_sql.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/accdb.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/arrow.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/avro.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/bson.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/cbor.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/cfg.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/conf.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/core.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/csv.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/dat.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/dta.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/duckdb.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/feather.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/fwf.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/gz.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/hbs.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/hdf5.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/ini.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/ion.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/jinja2.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/json.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/log.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/mat.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/mdb.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/msgpack.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/mustache.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/nc.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/ndjson.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/numbers.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/ods.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/orc.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/parquet.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/pb.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/pbf.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/properties.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/proto.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/psv.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/rda.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/rds.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/sas7bdat.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/sav.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/sqlite.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/stub.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/sylk.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/tab.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/toml.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/tsv.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/txt.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/vm.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/wks.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/xls.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/xlsm.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/xlsx.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/xml.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/xpt.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/yaml.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/zip.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/file/zsav.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/mixins.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/extract.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/load.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/run.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/transform.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/ops/validate.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/py.typed +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/templates/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/templates/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/templates/ddl.sql.j2 +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/templates/view.sql.j2 +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/workflow/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/workflow/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/workflow/dag.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/workflow/jobs.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus/workflow/profile.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus.egg-info/dependency_links.txt +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus.egg-info/entry_points.txt +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus.egg-info/requires.txt +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/etlplus.egg-info/top_level.txt +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/configs/ddl_spec.yml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/configs/pipeline.yml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/data/sample.csv +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/data/sample.json +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/data/sample.xml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/data/sample.xsd +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/data/sample.yaml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/examples/quickstart.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/pyproject.toml +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/pytest.ini +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/setup.cfg +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/setup.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/README.md +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/conftest.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_cli.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_config_load.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_examples_data_parity.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_pagination_strategy.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_run.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_run_profile_pagination_defaults.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/integration/test_i_run_profile_rate_limit_defaults.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/__init__.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_cli_check.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_cli_extract.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_cli_load.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_cli_render.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_cli_transform.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_cli_validate.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/smoke/test_s_pipeline.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_auth.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_endpoint_client.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_mocks.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_pagination_client.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_pagination_config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_paginator.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_rate_limit_config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_rate_limiter.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_request_manager.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_retry_manager.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_transport.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_types.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/api/test_u_api_utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/cli/test_u_cli_handlers.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/cli/test_u_cli_io.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/cli/test_u_cli_main.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/cli/test_u_cli_state.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/connector/test_u_connector_enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/connector/test_u_connector_utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/database/test_u_database_ddl.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/database/test_u_database_engine.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/database/test_u_database_orm.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/database/test_u_database_schema.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/file/test_u_file_enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_enums.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_extract.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_load.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_run.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_transform.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/ops/test_u_ops_validate.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/test_u_config.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/test_u_main.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/test_u_mixins.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/test_u_utils.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/test_u_version.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tests/unit/workflow/test_u_workflow_jobs.py +0 -0
- {etlplus-0.17.3 → etlplus-0.17.4}/tools/update_demo_snippets.py +0 -0
|
@@ -229,6 +229,7 @@ tests/unit/database/test_u_database_ddl.py
|
|
|
229
229
|
tests/unit/database/test_u_database_engine.py
|
|
230
230
|
tests/unit/database/test_u_database_orm.py
|
|
231
231
|
tests/unit/database/test_u_database_schema.py
|
|
232
|
+
tests/unit/file/conftest.py
|
|
232
233
|
tests/unit/file/test_u_file_core.py
|
|
233
234
|
tests/unit/file/test_u_file_enums.py
|
|
234
235
|
tests/unit/file/test_u_file_yaml.py
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"""
|
|
2
2
|
:mod:`tests.smoke.conftest` module.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Define shared fixtures and helpers for pytest-based smoke tests of
|
|
5
|
+
:mod:`etlplus`.
|
|
6
|
+
|
|
7
|
+
Notes
|
|
8
|
+
-----
|
|
9
|
+
- Fixtures are designed for reuse and DRY test setup.
|
|
5
10
|
"""
|
|
6
11
|
|
|
7
12
|
from __future__ import annotations
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""
|
|
2
2
|
:mod:`tests.unit.api.conftest` module.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Define shared fixtures and helpers for pytest-based unit tests of
|
|
5
5
|
:mod:`etlplus.api`.
|
|
6
6
|
|
|
7
7
|
Notes
|
|
8
8
|
-----
|
|
9
|
-
- Fixtures are designed for reuse and DRY test setup across API-focused
|
|
10
|
-
|
|
9
|
+
- Fixtures are designed for reuse and DRY test setup across API-focused unit
|
|
10
|
+
tests.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""
|
|
2
|
+
:mod:`tests.unit.file.conftest` module.
|
|
3
|
+
|
|
4
|
+
Define shared fixtures and helpers for pytest-based unit tests of
|
|
5
|
+
:mod:`etlplus.file`.
|
|
6
|
+
|
|
7
|
+
Notes
|
|
8
|
+
-----
|
|
9
|
+
- Fixtures are designed for reuse and DRY test setup across file-focused unit
|
|
10
|
+
tests.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import math
|
|
16
|
+
import numbers
|
|
17
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
|
|
20
|
+
from etlplus.types import JSONData
|
|
21
|
+
from etlplus.types import JSONDict
|
|
22
|
+
|
|
23
|
+
# SECTION: MARKERS ========================================================== #
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Directory-level marker for unit tests.
|
|
27
|
+
pytestmark = pytest.mark.unit
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# SECTION: HELPERS ========================================================== #
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def require_optional_modules(*modules: str) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Skip the test when optional dependencies are missing.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
*modules : str
|
|
40
|
+
Module names to verify via ``pytest.importorskip``.
|
|
41
|
+
"""
|
|
42
|
+
for module in modules:
|
|
43
|
+
pytest.importorskip(module)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _coerce_numeric_value(value: object) -> object:
|
|
47
|
+
"""Coerce numeric scalars into stable Python numeric types."""
|
|
48
|
+
if isinstance(value, numbers.Real):
|
|
49
|
+
try:
|
|
50
|
+
numeric = float(value)
|
|
51
|
+
if math.isnan(numeric):
|
|
52
|
+
return None
|
|
53
|
+
except (TypeError, ValueError):
|
|
54
|
+
return value
|
|
55
|
+
if numeric.is_integer():
|
|
56
|
+
return int(numeric)
|
|
57
|
+
return float(numeric)
|
|
58
|
+
return value
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def normalize_numeric_records(records: JSONData) -> JSONData:
|
|
62
|
+
"""
|
|
63
|
+
Normalize numeric record values for deterministic comparisons.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
records : JSONData
|
|
68
|
+
Record payloads to normalize.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
JSONData
|
|
73
|
+
Normalized record payloads.
|
|
74
|
+
"""
|
|
75
|
+
if isinstance(records, list):
|
|
76
|
+
normalized: list[JSONDict] = []
|
|
77
|
+
for row in records:
|
|
78
|
+
if not isinstance(row, dict):
|
|
79
|
+
normalized.append(row)
|
|
80
|
+
continue
|
|
81
|
+
cleaned: JSONDict = {}
|
|
82
|
+
for key, value in row.items():
|
|
83
|
+
cleaned[key] = _coerce_numeric_value(value)
|
|
84
|
+
normalized.append(cleaned)
|
|
85
|
+
return normalized
|
|
86
|
+
return records
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def normalize_xml_payload(payload: JSONData) -> JSONData:
|
|
90
|
+
"""
|
|
91
|
+
Normalize XML payloads to list-based item structures when possible.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
payload : JSONData
|
|
96
|
+
XML payload to normalize.
|
|
97
|
+
|
|
98
|
+
Returns
|
|
99
|
+
-------
|
|
100
|
+
JSONData
|
|
101
|
+
Normalized XML payload.
|
|
102
|
+
"""
|
|
103
|
+
if not isinstance(payload, dict):
|
|
104
|
+
return payload
|
|
105
|
+
root = payload.get('root')
|
|
106
|
+
if not isinstance(root, dict):
|
|
107
|
+
return payload
|
|
108
|
+
items = root.get('items')
|
|
109
|
+
if isinstance(items, dict):
|
|
110
|
+
root = {**root, 'items': [items]}
|
|
111
|
+
return {**payload, 'root': root}
|
|
112
|
+
return payload
|
|
@@ -11,17 +11,24 @@ Notes
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
-
import
|
|
15
|
-
import
|
|
14
|
+
import sqlite3
|
|
15
|
+
import zipfile
|
|
16
|
+
from os import PathLike
|
|
16
17
|
from pathlib import Path
|
|
18
|
+
from pathlib import PurePath
|
|
17
19
|
from typing import cast
|
|
18
20
|
|
|
19
21
|
import pytest
|
|
20
22
|
|
|
21
23
|
from etlplus.file import File
|
|
22
24
|
from etlplus.file import FileFormat
|
|
25
|
+
from etlplus.file import csv as csv_file
|
|
26
|
+
from etlplus.file import json as json_file
|
|
27
|
+
from etlplus.file import xml as xml_file
|
|
23
28
|
from etlplus.types import JSONData
|
|
24
|
-
from
|
|
29
|
+
from tests.unit.file.conftest import normalize_numeric_records
|
|
30
|
+
from tests.unit.file.conftest import normalize_xml_payload
|
|
31
|
+
from tests.unit.file.conftest import require_optional_modules
|
|
25
32
|
|
|
26
33
|
# SECTION: MARKERS ========================================================== #
|
|
27
34
|
|
|
@@ -299,64 +306,41 @@ FORMAT_CASES: list[FormatCase] = [
|
|
|
299
306
|
),
|
|
300
307
|
]
|
|
301
308
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
def _normalize_xml_payload(
|
|
339
|
-
payload: JSONData,
|
|
340
|
-
) -> JSONData:
|
|
341
|
-
"""Normalize XML payloads to list-based item structures when possible."""
|
|
342
|
-
if not isinstance(payload, dict):
|
|
343
|
-
return payload
|
|
344
|
-
root = payload.get('root')
|
|
345
|
-
if not isinstance(root, dict):
|
|
346
|
-
return payload
|
|
347
|
-
items = root.get('items')
|
|
348
|
-
if isinstance(items, dict):
|
|
349
|
-
root = {**root, 'items': [items]}
|
|
350
|
-
return {**payload, 'root': root}
|
|
351
|
-
return payload
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
def _require_modules(
|
|
355
|
-
modules: tuple[str, ...],
|
|
356
|
-
) -> None:
|
|
357
|
-
"""Skip the test when optional dependencies are missing."""
|
|
358
|
-
for module in modules:
|
|
359
|
-
pytest.importorskip(module)
|
|
309
|
+
STUBBED_FORMATS: tuple[tuple[FileFormat, str], ...] = (
|
|
310
|
+
# Permanent stub as formality
|
|
311
|
+
(FileFormat.STUB, 'data.stub'),
|
|
312
|
+
# Temporary stubs until implemented
|
|
313
|
+
(FileFormat.ACCDB, 'data.accdb'),
|
|
314
|
+
(FileFormat.CFG, 'data.cfg'),
|
|
315
|
+
(FileFormat.CONF, 'data.conf'),
|
|
316
|
+
(FileFormat.ION, 'data.ion'),
|
|
317
|
+
(FileFormat.JINJA2, 'data.jinja2'),
|
|
318
|
+
(FileFormat.LOG, 'data.log'),
|
|
319
|
+
(FileFormat.MAT, 'data.mat'),
|
|
320
|
+
(FileFormat.MDB, 'data.mdb'),
|
|
321
|
+
# (FileFormat.MDF, 'data.mdf'),
|
|
322
|
+
(FileFormat.MUSTACHE, 'data.mustache'),
|
|
323
|
+
(FileFormat.PBF, 'data.pbf'),
|
|
324
|
+
# (FileFormat.RAW, 'data.raw'),
|
|
325
|
+
# (FileFormat.RTF, 'data.rtf'),
|
|
326
|
+
# (FileFormat.SDF, 'data.sdf'),
|
|
327
|
+
# (FileFormat.SLV, 'data.slv'),
|
|
328
|
+
(FileFormat.SYLK, 'data.sylk'),
|
|
329
|
+
# (FileFormat.VCF, 'data.vcf'),
|
|
330
|
+
(FileFormat.VM, 'data.vm'),
|
|
331
|
+
# (FileFormat.WSV, 'data.wsv'),
|
|
332
|
+
(FileFormat.ZSAV, 'data.zsav'),
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
class _DummyPath(PathLike[str]):
|
|
337
|
+
"""Simple PathLike wrapper for StrPath tests."""
|
|
338
|
+
|
|
339
|
+
def __init__(self, path: str) -> None:
|
|
340
|
+
self._path = path
|
|
341
|
+
|
|
342
|
+
def __fspath__(self) -> str:
|
|
343
|
+
return self._path
|
|
360
344
|
|
|
361
345
|
|
|
362
346
|
# SECTION: FIXTURES ========================================================= #
|
|
@@ -365,31 +349,7 @@ def _require_modules(
|
|
|
365
349
|
@pytest.fixture(name='stubbed_formats')
|
|
366
350
|
def stubbed_formats_fixture() -> list[tuple[FileFormat, str]]:
|
|
367
351
|
"""Return a list of stubbed file formats for testing."""
|
|
368
|
-
return
|
|
369
|
-
# Permanent stub as formality
|
|
370
|
-
(FileFormat.STUB, 'data.stub'),
|
|
371
|
-
# Temporary stubs until implemented
|
|
372
|
-
(FileFormat.ACCDB, 'data.accdb'),
|
|
373
|
-
(FileFormat.CFG, 'data.cfg'),
|
|
374
|
-
(FileFormat.CONF, 'data.conf'),
|
|
375
|
-
(FileFormat.ION, 'data.ion'),
|
|
376
|
-
(FileFormat.JINJA2, 'data.jinja2'),
|
|
377
|
-
(FileFormat.LOG, 'data.log'),
|
|
378
|
-
(FileFormat.MAT, 'data.mat'),
|
|
379
|
-
(FileFormat.MDB, 'data.mdb'),
|
|
380
|
-
# (FileFormat.MDF, 'data.mdf'),
|
|
381
|
-
(FileFormat.MUSTACHE, 'data.mustache'),
|
|
382
|
-
(FileFormat.PBF, 'data.pbf'),
|
|
383
|
-
# (FileFormat.RAW, 'data.raw'),
|
|
384
|
-
# (FileFormat.RTF, 'data.rtf'),
|
|
385
|
-
# (FileFormat.SDF, 'data.sdf'),
|
|
386
|
-
# (FileFormat.SLV, 'data.slv'),
|
|
387
|
-
(FileFormat.SYLK, 'data.sylk'),
|
|
388
|
-
# (FileFormat.VCF, 'data.vcf'),
|
|
389
|
-
(FileFormat.VM, 'data.vm'),
|
|
390
|
-
# (FileFormat.WSV, 'data.wsv'),
|
|
391
|
-
(FileFormat.ZSAV, 'data.zsav'),
|
|
392
|
-
]
|
|
352
|
+
return list(STUBBED_FORMATS)
|
|
393
353
|
|
|
394
354
|
|
|
395
355
|
# SECTION: TESTS ============================================================ #
|
|
@@ -421,6 +381,40 @@ class TestFile:
|
|
|
421
381
|
f.read()
|
|
422
382
|
assert 'compressed file' in str(e.value)
|
|
423
383
|
|
|
384
|
+
def test_duckdb_read_fails_with_multiple_tables(
|
|
385
|
+
self,
|
|
386
|
+
tmp_path: Path,
|
|
387
|
+
) -> None:
|
|
388
|
+
"""
|
|
389
|
+
Test DuckDB reader rejects multiple table databases.
|
|
390
|
+
"""
|
|
391
|
+
duckdb = pytest.importorskip('duckdb')
|
|
392
|
+
path = tmp_path / 'multi.duckdb'
|
|
393
|
+
conn = duckdb.connect(str(path))
|
|
394
|
+
try:
|
|
395
|
+
conn.execute('CREATE TABLE one (id INTEGER)')
|
|
396
|
+
conn.execute('CREATE TABLE two (id INTEGER)')
|
|
397
|
+
finally:
|
|
398
|
+
conn.close()
|
|
399
|
+
|
|
400
|
+
with pytest.raises(ValueError, match='Multiple tables'):
|
|
401
|
+
File(path, FileFormat.DUCKDB).read()
|
|
402
|
+
|
|
403
|
+
def test_gz_round_trip_json(
|
|
404
|
+
self,
|
|
405
|
+
tmp_path: Path,
|
|
406
|
+
) -> None:
|
|
407
|
+
"""
|
|
408
|
+
Test JSON round-trip inside a gzip archive.
|
|
409
|
+
"""
|
|
410
|
+
path = tmp_path / 'data.json.gz'
|
|
411
|
+
payload = [{'name': 'Ada'}]
|
|
412
|
+
|
|
413
|
+
File(path, FileFormat.GZ).write(payload)
|
|
414
|
+
result = File(path, FileFormat.GZ).read()
|
|
415
|
+
|
|
416
|
+
assert result == payload
|
|
417
|
+
|
|
424
418
|
@pytest.mark.parametrize(
|
|
425
419
|
'filename,expected_format',
|
|
426
420
|
[
|
|
@@ -541,7 +535,7 @@ class TestFile:
|
|
|
541
535
|
requires: tuple[str, ...],
|
|
542
536
|
) -> None:
|
|
543
537
|
"""Test round-trip reads and writes across file formats."""
|
|
544
|
-
|
|
538
|
+
require_optional_modules(*requires)
|
|
545
539
|
path = tmp_path / filename
|
|
546
540
|
|
|
547
541
|
File(path, file_format).write(payload)
|
|
@@ -553,12 +547,57 @@ class TestFile:
|
|
|
553
547
|
raise
|
|
554
548
|
|
|
555
549
|
if file_format is FileFormat.XML:
|
|
556
|
-
result =
|
|
557
|
-
expected =
|
|
550
|
+
result = normalize_xml_payload(result)
|
|
551
|
+
expected = normalize_xml_payload(expected)
|
|
558
552
|
if file_format is FileFormat.XLS:
|
|
559
|
-
result =
|
|
553
|
+
result = normalize_numeric_records(result)
|
|
560
554
|
assert result == expected
|
|
561
555
|
|
|
556
|
+
def test_sqlite_read_fails_with_multiple_tables(
|
|
557
|
+
self,
|
|
558
|
+
tmp_path: Path,
|
|
559
|
+
) -> None:
|
|
560
|
+
"""
|
|
561
|
+
Test SQLite reader rejects multiple table databases.
|
|
562
|
+
"""
|
|
563
|
+
path = tmp_path / 'multi.sqlite'
|
|
564
|
+
conn = sqlite3.connect(path)
|
|
565
|
+
try:
|
|
566
|
+
conn.execute('CREATE TABLE one (id INTEGER)')
|
|
567
|
+
conn.execute('CREATE TABLE two (id INTEGER)')
|
|
568
|
+
conn.commit()
|
|
569
|
+
finally:
|
|
570
|
+
conn.close()
|
|
571
|
+
|
|
572
|
+
with pytest.raises(ValueError, match='Multiple tables'):
|
|
573
|
+
File(path, FileFormat.SQLITE).read()
|
|
574
|
+
|
|
575
|
+
def test_strpath_support_for_module_helpers(
|
|
576
|
+
self,
|
|
577
|
+
tmp_path: Path,
|
|
578
|
+
) -> None:
|
|
579
|
+
"""
|
|
580
|
+
Test module helpers accept ``StrPath`` inputs.
|
|
581
|
+
|
|
582
|
+
Uses ``str`` and ``PathLike`` inputs to validate normalization.
|
|
583
|
+
"""
|
|
584
|
+
csv_path = tmp_path / 'data.csv'
|
|
585
|
+
json_path = tmp_path / 'data.json'
|
|
586
|
+
xml_path = tmp_path / 'data.xml'
|
|
587
|
+
|
|
588
|
+
csv_file.write(str(csv_path), [{'name': 'Ada'}])
|
|
589
|
+
assert csv_file.read(str(csv_path)) == [{'name': 'Ada'}]
|
|
590
|
+
|
|
591
|
+
json_file.write(_DummyPath(str(json_path)), {'name': 'Ada'})
|
|
592
|
+
assert json_file.read(_DummyPath(str(json_path))) == {'name': 'Ada'}
|
|
593
|
+
|
|
594
|
+
xml_file.write(
|
|
595
|
+
PurePath(xml_path),
|
|
596
|
+
{'root': {'text': 'hello'}},
|
|
597
|
+
root_tag='root',
|
|
598
|
+
)
|
|
599
|
+
assert xml_file.read(PurePath(xml_path)) == {'root': {'text': 'hello'}}
|
|
600
|
+
|
|
562
601
|
def test_stub_formats_raise_on_read(
|
|
563
602
|
self,
|
|
564
603
|
tmp_path: Path,
|
|
@@ -680,3 +719,39 @@ class TestFile:
|
|
|
680
719
|
text = path.read_text(encoding='utf-8')
|
|
681
720
|
assert text.startswith('<?xml')
|
|
682
721
|
assert '<records>' in text
|
|
722
|
+
|
|
723
|
+
def test_xml_round_trip_with_attributes(
|
|
724
|
+
self,
|
|
725
|
+
tmp_path: Path,
|
|
726
|
+
) -> None:
|
|
727
|
+
"""
|
|
728
|
+
Test XML read/write preserves attribute fields.
|
|
729
|
+
"""
|
|
730
|
+
path = tmp_path / 'attrs.xml'
|
|
731
|
+
payload: JSONData = {
|
|
732
|
+
'root': {
|
|
733
|
+
'@id': '42',
|
|
734
|
+
'item': {'@lang': 'en', 'text': 'Hello'},
|
|
735
|
+
},
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
File(path, FileFormat.XML).write(payload)
|
|
739
|
+
result = File(path, FileFormat.XML).read()
|
|
740
|
+
|
|
741
|
+
assert result == payload
|
|
742
|
+
|
|
743
|
+
def test_zip_multi_file_read(
|
|
744
|
+
self,
|
|
745
|
+
tmp_path: Path,
|
|
746
|
+
) -> None:
|
|
747
|
+
"""
|
|
748
|
+
Test ZIP files with multiple entries return a dict payload.
|
|
749
|
+
"""
|
|
750
|
+
path = tmp_path / 'bundle.zip'
|
|
751
|
+
with zipfile.ZipFile(path, 'w') as archive:
|
|
752
|
+
archive.writestr('a.json', '{"a": 1}')
|
|
753
|
+
archive.writestr('b.json', '{"b": 2}')
|
|
754
|
+
|
|
755
|
+
result = File(path, FileFormat.ZIP).read()
|
|
756
|
+
|
|
757
|
+
assert result == {'a.json': {'a': 1}, 'b.json': {'b': 2}}
|
|
@@ -6,7 +6,7 @@ Unit tests for :mod:`etlplus.file.yaml`.
|
|
|
6
6
|
Notes
|
|
7
7
|
-----
|
|
8
8
|
- Uses ``tmp_path`` for filesystem isolation.
|
|
9
|
-
- Exercises
|
|
9
|
+
- Exercises YAML read/write helpers with a stubbed PyYAML module.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
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
|