From 925cbb33e38e98915418a4557184a46d28ebdb1f Mon Sep 17 00:00:00 2001 From: roll Date: Mon, 29 Apr 2024 13:54:06 +0100 Subject: [PATCH] Update development dependencies and improve release process (#1652) * Recover dependencies; merge make/hatch * Fixed linting * Use hatch shortcuts * Fixed analyzer/schema/steps type errors * Fixed resource type errors * Fixed lazy_fixtures usage * Started moving tests closer to the codebase * Migrated schemes tests * Migrated resources tests * Migrated formats tests * Migrated portals tests * Improved modularity * Recover python3.12 on CI * Skip tests failing on pyhton3.12 * Recover python3.8/9 on CI * Skip pytest-vcr related failures on python3.8/9 * Added py3.12 into project description * Fixed tests * Don't use __all__ in formats * Don't use __all__ in portals * Don't use __all__ in schemes * Don't use __all__ in steps * Don't use __all__ in checks * Don't use __all__ in resources * Don't user __all__ in fields * Don't use __all__ in errors * Don't use __all__ in root * Updated Python3.12+ test skip messages * Remove `jsonschema` uppder version limit * Fixed macos setup on CI * Downgrade macos version on CI * Downgrage macos on CI --- .github/workflows/general.yaml | 16 ++- CONTRIBUTING.md | 28 +++-- Makefile | 40 ------- frictionless/__init__.py | 109 +++++++----------- .../actions/__spec__}/__init__.py | 0 .../actions/__spec__}/test_describe.py | 0 .../actions/__spec__}/test_extract.py | 0 .../actions/__spec__}/test_list.py | 0 .../actions/__spec__}/test_transform.py | 0 .../actions/__spec__}/test_validate.py | 0 .../analyzer/__spec__}/__init__.py | 0 .../analyzer/__spec__}/test_package.py | 0 .../analyzer/__spec__}/test_resource.py | 4 + frictionless/analyzer/analyzer.py | 12 +- .../catalog/__spec__}/__init__.py | 0 .../catalog/__spec__}/test_dereference.py | 0 .../catalog/__spec__}/test_general.py | 0 .../catalog/__spec__}/test_infer.py | 0 .../checklist/__spec__}/__init__.py | 0 .../checklist/__spec__/check}/__init__.py | 0 .../checklist/__spec__}/check/test_convert.py | 0 .../checklist/__spec__}/check/test_general.py | 0 .../checklist/__spec__}/test_convert.py | 0 .../checklist/__spec__}/test_general.py | 0 frictionless/checks/__init__.py | 16 +-- .../checks/__spec__}/test_baseline.py | 0 .../checks/cell/__spec__}/test_ascii_value.py | 0 .../cell/__spec__}/test_deviated_cell.py | 0 .../cell/__spec__}/test_deviated_value.py | 0 .../cell/__spec__}/test_forbidden_value.py | 0 .../cell/__spec__}/test_required_value.py | 0 .../cell/__spec__}/test_sequential_value.py | 0 .../cell/__spec__}/test_truncated_value.py | 0 .../row/__spec__}/test_duplicate_row.py | 0 .../row/__spec__}/test_row_constraint.py | 0 .../table/__spec__}/test_table_dimensions.py | 0 {tests => frictionless}/conftest.py | 4 +- .../console/__spec__}/__init__.py | 0 .../console/__spec__}/test_console.py | 0 frictionless/console/commands/__init__.py | 17 ++- .../console/commands/__spec__}/__init__.py | 0 .../commands/__spec__}/test_convert.py | 0 .../commands/__spec__}/test_describe.py | 0 .../commands/__spec__}/test_extract.py | 0 .../commands/__spec__}/test_summary.py | 0 .../commands/__spec__}/test_transform.py | 0 .../commands/__spec__}/test_validate.py | 0 .../detector/__spec__}/__init__.py | 0 .../detector/__spec__}/test_general.py | 0 .../dialect/__spec__}/__init__.py | 0 .../dialect/__spec__/control}/__init__.py | 0 .../dialect/__spec__}/control/test_general.py | 0 .../dialect/__spec__}/test_convert.py | 0 .../dialect/__spec__}/test_describe.py | 0 .../dialect/__spec__}/test_general.py | 0 .../error/__spec__}/__init__.py | 0 .../error/__spec__}/test_error.py | 0 frictionless/errors/__init__.py | 62 ---------- frictionless/fields/__init__.py | 48 +++----- .../fields/__spec__}/test_any.py | 0 .../fields/__spec__}/test_array.py | 0 .../fields/__spec__}/test_boolean.py | 0 .../fields/__spec__}/test_date.py | 0 .../fields/__spec__}/test_datetime.py | 0 .../fields/__spec__}/test_duration.py | 0 .../fields/__spec__}/test_geojson.py | 0 .../fields/__spec__}/test_geopoint.py | 0 .../fields/__spec__}/test_integer.py | 0 .../fields/__spec__}/test_number.py | 0 .../fields/__spec__}/test_object.py | 0 .../fields/__spec__}/test_string.py | 0 .../fields/__spec__}/test_time.py | 0 .../fields/__spec__}/test_year.py | 0 .../fields/__spec__}/test_yearmonth.py | 0 frictionless/formats/csv/__init__.py | 12 +- .../formats/csv/__spec__}/__init__.py | 0 .../formats/csv/__spec__}/test_parser.py | 3 + frictionless/formats/document/__init__.py | 6 +- frictionless/formats/erd/__init__.py | 6 +- .../formats/erd/__spec__}/__init__.py | 0 .../formats/erd/__spec__}/test_mapper.py | 0 frictionless/formats/excel/__init__.py | 19 +-- .../formats/excel/__spec__}/__init__.py | 0 .../formats/excel/__spec__}/test_adapter.py | 0 .../formats/excel/__spec__}/test_control.py | 0 .../formats/excel/__spec__}/test_mapper.py | 0 .../excel/parsers/__spec__}/test_xls.py | 0 .../excel/parsers/__spec__}/test_xlsx.py | 23 +++- frictionless/formats/gsheets/__init__.py | 12 +- .../formats/gsheets/__spec__}/__init__.py | 0 .../formats/gsheets/__spec__}/test_parser.py | 0 frictionless/formats/html/__init__.py | 12 +- .../formats/html/__spec__}/__init__.py | 0 .../formats/html/__spec__}/test_parser.py | 0 frictionless/formats/image/__init__.py | 6 +- frictionless/formats/inline/__init__.py | 12 +- .../formats/inline/__spec__}/__init__.py | 0 .../formats/inline/__spec__}/test_parser.py | 0 frictionless/formats/json/__init__.py | 13 +-- .../formats/json/__spec__}/__init__.py | 0 .../formats/json/__spec__}/test_control.py | 0 .../json/parsers/__spec__}/__init__.py | 0 .../json/parsers/__spec__}/test_json.py | 3 + .../json/parsers/__spec__}/test_jsonl.py | 0 frictionless/formats/jsonschema/__init__.py | 6 +- .../formats/jsonschema/__spec__}/__init__.py | 0 .../jsonschema/__spec__}/test_mapper.py | 0 frictionless/formats/markdown/__init__.py | 9 +- .../formats/markdown/__spec__}/__init__.py | 0 .../formats/markdown/__spec__}/test_mapper.py | 12 +- frictionless/formats/ods/__init__.py | 15 +-- .../formats/ods/__spec__}/__init__.py | 0 .../formats/ods/__spec__}/test_adapter.py | 0 .../formats/ods/__spec__}/test_parser.py | 0 frictionless/formats/pandas/__init__.py | 12 +- .../formats/pandas/__spec__}/__init__.py | 0 .../formats/pandas/__spec__}/test_parser.py | 0 frictionless/formats/parquet/__init__.py | 12 +- .../formats/parquet/__spec__}/__init__.py | 0 .../formats/parquet/__spec__}/test_parser.py | 0 frictionless/formats/python/__init__.py | 6 +- frictionless/formats/qsv/__init__.py | 9 +- frictionless/formats/spss/__init__.py | 12 +- .../formats/spss/__spec__}/__init__.py | 0 .../formats/spss/__spec__}/test_parser.py | 0 frictionless/formats/sql/__init__.py | 18 +-- .../formats/sql/__spec__}/__init__.py | 0 .../formats/sql/__spec__}/conftest.py | 0 .../formats/sql/__spec__/duckdb}/__init__.py | 0 .../sql/__spec__}/duckdb/test_adapter.py | 0 .../sql/__spec__}/duckdb/test_mapper.py | 0 .../sql/__spec__}/duckdb/test_parser.py | 0 .../formats/sql/__spec__/mysql}/__init__.py | 0 .../sql/__spec__}/mysql/test_adapter.py | 0 .../sql/__spec__}/mysql/test_mapper.py | 0 .../sql/__spec__}/mysql/test_parser.py | 0 .../sql/__spec__/postgresql}/__init__.py | 0 .../sql/__spec__}/postgresql/test_adapter.py | 0 .../sql/__spec__}/postgresql/test_mapper.py | 0 .../sql/__spec__}/postgresql/test_parser.py | 0 .../formats/sql/__spec__}/test_adapter.py | 0 .../formats/sql/__spec__}/test_mapper.py | 0 .../formats/sql/__spec__}/test_parser.py | 0 frictionless/formats/sql/adapter.py | 5 +- frictionless/formats/text/__init__.py | 6 +- frictionless/formats/yaml/__init__.py | 12 +- .../formats/yaml/__spec__}/__init__.py | 0 .../formats/yaml/__spec__}/test_parser.py | 0 frictionless/formats/zip/__init__.py | 12 +- .../formats/zip/__spec__}/__init__.py | 0 .../formats/zip/__spec__}/test_adapter.py | 2 + frictionless/formats/zip/adapter.py | 6 +- frictionless/helpers/__init__.py | 1 + .../helpers/__spec__/test_general.py | 0 .../{helpers.py => helpers/general.py} | 6 +- .../indexer/__spec__}/__init__.py | 0 .../indexer/__spec__}/test_resource.py | 9 +- .../inquiry/__spec__}/__init__.py | 0 .../inquiry/__spec__/task}/__init__.py | 0 .../inquiry/__spec__}/task/test_convert.py | 0 .../inquiry/__spec__}/task/test_general.py | 0 .../inquiry/__spec__}/task/test_validate.py | 0 .../inquiry/__spec__}/test_convert.py | 0 .../inquiry/__spec__}/test_general.py | 0 .../inquiry/__spec__}/test_validate.py | 0 frictionless/metadata/__init__.py | 1 + .../metadata/__spec__}/test_metadata.py | 0 frictionless/{ => metadata}/metadata.py | 30 +++-- .../package/__spec__}/__init__.py | 0 .../package/__spec__}/test_compression.py | 0 .../package/__spec__}/test_convert.py | 0 .../package/__spec__}/test_dereference.py | 0 .../package/__spec__}/test_describe.py | 0 .../package/__spec__}/test_extract.py | 0 .../package/__spec__}/test_general.py | 4 + .../package/__spec__}/test_infer.py | 0 .../package/__spec__}/test_onerror.py | 0 .../package/__spec__}/test_profile.py | 5 + .../package/__spec__}/test_resources.py | 0 .../package/__spec__}/test_schema.py | 0 .../package/__spec__}/test_security.py | 3 + frictionless/package/package.py | 5 +- .../pipeline/__spec__}/__init__.py | 0 .../pipeline/__spec__/step}/__init__.py | 0 .../pipeline/__spec__}/step/test_convert.py | 0 .../pipeline/__spec__}/step/test_general.py | 0 .../pipeline/__spec__}/test_convert.py | 0 .../pipeline/__spec__}/test_general.py | 0 .../pipeline/__spec__}/test_validate.py | 0 frictionless/portals/ckan/__init__.py | 12 +- .../portals/ckan/__spec__}/__init__.py | 0 .../portals/ckan/__spec__}/conftest.py | 0 .../portals/ckan/__spec__}/test_adapter.py | 0 frictionless/portals/ckan/adapter.py | 6 +- frictionless/portals/github/__init__.py | 12 +- .../portals/github/__spec__}/__init__.py | 0 .../portals/github/__spec__}/conftest.py | 0 .../portals/github/__spec__}/test_adapter.py | 0 frictionless/portals/github/adapter.py | 5 +- frictionless/portals/zenodo/__init__.py | 12 +- .../portals/zenodo/__spec__}/__init__.py | 0 .../portals/zenodo/__spec__}/conftest.py | 0 .../portals/zenodo/__spec__}/test_adapter.py | 0 frictionless/portals/zenodo/adapter.py | 5 +- .../report/__spec__}/__init__.py | 0 .../report/__spec__/task}/__init__.py | 0 .../report/__spec__}/task/test_convert.py | 0 .../report/__spec__}/task/test_general.py | 0 .../report/__spec__}/test_convert.py | 0 .../report/__spec__}/test_general.py | 0 .../report/__spec__}/test_validate.py | 0 .../resource/__spec__}/__init__.py | 0 .../resource/__spec__}/test_datatype.py | 0 .../resource/__spec__}/test_dereference.py | 3 + .../resource/__spec__}/test_describe.py | 0 .../resource/__spec__}/test_export.py | 0 .../resource/__spec__}/test_extrapaths.py | 0 .../resource/__spec__}/test_format.py | 0 .../resource/__spec__}/test_general.py | 2 + .../resource/__spec__}/test_infer.py | 0 .../resource/__spec__}/test_profile.py | 0 .../resource/__spec__}/test_read.py | 0 .../resource/__spec__}/test_scheme.py | 3 + .../resource/__spec__}/test_security.py | 9 ++ frictionless/resource/factory.py | 4 +- frictionless/resources/__init__.py | 29 ----- .../resources/__spec__}/__init__.py | 0 .../resources/__spec__/file}/__init__.py | 0 .../resources/__spec__}/file/test_read.py | 0 .../resources/__spec__}/file/test_write.py | 0 .../resources/__spec__/json}/__init__.py | 0 .../resources/__spec__}/json/test_read.py | 0 .../resources/__spec__}/json/test_write.py | 0 .../resources/__spec__/table}/__init__.py | 0 .../__spec__}/table/test_compression.py | 0 .../__spec__}/table/test_describe.py | 0 .../__spec__}/table/test_detector.py | 0 .../resources/__spec__}/table/test_dialect.py | 0 .../__spec__}/table/test_encoding.py | 0 .../resources/__spec__}/table/test_export.py | 0 .../resources/__spec__}/table/test_extract.py | 0 .../resources/__spec__}/table/test_general.py | 4 + .../__spec__}/table/test_innerpath.py | 0 .../resources/__spec__}/table/test_onerror.py | 0 .../resources/__spec__}/table/test_open.py | 0 .../resources/__spec__}/table/test_schema.py | 3 + .../__spec__}/table/test_security.py | 3 + .../resources/__spec__}/table/test_stats.py | 6 + .../resources/__spec__}/table/test_write.py | 0 .../resources/__spec__/text}/__init__.py | 0 .../resources/__spec__}/text/test_read.py | 0 .../resources/__spec__}/text/test_write.py | 0 .../schema/__spec__}/__init__.py | 0 .../schema/__spec__/field}/__init__.py | 0 .../__spec__}/field/test_constraints.py | 0 .../schema/__spec__}/field/test_convert.py | 0 .../schema/__spec__}/field/test_custom.py | 0 .../schema/__spec__}/field/test_general.py | 0 .../schema/__spec__}/field/test_read.py | 0 .../schema/__spec__}/test_convert.py | 0 .../schema/__spec__}/test_describe.py | 0 .../schema/__spec__}/test_general.py | 2 + .../schema/__spec__}/test_validate.py | 0 frictionless/schema/field.py | 3 +- frictionless/schema/types.py | 8 +- frictionless/schemes/aws/__init__.py | 12 +- .../schemes/aws/__spec__}/__init__.py | 0 .../schemes/aws/__spec__}/test_control.py | 0 .../schemes/aws/loaders/__spec__}/__init__.py | 0 .../schemes/aws/loaders/__spec__}/test_s3.py | 12 +- frictionless/schemes/buffer/__init__.py | 12 +- .../schemes/buffer/__spec__}/__init__.py | 0 .../schemes/buffer/__spec__}/test_loader.py | 0 frictionless/schemes/local/__init__.py | 12 +- .../schemes/local/__spec__}/__init__.py | 0 .../schemes/local/__spec__}/test_loader.py | 0 frictionless/schemes/multipart/__init__.py | 12 +- .../schemes/multipart/__spec__}/__init__.py | 0 .../multipart/__spec__}/test_loader.py | 3 + frictionless/schemes/remote/__init__.py | 12 +- .../schemes/remote/__spec__}/__init__.py | 0 .../schemes/remote/__spec__}/test_loader.py | 7 ++ frictionless/schemes/stream/__init__.py | 12 +- .../schemes/stream/__spec__}/__init__.py | 0 .../schemes/stream/__spec__}/test_loader.py | 0 frictionless/steps/__init__.py | 44 ------- .../steps/cell/__spec__}/test_cell_convert.py | 0 .../steps/cell/__spec__}/test_cell_fill.py | 0 .../steps/cell/__spec__}/test_cell_format.py | 0 .../cell/__spec__}/test_cell_interpolate.py | 0 .../steps/cell/__spec__}/test_cell_replace.py | 0 .../steps/cell/__spec__}/test_cell_set.py | 0 .../steps/field/__spec__}/test_field_add.py | 0 .../field/__spec__}/test_field_filter.py | 0 .../steps/field/__spec__}/test_field_merge.py | 0 .../steps/field/__spec__}/test_field_move.py | 0 .../steps/field/__spec__}/test_field_pack.py | 0 .../field/__spec__}/test_field_remove.py | 0 .../steps/field/__spec__}/test_field_split.py | 0 .../field/__spec__}/test_field_unpack.py | 0 .../field/__spec__}/test_field_update.py | 0 .../resource/__spec__}/test_resource_add.py | 0 .../__spec__}/test_resource_remove.py | 0 .../__spec__}/test_resource_transform.py | 0 .../__spec__}/test_resource_update.py | 0 .../steps/row/__spec__}/test_row_filter.py | 0 .../steps/row/__spec__}/test_row_search.py | 0 .../steps/row/__spec__}/test_row_slice.py | 0 .../steps/row/__spec__}/test_row_sort.py | 0 .../steps/row/__spec__}/test_row_split.py | 0 .../steps/row/__spec__}/test_row_subset.py | 0 .../steps/row/__spec__}/test_row_ungroup.py | 0 .../table/__spec__}/test_table_aggregate.py | 0 .../table/__spec__}/test_table_attach.py | 0 .../steps/table/__spec__}/test_table_diff.py | 0 .../table/__spec__}/test_table_intersect.py | 0 .../steps/table/__spec__}/test_table_join.py | 0 .../steps/table/__spec__}/test_table_melt.py | 0 .../steps/table/__spec__}/test_table_merge.py | 0 .../steps/table/__spec__}/test_table_pivot.py | 0 .../table/__spec__}/test_table_recast.py | 0 .../table/__spec__}/test_table_transpose.py | 0 .../table/__spec__}/test_table_validate.py | 0 .../steps/table/__spec__}/test_table_write.py | 0 frictionless/steps/table/table_merge.py | 5 +- frictionless/system/__init__.py | 1 + .../system/__spec__}/__init__.py | 0 .../system/__spec__}/test_plugin.py | 0 .../system/__spec__}/test_system.py | 3 + frictionless/system/adapter.py | 2 +- frictionless/{ => system}/models.py | 0 .../table/__spec__}/__init__.py | 0 .../table/__spec__}/test_header.py | 0 .../table/__spec__}/test_row.py | 0 .../transformer/__spec__}/__init__.py | 0 .../__spec__/resource}/__init__.py | 0 .../__spec__}/resource/test_general.py | 0 .../__spec__}/resource/test_pipeline.py | 0 .../transformer/__spec__}/test_package.py | 0 frictionless/types.py | 32 ++--- .../validator/__spec__}/__init__.py | 0 .../validator/__spec__/package}/__init__.py | 0 .../__spec__}/package/test_general.py | 11 +- .../__spec__}/package/test_parallel.py | 0 .../__spec__}/package/test_schema.py | 0 .../validator/__spec__}/package/test_stats.py | 0 .../validator/__spec__/resource}/__init__.py | 0 .../__spec__}/resource/test_checklist.py | 0 .../__spec__}/resource/test_compression.py | 0 .../__spec__}/resource/test_detector.py | 0 .../__spec__}/resource/test_dialect.py | 0 .../__spec__}/resource/test_encoding.py | 0 .../validator/__spec__}/resource/test_file.py | 0 .../__spec__}/resource/test_format.py | 0 .../__spec__}/resource/test_general.py | 10 +- .../__spec__}/resource/test_schema.py | 0 .../__spec__}/resource/test_scheme.py | 0 .../__spec__}/resource/test_stats.py | 0 pyproject.toml | 72 +++++++----- tests/table/__init__.py | 0 tests/test_exception.py | 0 tests/test_interfaces.py | 0 tests/test_settings.py | 0 tests/transformer/__init__.py | 0 tests/transformer/resource/__init__.py | 0 tests/validator/__init__.py | 0 tests/validator/package/__init__.py | 0 tests/validator/resource/__init__.py | 0 368 files changed, 438 insertions(+), 668 deletions(-) delete mode 100644 Makefile rename {tests => frictionless/actions/__spec__}/__init__.py (100%) rename {tests/actions => frictionless/actions/__spec__}/test_describe.py (100%) rename {tests/actions => frictionless/actions/__spec__}/test_extract.py (100%) rename {tests/actions => frictionless/actions/__spec__}/test_list.py (100%) rename {tests/actions => frictionless/actions/__spec__}/test_transform.py (100%) rename {tests/actions => frictionless/actions/__spec__}/test_validate.py (100%) rename {tests/actions => frictionless/analyzer/__spec__}/__init__.py (100%) rename {tests/analyzer => frictionless/analyzer/__spec__}/test_package.py (100%) rename {tests/analyzer => frictionless/analyzer/__spec__}/test_resource.py (98%) rename {tests/analyzer => frictionless/catalog/__spec__}/__init__.py (100%) rename {tests/catalog => frictionless/catalog/__spec__}/test_dereference.py (100%) rename {tests/catalog => frictionless/catalog/__spec__}/test_general.py (100%) rename {tests/catalog => frictionless/catalog/__spec__}/test_infer.py (100%) rename {tests/assets => frictionless/checklist/__spec__}/__init__.py (100%) rename {tests/catalog => frictionless/checklist/__spec__/check}/__init__.py (100%) rename {tests/checklist => frictionless/checklist/__spec__}/check/test_convert.py (100%) rename {tests/checklist => frictionless/checklist/__spec__}/check/test_general.py (100%) rename {tests/checklist => frictionless/checklist/__spec__}/test_convert.py (100%) rename {tests/checklist => frictionless/checklist/__spec__}/test_general.py (100%) rename {tests/checks => frictionless/checks/__spec__}/test_baseline.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_ascii_value.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_deviated_cell.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_deviated_value.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_forbidden_value.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_required_value.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_sequential_value.py (100%) rename {tests/checks/cell => frictionless/checks/cell/__spec__}/test_truncated_value.py (100%) rename {tests/checks/row => frictionless/checks/row/__spec__}/test_duplicate_row.py (100%) rename {tests/checks/row => frictionless/checks/row/__spec__}/test_row_constraint.py (100%) rename {tests/checks/table => frictionless/checks/table/__spec__}/test_table_dimensions.py (100%) rename {tests => frictionless}/conftest.py (96%) rename {tests/checklist => frictionless/console/__spec__}/__init__.py (100%) rename {tests/console => frictionless/console/__spec__}/test_console.py (100%) rename {tests/checklist/check => frictionless/console/commands/__spec__}/__init__.py (100%) rename {tests/console/commands => frictionless/console/commands/__spec__}/test_convert.py (100%) rename {tests/console/commands => frictionless/console/commands/__spec__}/test_describe.py (100%) rename {tests/console/commands => frictionless/console/commands/__spec__}/test_extract.py (100%) rename {tests/console/commands => frictionless/console/commands/__spec__}/test_summary.py (100%) rename {tests/console/commands => frictionless/console/commands/__spec__}/test_transform.py (100%) rename {tests/console/commands => frictionless/console/commands/__spec__}/test_validate.py (100%) rename {tests/console => frictionless/detector/__spec__}/__init__.py (100%) rename {tests/detector => frictionless/detector/__spec__}/test_general.py (100%) rename {tests/console/commands => frictionless/dialect/__spec__}/__init__.py (100%) rename {tests/detector => frictionless/dialect/__spec__/control}/__init__.py (100%) rename {tests/dialect => frictionless/dialect/__spec__}/control/test_general.py (100%) rename {tests/dialect => frictionless/dialect/__spec__}/test_convert.py (100%) rename {tests/dialect => frictionless/dialect/__spec__}/test_describe.py (100%) rename {tests/dialect => frictionless/dialect/__spec__}/test_general.py (100%) rename {tests/dialect => frictionless/error/__spec__}/__init__.py (100%) rename {tests => frictionless/error/__spec__}/test_error.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_any.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_array.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_boolean.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_date.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_datetime.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_duration.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_geojson.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_geopoint.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_integer.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_number.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_object.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_string.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_time.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_year.py (100%) rename {tests/fields => frictionless/fields/__spec__}/test_yearmonth.py (100%) rename {tests/dialect/control => frictionless/formats/csv/__spec__}/__init__.py (100%) rename {tests/formats/csv => frictionless/formats/csv/__spec__}/test_parser.py (99%) rename {tests/errors => frictionless/formats/erd/__spec__}/__init__.py (100%) rename {tests/formats/erd => frictionless/formats/erd/__spec__}/test_mapper.py (100%) rename {tests/formats => frictionless/formats/excel/__spec__}/__init__.py (100%) rename {tests/formats/excel => frictionless/formats/excel/__spec__}/test_adapter.py (100%) rename {tests/formats/excel => frictionless/formats/excel/__spec__}/test_control.py (100%) rename {tests/formats/excel => frictionless/formats/excel/__spec__}/test_mapper.py (100%) rename {tests/formats/excel/parsers => frictionless/formats/excel/parsers/__spec__}/test_xls.py (100%) rename {tests/formats/excel/parsers => frictionless/formats/excel/parsers/__spec__}/test_xlsx.py (95%) rename {tests/formats/csv => frictionless/formats/gsheets/__spec__}/__init__.py (100%) rename {tests/formats/gsheets => frictionless/formats/gsheets/__spec__}/test_parser.py (100%) rename {tests/formats/erd => frictionless/formats/html/__spec__}/__init__.py (100%) rename {tests/formats/html => frictionless/formats/html/__spec__}/test_parser.py (100%) rename {tests/formats/excel => frictionless/formats/inline/__spec__}/__init__.py (100%) rename {tests/formats/inline => frictionless/formats/inline/__spec__}/test_parser.py (100%) rename {tests/formats/gsheets => frictionless/formats/json/__spec__}/__init__.py (100%) rename {tests/formats/json => frictionless/formats/json/__spec__}/test_control.py (100%) rename {tests/formats/html => frictionless/formats/json/parsers/__spec__}/__init__.py (100%) rename {tests/formats/json/parsers => frictionless/formats/json/parsers/__spec__}/test_json.py (96%) rename {tests/formats/json/parsers => frictionless/formats/json/parsers/__spec__}/test_jsonl.py (100%) rename {tests/formats/inline => frictionless/formats/jsonschema/__spec__}/__init__.py (100%) rename {tests/formats/jsonschema => frictionless/formats/jsonschema/__spec__}/test_mapper.py (100%) rename {tests/formats/json => frictionless/formats/markdown/__spec__}/__init__.py (100%) rename {tests/formats/markdown => frictionless/formats/markdown/__spec__}/test_mapper.py (98%) rename {tests/formats/json/parsers => frictionless/formats/ods/__spec__}/__init__.py (100%) rename {tests/formats/ods => frictionless/formats/ods/__spec__}/test_adapter.py (100%) rename {tests/formats/ods => frictionless/formats/ods/__spec__}/test_parser.py (100%) rename {tests/formats/jsonschema => frictionless/formats/pandas/__spec__}/__init__.py (100%) rename {tests/formats/pandas => frictionless/formats/pandas/__spec__}/test_parser.py (100%) rename {tests/formats/markdown => frictionless/formats/parquet/__spec__}/__init__.py (100%) rename {tests/formats/parquet => frictionless/formats/parquet/__spec__}/test_parser.py (100%) rename {tests/formats/ods => frictionless/formats/spss/__spec__}/__init__.py (100%) rename {tests/formats/spss => frictionless/formats/spss/__spec__}/test_parser.py (100%) rename {tests/formats/pandas => frictionless/formats/sql/__spec__}/__init__.py (100%) rename {tests/formats/sql => frictionless/formats/sql/__spec__}/conftest.py (100%) rename {tests/formats/parquet => frictionless/formats/sql/__spec__/duckdb}/__init__.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/duckdb/test_adapter.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/duckdb/test_mapper.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/duckdb/test_parser.py (100%) rename {tests/formats/spss => frictionless/formats/sql/__spec__/mysql}/__init__.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/mysql/test_adapter.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/mysql/test_mapper.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/mysql/test_parser.py (100%) rename {tests/formats/sql => frictionless/formats/sql/__spec__/postgresql}/__init__.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/postgresql/test_adapter.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/postgresql/test_mapper.py (100%) rename {tests/formats/sql/databases => frictionless/formats/sql/__spec__}/postgresql/test_parser.py (100%) rename {tests/formats/sql => frictionless/formats/sql/__spec__}/test_adapter.py (100%) rename {tests/formats/sql => frictionless/formats/sql/__spec__}/test_mapper.py (100%) rename {tests/formats/sql => frictionless/formats/sql/__spec__}/test_parser.py (100%) rename {tests/formats/sql/databases => frictionless/formats/yaml/__spec__}/__init__.py (100%) rename {tests/formats/yaml => frictionless/formats/yaml/__spec__}/test_parser.py (100%) rename {tests/formats/sql/databases/duckdb => frictionless/formats/zip/__spec__}/__init__.py (100%) rename {tests/formats/zip => frictionless/formats/zip/__spec__}/test_adapter.py (98%) create mode 100644 frictionless/helpers/__init__.py rename tests/test_helpers.py => frictionless/helpers/__spec__/test_general.py (100%) rename frictionless/{helpers.py => helpers/general.py} (99%) rename {tests/formats/sql/databases/mysql => frictionless/indexer/__spec__}/__init__.py (100%) rename {tests/indexer => frictionless/indexer/__spec__}/test_resource.py (94%) rename {tests/formats/sql/databases/postgresql => frictionless/inquiry/__spec__}/__init__.py (100%) rename {tests/formats/yaml => frictionless/inquiry/__spec__/task}/__init__.py (100%) rename {tests/inquiry => frictionless/inquiry/__spec__}/task/test_convert.py (100%) rename {tests/inquiry => frictionless/inquiry/__spec__}/task/test_general.py (100%) rename {tests/inquiry => frictionless/inquiry/__spec__}/task/test_validate.py (100%) rename {tests/inquiry => frictionless/inquiry/__spec__}/test_convert.py (100%) rename {tests/inquiry => frictionless/inquiry/__spec__}/test_general.py (100%) rename {tests/inquiry => frictionless/inquiry/__spec__}/test_validate.py (100%) create mode 100644 frictionless/metadata/__init__.py rename {tests => frictionless/metadata/__spec__}/test_metadata.py (100%) rename frictionless/{ => metadata}/metadata.py (97%) rename {tests/formats/zip => frictionless/package/__spec__}/__init__.py (100%) rename {tests/package => frictionless/package/__spec__}/test_compression.py (100%) rename {tests/package => frictionless/package/__spec__}/test_convert.py (100%) rename {tests/package => frictionless/package/__spec__}/test_dereference.py (100%) rename {tests/package => frictionless/package/__spec__}/test_describe.py (100%) rename {tests/package => frictionless/package/__spec__}/test_extract.py (100%) rename {tests/package => frictionless/package/__spec__}/test_general.py (97%) rename {tests/package => frictionless/package/__spec__}/test_infer.py (100%) rename {tests/package => frictionless/package/__spec__}/test_onerror.py (100%) rename {tests/package => frictionless/package/__spec__}/test_profile.py (94%) rename {tests/package => frictionless/package/__spec__}/test_resources.py (100%) rename {tests/package => frictionless/package/__spec__}/test_schema.py (100%) rename {tests/package => frictionless/package/__spec__}/test_security.py (95%) rename {tests/indexer => frictionless/pipeline/__spec__}/__init__.py (100%) rename {tests/inquiry => frictionless/pipeline/__spec__/step}/__init__.py (100%) rename {tests/pipeline => frictionless/pipeline/__spec__}/step/test_convert.py (100%) rename {tests/pipeline => frictionless/pipeline/__spec__}/step/test_general.py (100%) rename {tests/pipeline => frictionless/pipeline/__spec__}/test_convert.py (100%) rename {tests/pipeline => frictionless/pipeline/__spec__}/test_general.py (100%) rename {tests/pipeline => frictionless/pipeline/__spec__}/test_validate.py (100%) rename {tests/inquiry/task => frictionless/portals/ckan/__spec__}/__init__.py (100%) rename {tests/portals/ckan => frictionless/portals/ckan/__spec__}/conftest.py (100%) rename {tests/portals/ckan => frictionless/portals/ckan/__spec__}/test_adapter.py (100%) rename {tests/package => frictionless/portals/github/__spec__}/__init__.py (100%) rename {tests/portals/github => frictionless/portals/github/__spec__}/conftest.py (100%) rename {tests/portals/github => frictionless/portals/github/__spec__}/test_adapter.py (100%) rename {tests/pipeline => frictionless/portals/zenodo/__spec__}/__init__.py (100%) rename {tests/portals/zenodo => frictionless/portals/zenodo/__spec__}/conftest.py (100%) rename {tests/portals/zenodo => frictionless/portals/zenodo/__spec__}/test_adapter.py (100%) rename {tests/pipeline/step => frictionless/report/__spec__}/__init__.py (100%) rename {tests/portals => frictionless/report/__spec__/task}/__init__.py (100%) rename {tests/report => frictionless/report/__spec__}/task/test_convert.py (100%) rename {tests/report => frictionless/report/__spec__}/task/test_general.py (100%) rename {tests/report => frictionless/report/__spec__}/test_convert.py (100%) rename {tests/report => frictionless/report/__spec__}/test_general.py (100%) rename {tests/report => frictionless/report/__spec__}/test_validate.py (100%) rename {tests/portals/ckan => frictionless/resource/__spec__}/__init__.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_datatype.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_dereference.py (96%) rename {tests/resource => frictionless/resource/__spec__}/test_describe.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_export.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_extrapaths.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_format.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_general.py (98%) rename {tests/resource => frictionless/resource/__spec__}/test_infer.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_profile.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_read.py (100%) rename {tests/resource => frictionless/resource/__spec__}/test_scheme.py (96%) rename {tests/resource => frictionless/resource/__spec__}/test_security.py (86%) rename {tests/portals/github => frictionless/resources/__spec__}/__init__.py (100%) rename {tests/portals/zenodo => frictionless/resources/__spec__/file}/__init__.py (100%) rename {tests/resources => frictionless/resources/__spec__}/file/test_read.py (100%) rename {tests/resources => frictionless/resources/__spec__}/file/test_write.py (100%) rename {tests/report => frictionless/resources/__spec__/json}/__init__.py (100%) rename {tests/resources => frictionless/resources/__spec__}/json/test_read.py (100%) rename {tests/resources => frictionless/resources/__spec__}/json/test_write.py (100%) rename {tests/report/task => frictionless/resources/__spec__/table}/__init__.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_compression.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_describe.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_detector.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_dialect.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_encoding.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_export.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_extract.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_general.py (96%) rename {tests/resources => frictionless/resources/__spec__}/table/test_innerpath.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_onerror.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_open.py (100%) rename {tests/resources => frictionless/resources/__spec__}/table/test_schema.py (98%) rename {tests/resources => frictionless/resources/__spec__}/table/test_security.py (91%) rename {tests/resources => frictionless/resources/__spec__}/table/test_stats.py (88%) rename {tests/resources => frictionless/resources/__spec__}/table/test_write.py (100%) rename {tests/resource => frictionless/resources/__spec__/text}/__init__.py (100%) rename {tests/resources => frictionless/resources/__spec__}/text/test_read.py (100%) rename {tests/resources => frictionless/resources/__spec__}/text/test_write.py (100%) rename {tests/resources => frictionless/schema/__spec__}/__init__.py (100%) rename {tests/resources/file => frictionless/schema/__spec__/field}/__init__.py (100%) rename {tests/schema => frictionless/schema/__spec__}/field/test_constraints.py (100%) rename {tests/schema => frictionless/schema/__spec__}/field/test_convert.py (100%) rename {tests/schema => frictionless/schema/__spec__}/field/test_custom.py (100%) rename {tests/schema => frictionless/schema/__spec__}/field/test_general.py (100%) rename {tests/schema => frictionless/schema/__spec__}/field/test_read.py (100%) rename {tests/schema => frictionless/schema/__spec__}/test_convert.py (100%) rename {tests/schema => frictionless/schema/__spec__}/test_describe.py (100%) rename {tests/schema => frictionless/schema/__spec__}/test_general.py (99%) rename {tests/schema => frictionless/schema/__spec__}/test_validate.py (100%) rename {tests/resources/json => frictionless/schemes/aws/__spec__}/__init__.py (100%) rename {tests/schemes/aws => frictionless/schemes/aws/__spec__}/test_control.py (100%) rename {tests/resources/table => frictionless/schemes/aws/loaders/__spec__}/__init__.py (100%) rename {tests/schemes/aws/loaders => frictionless/schemes/aws/loaders/__spec__}/test_s3.py (98%) rename {tests/resources/text => frictionless/schemes/buffer/__spec__}/__init__.py (100%) rename {tests/schemes/buffer => frictionless/schemes/buffer/__spec__}/test_loader.py (100%) rename {tests/schema => frictionless/schemes/local/__spec__}/__init__.py (100%) rename {tests/schemes/local => frictionless/schemes/local/__spec__}/test_loader.py (100%) rename {tests/schema/field => frictionless/schemes/multipart/__spec__}/__init__.py (100%) rename {tests/schemes/multipart => frictionless/schemes/multipart/__spec__}/test_loader.py (96%) rename {tests/schemes => frictionless/schemes/remote/__spec__}/__init__.py (100%) rename {tests/schemes/remote => frictionless/schemes/remote/__spec__}/test_loader.py (85%) rename {tests/schemes/aws => frictionless/schemes/stream/__spec__}/__init__.py (100%) rename {tests/schemes/stream => frictionless/schemes/stream/__spec__}/test_loader.py (100%) rename {tests/steps/cell => frictionless/steps/cell/__spec__}/test_cell_convert.py (100%) rename {tests/steps/cell => frictionless/steps/cell/__spec__}/test_cell_fill.py (100%) rename {tests/steps/cell => frictionless/steps/cell/__spec__}/test_cell_format.py (100%) rename {tests/steps/cell => frictionless/steps/cell/__spec__}/test_cell_interpolate.py (100%) rename {tests/steps/cell => frictionless/steps/cell/__spec__}/test_cell_replace.py (100%) rename {tests/steps/cell => frictionless/steps/cell/__spec__}/test_cell_set.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_add.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_filter.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_merge.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_move.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_pack.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_remove.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_split.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_unpack.py (100%) rename {tests/steps/field => frictionless/steps/field/__spec__}/test_field_update.py (100%) rename {tests/steps/resource => frictionless/steps/resource/__spec__}/test_resource_add.py (100%) rename {tests/steps/resource => frictionless/steps/resource/__spec__}/test_resource_remove.py (100%) rename {tests/steps/resource => frictionless/steps/resource/__spec__}/test_resource_transform.py (100%) rename {tests/steps/resource => frictionless/steps/resource/__spec__}/test_resource_update.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_filter.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_search.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_slice.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_sort.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_split.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_subset.py (100%) rename {tests/steps/row => frictionless/steps/row/__spec__}/test_row_ungroup.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_aggregate.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_attach.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_diff.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_intersect.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_join.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_melt.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_merge.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_pivot.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_recast.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_transpose.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_validate.py (100%) rename {tests/steps/table => frictionless/steps/table/__spec__}/test_table_write.py (100%) rename {tests/schemes/aws/loaders => frictionless/system/__spec__}/__init__.py (100%) rename {tests/system => frictionless/system/__spec__}/test_plugin.py (100%) rename {tests/system => frictionless/system/__spec__}/test_system.py (87%) rename frictionless/{ => system}/models.py (100%) rename {tests/schemes/buffer => frictionless/table/__spec__}/__init__.py (100%) rename {tests/table => frictionless/table/__spec__}/test_header.py (100%) rename {tests/table => frictionless/table/__spec__}/test_row.py (100%) rename {tests/schemes/local => frictionless/transformer/__spec__}/__init__.py (100%) rename {tests/schemes/multipart => frictionless/transformer/__spec__/resource}/__init__.py (100%) rename {tests/transformer => frictionless/transformer/__spec__}/resource/test_general.py (100%) rename {tests/transformer => frictionless/transformer/__spec__}/resource/test_pipeline.py (100%) rename {tests/transformer => frictionless/transformer/__spec__}/test_package.py (100%) rename {tests/schemes/remote => frictionless/validator/__spec__}/__init__.py (100%) rename {tests/schemes/stream => frictionless/validator/__spec__/package}/__init__.py (100%) rename {tests/validator => frictionless/validator/__spec__}/package/test_general.py (98%) rename {tests/validator => frictionless/validator/__spec__}/package/test_parallel.py (100%) rename {tests/validator => frictionless/validator/__spec__}/package/test_schema.py (100%) rename {tests/validator => frictionless/validator/__spec__}/package/test_stats.py (100%) rename {tests/system => frictionless/validator/__spec__/resource}/__init__.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_checklist.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_compression.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_detector.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_dialect.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_encoding.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_file.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_format.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_general.py (99%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_schema.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_scheme.py (100%) rename {tests/validator => frictionless/validator/__spec__}/resource/test_stats.py (100%) delete mode 100644 tests/table/__init__.py delete mode 100644 tests/test_exception.py delete mode 100644 tests/test_interfaces.py delete mode 100644 tests/test_settings.py delete mode 100644 tests/transformer/__init__.py delete mode 100644 tests/transformer/resource/__init__.py delete mode 100644 tests/validator/__init__.py delete mode 100644 tests/validator/package/__init__.py delete mode 100644 tests/validator/resource/__init__.py diff --git a/.github/workflows/general.yaml b/.github/workflows/general.yaml index a44ccc96aa..93a6f0c3e3 100644 --- a/.github/workflows/general.yaml +++ b/.github/workflows/general.yaml @@ -20,12 +20,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # TODO: recover 3.8 and 3.9 when pytest-vcr is fixed - # https://github.com/ktosiek/pytest-vcr/issues/53 - # TODO: recover 3.12 when duck is fixed - # https://github.com/duckdb/duckdb/issues/9563 - # python-version: [3.8, 3.9, "3.10", "3.11", "3.12"] - python-version: ["3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - name: Checkout repository uses: actions/checkout@v4 @@ -76,7 +71,10 @@ jobs: test-macos: if: github.event_name != 'schedule' || github.repository_owner == 'frictionlessdata' - runs-on: macos-latest + # TODO: migrate to macos-latest after figuring out how to + # make `posgres/pg_config` works in the environment. Currently, it fails + # with the following error: "pg_config" not found" + runs-on: macos-12 steps: - name: Checkout repository uses: actions/checkout@v4 @@ -90,7 +88,7 @@ jobs: run: cp .env.example .env - name: Test software # https://stackoverflow.com/questions/9678408/cant-install-psycopg2-with-pip-in-virtualenv-on-mac-os-x-10-7 - run: LDFLAGS=`echo $(pg_config --ldflags)` make test + run: LDFLAGS=`echo $(pg_config --ldflags)` hatch run +py=3.10 ci:test # Test (Windows) @@ -109,7 +107,7 @@ jobs: - name: Prepare variables run: cp .env.example .env - name: Test software - run: make test + run: hatch run +py=3.10 ci:test # Deploy diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac00c6999e..351207ce14 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,12 +49,10 @@ hatch shell Use the following command to build the container: ```bash tabs=CLI -make docker +hatch run image ``` -This should take care of setting up everything. If the container is -built without errors, you can then run commands like `make` inside the -container to accomplish various tasks (see the next section for details). +This should take care of setting up everything. If the container is built without errors, you can then run commands like `hatch` inside the container to accomplish various tasks (see the next section for details). To make things easier, we can create an alias: @@ -65,7 +63,7 @@ alias "frictionless-dev=docker run --rm -v $PWD:/home/frictionless -it frictionl Then, for example, to run the tests, we can use: ```bash tabs=CLI -frictionless-dev make test +frictionless-dev hatch run test ``` ## Development @@ -74,13 +72,11 @@ frictionless-dev make test Frictionless is a Python3.8+ framework, and it uses some common Python tools for the development process (we recommend enabling support of these tools in your IDE): -- code linting: `ruff` -- import sorting: `isort` -- code formatting: `black` +- linting/formatting: `ruff` - type checking: `pyright` - code testing: `pytest` -You also need `git` to work on the project, and `make` is recommended. +You also need `git` to work on the project. ### Documentation @@ -117,33 +113,44 @@ def vcr_config(): - Setup CKAN local instance: https://github.com/okfn/docker-ckan - Create a sysadmin account and generate api token - Set apikey token in .env file + ``` CKAN_APIKEY=*************************** ``` + #### Regenerating cassettes for Zenodo **Read** + - To read, we need to use live site, the api library uses it by default. - Login to zenodo if you have an account and create an access token. - Set access token in .env file. + ``` ZENODO_ACCESS_TOKEN=*************************** ``` + **Write** + - To write we can use either live site or sandbox. We recommend to use sandbox (https://sandbox.zenodo.org/api/). - Login to zenodo(sandbox) if you have an account and create an access token. - Set access token in .env file. + ``` ZENODO_SANDBOX_ACCESS_TOKEN=*************************** ``` + - Set base_url in the control params + ``` base_url='base_url="https://sandbox.zenodo.org/api/' ``` + #### Regenerating cassettes for Github - Login to github if you have an account and create an access token(Developer settings > Personal access tokens > Tokens). - Set access token and other details in .env file. If email/name of the user is hidden we need to provide those details as well. + ``` GITHUB_NAME=FD GITHUB_EMAIL=frictionlessdata@okfn.org @@ -153,8 +160,9 @@ GITHUB_ACCESS_TOKEN=*************************** ## Releasing To release a new version: + - check that you have push access to the `main` branch - run `hatch version ` to update the version - add changes to `CHANGELOG.md` if it's not a patch release (major or minor) -- run `make release` which create a release commit and tag and push it to Github +- run `hatch run release` which create a release commit and tag and push it to Github - an actual release will happen on the Github CI platform after running the tests diff --git a/Makefile b/Makefile deleted file mode 100644 index 3f63cc9955..0000000000 --- a/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -.PHONY: all coverage docker-setup docs install format github lint release test test-ci write - - -PACKAGE := $(shell grep '^name =' pyproject.toml | cut -d '"' -f2) -VERSION := $(shell grep '^VERSION =' ${PACKAGE}/settings.py | cut -d '"' -f2) - - -all: - @grep '^\.PHONY' Makefile | cut -d' ' -f2- | tr ' ' '\n' - -coverage: - hatch run coverage - -docker: - docker build --rm -t frictionless-dev . - -docs: - hatch run docs - -format: - hatch run format - -lint: - hatch run lint - -release: - git checkout main && git pull origin && git fetch -p - @git log --pretty=format:"%C(yellow)%h%Creset %s%Cgreen%d" --reverse -20 - @echo "\nReleasing v$(VERSION) in 10 seconds. Press to abort\n" && sleep 10 - make test && git commit -a -m 'v$(VERSION)' && git tag -a v$(VERSION) -m 'v$(VERSION)' - git push --follow-tags - -test: - hatch run test - -version: - @echo $(VERSION) - -write: - hatch run write diff --git a/frictionless/__init__.py b/frictionless/__init__.py index 15042efd9a..163a0df895 100644 --- a/frictionless/__init__.py +++ b/frictionless/__init__.py @@ -1,68 +1,43 @@ -from .actions import convert, describe, extract, index, list, transform, validate -from .analyzer import Analyzer -from .catalog import Catalog, Dataset -from .checklist import Check, Checklist -from .detector import Detector -from .dialect import Control, Dialect -from .error import Error -from .exception import FrictionlessException -from .indexer import Indexer -from .inquiry import Inquiry, InquiryTask -from .metadata import Metadata -from .package import Package -from .pipeline import Pipeline, Step -from .platform import Platform, platform -from .report import Report, ReportTask -from .resource import Resource -from .schema import Field, Schema +from .actions import convert as convert +from .actions import describe as describe +from .actions import extract as extract +from .actions import list as list +from .actions import transform as transform +from .actions import validate as validate +from .analyzer import Analyzer as Analyzer +from .catalog import Catalog as Catalog +from .catalog import Dataset as Dataset +from .checklist import Check as Check +from .checklist import Checklist as Checklist +from .detector import Detector as Detector +from .dialect import Control as Control +from .dialect import Dialect as Dialect +from .error import Error as Error +from .exception import FrictionlessException as FrictionlessException +from .indexer import Indexer as Indexer +from .inquiry import Inquiry as Inquiry +from .inquiry import InquiryTask as InquiryTask +from .metadata import Metadata as Metadata +from .package import Package as Package +from .pipeline import Pipeline as Pipeline +from .pipeline import Step as Step +from .platform import Platform as Platform +from .platform import platform as platform +from .report import Report as Report +from .report import ReportTask as ReportTask +from .resource import Resource as Resource +from .schema import Field as Field +from .schema import Schema as Schema from .settings import VERSION as __version__ -from .system import Adapter, Loader, Mapper, Parser, Plugin, System, system -from .table import Header, Lookup, Row -from .transformer import Transformer -from .validator import Validator - -__all__ = [ - "Adapter", - "Analyzer", - "Catalog", - "Check", - "Checklist", - "Control", - "Dataset", - "Detector", - "Dialect", - "Error", - "Field", - "FrictionlessException", - "Header", - "Indexer", - "Inquiry", - "InquiryTask", - "Loader", - "Lookup", - "Mapper", - "Metadata", - "Package", - "Parser", - "Pipeline", - "Platform", - "Plugin", - "Report", - "ReportTask", - "Resource", - "Row", - "Schema", - "Step", - "System", - "Transformer", - "Validator", - "convert", - "describe", - "extract", - "index", - "list", - "platform", - "system", - "transform", - "validate", -] +from .system import Adapter as Adapter +from .system import Loader as Loader +from .system import Mapper as Mapper +from .system import Parser as Parser +from .system import Plugin as Plugin +from .system import System as System +from .system import system as system +from .table import Header as Header +from .table import Lookup as Lookup +from .table import Row as Row +from .transformer import Transformer as Transformer +from .validator import Validator as Validator diff --git a/tests/__init__.py b/frictionless/actions/__spec__/__init__.py similarity index 100% rename from tests/__init__.py rename to frictionless/actions/__spec__/__init__.py diff --git a/tests/actions/test_describe.py b/frictionless/actions/__spec__/test_describe.py similarity index 100% rename from tests/actions/test_describe.py rename to frictionless/actions/__spec__/test_describe.py diff --git a/tests/actions/test_extract.py b/frictionless/actions/__spec__/test_extract.py similarity index 100% rename from tests/actions/test_extract.py rename to frictionless/actions/__spec__/test_extract.py diff --git a/tests/actions/test_list.py b/frictionless/actions/__spec__/test_list.py similarity index 100% rename from tests/actions/test_list.py rename to frictionless/actions/__spec__/test_list.py diff --git a/tests/actions/test_transform.py b/frictionless/actions/__spec__/test_transform.py similarity index 100% rename from tests/actions/test_transform.py rename to frictionless/actions/__spec__/test_transform.py diff --git a/tests/actions/test_validate.py b/frictionless/actions/__spec__/test_validate.py similarity index 100% rename from tests/actions/test_validate.py rename to frictionless/actions/__spec__/test_validate.py diff --git a/tests/actions/__init__.py b/frictionless/analyzer/__spec__/__init__.py similarity index 100% rename from tests/actions/__init__.py rename to frictionless/analyzer/__spec__/__init__.py diff --git a/tests/analyzer/test_package.py b/frictionless/analyzer/__spec__/test_package.py similarity index 100% rename from tests/analyzer/test_package.py rename to frictionless/analyzer/__spec__/test_package.py diff --git a/tests/analyzer/test_resource.py b/frictionless/analyzer/__spec__/test_resource.py similarity index 98% rename from tests/analyzer/test_resource.py rename to frictionless/analyzer/__spec__/test_resource.py index 53da72cc12..fae992dfc2 100644 --- a/tests/analyzer/test_resource.py +++ b/frictionless/analyzer/__spec__/test_resource.py @@ -134,6 +134,10 @@ def test_analyze_resource_detailed_descriptive_statistics_with_outliers(): assert analysis["fieldStats"]["average_grades"]["outliers"] == [10000.0] +@pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="Fix for Python3.12+ (possible bug to investigate)", +) def test_analyze_resource_detailed_descriptive_statistics_variables_correlation(): resource = TableResource(path="data/analysis-data.csv") analysis = resource.analyze(detailed=True) diff --git a/frictionless/analyzer/analyzer.py b/frictionless/analyzer/analyzer.py index f015e70cd8..f28c8ccdd6 100644 --- a/frictionless/analyzer/analyzer.py +++ b/frictionless/analyzer/analyzer.py @@ -84,7 +84,9 @@ def analyze_table_resource( _statistics(rows_without_nan_values) # type: ignore ) analysis_report["fieldStats"][field.name]["outliers"] = [] - analysis_report["fieldStats"][field.name]["missingValues"] = resource.stats.rows - len(rows_without_nan_values) # type: ignore + analysis_report["fieldStats"][field.name]["missingValues"] = ( + resource.stats.rows - len(rows_without_nan_values) # type: ignore + ) # calculate correlation between variables(columns/fields) for field_y in resource.schema.fields: @@ -123,10 +125,14 @@ def analyze_table_resource( "outliers" ].append(cell) - analysis_report["notNullRows"] = resource.stats.rows - analysis_report["rowsWithNullValues"] # type: ignore + analysis_report["notNullRows"] = ( # type: ignore + resource.stats.rows - analysis_report["rowsWithNullValues"] # type: ignore + ) analysis_report["averageRecordSizeInBytes"] = 0 if resource.stats.rows and resource.stats.bytes: - analysis_report["averageRecordSizeInBytes"] = resource.stats.bytes / resource.stats.rows # type: ignore + analysis_report["averageRecordSizeInBytes"] = ( + resource.stats.bytes / resource.stats.rows + ) # type: ignore analysis_report["timeTaken"] = timer.time return { **analysis_report, diff --git a/tests/analyzer/__init__.py b/frictionless/catalog/__spec__/__init__.py similarity index 100% rename from tests/analyzer/__init__.py rename to frictionless/catalog/__spec__/__init__.py diff --git a/tests/catalog/test_dereference.py b/frictionless/catalog/__spec__/test_dereference.py similarity index 100% rename from tests/catalog/test_dereference.py rename to frictionless/catalog/__spec__/test_dereference.py diff --git a/tests/catalog/test_general.py b/frictionless/catalog/__spec__/test_general.py similarity index 100% rename from tests/catalog/test_general.py rename to frictionless/catalog/__spec__/test_general.py diff --git a/tests/catalog/test_infer.py b/frictionless/catalog/__spec__/test_infer.py similarity index 100% rename from tests/catalog/test_infer.py rename to frictionless/catalog/__spec__/test_infer.py diff --git a/tests/assets/__init__.py b/frictionless/checklist/__spec__/__init__.py similarity index 100% rename from tests/assets/__init__.py rename to frictionless/checklist/__spec__/__init__.py diff --git a/tests/catalog/__init__.py b/frictionless/checklist/__spec__/check/__init__.py similarity index 100% rename from tests/catalog/__init__.py rename to frictionless/checklist/__spec__/check/__init__.py diff --git a/tests/checklist/check/test_convert.py b/frictionless/checklist/__spec__/check/test_convert.py similarity index 100% rename from tests/checklist/check/test_convert.py rename to frictionless/checklist/__spec__/check/test_convert.py diff --git a/tests/checklist/check/test_general.py b/frictionless/checklist/__spec__/check/test_general.py similarity index 100% rename from tests/checklist/check/test_general.py rename to frictionless/checklist/__spec__/check/test_general.py diff --git a/tests/checklist/test_convert.py b/frictionless/checklist/__spec__/test_convert.py similarity index 100% rename from tests/checklist/test_convert.py rename to frictionless/checklist/__spec__/test_convert.py diff --git a/tests/checklist/test_general.py b/frictionless/checklist/__spec__/test_general.py similarity index 100% rename from tests/checklist/test_general.py rename to frictionless/checklist/__spec__/test_general.py diff --git a/frictionless/checks/__init__.py b/frictionless/checks/__init__.py index 5d7c4a0e79..e0450b8100 100644 --- a/frictionless/checks/__init__.py +++ b/frictionless/checks/__init__.py @@ -1,18 +1,4 @@ -from .baseline import baseline +from .baseline import baseline as baseline from .cell import * from .row import * from .table import * - -__all__ = [ - "ascii_value", - "baseline", - "deviated_cell", - "deviated_value", - "duplicate_row", - "forbidden_value", - "required_value", - "row_constraint", - "sequential_value", - "table_dimensions", - "truncated_value", -] diff --git a/tests/checks/test_baseline.py b/frictionless/checks/__spec__/test_baseline.py similarity index 100% rename from tests/checks/test_baseline.py rename to frictionless/checks/__spec__/test_baseline.py diff --git a/tests/checks/cell/test_ascii_value.py b/frictionless/checks/cell/__spec__/test_ascii_value.py similarity index 100% rename from tests/checks/cell/test_ascii_value.py rename to frictionless/checks/cell/__spec__/test_ascii_value.py diff --git a/tests/checks/cell/test_deviated_cell.py b/frictionless/checks/cell/__spec__/test_deviated_cell.py similarity index 100% rename from tests/checks/cell/test_deviated_cell.py rename to frictionless/checks/cell/__spec__/test_deviated_cell.py diff --git a/tests/checks/cell/test_deviated_value.py b/frictionless/checks/cell/__spec__/test_deviated_value.py similarity index 100% rename from tests/checks/cell/test_deviated_value.py rename to frictionless/checks/cell/__spec__/test_deviated_value.py diff --git a/tests/checks/cell/test_forbidden_value.py b/frictionless/checks/cell/__spec__/test_forbidden_value.py similarity index 100% rename from tests/checks/cell/test_forbidden_value.py rename to frictionless/checks/cell/__spec__/test_forbidden_value.py diff --git a/tests/checks/cell/test_required_value.py b/frictionless/checks/cell/__spec__/test_required_value.py similarity index 100% rename from tests/checks/cell/test_required_value.py rename to frictionless/checks/cell/__spec__/test_required_value.py diff --git a/tests/checks/cell/test_sequential_value.py b/frictionless/checks/cell/__spec__/test_sequential_value.py similarity index 100% rename from tests/checks/cell/test_sequential_value.py rename to frictionless/checks/cell/__spec__/test_sequential_value.py diff --git a/tests/checks/cell/test_truncated_value.py b/frictionless/checks/cell/__spec__/test_truncated_value.py similarity index 100% rename from tests/checks/cell/test_truncated_value.py rename to frictionless/checks/cell/__spec__/test_truncated_value.py diff --git a/tests/checks/row/test_duplicate_row.py b/frictionless/checks/row/__spec__/test_duplicate_row.py similarity index 100% rename from tests/checks/row/test_duplicate_row.py rename to frictionless/checks/row/__spec__/test_duplicate_row.py diff --git a/tests/checks/row/test_row_constraint.py b/frictionless/checks/row/__spec__/test_row_constraint.py similarity index 100% rename from tests/checks/row/test_row_constraint.py rename to frictionless/checks/row/__spec__/test_row_constraint.py diff --git a/tests/checks/table/test_table_dimensions.py b/frictionless/checks/table/__spec__/test_table_dimensions.py similarity index 100% rename from tests/checks/table/test_table_dimensions.py rename to frictionless/checks/table/__spec__/test_table_dimensions.py diff --git a/tests/conftest.py b/frictionless/conftest.py similarity index 96% rename from tests/conftest.py rename to frictionless/conftest.py index 1546e8b029..18ea81a3bb 100644 --- a/tests/conftest.py +++ b/frictionless/conftest.py @@ -129,7 +129,9 @@ def vcr_cassette_dir(request): def populate_db(engine): with engine.begin() as conn: conn.execute(sa.text('CREATE TABLE "table" (id INTEGER PRIMARY KEY, name TEXT)')) - conn.execute(sa.text("INSERT INTO \"table\" VALUES (1, 'english'), (2, '中国人')")) + conn.execute( + sa.text("INSERT INTO \"table\" VALUES (1, 'english'), (2, '中国人')") + ) conn.execute( sa.text( "CREATE TABLE fruits (uid INTEGER PRIMARY KEY, fruit_name TEXT, calories INTEGER)" diff --git a/tests/checklist/__init__.py b/frictionless/console/__spec__/__init__.py similarity index 100% rename from tests/checklist/__init__.py rename to frictionless/console/__spec__/__init__.py diff --git a/tests/console/test_console.py b/frictionless/console/__spec__/test_console.py similarity index 100% rename from tests/console/test_console.py rename to frictionless/console/__spec__/test_console.py diff --git a/frictionless/console/commands/__init__.py b/frictionless/console/commands/__init__.py index d4fdd275e4..e04ca4042a 100644 --- a/frictionless/console/commands/__init__.py +++ b/frictionless/console/commands/__init__.py @@ -1,3 +1,16 @@ # Register modules -from . import convert, describe, explore, extract, index, inspect, list, publish, query -from . import script, summary, transform, validate +from . import ( + convert, + describe, + explore, + extract, + index, + inspect, + list, + publish, + query, + script, + summary, + transform, + validate, +) diff --git a/tests/checklist/check/__init__.py b/frictionless/console/commands/__spec__/__init__.py similarity index 100% rename from tests/checklist/check/__init__.py rename to frictionless/console/commands/__spec__/__init__.py diff --git a/tests/console/commands/test_convert.py b/frictionless/console/commands/__spec__/test_convert.py similarity index 100% rename from tests/console/commands/test_convert.py rename to frictionless/console/commands/__spec__/test_convert.py diff --git a/tests/console/commands/test_describe.py b/frictionless/console/commands/__spec__/test_describe.py similarity index 100% rename from tests/console/commands/test_describe.py rename to frictionless/console/commands/__spec__/test_describe.py diff --git a/tests/console/commands/test_extract.py b/frictionless/console/commands/__spec__/test_extract.py similarity index 100% rename from tests/console/commands/test_extract.py rename to frictionless/console/commands/__spec__/test_extract.py diff --git a/tests/console/commands/test_summary.py b/frictionless/console/commands/__spec__/test_summary.py similarity index 100% rename from tests/console/commands/test_summary.py rename to frictionless/console/commands/__spec__/test_summary.py diff --git a/tests/console/commands/test_transform.py b/frictionless/console/commands/__spec__/test_transform.py similarity index 100% rename from tests/console/commands/test_transform.py rename to frictionless/console/commands/__spec__/test_transform.py diff --git a/tests/console/commands/test_validate.py b/frictionless/console/commands/__spec__/test_validate.py similarity index 100% rename from tests/console/commands/test_validate.py rename to frictionless/console/commands/__spec__/test_validate.py diff --git a/tests/console/__init__.py b/frictionless/detector/__spec__/__init__.py similarity index 100% rename from tests/console/__init__.py rename to frictionless/detector/__spec__/__init__.py diff --git a/tests/detector/test_general.py b/frictionless/detector/__spec__/test_general.py similarity index 100% rename from tests/detector/test_general.py rename to frictionless/detector/__spec__/test_general.py diff --git a/tests/console/commands/__init__.py b/frictionless/dialect/__spec__/__init__.py similarity index 100% rename from tests/console/commands/__init__.py rename to frictionless/dialect/__spec__/__init__.py diff --git a/tests/detector/__init__.py b/frictionless/dialect/__spec__/control/__init__.py similarity index 100% rename from tests/detector/__init__.py rename to frictionless/dialect/__spec__/control/__init__.py diff --git a/tests/dialect/control/test_general.py b/frictionless/dialect/__spec__/control/test_general.py similarity index 100% rename from tests/dialect/control/test_general.py rename to frictionless/dialect/__spec__/control/test_general.py diff --git a/tests/dialect/test_convert.py b/frictionless/dialect/__spec__/test_convert.py similarity index 100% rename from tests/dialect/test_convert.py rename to frictionless/dialect/__spec__/test_convert.py diff --git a/tests/dialect/test_describe.py b/frictionless/dialect/__spec__/test_describe.py similarity index 100% rename from tests/dialect/test_describe.py rename to frictionless/dialect/__spec__/test_describe.py diff --git a/tests/dialect/test_general.py b/frictionless/dialect/__spec__/test_general.py similarity index 100% rename from tests/dialect/test_general.py rename to frictionless/dialect/__spec__/test_general.py diff --git a/tests/dialect/__init__.py b/frictionless/error/__spec__/__init__.py similarity index 100% rename from tests/dialect/__init__.py rename to frictionless/error/__spec__/__init__.py diff --git a/tests/test_error.py b/frictionless/error/__spec__/test_error.py similarity index 100% rename from tests/test_error.py rename to frictionless/error/__spec__/test_error.py diff --git a/frictionless/errors/__init__.py b/frictionless/errors/__init__.py index 07d7c5691e..6dcc50c98a 100644 --- a/frictionless/errors/__init__.py +++ b/frictionless/errors/__init__.py @@ -7,65 +7,3 @@ from .resource import * from .row import * from .table import * - -__all__ = [ - "AsciiValueError", - "BlankHeaderError", - "BlankLabelError", - "BlankRowError", - "ByteCountError", - "CatalogError", - "CellError", - "CheckError", - "ChecklistError", - "CompressionError", - "ConstraintError", - "ControlError", - "DataError", - "DatasetError", - "DetectorError", - "DeviatedCellError", - "DeviatedValueError", - "DialectError", - "DuplicateLabelError", - "DuplicateRowError", - "EncodingError", - "ExtraCellError", - "ExtraLabelError", - "FieldCountError", - "FieldError", - "FileError", - "ForbiddenValueError", - "ForeignKeyError", - "FormatError", - "HashCountError", - "HeaderError", - "IncorrectLabelError", - "InquiryError", - "InquiryTaskError", - "LabelError", - "MetadataError", - "MissingCellError", - "MissingLabelError", - "PackageError", - "PipelineError", - "PrimaryKeyError", - "ReportError", - "ReportTaskError", - "RequiredValueError", - "ResourceError", - "RowConstraintError", - "RowCountError", - "RowError", - "SchemaError", - "SchemeError", - "SequentialValueError", - "SourceError", - "StatsError", - "StepError", - "TableDimensionsError", - "TableError", - "TruncatedValueError", - "TypeError", - "UniqueError", -] diff --git a/frictionless/fields/__init__.py b/frictionless/fields/__init__.py index baed0dd442..550d07b079 100644 --- a/frictionless/fields/__init__.py +++ b/frictionless/fields/__init__.py @@ -1,33 +1,15 @@ -from .any import AnyField -from .array import ArrayField -from .boolean import BooleanField -from .date import DateField -from .datetime import DatetimeField -from .duration import DurationField -from .geojson import GeojsonField -from .geopoint import GeopointField -from .integer import IntegerField -from .number import NumberField -from .object import ObjectField -from .string import StringField -from .time import TimeField -from .year import YearField -from .yearmonth import YearmonthField - -__all__ = [ - "AnyField" - "ArrayField" - "BooleanField" - "DateField" - "DatetimeField" - "DurationField" - "GeojsonField" - "GeopointField" - "IntegerField" - "NumberField" - "ObjectField" - "StringField" - "TimeField" - "YearField" - "YearmonthField" -] +from .any import AnyField as AnyField +from .array import ArrayField as ArrayField +from .boolean import BooleanField as BooleanField +from .date import DateField as DateField +from .datetime import DatetimeField as DatetimeField +from .duration import DurationField as DurationField +from .geojson import GeojsonField as GeojsonField +from .geopoint import GeopointField as GeopointField +from .integer import IntegerField as IntegerField +from .number import NumberField as NumberField +from .object import ObjectField as ObjectField +from .string import StringField as StringField +from .time import TimeField as TimeField +from .year import YearField as YearField +from .yearmonth import YearmonthField as YearmonthField diff --git a/tests/fields/test_any.py b/frictionless/fields/__spec__/test_any.py similarity index 100% rename from tests/fields/test_any.py rename to frictionless/fields/__spec__/test_any.py diff --git a/tests/fields/test_array.py b/frictionless/fields/__spec__/test_array.py similarity index 100% rename from tests/fields/test_array.py rename to frictionless/fields/__spec__/test_array.py diff --git a/tests/fields/test_boolean.py b/frictionless/fields/__spec__/test_boolean.py similarity index 100% rename from tests/fields/test_boolean.py rename to frictionless/fields/__spec__/test_boolean.py diff --git a/tests/fields/test_date.py b/frictionless/fields/__spec__/test_date.py similarity index 100% rename from tests/fields/test_date.py rename to frictionless/fields/__spec__/test_date.py diff --git a/tests/fields/test_datetime.py b/frictionless/fields/__spec__/test_datetime.py similarity index 100% rename from tests/fields/test_datetime.py rename to frictionless/fields/__spec__/test_datetime.py diff --git a/tests/fields/test_duration.py b/frictionless/fields/__spec__/test_duration.py similarity index 100% rename from tests/fields/test_duration.py rename to frictionless/fields/__spec__/test_duration.py diff --git a/tests/fields/test_geojson.py b/frictionless/fields/__spec__/test_geojson.py similarity index 100% rename from tests/fields/test_geojson.py rename to frictionless/fields/__spec__/test_geojson.py diff --git a/tests/fields/test_geopoint.py b/frictionless/fields/__spec__/test_geopoint.py similarity index 100% rename from tests/fields/test_geopoint.py rename to frictionless/fields/__spec__/test_geopoint.py diff --git a/tests/fields/test_integer.py b/frictionless/fields/__spec__/test_integer.py similarity index 100% rename from tests/fields/test_integer.py rename to frictionless/fields/__spec__/test_integer.py diff --git a/tests/fields/test_number.py b/frictionless/fields/__spec__/test_number.py similarity index 100% rename from tests/fields/test_number.py rename to frictionless/fields/__spec__/test_number.py diff --git a/tests/fields/test_object.py b/frictionless/fields/__spec__/test_object.py similarity index 100% rename from tests/fields/test_object.py rename to frictionless/fields/__spec__/test_object.py diff --git a/tests/fields/test_string.py b/frictionless/fields/__spec__/test_string.py similarity index 100% rename from tests/fields/test_string.py rename to frictionless/fields/__spec__/test_string.py diff --git a/tests/fields/test_time.py b/frictionless/fields/__spec__/test_time.py similarity index 100% rename from tests/fields/test_time.py rename to frictionless/fields/__spec__/test_time.py diff --git a/tests/fields/test_year.py b/frictionless/fields/__spec__/test_year.py similarity index 100% rename from tests/fields/test_year.py rename to frictionless/fields/__spec__/test_year.py diff --git a/tests/fields/test_yearmonth.py b/frictionless/fields/__spec__/test_yearmonth.py similarity index 100% rename from tests/fields/test_yearmonth.py rename to frictionless/fields/__spec__/test_yearmonth.py diff --git a/frictionless/formats/csv/__init__.py b/frictionless/formats/csv/__init__.py index 52cfee3681..6d141ceaec 100644 --- a/frictionless/formats/csv/__init__.py +++ b/frictionless/formats/csv/__init__.py @@ -1,9 +1,3 @@ -from .control import CsvControl -from .parser import CsvParser -from .plugin import CsvPlugin - -__all__ = [ - "CsvControl", - "CsvParser", - "CsvPlugin", -] +from .control import CsvControl as CsvControl +from .parser import CsvParser as CsvParser +from .plugin import CsvPlugin as CsvPlugin diff --git a/tests/dialect/control/__init__.py b/frictionless/formats/csv/__spec__/__init__.py similarity index 100% rename from tests/dialect/control/__init__.py rename to frictionless/formats/csv/__spec__/__init__.py diff --git a/tests/formats/csv/test_parser.py b/frictionless/formats/csv/__spec__/test_parser.py similarity index 99% rename from tests/formats/csv/test_parser.py rename to frictionless/formats/csv/__spec__/test_parser.py index 2bf4bca368..3a17427091 100644 --- a/tests/formats/csv/test_parser.py +++ b/frictionless/formats/csv/__spec__/test_parser.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import Detector, Dialect, formats, platform @@ -106,6 +108,7 @@ def test_csv_parser_buffer(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_csv_parser_remote(): with TableResource(path=BASEURL % "data/table.csv") as resource: assert resource.header == ["id", "name"] diff --git a/frictionless/formats/document/__init__.py b/frictionless/formats/document/__init__.py index f94f3e65d1..60325767f5 100644 --- a/frictionless/formats/document/__init__.py +++ b/frictionless/formats/document/__init__.py @@ -1,5 +1 @@ -from .plugin import DocumentPlugin - -__all__ = [ - "DocumentPlugin", -] +from .plugin import DocumentPlugin as DocumentPlugin diff --git a/frictionless/formats/erd/__init__.py b/frictionless/formats/erd/__init__.py index 4ce657bb0d..2fd025d6ed 100644 --- a/frictionless/formats/erd/__init__.py +++ b/frictionless/formats/erd/__init__.py @@ -1,5 +1 @@ -from .mapper import ErdMapper - -__all__ = [ - "ErdMapper", -] +from .mapper import ErdMapper as ErdMapper diff --git a/tests/errors/__init__.py b/frictionless/formats/erd/__spec__/__init__.py similarity index 100% rename from tests/errors/__init__.py rename to frictionless/formats/erd/__spec__/__init__.py diff --git a/tests/formats/erd/test_mapper.py b/frictionless/formats/erd/__spec__/test_mapper.py similarity index 100% rename from tests/formats/erd/test_mapper.py rename to frictionless/formats/erd/__spec__/test_mapper.py diff --git a/frictionless/formats/excel/__init__.py b/frictionless/formats/excel/__init__.py index 756e96fc22..9430a9e8a2 100644 --- a/frictionless/formats/excel/__init__.py +++ b/frictionless/formats/excel/__init__.py @@ -1,14 +1,5 @@ -from .adapter import ExcelAdapter -from .control import ExcelControl -from .mapper import ExcelMapper -from .parsers import XlsParser, XlsxParser -from .plugin import ExcelPlugin - -__all__ = [ - "ExcelAdapter", - "ExcelControl", - "ExcelMapper", - "ExcelPlugin", - "XlsParser", - "XlsxParser", -] +from .adapter import ExcelAdapter as ExcelAdapter +from .control import ExcelControl as ExcelControl +from .mapper import ExcelMapper as ExcelMapper +from .parsers import * +from .plugin import ExcelPlugin as ExcelPlugin diff --git a/tests/formats/__init__.py b/frictionless/formats/excel/__spec__/__init__.py similarity index 100% rename from tests/formats/__init__.py rename to frictionless/formats/excel/__spec__/__init__.py diff --git a/tests/formats/excel/test_adapter.py b/frictionless/formats/excel/__spec__/test_adapter.py similarity index 100% rename from tests/formats/excel/test_adapter.py rename to frictionless/formats/excel/__spec__/test_adapter.py diff --git a/tests/formats/excel/test_control.py b/frictionless/formats/excel/__spec__/test_control.py similarity index 100% rename from tests/formats/excel/test_control.py rename to frictionless/formats/excel/__spec__/test_control.py diff --git a/tests/formats/excel/test_mapper.py b/frictionless/formats/excel/__spec__/test_mapper.py similarity index 100% rename from tests/formats/excel/test_mapper.py rename to frictionless/formats/excel/__spec__/test_mapper.py diff --git a/tests/formats/excel/parsers/test_xls.py b/frictionless/formats/excel/parsers/__spec__/test_xls.py similarity index 100% rename from tests/formats/excel/parsers/test_xls.py rename to frictionless/formats/excel/parsers/__spec__/test_xls.py diff --git a/tests/formats/excel/parsers/test_xlsx.py b/frictionless/formats/excel/parsers/__spec__/test_xlsx.py similarity index 95% rename from tests/formats/excel/parsers/test_xlsx.py rename to frictionless/formats/excel/parsers/__spec__/test_xlsx.py index 2deb051e7f..0f250c1dc5 100644 --- a/tests/formats/excel/parsers/test_xlsx.py +++ b/frictionless/formats/excel/parsers/__spec__/test_xlsx.py @@ -1,10 +1,17 @@ import io +import sys from decimal import Decimal import pytest -from frictionless import Detector, Dialect, FrictionlessException, Package, formats -from frictionless import platform +from frictionless import ( + Detector, + Dialect, + FrictionlessException, + Package, + formats, + platform, +) from frictionless.resources import TableResource BASEURL = "https://raw.githubusercontent.com/frictionlessdata/frictionless-py/master/%s" @@ -24,6 +31,10 @@ def test_xlsx_parser_table(): @pytest.mark.vcr +@pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="Fix for Python3.12+ (possible bug to investigate)", +) def test_xlsx_parser_remote(): path = BASEURL % "data/table.xlsx" with TableResource(path=path) as resource: @@ -166,6 +177,10 @@ def test_xlsx_parser_preserve_formatting_number_multicode(): @pytest.mark.vcr +@pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="Fix for Python3.12+ (possible bug to investigate)", +) def test_xlsx_parser_workbook_cache(): path = BASEURL % "data/sheets.xlsx" for sheet in ["Sheet1", "Sheet2", "Sheet3"]: @@ -201,6 +216,10 @@ def test_xlsx_parser_merged_cells_fill_boolean(): @pytest.mark.vcr +@pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="Fix for Python3.12+ (possible bug to investigate)", +) def test_xlsx_parser_fix_for_2007_xls(): path = "https://ams3.digitaloceanspaces.com/budgetkey-files/spending-reports/2018-3-משרד התרבות והספורט-לשכת הפרסום הממשלתית-2018-10-22-c457.xls" with TableResource(path=path, format="xlsx") as resource: diff --git a/frictionless/formats/gsheets/__init__.py b/frictionless/formats/gsheets/__init__.py index c69c10dd9c..21145f115a 100644 --- a/frictionless/formats/gsheets/__init__.py +++ b/frictionless/formats/gsheets/__init__.py @@ -1,9 +1,3 @@ -from .control import GsheetsControl -from .parser import GsheetsParser -from .plugin import GsheetsPlugin - -__all__ = [ - "GsheetsControl", - "GsheetsParser", - "GsheetsPlugin", -] +from .control import GsheetsControl as GsheetsControl +from .parser import GsheetsParser as GsheetsParser +from .plugin import GsheetsPlugin as GsheetsPlugin diff --git a/tests/formats/csv/__init__.py b/frictionless/formats/gsheets/__spec__/__init__.py similarity index 100% rename from tests/formats/csv/__init__.py rename to frictionless/formats/gsheets/__spec__/__init__.py diff --git a/tests/formats/gsheets/test_parser.py b/frictionless/formats/gsheets/__spec__/test_parser.py similarity index 100% rename from tests/formats/gsheets/test_parser.py rename to frictionless/formats/gsheets/__spec__/test_parser.py diff --git a/frictionless/formats/html/__init__.py b/frictionless/formats/html/__init__.py index e5083d06ea..3e29c9b1e6 100644 --- a/frictionless/formats/html/__init__.py +++ b/frictionless/formats/html/__init__.py @@ -1,9 +1,3 @@ -from .control import HtmlControl -from .parser import HtmlParser -from .plugin import HtmlPlugin - -__all__ = [ - "HtmlControl", - "HtmlParser", - "HtmlPlugin", -] +from .control import HtmlControl as HtmlControl +from .parser import HtmlParser as HtmlParser +from .plugin import HtmlPlugin as HtmlPlugin diff --git a/tests/formats/erd/__init__.py b/frictionless/formats/html/__spec__/__init__.py similarity index 100% rename from tests/formats/erd/__init__.py rename to frictionless/formats/html/__spec__/__init__.py diff --git a/tests/formats/html/test_parser.py b/frictionless/formats/html/__spec__/test_parser.py similarity index 100% rename from tests/formats/html/test_parser.py rename to frictionless/formats/html/__spec__/test_parser.py diff --git a/frictionless/formats/image/__init__.py b/frictionless/formats/image/__init__.py index b45fa8323d..267489951c 100644 --- a/frictionless/formats/image/__init__.py +++ b/frictionless/formats/image/__init__.py @@ -1,5 +1 @@ -from .plugin import ImagePlugin - -__all__ = [ - "ImagePlugin", -] +from .plugin import ImagePlugin as ImagePlugin diff --git a/frictionless/formats/inline/__init__.py b/frictionless/formats/inline/__init__.py index 3e24fbdd68..62e44f93fe 100644 --- a/frictionless/formats/inline/__init__.py +++ b/frictionless/formats/inline/__init__.py @@ -1,9 +1,3 @@ -from .control import InlineControl -from .parser import InlineParser -from .plugin import InlinePlugin - -__all__ = [ - "InlineControl", - "InlineParser", - "InlinePlugin", -] +from .control import InlineControl as InlineControl +from .parser import InlineParser as InlineParser +from .plugin import InlinePlugin as InlinePlugin diff --git a/tests/formats/excel/__init__.py b/frictionless/formats/inline/__spec__/__init__.py similarity index 100% rename from tests/formats/excel/__init__.py rename to frictionless/formats/inline/__spec__/__init__.py diff --git a/tests/formats/inline/test_parser.py b/frictionless/formats/inline/__spec__/test_parser.py similarity index 100% rename from tests/formats/inline/test_parser.py rename to frictionless/formats/inline/__spec__/test_parser.py diff --git a/frictionless/formats/json/__init__.py b/frictionless/formats/json/__init__.py index f5eff620dc..4c262ff8f7 100644 --- a/frictionless/formats/json/__init__.py +++ b/frictionless/formats/json/__init__.py @@ -1,10 +1,3 @@ -from .control import JsonControl -from .parsers import JsonlParser, JsonParser -from .plugin import JsonPlugin - -__all__ = [ - "JsonControl", - "JsonParser", - "JsonPlugin", - "JsonlParser", -] +from .control import JsonControl as JsonControl +from .parsers import * +from .plugin import JsonPlugin as JsonPlugin diff --git a/tests/formats/gsheets/__init__.py b/frictionless/formats/json/__spec__/__init__.py similarity index 100% rename from tests/formats/gsheets/__init__.py rename to frictionless/formats/json/__spec__/__init__.py diff --git a/tests/formats/json/test_control.py b/frictionless/formats/json/__spec__/test_control.py similarity index 100% rename from tests/formats/json/test_control.py rename to frictionless/formats/json/__spec__/test_control.py diff --git a/tests/formats/html/__init__.py b/frictionless/formats/json/parsers/__spec__/__init__.py similarity index 100% rename from tests/formats/html/__init__.py rename to frictionless/formats/json/parsers/__spec__/__init__.py diff --git a/tests/formats/json/parsers/test_json.py b/frictionless/formats/json/parsers/__spec__/test_json.py similarity index 96% rename from tests/formats/json/parsers/test_json.py rename to frictionless/formats/json/parsers/__spec__/test_json.py index 12a49af9a6..cf473ca415 100644 --- a/tests/formats/json/parsers/test_json.py +++ b/frictionless/formats/json/parsers/__spec__/test_json.py @@ -1,4 +1,5 @@ import json +import sys import pytest @@ -66,6 +67,7 @@ def test_json_parser_from_buffer_keyed(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_json_parser_from_remote(): with TableResource(path=BASEURL % "data/table.json") as resource: assert resource.header == ["id", "name"] @@ -76,6 +78,7 @@ def test_json_parser_from_remote(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_json_parser_from_remote_keyed(): with TableResource(path=BASEURL % "data/table.keyed.json") as resource: assert resource.dialect.to_descriptor() == {"json": {"keyed": True}} diff --git a/tests/formats/json/parsers/test_jsonl.py b/frictionless/formats/json/parsers/__spec__/test_jsonl.py similarity index 100% rename from tests/formats/json/parsers/test_jsonl.py rename to frictionless/formats/json/parsers/__spec__/test_jsonl.py diff --git a/frictionless/formats/jsonschema/__init__.py b/frictionless/formats/jsonschema/__init__.py index ce90e4f21d..a8d3e2cf82 100644 --- a/frictionless/formats/jsonschema/__init__.py +++ b/frictionless/formats/jsonschema/__init__.py @@ -1,5 +1 @@ -from .mapper import JsonschemaMapper - -__all__ = [ - "JsonschemaMapper", -] +from .mapper import JsonschemaMapper as JsonschemaMapper diff --git a/tests/formats/inline/__init__.py b/frictionless/formats/jsonschema/__spec__/__init__.py similarity index 100% rename from tests/formats/inline/__init__.py rename to frictionless/formats/jsonschema/__spec__/__init__.py diff --git a/tests/formats/jsonschema/test_mapper.py b/frictionless/formats/jsonschema/__spec__/test_mapper.py similarity index 100% rename from tests/formats/jsonschema/test_mapper.py rename to frictionless/formats/jsonschema/__spec__/test_mapper.py diff --git a/frictionless/formats/markdown/__init__.py b/frictionless/formats/markdown/__init__.py index 30fb6c91ab..ab949b9b2e 100644 --- a/frictionless/formats/markdown/__init__.py +++ b/frictionless/formats/markdown/__init__.py @@ -1,7 +1,2 @@ -from .mapper import MarkdownMapper -from .plugin import MarkdownPlugin - -__all__ = [ - "MarkdownMapper", - "MarkdownPlugin", -] +from .mapper import MarkdownMapper as MarkdownMapper +from .plugin import MarkdownPlugin as MarkdownPlugin diff --git a/tests/formats/json/__init__.py b/frictionless/formats/markdown/__spec__/__init__.py similarity index 100% rename from tests/formats/json/__init__.py rename to frictionless/formats/markdown/__spec__/__init__.py diff --git a/tests/formats/markdown/test_mapper.py b/frictionless/formats/markdown/__spec__/test_mapper.py similarity index 98% rename from tests/formats/markdown/test_mapper.py rename to frictionless/formats/markdown/__spec__/test_mapper.py index 8654f80440..b1c345b645 100644 --- a/tests/formats/markdown/test_mapper.py +++ b/frictionless/formats/markdown/__spec__/test_mapper.py @@ -1,7 +1,15 @@ import pytest -from frictionless import Checklist, Dialect, Inquiry, Package, Pipeline, Report -from frictionless import Resource, Schema +from frictionless import ( + Checklist, + Dialect, + Inquiry, + Package, + Pipeline, + Report, + Resource, + Schema, +) SCHEMA = { "fields": [ diff --git a/frictionless/formats/ods/__init__.py b/frictionless/formats/ods/__init__.py index ff472c7b4c..df05ea267c 100644 --- a/frictionless/formats/ods/__init__.py +++ b/frictionless/formats/ods/__init__.py @@ -1,11 +1,4 @@ -from .adapter import OdsAdapter -from .control import OdsControl -from .parser import OdsParser -from .plugin import OdsPlugin - -__all__ = [ - "OdsAdapter", - "OdsControl", - "OdsParser", - "OdsPlugin", -] +from .adapter import OdsAdapter as OdsAdapter +from .control import OdsControl as OdsControl +from .parser import OdsParser as OdsParser +from .plugin import OdsPlugin as OdsPlugin diff --git a/tests/formats/json/parsers/__init__.py b/frictionless/formats/ods/__spec__/__init__.py similarity index 100% rename from tests/formats/json/parsers/__init__.py rename to frictionless/formats/ods/__spec__/__init__.py diff --git a/tests/formats/ods/test_adapter.py b/frictionless/formats/ods/__spec__/test_adapter.py similarity index 100% rename from tests/formats/ods/test_adapter.py rename to frictionless/formats/ods/__spec__/test_adapter.py diff --git a/tests/formats/ods/test_parser.py b/frictionless/formats/ods/__spec__/test_parser.py similarity index 100% rename from tests/formats/ods/test_parser.py rename to frictionless/formats/ods/__spec__/test_parser.py diff --git a/frictionless/formats/pandas/__init__.py b/frictionless/formats/pandas/__init__.py index bf5d1c7bc9..15890d35d3 100644 --- a/frictionless/formats/pandas/__init__.py +++ b/frictionless/formats/pandas/__init__.py @@ -1,9 +1,3 @@ -from .control import PandasControl -from .parser import PandasParser -from .plugin import PandasPlugin - -__all__ = [ - "PandasControl", - "PandasParser", - "PandasPlugin", -] +from .control import PandasControl as PandasControl +from .parser import PandasParser as PandasParser +from .plugin import PandasPlugin as PandasPlugin diff --git a/tests/formats/jsonschema/__init__.py b/frictionless/formats/pandas/__spec__/__init__.py similarity index 100% rename from tests/formats/jsonschema/__init__.py rename to frictionless/formats/pandas/__spec__/__init__.py diff --git a/tests/formats/pandas/test_parser.py b/frictionless/formats/pandas/__spec__/test_parser.py similarity index 100% rename from tests/formats/pandas/test_parser.py rename to frictionless/formats/pandas/__spec__/test_parser.py diff --git a/frictionless/formats/parquet/__init__.py b/frictionless/formats/parquet/__init__.py index 1de3559e2a..50f2bd30b5 100644 --- a/frictionless/formats/parquet/__init__.py +++ b/frictionless/formats/parquet/__init__.py @@ -1,9 +1,3 @@ -from .control import ParquetControl -from .parser import ParquetParser -from .plugin import ParquetPlugin - -__all__ = [ - "ParquetControl", - "ParquetParser", - "ParquetPlugin", -] +from .control import ParquetControl as ParquetControl +from .parser import ParquetParser as ParquetParser +from .plugin import ParquetPlugin as ParquetPlugin diff --git a/tests/formats/markdown/__init__.py b/frictionless/formats/parquet/__spec__/__init__.py similarity index 100% rename from tests/formats/markdown/__init__.py rename to frictionless/formats/parquet/__spec__/__init__.py diff --git a/tests/formats/parquet/test_parser.py b/frictionless/formats/parquet/__spec__/test_parser.py similarity index 100% rename from tests/formats/parquet/test_parser.py rename to frictionless/formats/parquet/__spec__/test_parser.py diff --git a/frictionless/formats/python/__init__.py b/frictionless/formats/python/__init__.py index 679670eba2..d29528acc0 100644 --- a/frictionless/formats/python/__init__.py +++ b/frictionless/formats/python/__init__.py @@ -1,5 +1 @@ -from .plugin import PythonPlugin - -__all__ = [ - "PythonPlugin", -] +from .plugin import PythonPlugin as PythonPlugin diff --git a/frictionless/formats/qsv/__init__.py b/frictionless/formats/qsv/__init__.py index b1c50004db..0e8ac6aff5 100644 --- a/frictionless/formats/qsv/__init__.py +++ b/frictionless/formats/qsv/__init__.py @@ -1,7 +1,2 @@ -from .adapter import QsvAdapter -from .mapper import QsvMapper - -__all__ = [ - "QsvAdapter", - "QsvMapper", -] +from .adapter import QsvAdapter as QsvAdapter +from .mapper import QsvMapper as QsvMapper diff --git a/frictionless/formats/spss/__init__.py b/frictionless/formats/spss/__init__.py index 3bf1d9c175..9f574a0fe9 100644 --- a/frictionless/formats/spss/__init__.py +++ b/frictionless/formats/spss/__init__.py @@ -1,9 +1,3 @@ -from .control import SpssControl -from .parser import SpssParser -from .plugin import SpssPlugin - -__all__ = [ - "SpssControl", - "SpssParser", - "SpssPlugin", -] +from .control import SpssControl as SpssControl +from .parser import SpssParser as SpssParser +from .plugin import SpssPlugin as SpssPlugin diff --git a/tests/formats/ods/__init__.py b/frictionless/formats/spss/__spec__/__init__.py similarity index 100% rename from tests/formats/ods/__init__.py rename to frictionless/formats/spss/__spec__/__init__.py diff --git a/tests/formats/spss/test_parser.py b/frictionless/formats/spss/__spec__/test_parser.py similarity index 100% rename from tests/formats/spss/test_parser.py rename to frictionless/formats/spss/__spec__/test_parser.py diff --git a/frictionless/formats/sql/__init__.py b/frictionless/formats/sql/__init__.py index 4587104077..128fd3a35a 100644 --- a/frictionless/formats/sql/__init__.py +++ b/frictionless/formats/sql/__init__.py @@ -1,13 +1,5 @@ -from .adapter import SqlAdapter -from .control import SqlControl -from .mapper import SqlMapper -from .parser import SqlParser -from .plugin import SqlPlugin - -__all__ = [ - "SqlAdapter", - "SqlControl", - "SqlMapper", - "SqlParser", - "SqlPlugin", -] +from .adapter import SqlAdapter as SqlAdapter +from .control import SqlControl as SqlControl +from .mapper import SqlMapper as SqlMapper +from .parser import SqlParser as SqlParser +from .plugin import SqlPlugin as SqlPlugin diff --git a/tests/formats/pandas/__init__.py b/frictionless/formats/sql/__spec__/__init__.py similarity index 100% rename from tests/formats/pandas/__init__.py rename to frictionless/formats/sql/__spec__/__init__.py diff --git a/tests/formats/sql/conftest.py b/frictionless/formats/sql/__spec__/conftest.py similarity index 100% rename from tests/formats/sql/conftest.py rename to frictionless/formats/sql/__spec__/conftest.py diff --git a/tests/formats/parquet/__init__.py b/frictionless/formats/sql/__spec__/duckdb/__init__.py similarity index 100% rename from tests/formats/parquet/__init__.py rename to frictionless/formats/sql/__spec__/duckdb/__init__.py diff --git a/tests/formats/sql/databases/duckdb/test_adapter.py b/frictionless/formats/sql/__spec__/duckdb/test_adapter.py similarity index 100% rename from tests/formats/sql/databases/duckdb/test_adapter.py rename to frictionless/formats/sql/__spec__/duckdb/test_adapter.py diff --git a/tests/formats/sql/databases/duckdb/test_mapper.py b/frictionless/formats/sql/__spec__/duckdb/test_mapper.py similarity index 100% rename from tests/formats/sql/databases/duckdb/test_mapper.py rename to frictionless/formats/sql/__spec__/duckdb/test_mapper.py diff --git a/tests/formats/sql/databases/duckdb/test_parser.py b/frictionless/formats/sql/__spec__/duckdb/test_parser.py similarity index 100% rename from tests/formats/sql/databases/duckdb/test_parser.py rename to frictionless/formats/sql/__spec__/duckdb/test_parser.py diff --git a/tests/formats/spss/__init__.py b/frictionless/formats/sql/__spec__/mysql/__init__.py similarity index 100% rename from tests/formats/spss/__init__.py rename to frictionless/formats/sql/__spec__/mysql/__init__.py diff --git a/tests/formats/sql/databases/mysql/test_adapter.py b/frictionless/formats/sql/__spec__/mysql/test_adapter.py similarity index 100% rename from tests/formats/sql/databases/mysql/test_adapter.py rename to frictionless/formats/sql/__spec__/mysql/test_adapter.py diff --git a/tests/formats/sql/databases/mysql/test_mapper.py b/frictionless/formats/sql/__spec__/mysql/test_mapper.py similarity index 100% rename from tests/formats/sql/databases/mysql/test_mapper.py rename to frictionless/formats/sql/__spec__/mysql/test_mapper.py diff --git a/tests/formats/sql/databases/mysql/test_parser.py b/frictionless/formats/sql/__spec__/mysql/test_parser.py similarity index 100% rename from tests/formats/sql/databases/mysql/test_parser.py rename to frictionless/formats/sql/__spec__/mysql/test_parser.py diff --git a/tests/formats/sql/__init__.py b/frictionless/formats/sql/__spec__/postgresql/__init__.py similarity index 100% rename from tests/formats/sql/__init__.py rename to frictionless/formats/sql/__spec__/postgresql/__init__.py diff --git a/tests/formats/sql/databases/postgresql/test_adapter.py b/frictionless/formats/sql/__spec__/postgresql/test_adapter.py similarity index 100% rename from tests/formats/sql/databases/postgresql/test_adapter.py rename to frictionless/formats/sql/__spec__/postgresql/test_adapter.py diff --git a/tests/formats/sql/databases/postgresql/test_mapper.py b/frictionless/formats/sql/__spec__/postgresql/test_mapper.py similarity index 100% rename from tests/formats/sql/databases/postgresql/test_mapper.py rename to frictionless/formats/sql/__spec__/postgresql/test_mapper.py diff --git a/tests/formats/sql/databases/postgresql/test_parser.py b/frictionless/formats/sql/__spec__/postgresql/test_parser.py similarity index 100% rename from tests/formats/sql/databases/postgresql/test_parser.py rename to frictionless/formats/sql/__spec__/postgresql/test_parser.py diff --git a/tests/formats/sql/test_adapter.py b/frictionless/formats/sql/__spec__/test_adapter.py similarity index 100% rename from tests/formats/sql/test_adapter.py rename to frictionless/formats/sql/__spec__/test_adapter.py diff --git a/tests/formats/sql/test_mapper.py b/frictionless/formats/sql/__spec__/test_mapper.py similarity index 100% rename from tests/formats/sql/test_mapper.py rename to frictionless/formats/sql/__spec__/test_mapper.py diff --git a/tests/formats/sql/test_parser.py b/frictionless/formats/sql/__spec__/test_parser.py similarity index 100% rename from tests/formats/sql/test_parser.py rename to frictionless/formats/sql/__spec__/test_parser.py diff --git a/frictionless/formats/sql/adapter.py b/frictionless/formats/sql/adapter.py index 5f49b7b4b5..51e80c16f1 100644 --- a/frictionless/formats/sql/adapter.py +++ b/frictionless/formats/sql/adapter.py @@ -3,11 +3,10 @@ import re from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, List, Optional -from ... import models from ...package import Package from ...platform import platform from ...resource import Resource -from ...system import Adapter +from ...system import Adapter, PublishResult from . import settings from .control import SqlControl from .mapper import SqlMapper @@ -111,7 +110,7 @@ def write_package(self, package: Package): resource = package.get_table_resource(table.name) with resource: self.write_row_stream(resource.row_stream, table_name=table.name) - return models.PublishResult( + return PublishResult( url=self.engine.url.render_as_string(hide_password=True), context=dict(engine=self.engine), ) diff --git a/frictionless/formats/text/__init__.py b/frictionless/formats/text/__init__.py index 3f7a76a890..2f73a75213 100644 --- a/frictionless/formats/text/__init__.py +++ b/frictionless/formats/text/__init__.py @@ -1,5 +1 @@ -from .plugin import TextPlugin - -__all__ = [ - "TextPlugin", -] +from .plugin import TextPlugin as TextPlugin diff --git a/frictionless/formats/yaml/__init__.py b/frictionless/formats/yaml/__init__.py index 49710157da..bb1bf1d1db 100644 --- a/frictionless/formats/yaml/__init__.py +++ b/frictionless/formats/yaml/__init__.py @@ -1,9 +1,3 @@ -from .control import YamlControl -from .parser import YamlParser -from .plugin import YamlPlugin - -__all__ = [ - "YamlControl", - "YamlParser", - "YamlPlugin", -] +from .control import YamlControl as YamlControl +from .parser import YamlParser as YamlParser +from .plugin import YamlPlugin as YamlPlugin diff --git a/tests/formats/sql/databases/__init__.py b/frictionless/formats/yaml/__spec__/__init__.py similarity index 100% rename from tests/formats/sql/databases/__init__.py rename to frictionless/formats/yaml/__spec__/__init__.py diff --git a/tests/formats/yaml/test_parser.py b/frictionless/formats/yaml/__spec__/test_parser.py similarity index 100% rename from tests/formats/yaml/test_parser.py rename to frictionless/formats/yaml/__spec__/test_parser.py diff --git a/frictionless/formats/zip/__init__.py b/frictionless/formats/zip/__init__.py index adcc49ea78..914a193973 100644 --- a/frictionless/formats/zip/__init__.py +++ b/frictionless/formats/zip/__init__.py @@ -1,9 +1,3 @@ -from .adapter import ZipAdapter -from .control import ZipControl -from .plugin import ZipPlugin - -__all__ = [ - "ZipAdapter", - "ZipControl", - "ZipPlugin", -] +from .adapter import ZipAdapter as ZipAdapter +from .control import ZipControl as ZipControl +from .plugin import ZipPlugin as ZipPlugin diff --git a/tests/formats/sql/databases/duckdb/__init__.py b/frictionless/formats/zip/__spec__/__init__.py similarity index 100% rename from tests/formats/sql/databases/duckdb/__init__.py rename to frictionless/formats/zip/__spec__/__init__.py diff --git a/tests/formats/zip/test_adapter.py b/frictionless/formats/zip/__spec__/test_adapter.py similarity index 98% rename from tests/formats/zip/test_adapter.py rename to frictionless/formats/zip/__spec__/test_adapter.py index e64cf028e4..d458b8075a 100644 --- a/tests/formats/zip/test_adapter.py +++ b/frictionless/formats/zip/__spec__/test_adapter.py @@ -1,4 +1,5 @@ import os +import sys import zipfile import pytest @@ -39,6 +40,7 @@ def test_zip_adapter_to_zip_resource_path(tmpdir): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_zip_adapter_to_zip_resource_remote_path(tmpdir): path = os.path.join(tmpdir, "package.zip") source = Package(resources=[Resource(path=BASEURL % "data/table.csv")]) diff --git a/frictionless/formats/zip/adapter.py b/frictionless/formats/zip/adapter.py index 326187d813..fa34316d0a 100644 --- a/frictionless/formats/zip/adapter.py +++ b/frictionless/formats/zip/adapter.py @@ -5,12 +5,12 @@ import tempfile from typing import Optional -from ... import errors, helpers, models +from ... import errors, helpers from ...exception import FrictionlessException from ...package import Package from ...platform import platform from ...resources import FileResource, TableResource -from ...system import Adapter +from ...system import Adapter, PublishResult from .control import ZipControl # NOTE: @@ -112,4 +112,4 @@ def write_package(self, package: Package): error = errors.PackageError(note=str(exception)) raise FrictionlessException(error) from exception - return models.PublishResult(context=dict(path=path)) + return PublishResult(context=dict(path=path)) diff --git a/frictionless/helpers/__init__.py b/frictionless/helpers/__init__.py new file mode 100644 index 0000000000..2a1891cc7f --- /dev/null +++ b/frictionless/helpers/__init__.py @@ -0,0 +1 @@ +from .general import * diff --git a/tests/test_helpers.py b/frictionless/helpers/__spec__/test_general.py similarity index 100% rename from tests/test_helpers.py rename to frictionless/helpers/__spec__/test_general.py diff --git a/frictionless/helpers.py b/frictionless/helpers/general.py similarity index 99% rename from frictionless/helpers.py rename to frictionless/helpers/general.py index f0d17f2394..45e27ce5b7 100644 --- a/frictionless/helpers.py +++ b/frictionless/helpers/general.py @@ -19,8 +19,6 @@ import stringcase # type: ignore -from .platform import platform - # General @@ -64,6 +62,8 @@ def to_json(obj: Any, *, encoder_class: Optional[Any] = None) -> str: def to_yaml(obj: Any) -> str: + from ..platform import platform + return platform.yaml.dump( obj, sort_keys=False, @@ -358,6 +358,8 @@ def slugify(text: str, **options: Any): def create_yaml_dumper(): + from ..platform import platform + class IndentDumper(platform.yaml.SafeDumper): def increase_indent(self, flow: bool = False, indentless: bool = False) -> Any: return super().increase_indent(flow, False) # type: ignore diff --git a/tests/formats/sql/databases/mysql/__init__.py b/frictionless/indexer/__spec__/__init__.py similarity index 100% rename from tests/formats/sql/databases/mysql/__init__.py rename to frictionless/indexer/__spec__/__init__.py diff --git a/tests/indexer/test_resource.py b/frictionless/indexer/__spec__/test_resource.py similarity index 94% rename from tests/indexer/test_resource.py rename to frictionless/indexer/__spec__/test_resource.py index 5df10bb027..8d7200716e 100644 --- a/tests/indexer/test_resource.py +++ b/frictionless/indexer/__spec__/test_resource.py @@ -1,20 +1,19 @@ import pytest -from pytest_lazyfixture import lazy_fixture from frictionless import formats, platform from frictionless.resources import TableResource control = formats.sql.SqlControl(table="table") fast_database_urls = [ - lazy_fixture("sqlite_url"), - lazy_fixture("postgresql_url"), + pytest.lazy_fixtures("sqlite_url"), + pytest.lazy_fixtures("postgresql_url"), ] database_urls = fast_database_urls + [ - lazy_fixture("mysql_url"), + pytest.lazy_fixtures("mysql_url"), ] if platform.type != "windows": database_urls += [ - lazy_fixture("duckdb_url"), + pytest.lazy_fixtures("duckdb_url"), ] pytestmark = pytest.mark.skipif( platform.type == "darwin" or platform.type == "windows", diff --git a/tests/formats/sql/databases/postgresql/__init__.py b/frictionless/inquiry/__spec__/__init__.py similarity index 100% rename from tests/formats/sql/databases/postgresql/__init__.py rename to frictionless/inquiry/__spec__/__init__.py diff --git a/tests/formats/yaml/__init__.py b/frictionless/inquiry/__spec__/task/__init__.py similarity index 100% rename from tests/formats/yaml/__init__.py rename to frictionless/inquiry/__spec__/task/__init__.py diff --git a/tests/inquiry/task/test_convert.py b/frictionless/inquiry/__spec__/task/test_convert.py similarity index 100% rename from tests/inquiry/task/test_convert.py rename to frictionless/inquiry/__spec__/task/test_convert.py diff --git a/tests/inquiry/task/test_general.py b/frictionless/inquiry/__spec__/task/test_general.py similarity index 100% rename from tests/inquiry/task/test_general.py rename to frictionless/inquiry/__spec__/task/test_general.py diff --git a/tests/inquiry/task/test_validate.py b/frictionless/inquiry/__spec__/task/test_validate.py similarity index 100% rename from tests/inquiry/task/test_validate.py rename to frictionless/inquiry/__spec__/task/test_validate.py diff --git a/tests/inquiry/test_convert.py b/frictionless/inquiry/__spec__/test_convert.py similarity index 100% rename from tests/inquiry/test_convert.py rename to frictionless/inquiry/__spec__/test_convert.py diff --git a/tests/inquiry/test_general.py b/frictionless/inquiry/__spec__/test_general.py similarity index 100% rename from tests/inquiry/test_general.py rename to frictionless/inquiry/__spec__/test_general.py diff --git a/tests/inquiry/test_validate.py b/frictionless/inquiry/__spec__/test_validate.py similarity index 100% rename from tests/inquiry/test_validate.py rename to frictionless/inquiry/__spec__/test_validate.py diff --git a/frictionless/metadata/__init__.py b/frictionless/metadata/__init__.py new file mode 100644 index 0000000000..940857d701 --- /dev/null +++ b/frictionless/metadata/__init__.py @@ -0,0 +1 @@ +from .metadata import Metadata diff --git a/tests/test_metadata.py b/frictionless/metadata/__spec__/test_metadata.py similarity index 100% rename from tests/test_metadata.py rename to frictionless/metadata/__spec__/test_metadata.py diff --git a/frictionless/metadata.py b/frictionless/metadata/metadata.py similarity index 97% rename from frictionless/metadata.py rename to frictionless/metadata/metadata.py index c8fb57c675..dbf9e572df 100644 --- a/frictionless/metadata.py +++ b/frictionless/metadata/metadata.py @@ -8,20 +8,30 @@ from collections.abc import Mapping from copy import deepcopy from pathlib import Path -from typing import TYPE_CHECKING, Any, ClassVar, Dict, Generator, List, Optional, Set -from typing import Type, Union +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Dict, + Generator, + List, + Optional, + Set, + Type, + Union, +) import stringcase # type: ignore from typing_extensions import Self -from . import helpers -from .exception import FrictionlessException -from .platform import platform +from .. import helpers +from ..exception import FrictionlessException +from ..platform import platform if TYPE_CHECKING: - from . import types - from .error import Error - from .report import Report + from .. import types + from ..error import Error + from ..report import Report class Metadata: @@ -179,7 +189,7 @@ def from_descriptor( if descriptor_path: metadata.metadata_descriptor_path = descriptor_path metadata.metadata_descriptor_initial = metadata.to_descriptor() - return metadata + return metadata # type: ignore def to_descriptor(self, *, validate: bool = False) -> types.IDescriptor: descriptor = self.metadata_export() @@ -251,7 +261,7 @@ def to_markdown(self, path: Optional[str] = None, table: bool = False) -> str: """ Error = self.metadata_Error or platform.frictionless_errors.MetadataError mapper = platform.frictionless_formats.markdown.MarkdownMapper() - text = mapper.write_metadata(self, table=table) + text = mapper.write_metadata(self, table=table) # type: ignore if path: try: helpers.write_file(path, text) diff --git a/tests/formats/zip/__init__.py b/frictionless/package/__spec__/__init__.py similarity index 100% rename from tests/formats/zip/__init__.py rename to frictionless/package/__spec__/__init__.py diff --git a/tests/package/test_compression.py b/frictionless/package/__spec__/test_compression.py similarity index 100% rename from tests/package/test_compression.py rename to frictionless/package/__spec__/test_compression.py diff --git a/tests/package/test_convert.py b/frictionless/package/__spec__/test_convert.py similarity index 100% rename from tests/package/test_convert.py rename to frictionless/package/__spec__/test_convert.py diff --git a/tests/package/test_dereference.py b/frictionless/package/__spec__/test_dereference.py similarity index 100% rename from tests/package/test_dereference.py rename to frictionless/package/__spec__/test_dereference.py diff --git a/tests/package/test_describe.py b/frictionless/package/__spec__/test_describe.py similarity index 100% rename from tests/package/test_describe.py rename to frictionless/package/__spec__/test_describe.py diff --git a/tests/package/test_extract.py b/frictionless/package/__spec__/test_extract.py similarity index 100% rename from tests/package/test_extract.py rename to frictionless/package/__spec__/test_extract.py diff --git a/tests/package/test_general.py b/frictionless/package/__spec__/test_general.py similarity index 97% rename from tests/package/test_general.py rename to frictionless/package/__spec__/test_general.py index 0f0ff72b52..0a95a60210 100644 --- a/tests/package/test_general.py +++ b/frictionless/package/__spec__/test_general.py @@ -1,3 +1,4 @@ +import sys import textwrap from collections.abc import Mapping from importlib import import_module @@ -126,6 +127,7 @@ def test_package_from_path_error_bad_json_not_dict(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_from_path_remote(): package = Package.from_descriptor(BASEURL % "data/package.json") assert package.basepath == BASEURL % "data" @@ -314,6 +316,7 @@ def test_package_validation_duplicate_resource_names_issue_942(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_remote_scheme_regression_for_resources_issue_1388(): package = Package.from_descriptor( "https://raw.githubusercontent.com/fdtester/test-write-package-with-dialect/main/datapackage.json" @@ -323,6 +326,7 @@ def test_package_remote_scheme_regression_for_resources_issue_1388(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_remote_windows_1505(): url = "https://raw.githubusercontent.com/transparencia-mg/datapackage-reprex/foreign-key-constraint/datapackage.json" package = Package(url) diff --git a/tests/package/test_infer.py b/frictionless/package/__spec__/test_infer.py similarity index 100% rename from tests/package/test_infer.py rename to frictionless/package/__spec__/test_infer.py diff --git a/tests/package/test_onerror.py b/frictionless/package/__spec__/test_onerror.py similarity index 100% rename from tests/package/test_onerror.py rename to frictionless/package/__spec__/test_onerror.py diff --git a/tests/package/test_profile.py b/frictionless/package/__spec__/test_profile.py similarity index 94% rename from tests/package/test_profile.py rename to frictionless/package/__spec__/test_profile.py index 780b9af754..b12f520ea7 100644 --- a/tests/package/test_profile.py +++ b/frictionless/package/__spec__/test_profile.py @@ -1,3 +1,5 @@ +import sys + import pytest import yaml @@ -7,6 +9,7 @@ @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_profiles_invalid_local(): profile = "data/profiles/camtrap.json" resource = Resource(name="table", path="data/table.csv") @@ -20,6 +23,7 @@ def test_package_profiles_invalid_local(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_profiles_invalid_local_from_descriptor(): profile = "data/profiles/camtrap.json" resource = Resource(name="table", path="data/table.csv") @@ -80,6 +84,7 @@ def test_package_profile_type(profile): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_profiles_from_descriptor_standards_v1(): profile = "data/profiles/camtrap.json" resource = Resource(name="table", path="data/table.csv") diff --git a/tests/package/test_resources.py b/frictionless/package/__spec__/test_resources.py similarity index 100% rename from tests/package/test_resources.py rename to frictionless/package/__spec__/test_resources.py diff --git a/tests/package/test_schema.py b/frictionless/package/__spec__/test_schema.py similarity index 100% rename from tests/package/test_schema.py rename to frictionless/package/__spec__/test_schema.py diff --git a/tests/package/test_security.py b/frictionless/package/__spec__/test_security.py similarity index 95% rename from tests/package/test_security.py rename to frictionless/package/__spec__/test_security.py index 119e92fa28..8ece99764a 100644 --- a/tests/package/test_security.py +++ b/frictionless/package/__spec__/test_security.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import FrictionlessException, Package, Resource, platform, system @@ -44,6 +46,7 @@ def test_package_external_profile_invalid_local_from_descriptor_unsafe(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_package_external_profile_invalid_local_from_descriptor_unsafe_trusted(): profile = "data/../data/profiles/camtrap.json" resource = Resource(name="table", path="data/table.csv") diff --git a/frictionless/package/package.py b/frictionless/package/package.py index b8dee6bbe3..bf5e180c7f 100644 --- a/frictionless/package/package.py +++ b/frictionless/package/package.py @@ -5,7 +5,7 @@ import attrs from typing_extensions import Self -from .. import errors, fields, helpers, models, settings +from .. import errors, fields, helpers, settings from ..exception import FrictionlessException from ..metadata import Metadata from ..platform import platform @@ -24,6 +24,7 @@ from ..indexer import IOnProgress, IOnRow from ..pipeline import Pipeline from ..resources import TableResource + from ..system import PublishResult @attrs.define(kw_only=True, repr=False) @@ -293,7 +294,7 @@ def infer(self, *, stats: bool = False) -> None: def publish( self, target: Any = None, *, control: Optional[Control] = None - ) -> models.PublishResult: + ) -> PublishResult: """Publish package to any supported data portal Parameters: diff --git a/tests/indexer/__init__.py b/frictionless/pipeline/__spec__/__init__.py similarity index 100% rename from tests/indexer/__init__.py rename to frictionless/pipeline/__spec__/__init__.py diff --git a/tests/inquiry/__init__.py b/frictionless/pipeline/__spec__/step/__init__.py similarity index 100% rename from tests/inquiry/__init__.py rename to frictionless/pipeline/__spec__/step/__init__.py diff --git a/tests/pipeline/step/test_convert.py b/frictionless/pipeline/__spec__/step/test_convert.py similarity index 100% rename from tests/pipeline/step/test_convert.py rename to frictionless/pipeline/__spec__/step/test_convert.py diff --git a/tests/pipeline/step/test_general.py b/frictionless/pipeline/__spec__/step/test_general.py similarity index 100% rename from tests/pipeline/step/test_general.py rename to frictionless/pipeline/__spec__/step/test_general.py diff --git a/tests/pipeline/test_convert.py b/frictionless/pipeline/__spec__/test_convert.py similarity index 100% rename from tests/pipeline/test_convert.py rename to frictionless/pipeline/__spec__/test_convert.py diff --git a/tests/pipeline/test_general.py b/frictionless/pipeline/__spec__/test_general.py similarity index 100% rename from tests/pipeline/test_general.py rename to frictionless/pipeline/__spec__/test_general.py diff --git a/tests/pipeline/test_validate.py b/frictionless/pipeline/__spec__/test_validate.py similarity index 100% rename from tests/pipeline/test_validate.py rename to frictionless/pipeline/__spec__/test_validate.py diff --git a/frictionless/portals/ckan/__init__.py b/frictionless/portals/ckan/__init__.py index 9c6efa2be7..db032034ed 100644 --- a/frictionless/portals/ckan/__init__.py +++ b/frictionless/portals/ckan/__init__.py @@ -1,9 +1,3 @@ -from .adapter import CkanAdapter -from .control import CkanControl -from .plugin import CkanPlugin - -__all__ = [ - "CkanAdapter", - "CkanControl", - "CkanPlugin", -] +from .adapter import CkanAdapter as CkanAdapter +from .control import CkanControl as CkanControl +from .plugin import CkanPlugin as CkanPlugin diff --git a/tests/inquiry/task/__init__.py b/frictionless/portals/ckan/__spec__/__init__.py similarity index 100% rename from tests/inquiry/task/__init__.py rename to frictionless/portals/ckan/__spec__/__init__.py diff --git a/tests/portals/ckan/conftest.py b/frictionless/portals/ckan/__spec__/conftest.py similarity index 100% rename from tests/portals/ckan/conftest.py rename to frictionless/portals/ckan/__spec__/conftest.py diff --git a/tests/portals/ckan/test_adapter.py b/frictionless/portals/ckan/__spec__/test_adapter.py similarity index 100% rename from tests/portals/ckan/test_adapter.py rename to frictionless/portals/ckan/__spec__/test_adapter.py diff --git a/frictionless/portals/ckan/adapter.py b/frictionless/portals/ckan/adapter.py index 1f6be1be75..2f777a9879 100644 --- a/frictionless/portals/ckan/adapter.py +++ b/frictionless/portals/ckan/adapter.py @@ -4,13 +4,13 @@ from typing import Any, Dict, Optional from urllib.parse import urljoin -from ... import helpers, models +from ... import helpers from ...catalog import Catalog, Dataset from ...exception import FrictionlessException from ...package import Package from ...platform import platform from ...resource import Resource -from ...system import Adapter, system +from ...system import Adapter, PublishResult, system from .control import CkanControl @@ -141,7 +141,7 @@ def write_package(self, package: Package): ) }, ) - return models.PublishResult( + return PublishResult( url=urljoin( self.control.baseurl or "", str(PurePosixPath("dataset").joinpath(dataset_name)), diff --git a/frictionless/portals/github/__init__.py b/frictionless/portals/github/__init__.py index 08018f1890..5713b9b3a4 100644 --- a/frictionless/portals/github/__init__.py +++ b/frictionless/portals/github/__init__.py @@ -1,9 +1,3 @@ -from .adapter import GithubAdapter -from .control import GithubControl -from .plugin import GithubPlugin - -__all__ = [ - "GithubAdapter", - "GithubControl", - "GithubPlugin", -] +from .adapter import GithubAdapter as GithubAdapter +from .control import GithubControl as GithubControl +from .plugin import GithubPlugin as GithubPlugin diff --git a/tests/package/__init__.py b/frictionless/portals/github/__spec__/__init__.py similarity index 100% rename from tests/package/__init__.py rename to frictionless/portals/github/__spec__/__init__.py diff --git a/tests/portals/github/conftest.py b/frictionless/portals/github/__spec__/conftest.py similarity index 100% rename from tests/portals/github/conftest.py rename to frictionless/portals/github/__spec__/conftest.py diff --git a/tests/portals/github/test_adapter.py b/frictionless/portals/github/__spec__/test_adapter.py similarity index 100% rename from tests/portals/github/test_adapter.py rename to frictionless/portals/github/__spec__/test_adapter.py diff --git a/frictionless/portals/github/adapter.py b/frictionless/portals/github/adapter.py index 8ca28a15b3..b44c374034 100644 --- a/frictionless/portals/github/adapter.py +++ b/frictionless/portals/github/adapter.py @@ -3,13 +3,12 @@ import os from typing import TYPE_CHECKING, Any, Dict, List, Union -from ... import models from ...catalog import Catalog, Dataset from ...exception import FrictionlessException from ...package import Package from ...platform import platform from ...resource import Resource -from ...system import Adapter +from ...system import Adapter, PublishResult from .control import GithubControl if TYPE_CHECKING: @@ -134,7 +133,7 @@ def write_package(self, package: Package): note = "Github API error:" + repr(exception) raise FrictionlessException(note) - return models.PublishResult(url=url, context=dict(repository=repository)) + return PublishResult(url=url, context=dict(repository=repository)) # Experimental diff --git a/frictionless/portals/zenodo/__init__.py b/frictionless/portals/zenodo/__init__.py index cc88a5454d..f02ead5665 100644 --- a/frictionless/portals/zenodo/__init__.py +++ b/frictionless/portals/zenodo/__init__.py @@ -1,9 +1,3 @@ -from .adapter import ZenodoAdapter -from .control import ZenodoControl -from .plugin import ZenodoPlugin - -__all__ = [ - "ZenodoAdapter", - "ZenodoControl", - "ZenodoPlugin", -] +from .adapter import ZenodoAdapter as ZenodoAdapter +from .control import ZenodoControl as ZenodoControl +from .plugin import ZenodoPlugin as ZenodoPlugin diff --git a/tests/pipeline/__init__.py b/frictionless/portals/zenodo/__spec__/__init__.py similarity index 100% rename from tests/pipeline/__init__.py rename to frictionless/portals/zenodo/__spec__/__init__.py diff --git a/tests/portals/zenodo/conftest.py b/frictionless/portals/zenodo/__spec__/conftest.py similarity index 100% rename from tests/portals/zenodo/conftest.py rename to frictionless/portals/zenodo/__spec__/conftest.py diff --git a/tests/portals/zenodo/test_adapter.py b/frictionless/portals/zenodo/__spec__/test_adapter.py similarity index 100% rename from tests/portals/zenodo/test_adapter.py rename to frictionless/portals/zenodo/__spec__/test_adapter.py diff --git a/frictionless/portals/zenodo/adapter.py b/frictionless/portals/zenodo/adapter.py index 8cc8dc70ae..6997b7851d 100644 --- a/frictionless/portals/zenodo/adapter.py +++ b/frictionless/portals/zenodo/adapter.py @@ -6,13 +6,12 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Dict, List, Union, cast -from ... import models from ...catalog import Catalog, Dataset from ...exception import FrictionlessException from ...package import Package from ...platform import platform from ...resource import Resource -from ...system import Adapter +from ...system import Adapter, PublishResult from .control import ZenodoControl from .models import ZenodoCreator, ZenodoMetadata @@ -136,7 +135,7 @@ def write_package(self, package: Package): ) # Return result - return models.PublishResult( + return PublishResult( url=f"https://zenodo.org/deposit/{deposition_id}", context=dict(deposition_id=deposition_id), ) diff --git a/tests/pipeline/step/__init__.py b/frictionless/report/__spec__/__init__.py similarity index 100% rename from tests/pipeline/step/__init__.py rename to frictionless/report/__spec__/__init__.py diff --git a/tests/portals/__init__.py b/frictionless/report/__spec__/task/__init__.py similarity index 100% rename from tests/portals/__init__.py rename to frictionless/report/__spec__/task/__init__.py diff --git a/tests/report/task/test_convert.py b/frictionless/report/__spec__/task/test_convert.py similarity index 100% rename from tests/report/task/test_convert.py rename to frictionless/report/__spec__/task/test_convert.py diff --git a/tests/report/task/test_general.py b/frictionless/report/__spec__/task/test_general.py similarity index 100% rename from tests/report/task/test_general.py rename to frictionless/report/__spec__/task/test_general.py diff --git a/tests/report/test_convert.py b/frictionless/report/__spec__/test_convert.py similarity index 100% rename from tests/report/test_convert.py rename to frictionless/report/__spec__/test_convert.py diff --git a/tests/report/test_general.py b/frictionless/report/__spec__/test_general.py similarity index 100% rename from tests/report/test_general.py rename to frictionless/report/__spec__/test_general.py diff --git a/tests/report/test_validate.py b/frictionless/report/__spec__/test_validate.py similarity index 100% rename from tests/report/test_validate.py rename to frictionless/report/__spec__/test_validate.py diff --git a/tests/portals/ckan/__init__.py b/frictionless/resource/__spec__/__init__.py similarity index 100% rename from tests/portals/ckan/__init__.py rename to frictionless/resource/__spec__/__init__.py diff --git a/tests/resource/test_datatype.py b/frictionless/resource/__spec__/test_datatype.py similarity index 100% rename from tests/resource/test_datatype.py rename to frictionless/resource/__spec__/test_datatype.py diff --git a/tests/resource/test_dereference.py b/frictionless/resource/__spec__/test_dereference.py similarity index 96% rename from tests/resource/test_dereference.py rename to frictionless/resource/__spec__/test_dereference.py index bb06add167..3b4138a9f9 100644 --- a/tests/resource/test_dereference.py +++ b/frictionless/resource/__spec__/test_dereference.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import Resource, platform @@ -59,6 +61,7 @@ def test_resource_dialect_schema_from_path(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_resource_dialect_schema_from_path_remote(): resource = Resource(BASEURL % "data/resource-with-dereferencing.json") diff --git a/tests/resource/test_describe.py b/frictionless/resource/__spec__/test_describe.py similarity index 100% rename from tests/resource/test_describe.py rename to frictionless/resource/__spec__/test_describe.py diff --git a/tests/resource/test_export.py b/frictionless/resource/__spec__/test_export.py similarity index 100% rename from tests/resource/test_export.py rename to frictionless/resource/__spec__/test_export.py diff --git a/tests/resource/test_extrapaths.py b/frictionless/resource/__spec__/test_extrapaths.py similarity index 100% rename from tests/resource/test_extrapaths.py rename to frictionless/resource/__spec__/test_extrapaths.py diff --git a/tests/resource/test_format.py b/frictionless/resource/__spec__/test_format.py similarity index 100% rename from tests/resource/test_format.py rename to frictionless/resource/__spec__/test_format.py diff --git a/tests/resource/test_general.py b/frictionless/resource/__spec__/test_general.py similarity index 98% rename from tests/resource/test_general.py rename to frictionless/resource/__spec__/test_general.py index 6f5a8de6c3..5aa8667eed 100644 --- a/tests/resource/test_general.py +++ b/frictionless/resource/__spec__/test_general.py @@ -1,3 +1,4 @@ +import sys import textwrap from importlib import import_module @@ -49,6 +50,7 @@ def test_resource_source_non_tabular(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_source_non_tabular_remote(): path = BASEURL % "data/text.txt" with Resource(path) as resource: diff --git a/tests/resource/test_infer.py b/frictionless/resource/__spec__/test_infer.py similarity index 100% rename from tests/resource/test_infer.py rename to frictionless/resource/__spec__/test_infer.py diff --git a/tests/resource/test_profile.py b/frictionless/resource/__spec__/test_profile.py similarity index 100% rename from tests/resource/test_profile.py rename to frictionless/resource/__spec__/test_profile.py diff --git a/tests/resource/test_read.py b/frictionless/resource/__spec__/test_read.py similarity index 100% rename from tests/resource/test_read.py rename to frictionless/resource/__spec__/test_read.py diff --git a/tests/resource/test_scheme.py b/frictionless/resource/__spec__/test_scheme.py similarity index 96% rename from tests/resource/test_scheme.py rename to frictionless/resource/__spec__/test_scheme.py index 5a94b6d965..834d4f600f 100644 --- a/tests/resource/test_scheme.py +++ b/frictionless/resource/__spec__/test_scheme.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import FrictionlessException, Resource @@ -14,6 +16,7 @@ def test_resource_scheme_file(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_scheme_https(): with Resource(BASEURL % "data/table.csv") as resource: assert resource.scheme == "https" diff --git a/tests/resource/test_security.py b/frictionless/resource/__spec__/test_security.py similarity index 86% rename from tests/resource/test_security.py rename to frictionless/resource/__spec__/test_security.py index 30ffacde33..e44916e727 100644 --- a/tests/resource/test_security.py +++ b/frictionless/resource/__spec__/test_security.py @@ -1,4 +1,5 @@ import os +import sys import pytest @@ -7,6 +8,7 @@ # General +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_source_path_error_bad_path_not_safe_absolute(): with pytest.raises(FrictionlessException) as excinfo: Resource({"name": "name", "path": os.path.abspath("data/table.csv")}) @@ -19,6 +21,7 @@ def test_resource_source_path_error_bad_path_not_safe_absolute(): assert reasons[0].note.count('table.csv" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_source_path_error_bad_path_not_safe_traversing(): with pytest.raises(FrictionlessException) as excinfo: Resource( @@ -38,6 +41,7 @@ def test_resource_source_path_error_bad_path_not_safe_traversing(): assert reasons[0].note.count('table.csv" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_dialect_from_path_error_path_not_safe(): dialect = os.path.abspath("data/dialect.json") with pytest.raises(FrictionlessException) as excinfo: @@ -51,6 +55,7 @@ def test_resource_dialect_from_path_error_path_not_safe(): assert reasons[0].note.count('dialect.json" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_schema_from_path_error_path_not_safe(): schema = os.path.abspath("data/schema.json") with pytest.raises(FrictionlessException) as excinfo: @@ -64,6 +69,7 @@ def test_resource_schema_from_path_error_path_not_safe(): assert reasons[0].note.count('schema.json" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_extrapaths_error_bad_path_not_safe_absolute(): extrapath = os.path.abspath("data/chunk2.csv") with pytest.raises(FrictionlessException) as excinfo: @@ -77,6 +83,7 @@ def test_resource_extrapaths_error_bad_path_not_safe_absolute(): assert reasons[0].note.count('chunk2.csv" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_resource_extrapaths_error_bad_path_not_safe_traversing(): extrapath = "data/../chunk2.csv" @@ -91,6 +98,7 @@ def test_resource_extrapaths_error_bad_path_not_safe_traversing(): assert reasons[0].note.count('chunk2.csv" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_profiles_error_bad_path_not_safe_absolute(): profile = os.path.abspath("data/profiles/camtrap.json") with pytest.raises(FrictionlessException) as excinfo: @@ -104,6 +112,7 @@ def test_resource_profiles_error_bad_path_not_safe_absolute(): assert reasons[0].note.count('camtrap.json" is not safe') +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_resource_profiles_error_bad_path_not_safe_traversing(): profile = "data/profiles/../profiles/camtrap.json" diff --git a/frictionless/resource/factory.py b/frictionless/resource/factory.py index 825c8a7c6f..dd6867ce10 100644 --- a/frictionless/resource/factory.py +++ b/frictionless/resource/factory.py @@ -54,7 +54,9 @@ def __call__( # Descriptor if source is not None: options.pop("format", None) - resource = cls.from_descriptor(source, control=control, basepath=basepath, **options) # type: ignore + resource = cls.from_descriptor( # type: ignore + source, control=control, basepath=basepath, **options + ) return cast(T, resource) # Control diff --git a/frictionless/resources/__init__.py b/frictionless/resources/__init__.py index 8b8795b601..d8c1515de5 100644 --- a/frictionless/resources/__init__.py +++ b/frictionless/resources/__init__.py @@ -3,32 +3,3 @@ from .table import * from .text import * from .types import * - -__all__ = [ - "ArticleResource", - "CatalogResource", - "ChartResource", - "ChecklistResource", - "DialectResource", - "DocumentResource", - "FileResource", - "ImageResource", - "InquiryResource", - "JsonResource", - "JsonschemaResource", - "MapResource", - "MetadataResource", - "PackageResource", - "PipelineResource", - "ReportResource", - "ResourceResource", - "SchemaResource", - "ScriptResource", - "TableResource", - "TextResource", - "ViewResource", - "Convertible", - "Extractable", - "Indexable", - "Transformable", -] diff --git a/tests/portals/github/__init__.py b/frictionless/resources/__spec__/__init__.py similarity index 100% rename from tests/portals/github/__init__.py rename to frictionless/resources/__spec__/__init__.py diff --git a/tests/portals/zenodo/__init__.py b/frictionless/resources/__spec__/file/__init__.py similarity index 100% rename from tests/portals/zenodo/__init__.py rename to frictionless/resources/__spec__/file/__init__.py diff --git a/tests/resources/file/test_read.py b/frictionless/resources/__spec__/file/test_read.py similarity index 100% rename from tests/resources/file/test_read.py rename to frictionless/resources/__spec__/file/test_read.py diff --git a/tests/resources/file/test_write.py b/frictionless/resources/__spec__/file/test_write.py similarity index 100% rename from tests/resources/file/test_write.py rename to frictionless/resources/__spec__/file/test_write.py diff --git a/tests/report/__init__.py b/frictionless/resources/__spec__/json/__init__.py similarity index 100% rename from tests/report/__init__.py rename to frictionless/resources/__spec__/json/__init__.py diff --git a/tests/resources/json/test_read.py b/frictionless/resources/__spec__/json/test_read.py similarity index 100% rename from tests/resources/json/test_read.py rename to frictionless/resources/__spec__/json/test_read.py diff --git a/tests/resources/json/test_write.py b/frictionless/resources/__spec__/json/test_write.py similarity index 100% rename from tests/resources/json/test_write.py rename to frictionless/resources/__spec__/json/test_write.py diff --git a/tests/report/task/__init__.py b/frictionless/resources/__spec__/table/__init__.py similarity index 100% rename from tests/report/task/__init__.py rename to frictionless/resources/__spec__/table/__init__.py diff --git a/tests/resources/table/test_compression.py b/frictionless/resources/__spec__/table/test_compression.py similarity index 100% rename from tests/resources/table/test_compression.py rename to frictionless/resources/__spec__/table/test_compression.py diff --git a/tests/resources/table/test_describe.py b/frictionless/resources/__spec__/table/test_describe.py similarity index 100% rename from tests/resources/table/test_describe.py rename to frictionless/resources/__spec__/table/test_describe.py diff --git a/tests/resources/table/test_detector.py b/frictionless/resources/__spec__/table/test_detector.py similarity index 100% rename from tests/resources/table/test_detector.py rename to frictionless/resources/__spec__/table/test_detector.py diff --git a/tests/resources/table/test_dialect.py b/frictionless/resources/__spec__/table/test_dialect.py similarity index 100% rename from tests/resources/table/test_dialect.py rename to frictionless/resources/__spec__/table/test_dialect.py diff --git a/tests/resources/table/test_encoding.py b/frictionless/resources/__spec__/table/test_encoding.py similarity index 100% rename from tests/resources/table/test_encoding.py rename to frictionless/resources/__spec__/table/test_encoding.py diff --git a/tests/resources/table/test_export.py b/frictionless/resources/__spec__/table/test_export.py similarity index 100% rename from tests/resources/table/test_export.py rename to frictionless/resources/__spec__/table/test_export.py diff --git a/tests/resources/table/test_extract.py b/frictionless/resources/__spec__/table/test_extract.py similarity index 100% rename from tests/resources/table/test_extract.py rename to frictionless/resources/__spec__/table/test_extract.py diff --git a/tests/resources/table/test_general.py b/frictionless/resources/__spec__/table/test_general.py similarity index 96% rename from tests/resources/table/test_general.py rename to frictionless/resources/__spec__/table/test_general.py index 090ad55e2a..fd0a5d8336 100644 --- a/tests/resources/table/test_general.py +++ b/frictionless/resources/__spec__/table/test_general.py @@ -78,6 +78,7 @@ def test_resource_from_path_yaml(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_from_path_remote(): resource = TableResource.from_descriptor(BASEURL % "data/resource.json") assert resource.path == "table.csv" @@ -90,6 +91,7 @@ def test_resource_from_path_remote(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_from_url_standards_v0(): resource = TableResource.from_descriptor( {"name": "name", "url": BASEURL % "data/table.csv"} @@ -153,6 +155,7 @@ def test_resource_source_path_and_basepath(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_source_path_and_basepath_remote(): resource = TableResource(path="table.csv", basepath=BASEURL % "data") assert resource.normpath == BASEURL % "data/table.csv" @@ -163,6 +166,7 @@ def test_resource_source_path_and_basepath_remote(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_source_path_remote_and_basepath_remote(): resource = TableResource(path=BASEURL % "data/table.csv", basepath=BASEURL % "data") assert resource.normpath == BASEURL % "data/table.csv" diff --git a/tests/resources/table/test_innerpath.py b/frictionless/resources/__spec__/table/test_innerpath.py similarity index 100% rename from tests/resources/table/test_innerpath.py rename to frictionless/resources/__spec__/table/test_innerpath.py diff --git a/tests/resources/table/test_onerror.py b/frictionless/resources/__spec__/table/test_onerror.py similarity index 100% rename from tests/resources/table/test_onerror.py rename to frictionless/resources/__spec__/table/test_onerror.py diff --git a/tests/resources/table/test_open.py b/frictionless/resources/__spec__/table/test_open.py similarity index 100% rename from tests/resources/table/test_open.py rename to frictionless/resources/__spec__/table/test_open.py diff --git a/tests/resources/table/test_schema.py b/frictionless/resources/__spec__/table/test_schema.py similarity index 98% rename from tests/resources/table/test_schema.py rename to frictionless/resources/__spec__/table/test_schema.py index 7cba413cc4..b9bf3ba91a 100644 --- a/tests/resources/table/test_schema.py +++ b/frictionless/resources/__spec__/table/test_schema.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import Detector, FrictionlessException, Schema, platform @@ -64,6 +66,7 @@ def test_resource_schema_source_data(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_resource_schema_source_remote(): descriptor = { diff --git a/tests/resources/table/test_security.py b/frictionless/resources/__spec__/table/test_security.py similarity index 91% rename from tests/resources/table/test_security.py rename to frictionless/resources/__spec__/table/test_security.py index 9ec0beddc7..b0253b5d04 100644 --- a/tests/resources/table/test_security.py +++ b/frictionless/resources/__spec__/table/test_security.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import FrictionlessException, platform, system @@ -6,6 +8,7 @@ # Bugs +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_relative_parent_path_with_trusted_option_issue_171(): path = ( "data/../data/table.csv" diff --git a/tests/resources/table/test_stats.py b/frictionless/resources/__spec__/table/test_stats.py similarity index 88% rename from tests/resources/table/test_stats.py rename to frictionless/resources/__spec__/table/test_stats.py index 716f41fe31..b31114e97c 100644 --- a/tests/resources/table/test_stats.py +++ b/frictionless/resources/__spec__/table/test_stats.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import Dialect @@ -28,6 +30,7 @@ def test_resource_stats_hash_compressed(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_stats_hash_remote(): with TableResource(path=BASEURL % "data/doublequote.csv") as resource: resource.read_rows() @@ -50,6 +53,7 @@ def test_resource_stats_bytes_compressed(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_stats_bytes_remote(): with TableResource(path=BASEURL % "data/doublequote.csv") as resource: resource.read_rows() @@ -66,6 +70,7 @@ def test_resource_stats_fields(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_stats_fields_remote(): with TableResource(path=BASEURL % "data/doublequote.csv") as resource: resource.read_rows() @@ -82,6 +87,7 @@ def test_resource_stats_rows(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_resource_stats_rows_remote(): with TableResource(path=BASEURL % "data/doublequote.csv") as resource: resource.read_rows() diff --git a/tests/resources/table/test_write.py b/frictionless/resources/__spec__/table/test_write.py similarity index 100% rename from tests/resources/table/test_write.py rename to frictionless/resources/__spec__/table/test_write.py diff --git a/tests/resource/__init__.py b/frictionless/resources/__spec__/text/__init__.py similarity index 100% rename from tests/resource/__init__.py rename to frictionless/resources/__spec__/text/__init__.py diff --git a/tests/resources/text/test_read.py b/frictionless/resources/__spec__/text/test_read.py similarity index 100% rename from tests/resources/text/test_read.py rename to frictionless/resources/__spec__/text/test_read.py diff --git a/tests/resources/text/test_write.py b/frictionless/resources/__spec__/text/test_write.py similarity index 100% rename from tests/resources/text/test_write.py rename to frictionless/resources/__spec__/text/test_write.py diff --git a/tests/resources/__init__.py b/frictionless/schema/__spec__/__init__.py similarity index 100% rename from tests/resources/__init__.py rename to frictionless/schema/__spec__/__init__.py diff --git a/tests/resources/file/__init__.py b/frictionless/schema/__spec__/field/__init__.py similarity index 100% rename from tests/resources/file/__init__.py rename to frictionless/schema/__spec__/field/__init__.py diff --git a/tests/schema/field/test_constraints.py b/frictionless/schema/__spec__/field/test_constraints.py similarity index 100% rename from tests/schema/field/test_constraints.py rename to frictionless/schema/__spec__/field/test_constraints.py diff --git a/tests/schema/field/test_convert.py b/frictionless/schema/__spec__/field/test_convert.py similarity index 100% rename from tests/schema/field/test_convert.py rename to frictionless/schema/__spec__/field/test_convert.py diff --git a/tests/schema/field/test_custom.py b/frictionless/schema/__spec__/field/test_custom.py similarity index 100% rename from tests/schema/field/test_custom.py rename to frictionless/schema/__spec__/field/test_custom.py diff --git a/tests/schema/field/test_general.py b/frictionless/schema/__spec__/field/test_general.py similarity index 100% rename from tests/schema/field/test_general.py rename to frictionless/schema/__spec__/field/test_general.py diff --git a/tests/schema/field/test_read.py b/frictionless/schema/__spec__/field/test_read.py similarity index 100% rename from tests/schema/field/test_read.py rename to frictionless/schema/__spec__/field/test_read.py diff --git a/tests/schema/test_convert.py b/frictionless/schema/__spec__/test_convert.py similarity index 100% rename from tests/schema/test_convert.py rename to frictionless/schema/__spec__/test_convert.py diff --git a/tests/schema/test_describe.py b/frictionless/schema/__spec__/test_describe.py similarity index 100% rename from tests/schema/test_describe.py rename to frictionless/schema/__spec__/test_describe.py diff --git a/tests/schema/test_general.py b/frictionless/schema/__spec__/test_general.py similarity index 99% rename from tests/schema/test_general.py rename to frictionless/schema/__spec__/test_general.py index ea5228005a..52dd3abf31 100644 --- a/tests/schema/test_general.py +++ b/frictionless/schema/__spec__/test_general.py @@ -1,5 +1,6 @@ import io import json +import sys import textwrap from decimal import Decimal from importlib import import_module @@ -60,6 +61,7 @@ def test_schema_descriptor_path(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_schema_descriptor_url(): url = BASEURL % "data/schema.json" schema = Schema(url) diff --git a/tests/schema/test_validate.py b/frictionless/schema/__spec__/test_validate.py similarity index 100% rename from tests/schema/test_validate.py rename to frictionless/schema/__spec__/test_validate.py diff --git a/frictionless/schema/field.py b/frictionless/schema/field.py index 38b1a137b7..75995174e3 100644 --- a/frictionless/schema/field.py +++ b/frictionless/schema/field.py @@ -261,7 +261,8 @@ def metadata_validate(cls, descriptor: IDescriptor): # type: ignore type = descriptor.get("type") Class = system.select_field_class(type) field = Class( - name=descriptor.get("name"), format=descriptor.get("format", "default") # type: ignore + name=descriptor.get("name", "example"), + format=descriptor.get("format", "default"), # type: ignore ) _, notes = field.read_cell(example) if notes is not None: diff --git a/frictionless/schema/types.py b/frictionless/schema/types.py index 8e3eb724d2..654ddf1101 100644 --- a/frictionless/schema/types.py +++ b/frictionless/schema/types.py @@ -109,10 +109,10 @@ class IForeignKeyReference(TypedDict, total=False): class ICellReader(Protocol): - def __call__(self, cell: Any) -> Tuple[Any, INotes]: - ... + def __call__(self, cell: Any) -> Tuple[Any, INotes]: ... class ICellWriter(Protocol): - def __call__(self, cell: Any, *, ignore_missing: bool = False) -> Tuple[Any, INotes]: - ... + def __call__( + self, cell: Any, *, ignore_missing: bool = False + ) -> Tuple[Any, INotes]: ... diff --git a/frictionless/schemes/aws/__init__.py b/frictionless/schemes/aws/__init__.py index 71c5fa5fa0..fa9b32e483 100644 --- a/frictionless/schemes/aws/__init__.py +++ b/frictionless/schemes/aws/__init__.py @@ -1,9 +1,3 @@ -from .control import AwsControl -from .loaders import S3Loader -from .plugin import AwsPlugin - -__all__ = [ - "AwsControl", - "AwsPlugin", - "S3Loader", -] +from .control import AwsControl as AwsControl +from .loaders import S3Loader as S3Loader +from .plugin import AwsPlugin as AwsPlugin diff --git a/tests/resources/json/__init__.py b/frictionless/schemes/aws/__spec__/__init__.py similarity index 100% rename from tests/resources/json/__init__.py rename to frictionless/schemes/aws/__spec__/__init__.py diff --git a/tests/schemes/aws/test_control.py b/frictionless/schemes/aws/__spec__/test_control.py similarity index 100% rename from tests/schemes/aws/test_control.py rename to frictionless/schemes/aws/__spec__/test_control.py diff --git a/tests/resources/table/__init__.py b/frictionless/schemes/aws/loaders/__spec__/__init__.py similarity index 100% rename from tests/resources/table/__init__.py rename to frictionless/schemes/aws/loaders/__spec__/__init__.py diff --git a/tests/schemes/aws/loaders/test_s3.py b/frictionless/schemes/aws/loaders/__spec__/test_s3.py similarity index 98% rename from tests/schemes/aws/loaders/test_s3.py rename to frictionless/schemes/aws/loaders/__spec__/test_s3.py index 2cba303022..347bf3d0fe 100644 --- a/tests/schemes/aws/loaders/test_s3.py +++ b/frictionless/schemes/aws/loaders/__spec__/test_s3.py @@ -3,7 +3,7 @@ import boto3 import pytest -from moto import mock_s3 +from moto import mock_aws from frictionless import Dialect, Package, platform from frictionless.resources import TableResource @@ -11,7 +11,7 @@ # Read -@mock_s3 +@mock_aws def test_s3_loader(bucket_name): # Write client = boto3.resource("s3", region_name="us-east-1") @@ -36,7 +36,7 @@ def test_s3_loader(bucket_name): # Write -@mock_s3 +@mock_aws @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_s3_loader_write(bucket_name): client = boto3.resource("s3", region_name="us-east-1") @@ -55,7 +55,7 @@ def test_s3_loader_write(bucket_name): ] -@mock_s3 +@mock_aws @pytest.mark.ci @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_s3_loader_big_file(bucket_name): @@ -89,7 +89,7 @@ def test_s3_loader_big_file(bucket_name): # Bugs -@mock_s3 +@mock_aws def test_s3_loader_multiprocessing_problem_issue_496(bucket_name): # Write client = boto3.resource("s3", region_name="us-east-1") @@ -117,7 +117,7 @@ def test_s3_loader_multiprocessing_problem_issue_496(bucket_name): assert report.stats["tasks"] == 2 -@mock_s3 +@mock_aws def test_s3_loader_problem_with_spaces_issue_501(bucket_name): # Write client = boto3.resource("s3", region_name="us-east-1") diff --git a/frictionless/schemes/buffer/__init__.py b/frictionless/schemes/buffer/__init__.py index 1a8025859b..d927571c07 100644 --- a/frictionless/schemes/buffer/__init__.py +++ b/frictionless/schemes/buffer/__init__.py @@ -1,9 +1,3 @@ -from .control import BufferControl -from .loader import BufferLoader -from .plugin import BufferPlugin - -__all__ = [ - "BufferControl", - "BufferLoader", - "BufferPlugin", -] +from .control import BufferControl as BufferControl +from .loader import BufferLoader as BufferLoader +from .plugin import BufferPlugin as BufferPlugin diff --git a/tests/resources/text/__init__.py b/frictionless/schemes/buffer/__spec__/__init__.py similarity index 100% rename from tests/resources/text/__init__.py rename to frictionless/schemes/buffer/__spec__/__init__.py diff --git a/tests/schemes/buffer/test_loader.py b/frictionless/schemes/buffer/__spec__/test_loader.py similarity index 100% rename from tests/schemes/buffer/test_loader.py rename to frictionless/schemes/buffer/__spec__/test_loader.py diff --git a/frictionless/schemes/local/__init__.py b/frictionless/schemes/local/__init__.py index 93f3defb9b..f31129ec61 100644 --- a/frictionless/schemes/local/__init__.py +++ b/frictionless/schemes/local/__init__.py @@ -1,9 +1,3 @@ -from .control import LocalControl -from .loader import LocalLoader -from .plugin import LocalPlugin - -__all__ = [ - "LocalControl", - "LocalLoader", - "LocalPlugin", -] +from .control import LocalControl as LocalControl +from .loader import LocalLoader as LocalLoader +from .plugin import LocalPlugin as LocalPlugin diff --git a/tests/schema/__init__.py b/frictionless/schemes/local/__spec__/__init__.py similarity index 100% rename from tests/schema/__init__.py rename to frictionless/schemes/local/__spec__/__init__.py diff --git a/tests/schemes/local/test_loader.py b/frictionless/schemes/local/__spec__/test_loader.py similarity index 100% rename from tests/schemes/local/test_loader.py rename to frictionless/schemes/local/__spec__/test_loader.py diff --git a/frictionless/schemes/multipart/__init__.py b/frictionless/schemes/multipart/__init__.py index 110d8ba167..368e61b08c 100644 --- a/frictionless/schemes/multipart/__init__.py +++ b/frictionless/schemes/multipart/__init__.py @@ -1,9 +1,3 @@ -from .control import MultipartControl -from .loader import MultipartLoader -from .plugin import MultipartPlugin - -__all__ = [ - "MultipartControl", - "MultipartLoader", - "MultipartPlugin", -] +from .control import MultipartControl as MultipartControl +from .loader import MultipartLoader as MultipartLoader +from .plugin import MultipartPlugin as MultipartPlugin diff --git a/tests/schema/field/__init__.py b/frictionless/schemes/multipart/__spec__/__init__.py similarity index 100% rename from tests/schema/field/__init__.py rename to frictionless/schemes/multipart/__spec__/__init__.py diff --git a/tests/schemes/multipart/test_loader.py b/frictionless/schemes/multipart/__spec__/test_loader.py similarity index 96% rename from tests/schemes/multipart/test_loader.py rename to frictionless/schemes/multipart/__spec__/test_loader.py index 8a5578fead..e7aac1abfa 100644 --- a/tests/schemes/multipart/test_loader.py +++ b/frictionless/schemes/multipart/__spec__/test_loader.py @@ -1,4 +1,5 @@ import json +import sys import pytest @@ -40,6 +41,7 @@ def test_multipart_loader_resource(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_multipart_loader_resource_remote(): descriptor = { @@ -60,6 +62,7 @@ def test_multipart_loader_resource_remote(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") @pytest.mark.skipif(platform.type == "windows", reason="Fix on Windows") def test_multipart_loader_resource_remote_both_path_and_basepath(): descriptor = { diff --git a/frictionless/schemes/remote/__init__.py b/frictionless/schemes/remote/__init__.py index 3c7a6b2ffb..6f85485d24 100644 --- a/frictionless/schemes/remote/__init__.py +++ b/frictionless/schemes/remote/__init__.py @@ -1,9 +1,3 @@ -from .control import RemoteControl -from .loader import RemoteLoader -from .plugin import RemotePlugin - -__all__ = [ - "RemoteControl", - "RemoteLoader", - "RemotePlugin", -] +from .control import RemoteControl as RemoteControl +from .loader import RemoteLoader as RemoteLoader +from .plugin import RemotePlugin as RemotePlugin diff --git a/tests/schemes/__init__.py b/frictionless/schemes/remote/__spec__/__init__.py similarity index 100% rename from tests/schemes/__init__.py rename to frictionless/schemes/remote/__spec__/__init__.py diff --git a/tests/schemes/remote/test_loader.py b/frictionless/schemes/remote/__spec__/test_loader.py similarity index 85% rename from tests/schemes/remote/test_loader.py rename to frictionless/schemes/remote/__spec__/test_loader.py index 119ababbe6..7c4800b3a3 100644 --- a/tests/schemes/remote/test_loader.py +++ b/frictionless/schemes/remote/__spec__/test_loader.py @@ -1,3 +1,5 @@ +import sys + import pytest from frictionless import Dialect, platform, schemes @@ -10,6 +12,7 @@ @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_remote_loader(): with TableResource(path=BASEURL % "data/table.csv") as resource: assert resource.header == ["id", "name"] @@ -20,6 +23,7 @@ def test_remote_loader(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_remote_loader_latin1(): # Github returns wrong encoding `utf-8` with TableResource(path=BASEURL % "data/latin1.csv") as resource: @@ -28,6 +32,7 @@ def test_remote_loader_latin1(): @pytest.mark.ci @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_remote_loader_big_file(): dialect = Dialect(header=False) with TableResource(path=BASEURL % "data/table-1MB.csv", dialect=dialect) as resource: @@ -43,6 +48,7 @@ def test_remote_loader_big_file(): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_remote_loader_http_preload(): control = schemes.RemoteControl(http_preload=True) with TableResource(path=BASEURL % "data/table.csv", control=control) as resource: @@ -73,6 +79,7 @@ def test_remote_loader_write(requests_mock): @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_remote_loader_if_remote_basepath_and_file_scheme_issue_1388(): resource = TableResource(path="table.csv", scheme="file", basepath=BASEURL % "data") assert resource.read_rows() == [ diff --git a/frictionless/schemes/stream/__init__.py b/frictionless/schemes/stream/__init__.py index 2e8dc838a4..86180ae724 100644 --- a/frictionless/schemes/stream/__init__.py +++ b/frictionless/schemes/stream/__init__.py @@ -1,9 +1,3 @@ -from .control import StreamControl -from .loader import StreamLoader -from .plugin import StreamPlugin - -__all__ = [ - "StreamControl", - "StreamLoader", - "StreamPlugin", -] +from .control import StreamControl as StreamControl +from .loader import StreamLoader as StreamLoader +from .plugin import StreamPlugin as StreamPlugin diff --git a/tests/schemes/aws/__init__.py b/frictionless/schemes/stream/__spec__/__init__.py similarity index 100% rename from tests/schemes/aws/__init__.py rename to frictionless/schemes/stream/__spec__/__init__.py diff --git a/tests/schemes/stream/test_loader.py b/frictionless/schemes/stream/__spec__/test_loader.py similarity index 100% rename from tests/schemes/stream/test_loader.py rename to frictionless/schemes/stream/__spec__/test_loader.py diff --git a/frictionless/steps/__init__.py b/frictionless/steps/__init__.py index 1272ad774d..dc3dbdad19 100644 --- a/frictionless/steps/__init__.py +++ b/frictionless/steps/__init__.py @@ -3,47 +3,3 @@ from .resource import * from .row import * from .table import * - -__all__ = [ - "cell_convert", - "cell_fill", - "cell_format", - "cell_interpolate", - "cell_replace", - "cell_set", - "field_add", - "field_filter", - "field_merge", - "field_move", - "field_pack", - "field_remove", - "field_split", - "field_unpack", - "field_update", - "resource_add", - "resource_remove", - "resource_transform", - "resource_update", - "row_filter", - "row_search", - "row_slice", - "row_sort", - "row_split", - "row_subset", - "row_ungroup", - "table_aggregate", - "table_attach", - "table_debug", - "table_diff", - "table_intersect", - "table_join", - "table_melt", - "table_merge", - "table_normalize", - "table_pivot", - "table_print", - "table_recast", - "table_transpose", - "table_validate", - "table_write", -] diff --git a/tests/steps/cell/test_cell_convert.py b/frictionless/steps/cell/__spec__/test_cell_convert.py similarity index 100% rename from tests/steps/cell/test_cell_convert.py rename to frictionless/steps/cell/__spec__/test_cell_convert.py diff --git a/tests/steps/cell/test_cell_fill.py b/frictionless/steps/cell/__spec__/test_cell_fill.py similarity index 100% rename from tests/steps/cell/test_cell_fill.py rename to frictionless/steps/cell/__spec__/test_cell_fill.py diff --git a/tests/steps/cell/test_cell_format.py b/frictionless/steps/cell/__spec__/test_cell_format.py similarity index 100% rename from tests/steps/cell/test_cell_format.py rename to frictionless/steps/cell/__spec__/test_cell_format.py diff --git a/tests/steps/cell/test_cell_interpolate.py b/frictionless/steps/cell/__spec__/test_cell_interpolate.py similarity index 100% rename from tests/steps/cell/test_cell_interpolate.py rename to frictionless/steps/cell/__spec__/test_cell_interpolate.py diff --git a/tests/steps/cell/test_cell_replace.py b/frictionless/steps/cell/__spec__/test_cell_replace.py similarity index 100% rename from tests/steps/cell/test_cell_replace.py rename to frictionless/steps/cell/__spec__/test_cell_replace.py diff --git a/tests/steps/cell/test_cell_set.py b/frictionless/steps/cell/__spec__/test_cell_set.py similarity index 100% rename from tests/steps/cell/test_cell_set.py rename to frictionless/steps/cell/__spec__/test_cell_set.py diff --git a/tests/steps/field/test_field_add.py b/frictionless/steps/field/__spec__/test_field_add.py similarity index 100% rename from tests/steps/field/test_field_add.py rename to frictionless/steps/field/__spec__/test_field_add.py diff --git a/tests/steps/field/test_field_filter.py b/frictionless/steps/field/__spec__/test_field_filter.py similarity index 100% rename from tests/steps/field/test_field_filter.py rename to frictionless/steps/field/__spec__/test_field_filter.py diff --git a/tests/steps/field/test_field_merge.py b/frictionless/steps/field/__spec__/test_field_merge.py similarity index 100% rename from tests/steps/field/test_field_merge.py rename to frictionless/steps/field/__spec__/test_field_merge.py diff --git a/tests/steps/field/test_field_move.py b/frictionless/steps/field/__spec__/test_field_move.py similarity index 100% rename from tests/steps/field/test_field_move.py rename to frictionless/steps/field/__spec__/test_field_move.py diff --git a/tests/steps/field/test_field_pack.py b/frictionless/steps/field/__spec__/test_field_pack.py similarity index 100% rename from tests/steps/field/test_field_pack.py rename to frictionless/steps/field/__spec__/test_field_pack.py diff --git a/tests/steps/field/test_field_remove.py b/frictionless/steps/field/__spec__/test_field_remove.py similarity index 100% rename from tests/steps/field/test_field_remove.py rename to frictionless/steps/field/__spec__/test_field_remove.py diff --git a/tests/steps/field/test_field_split.py b/frictionless/steps/field/__spec__/test_field_split.py similarity index 100% rename from tests/steps/field/test_field_split.py rename to frictionless/steps/field/__spec__/test_field_split.py diff --git a/tests/steps/field/test_field_unpack.py b/frictionless/steps/field/__spec__/test_field_unpack.py similarity index 100% rename from tests/steps/field/test_field_unpack.py rename to frictionless/steps/field/__spec__/test_field_unpack.py diff --git a/tests/steps/field/test_field_update.py b/frictionless/steps/field/__spec__/test_field_update.py similarity index 100% rename from tests/steps/field/test_field_update.py rename to frictionless/steps/field/__spec__/test_field_update.py diff --git a/tests/steps/resource/test_resource_add.py b/frictionless/steps/resource/__spec__/test_resource_add.py similarity index 100% rename from tests/steps/resource/test_resource_add.py rename to frictionless/steps/resource/__spec__/test_resource_add.py diff --git a/tests/steps/resource/test_resource_remove.py b/frictionless/steps/resource/__spec__/test_resource_remove.py similarity index 100% rename from tests/steps/resource/test_resource_remove.py rename to frictionless/steps/resource/__spec__/test_resource_remove.py diff --git a/tests/steps/resource/test_resource_transform.py b/frictionless/steps/resource/__spec__/test_resource_transform.py similarity index 100% rename from tests/steps/resource/test_resource_transform.py rename to frictionless/steps/resource/__spec__/test_resource_transform.py diff --git a/tests/steps/resource/test_resource_update.py b/frictionless/steps/resource/__spec__/test_resource_update.py similarity index 100% rename from tests/steps/resource/test_resource_update.py rename to frictionless/steps/resource/__spec__/test_resource_update.py diff --git a/tests/steps/row/test_row_filter.py b/frictionless/steps/row/__spec__/test_row_filter.py similarity index 100% rename from tests/steps/row/test_row_filter.py rename to frictionless/steps/row/__spec__/test_row_filter.py diff --git a/tests/steps/row/test_row_search.py b/frictionless/steps/row/__spec__/test_row_search.py similarity index 100% rename from tests/steps/row/test_row_search.py rename to frictionless/steps/row/__spec__/test_row_search.py diff --git a/tests/steps/row/test_row_slice.py b/frictionless/steps/row/__spec__/test_row_slice.py similarity index 100% rename from tests/steps/row/test_row_slice.py rename to frictionless/steps/row/__spec__/test_row_slice.py diff --git a/tests/steps/row/test_row_sort.py b/frictionless/steps/row/__spec__/test_row_sort.py similarity index 100% rename from tests/steps/row/test_row_sort.py rename to frictionless/steps/row/__spec__/test_row_sort.py diff --git a/tests/steps/row/test_row_split.py b/frictionless/steps/row/__spec__/test_row_split.py similarity index 100% rename from tests/steps/row/test_row_split.py rename to frictionless/steps/row/__spec__/test_row_split.py diff --git a/tests/steps/row/test_row_subset.py b/frictionless/steps/row/__spec__/test_row_subset.py similarity index 100% rename from tests/steps/row/test_row_subset.py rename to frictionless/steps/row/__spec__/test_row_subset.py diff --git a/tests/steps/row/test_row_ungroup.py b/frictionless/steps/row/__spec__/test_row_ungroup.py similarity index 100% rename from tests/steps/row/test_row_ungroup.py rename to frictionless/steps/row/__spec__/test_row_ungroup.py diff --git a/tests/steps/table/test_table_aggregate.py b/frictionless/steps/table/__spec__/test_table_aggregate.py similarity index 100% rename from tests/steps/table/test_table_aggregate.py rename to frictionless/steps/table/__spec__/test_table_aggregate.py diff --git a/tests/steps/table/test_table_attach.py b/frictionless/steps/table/__spec__/test_table_attach.py similarity index 100% rename from tests/steps/table/test_table_attach.py rename to frictionless/steps/table/__spec__/test_table_attach.py diff --git a/tests/steps/table/test_table_diff.py b/frictionless/steps/table/__spec__/test_table_diff.py similarity index 100% rename from tests/steps/table/test_table_diff.py rename to frictionless/steps/table/__spec__/test_table_diff.py diff --git a/tests/steps/table/test_table_intersect.py b/frictionless/steps/table/__spec__/test_table_intersect.py similarity index 100% rename from tests/steps/table/test_table_intersect.py rename to frictionless/steps/table/__spec__/test_table_intersect.py diff --git a/tests/steps/table/test_table_join.py b/frictionless/steps/table/__spec__/test_table_join.py similarity index 100% rename from tests/steps/table/test_table_join.py rename to frictionless/steps/table/__spec__/test_table_join.py diff --git a/tests/steps/table/test_table_melt.py b/frictionless/steps/table/__spec__/test_table_melt.py similarity index 100% rename from tests/steps/table/test_table_melt.py rename to frictionless/steps/table/__spec__/test_table_melt.py diff --git a/tests/steps/table/test_table_merge.py b/frictionless/steps/table/__spec__/test_table_merge.py similarity index 100% rename from tests/steps/table/test_table_merge.py rename to frictionless/steps/table/__spec__/test_table_merge.py diff --git a/tests/steps/table/test_table_pivot.py b/frictionless/steps/table/__spec__/test_table_pivot.py similarity index 100% rename from tests/steps/table/test_table_pivot.py rename to frictionless/steps/table/__spec__/test_table_pivot.py diff --git a/tests/steps/table/test_table_recast.py b/frictionless/steps/table/__spec__/test_table_recast.py similarity index 100% rename from tests/steps/table/test_table_recast.py rename to frictionless/steps/table/__spec__/test_table_recast.py diff --git a/tests/steps/table/test_table_transpose.py b/frictionless/steps/table/__spec__/test_table_transpose.py similarity index 100% rename from tests/steps/table/test_table_transpose.py rename to frictionless/steps/table/__spec__/test_table_transpose.py diff --git a/tests/steps/table/test_table_validate.py b/frictionless/steps/table/__spec__/test_table_validate.py similarity index 100% rename from tests/steps/table/test_table_validate.py rename to frictionless/steps/table/__spec__/test_table_validate.py diff --git a/tests/steps/table/test_table_write.py b/frictionless/steps/table/__spec__/test_table_write.py similarity index 100% rename from tests/steps/table/test_table_write.py rename to frictionless/steps/table/__spec__/test_table_write.py diff --git a/frictionless/steps/table/table_merge.py b/frictionless/steps/table/table_merge.py index b0a2b9cd5a..d08afa17f9 100644 --- a/frictionless/steps/table/table_merge.py +++ b/frictionless/steps/table/table_merge.py @@ -72,7 +72,10 @@ def transform_resource(self, resource: Resource): if self.sort_by_field: key = self.sort_by_field resource.data = platform.petl.mergesort( # type: ignore - view1, view2, key=key, header=field_names # type: ignore + view1, # type: ignore + view2, # type: ignore + key=key, + header=field_names, # type: ignore ) else: resource.data = platform.petl.cat(view1, view2, header=field_names) # type: ignore diff --git a/frictionless/system/__init__.py b/frictionless/system/__init__.py index ccfd359a23..4256bb821c 100644 --- a/frictionless/system/__init__.py +++ b/frictionless/system/__init__.py @@ -1,6 +1,7 @@ from .adapter import Adapter from .loader import Loader from .mapper import Mapper +from .models import PublishResult from .parser import Parser from .plugin import Plugin from .system import System, system diff --git a/tests/schemes/aws/loaders/__init__.py b/frictionless/system/__spec__/__init__.py similarity index 100% rename from tests/schemes/aws/loaders/__init__.py rename to frictionless/system/__spec__/__init__.py diff --git a/tests/system/test_plugin.py b/frictionless/system/__spec__/test_plugin.py similarity index 100% rename from tests/system/test_plugin.py rename to frictionless/system/__spec__/test_plugin.py diff --git a/tests/system/test_system.py b/frictionless/system/__spec__/test_system.py similarity index 87% rename from tests/system/test_system.py rename to frictionless/system/__spec__/test_system.py index 8cd6b910d7..3f6d7a9d59 100644 --- a/tests/system/test_system.py +++ b/frictionless/system/__spec__/test_system.py @@ -1,3 +1,5 @@ +import sys + import pytest import requests @@ -11,6 +13,7 @@ @pytest.mark.vcr +@pytest.mark.skipif(sys.version_info < (3, 10), reason="pytest-vcr bug in Python3.8/9") def test_system_use_context_http_session(): session = requests.Session() with system.use_context(http_session=session): diff --git a/frictionless/system/adapter.py b/frictionless/system/adapter.py index 2c1b547f93..5261f1592c 100644 --- a/frictionless/system/adapter.py +++ b/frictionless/system/adapter.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any -from .. import models +from . import models if TYPE_CHECKING: from ..catalog import Catalog diff --git a/frictionless/models.py b/frictionless/system/models.py similarity index 100% rename from frictionless/models.py rename to frictionless/system/models.py diff --git a/tests/schemes/buffer/__init__.py b/frictionless/table/__spec__/__init__.py similarity index 100% rename from tests/schemes/buffer/__init__.py rename to frictionless/table/__spec__/__init__.py diff --git a/tests/table/test_header.py b/frictionless/table/__spec__/test_header.py similarity index 100% rename from tests/table/test_header.py rename to frictionless/table/__spec__/test_header.py diff --git a/tests/table/test_row.py b/frictionless/table/__spec__/test_row.py similarity index 100% rename from tests/table/test_row.py rename to frictionless/table/__spec__/test_row.py diff --git a/tests/schemes/local/__init__.py b/frictionless/transformer/__spec__/__init__.py similarity index 100% rename from tests/schemes/local/__init__.py rename to frictionless/transformer/__spec__/__init__.py diff --git a/tests/schemes/multipart/__init__.py b/frictionless/transformer/__spec__/resource/__init__.py similarity index 100% rename from tests/schemes/multipart/__init__.py rename to frictionless/transformer/__spec__/resource/__init__.py diff --git a/tests/transformer/resource/test_general.py b/frictionless/transformer/__spec__/resource/test_general.py similarity index 100% rename from tests/transformer/resource/test_general.py rename to frictionless/transformer/__spec__/resource/test_general.py diff --git a/tests/transformer/resource/test_pipeline.py b/frictionless/transformer/__spec__/resource/test_pipeline.py similarity index 100% rename from tests/transformer/resource/test_pipeline.py rename to frictionless/transformer/__spec__/resource/test_pipeline.py diff --git a/tests/transformer/test_package.py b/frictionless/transformer/__spec__/test_package.py similarity index 100% rename from tests/transformer/test_package.py rename to frictionless/transformer/__spec__/test_package.py diff --git a/frictionless/types.py b/frictionless/types.py index 57be9f7057..7d49685d22 100644 --- a/frictionless/types.py +++ b/frictionless/types.py @@ -1,7 +1,17 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, BinaryIO, Dict, Iterable, List, Literal -from typing import Protocol, TextIO, Union +from typing import ( + TYPE_CHECKING, + Any, + BinaryIO, + Dict, + Iterable, + List, + Literal, + Protocol, + TextIO, + Union, +) if TYPE_CHECKING: from .error import Error @@ -31,30 +41,24 @@ class ICheckFunction(Protocol): - def __call__(self, row: Row) -> Iterable[Error]: - ... + def __call__(self, row: Row) -> Iterable[Error]: ... class IEncodingFunction(Protocol): - def __call__(self, buffer: IBuffer) -> str: - ... + def __call__(self, buffer: IBuffer) -> str: ... class IFilterFunction(Protocol): - def __call__(self, row: Row) -> bool: - ... + def __call__(self, row: Row) -> bool: ... class IProcessFunction(Protocol): - def __call__(self, row: Row) -> Dict[str, Any]: - ... + def __call__(self, row: Row) -> Dict[str, Any]: ... class ICallbackFunction(Protocol): - def __call__(self, row: Row) -> None: - ... + def __call__(self, row: Row) -> None: ... class IStepFunction(Protocol): - def __call__(self, source: Union[Resource, Package]) -> None: - ... + def __call__(self, source: Union[Resource, Package]) -> None: ... diff --git a/tests/schemes/remote/__init__.py b/frictionless/validator/__spec__/__init__.py similarity index 100% rename from tests/schemes/remote/__init__.py rename to frictionless/validator/__spec__/__init__.py diff --git a/tests/schemes/stream/__init__.py b/frictionless/validator/__spec__/package/__init__.py similarity index 100% rename from tests/schemes/stream/__init__.py rename to frictionless/validator/__spec__/package/__init__.py diff --git a/tests/validator/package/test_general.py b/frictionless/validator/__spec__/package/test_general.py similarity index 98% rename from tests/validator/package/test_general.py rename to frictionless/validator/__spec__/package/test_general.py index cd0adb4dbd..485abbdac0 100644 --- a/tests/validator/package/test_general.py +++ b/frictionless/validator/__spec__/package/test_general.py @@ -3,8 +3,15 @@ import pytest -from frictionless import Checklist, Detector, FrictionlessException, Package, Resource -from frictionless import Schema, fields +from frictionless import ( + Checklist, + Detector, + FrictionlessException, + Package, + Resource, + Schema, + fields, +) # General diff --git a/tests/validator/package/test_parallel.py b/frictionless/validator/__spec__/package/test_parallel.py similarity index 100% rename from tests/validator/package/test_parallel.py rename to frictionless/validator/__spec__/package/test_parallel.py diff --git a/tests/validator/package/test_schema.py b/frictionless/validator/__spec__/package/test_schema.py similarity index 100% rename from tests/validator/package/test_schema.py rename to frictionless/validator/__spec__/package/test_schema.py diff --git a/tests/validator/package/test_stats.py b/frictionless/validator/__spec__/package/test_stats.py similarity index 100% rename from tests/validator/package/test_stats.py rename to frictionless/validator/__spec__/package/test_stats.py diff --git a/tests/system/__init__.py b/frictionless/validator/__spec__/resource/__init__.py similarity index 100% rename from tests/system/__init__.py rename to frictionless/validator/__spec__/resource/__init__.py diff --git a/tests/validator/resource/test_checklist.py b/frictionless/validator/__spec__/resource/test_checklist.py similarity index 100% rename from tests/validator/resource/test_checklist.py rename to frictionless/validator/__spec__/resource/test_checklist.py diff --git a/tests/validator/resource/test_compression.py b/frictionless/validator/__spec__/resource/test_compression.py similarity index 100% rename from tests/validator/resource/test_compression.py rename to frictionless/validator/__spec__/resource/test_compression.py diff --git a/tests/validator/resource/test_detector.py b/frictionless/validator/__spec__/resource/test_detector.py similarity index 100% rename from tests/validator/resource/test_detector.py rename to frictionless/validator/__spec__/resource/test_detector.py diff --git a/tests/validator/resource/test_dialect.py b/frictionless/validator/__spec__/resource/test_dialect.py similarity index 100% rename from tests/validator/resource/test_dialect.py rename to frictionless/validator/__spec__/resource/test_dialect.py diff --git a/tests/validator/resource/test_encoding.py b/frictionless/validator/__spec__/resource/test_encoding.py similarity index 100% rename from tests/validator/resource/test_encoding.py rename to frictionless/validator/__spec__/resource/test_encoding.py diff --git a/tests/validator/resource/test_file.py b/frictionless/validator/__spec__/resource/test_file.py similarity index 100% rename from tests/validator/resource/test_file.py rename to frictionless/validator/__spec__/resource/test_file.py diff --git a/tests/validator/resource/test_format.py b/frictionless/validator/__spec__/resource/test_format.py similarity index 100% rename from tests/validator/resource/test_format.py rename to frictionless/validator/__spec__/resource/test_format.py diff --git a/tests/validator/resource/test_general.py b/frictionless/validator/__spec__/resource/test_general.py similarity index 99% rename from tests/validator/resource/test_general.py rename to frictionless/validator/__spec__/resource/test_general.py index 394a7be89a..31002ad4b1 100644 --- a/tests/validator/resource/test_general.py +++ b/frictionless/validator/__spec__/resource/test_general.py @@ -2,8 +2,14 @@ import pytest -from frictionless import Check, Checklist, Detector, FrictionlessException, Resource -from frictionless import errors +from frictionless import ( + Check, + Checklist, + Detector, + FrictionlessException, + Resource, + errors, +) from frictionless.resources import TableResource # General diff --git a/tests/validator/resource/test_schema.py b/frictionless/validator/__spec__/resource/test_schema.py similarity index 100% rename from tests/validator/resource/test_schema.py rename to frictionless/validator/__spec__/resource/test_schema.py diff --git a/tests/validator/resource/test_scheme.py b/frictionless/validator/__spec__/resource/test_scheme.py similarity index 100% rename from tests/validator/resource/test_scheme.py rename to frictionless/validator/__spec__/resource/test_scheme.py diff --git a/tests/validator/resource/test_stats.py b/frictionless/validator/__spec__/resource/test_stats.py similarity index 100% rename from tests/validator/resource/test_stats.py rename to frictionless/validator/__spec__/resource/test_stats.py diff --git a/pyproject.toml b/pyproject.toml index 1d0a510bf7..c6d3443ba2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ @@ -45,11 +46,10 @@ dependencies = [ "requests>=2.10", "humanize>=4.2", "tabulate>=0.8.10", - # TODO: remove the limit when https://github.com/python-jsonschema/jsonschema/issues/1119 is resolved - "jsonschema<4.18", + "jsonschema>=4.20", "simpleeval>=0.9.11", "stringcase>=1.2", - "typer[all]>=0.5", + "typer>=0.12", "validators>=0.18", "python-slugify>=1.2", "python-dateutil>=2.8", @@ -62,8 +62,6 @@ dev = [ "ruff", "httpx", "hatch", - "isort", - "black", "yattag", "neovim", "pytest", @@ -78,7 +76,7 @@ dev = [ "requests-mock", "pytest-dotenv", "pytest-timeout", - "pytest-lazy-fixture", + "pytest-lazy-fixtures", ] aws = ["boto3>=1.9"] bigquery = ["google-api-python-client>=1.12.1"] @@ -118,24 +116,40 @@ dependencies = [ coverage = [ "sensible-browser coverage/index.html", ] +image = [ + "docker build --rm -t frictionless-dev .", +] docs = [ "livemark build", ] format = [ - "ruff frictionless tests --fix", - "isort frictionless tests", - "black frictionless tests", + "ruff check --fix", + "ruff format frictionless", ] lint = [ - "ruff frictionless tests", - "isort frictionless tests --check", - "black frictionless tests --check", - "pyright frictionless tests", + "ruff check frictionless", ] -test = [ - "hatch run lint", +release = [ + """ + VERSION=$(hatch run version) + git checkout main && git pull origin && git fetch -p + git log --pretty=format:"%C(yellow)%h%Creset %s%Cgreen%d" --reverse -20 + echo "\nReleasing v$VERSION in 10 seconds. Press to abort\n" && sleep 10 + hatch run test && git commit -a -m "v$VERSION" && git tag -a "v$VERSION" -m "v$VERSION" + git push --follow-tags + """ +] +spec = [ "pytest --cov frictionless --cov-report term-missing --cov-report html:coverage --cov-fail-under 70 --timeout=300", ] +test = [ + "lint", + "type", + "spec", +] +type = [ + "pyright frictionless", +] write = [ "livemark serve", ] @@ -144,34 +158,34 @@ write = [ python = ["3.8", "3.9", "3.10", "3.11", "3.12"] [tool.hatch.envs.ci.scripts] -test = [ - "hatch run lint", +spec = [ "pytest --cov frictionless --cov-report term-missing --cov-report xml --cov-fail-under 75 --timeout=300 --ci", ] +test = [ + "lint", + "type", + "spec", +] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" -[tool.black] -line-length = 90 - -[tool.isort] -profile = "black" -multi_line_output = 9 - [tool.ruff] line-length = 90 + +[tool.ruff.lint] ignore = ["E501", "E731", "F405"] +extend-select = ["I"] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401", "F403"] [tool.pytest.ini_options] -testpaths = ["tests"] +testpaths = ["frictionless"] env_files = [".env"] markers = [ - "ci: integrational tests (select with '--ci')", + "ci: integration tests (select with '--ci')", ] filterwarnings = [ "ignore::DeprecationWarning:boto.*", @@ -183,6 +197,6 @@ filterwarnings = [ [tool.pyright] strict = ["frictionless"] -include = ["frictionless", "tests"] +include = ["frictionless"] exclude = ["frictionless/vendors"] -ignore = ["**/__init__.py"] +ignore = ["**/__spec__/**", "**/__init__.py", "**/conftest.py"] diff --git a/tests/table/__init__.py b/tests/table/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/test_exception.py b/tests/test_exception.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/test_settings.py b/tests/test_settings.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/transformer/__init__.py b/tests/transformer/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/transformer/resource/__init__.py b/tests/transformer/resource/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/validator/__init__.py b/tests/validator/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/validator/package/__init__.py b/tests/validator/package/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/validator/resource/__init__.py b/tests/validator/resource/__init__.py deleted file mode 100644 index e69de29bb2..0000000000