diff --git a/.github/workflows/schemacode_ci.yml b/.github/workflows/schemacode_ci.yml index db6e77700a..f193cd5601 100644 --- a/.github/workflows/schemacode_ci.yml +++ b/.github/workflows/schemacode_ci.yml @@ -4,10 +4,13 @@ on: push: branches: - "master" + - "maint/*" tags: - "schema-*" pull_request: branches: + - "master" + - "maint/*" - "*" concurrency: @@ -87,14 +90,15 @@ jobs: - name: "Run tests" run: | - python -m pytest -vs --pyargs bidsschematools -m "not validate_schema" \ - --cov-append --cov-report=xml --cov=bidsschematools --doctest-modules + python -m pytest -vs --doctest-modules -m "not validate_schema" \ + --cov-append --cov-report=xml --cov-report=term --cov=src/bidsschematools + working-directory: tools/schemacode - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: unit_${{ matrix.os }}_${{ matrix.python-version }} - path: coverage.xml + path: tools/schemacode/coverage.xml if: success() publish: @@ -143,13 +147,16 @@ jobs: python -m pip install -e ./tools/schemacode[all] - name: Run schema validation tests - run: python -m pytest --pyargs bidsschematools -m "validate_schema" --cov-append --cov-report=xml --cov=bidsschematools + run: | + python -m pytest -vs --doctest-modules -m "not validate_schema" \ + --cov-append --cov-report=xml --cov-report=term --cov=src/bidsschematools + working-directory: tools/schemacode - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: schema_validation - path: coverage.xml + path: tools/schemacode/coverage.xml if: success() upload_to_codecov: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 277632e355..c2261af7e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks ci: skip: [shellcheck] -exclude: 'tools/schemacode/bidsschematools/tests/data/broken_dataset_description.json' +exclude: 'tools/schemacode/src/bidsschematools/tests/data/broken_dataset_description.json' repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 @@ -83,7 +83,7 @@ repos: - types-jsonschema - jsonschema - httpx - args: ["tools/schemacode/bidsschematools"] + args: ["tools/schemacode/src"] pass_filenames: false - repo: https://github.com/koalaman/shellcheck-precommit rev: v0.10.0 diff --git a/tools/schemacode/MANIFEST.in b/tools/schemacode/MANIFEST.in new file mode 100644 index 0000000000..37f630a4ae --- /dev/null +++ b/tools/schemacode/MANIFEST.in @@ -0,0 +1 @@ +recursive-include tests * diff --git a/tools/schemacode/bidsschematools/data/metaschema.json b/tools/schemacode/bidsschematools/data/metaschema.json deleted file mode 120000 index ae3cfc38f9..0000000000 --- a/tools/schemacode/bidsschematools/data/metaschema.json +++ /dev/null @@ -1 +0,0 @@ -../../../../src/metaschema.json \ No newline at end of file diff --git a/tools/schemacode/bidsschematools/data/schema b/tools/schemacode/bidsschematools/data/schema deleted file mode 120000 index a06955547a..0000000000 --- a/tools/schemacode/bidsschematools/data/schema +++ /dev/null @@ -1 +0,0 @@ -../../../../src/schema \ No newline at end of file diff --git a/tools/schemacode/bidsschematools/tests/test_make_testdata.py b/tools/schemacode/bidsschematools/tests/test_make_testdata.py deleted file mode 100644 index 5721b630d6..0000000000 --- a/tools/schemacode/bidsschematools/tests/test_make_testdata.py +++ /dev/null @@ -1,48 +0,0 @@ -import os -import shutil - -try: - from importlib.resources import files -except ImportError: # PY<3.9 - from importlib_resources import files - -import pytest - - -def require_env(var): - env = os.environ.get(var) - return pytest.mark.skipif( - not env, reason=f"To activate this test/feature `export {var}=1` and re-run." - ) - - -@require_env("BIDSSCHEMATOOLS_RELEASE") -def test_make_archive(bids_examples, bids_error_examples): - """ - ATTENTION! This is not a test! - Create static testdata archive containing the bidsschematools data reference whitelist. - - Notes - ----- - Due to intricacies arising from: - - (1) fixtures not working outside of pytest - (2) implicit teardown leveraging tempdata removal (while held open by yield) - (3) wrappers evaluating the yield statement - (4) the desire to not download testdata twice for archive creation - - testdata archive creation is now inconspicuously posing as a test. - """ - - testdata_dir = files("bidsschematools.tests.data") - ignore_git = shutil.ignore_patterns(".git*") - shutil.copytree(bids_examples, testdata_dir / "bids-examples", ignore=ignore_git) - shutil.copytree(bids_error_examples, testdata_dir / "bids-error-examples", ignore=ignore_git) - - # Keeping this for now, it would be really nice to have a separate archive someday. - # archive_name = f"bidsschematools-testdata-{__version__}" - # archive_path = f"/tmp/{archive_name}.tar.gz" - - # with tarfile.open(archive_path, "w:gz") as tar: - # tar.add(bids_examples, arcname=f"{archive_name}/bids-examples") - # tar.add(bids_error_examples, arcname=f"{archive_name}/bids-error-examples") diff --git a/tools/schemacode/pyproject.toml b/tools/schemacode/pyproject.toml index 22547f33ef..ce49dcd818 100644 --- a/tools/schemacode/pyproject.toml +++ b/tools/schemacode/pyproject.toml @@ -30,9 +30,11 @@ markers = [ "validate_schema: tests that validate the schema itself", ] +[tool.coverage.paths] +source = [ + "src/bidsschematools", + "**/site-packages/bidsschematools", +] + [tool.coverage.run] parallel = true -omit = [ - "*/*/tests/*", - "**/tests/*" -] diff --git a/tools/schemacode/setup.cfg b/tools/schemacode/setup.cfg index f75732b593..aa3d19de1b 100644 --- a/tools/schemacode/setup.cfg +++ b/tools/schemacode/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = bidsschematools -version = file:bidsschematools/data/schema/SCHEMA_VERSION +version = file:src/bidsschematools/data/schema/SCHEMA_VERSION url = https://github.com/bids-standard/bids-specification author = bids-standard developers author_email = bids.maintenance@gmail.com @@ -25,8 +25,6 @@ install_requires = pyyaml importlib_resources; python_version < "3.9" jsonschema -packages = find: -include_package_data = false zip_safe = false [options.extras_require] @@ -59,8 +57,7 @@ bidsschematools = data/schema/BIDS_VERSION data/schema/SCHEMA_VERSION data/schema/**/*.yaml - tests/data/**/* - tests/data/**/.bidsignore + tests/data/* [options.entry_points] console_scripts = diff --git a/tools/schemacode/bidsschematools/__init__.py b/tools/schemacode/src/bidsschematools/__init__.py similarity index 100% rename from tools/schemacode/bidsschematools/__init__.py rename to tools/schemacode/src/bidsschematools/__init__.py diff --git a/tools/schemacode/bidsschematools/__main__.py b/tools/schemacode/src/bidsschematools/__main__.py similarity index 100% rename from tools/schemacode/bidsschematools/__main__.py rename to tools/schemacode/src/bidsschematools/__main__.py diff --git a/tools/schemacode/bidsschematools/conftest.py b/tools/schemacode/src/bidsschematools/conftest.py similarity index 82% rename from tools/schemacode/bidsschematools/conftest.py rename to tools/schemacode/src/bidsschematools/conftest.py index 2e5eaec86f..0a47d26535 100644 --- a/tools/schemacode/bidsschematools/conftest.py +++ b/tools/schemacode/src/bidsschematools/conftest.py @@ -1,12 +1,8 @@ import logging import tempfile +from pathlib import Path from subprocess import run -try: - from importlib.resources import as_file, files -except ImportError: # PY<3.9 - from importlib_resources import as_file, files - import pytest lgr = logging.getLogger() @@ -35,23 +31,37 @@ ] +@pytest.fixture(scope="session") +def tests_data_dir(): + try: + this_file = Path(__file__) + except NameError: + return None + + data_dir = this_file.parent.parent.parent / "tests" / "data" + + if data_dir.exists(): + return data_dir + + def get_gitrepo_fixture(url, whitelist): @pytest.fixture(scope="session") - def fixture(): + def fixture(tests_data_dir): + if tests_data_dir is None: + pytest.skip("No test data directory found; probably in an installed package") archive_name = url.rsplit("/", 1)[-1] - testdata_dir = files("bidsschematools.tests.data") / archive_name - if testdata_dir.is_dir(): + archive_dir = tests_data_dir / archive_name + if archive_dir.is_dir(): lgr.info( - f"Found static testdata archive under `{testdata_dir}`. " + f"Found static testdata archive under `{archive_dir}`. " "Not downloading latest data from version control." ) - with as_file(testdata_dir) as path: - yield path + yield archive_dir else: lgr.info( "No static testdata available under `%s`. " "Attempting to fetch live data from version control.", - testdata_dir, + archive_dir, ) with tempfile.TemporaryDirectory() as path: lgr.debug("Cloning %r into %r", url, path) diff --git a/tools/schemacode/bidsschematools/data/__init__.py b/tools/schemacode/src/bidsschematools/data/__init__.py similarity index 100% rename from tools/schemacode/bidsschematools/data/__init__.py rename to tools/schemacode/src/bidsschematools/data/__init__.py diff --git a/tools/schemacode/src/bidsschematools/data/metaschema.json b/tools/schemacode/src/bidsschematools/data/metaschema.json new file mode 120000 index 0000000000..399e1beffb --- /dev/null +++ b/tools/schemacode/src/bidsschematools/data/metaschema.json @@ -0,0 +1 @@ +../../../../../src/metaschema.json \ No newline at end of file diff --git a/tools/schemacode/src/bidsschematools/data/schema b/tools/schemacode/src/bidsschematools/data/schema new file mode 120000 index 0000000000..1e33d0b966 --- /dev/null +++ b/tools/schemacode/src/bidsschematools/data/schema @@ -0,0 +1 @@ +../../../../../src/schema \ No newline at end of file diff --git a/tools/schemacode/bidsschematools/data/tests/test_rules.py b/tools/schemacode/src/bidsschematools/data/tests/test_rules.py similarity index 100% rename from tools/schemacode/bidsschematools/data/tests/test_rules.py rename to tools/schemacode/src/bidsschematools/data/tests/test_rules.py diff --git a/tools/schemacode/bidsschematools/expressions.py b/tools/schemacode/src/bidsschematools/expressions.py similarity index 100% rename from tools/schemacode/bidsschematools/expressions.py rename to tools/schemacode/src/bidsschematools/expressions.py diff --git a/tools/schemacode/bidsschematools/render/__init__.py b/tools/schemacode/src/bidsschematools/render/__init__.py similarity index 100% rename from tools/schemacode/bidsschematools/render/__init__.py rename to tools/schemacode/src/bidsschematools/render/__init__.py diff --git a/tools/schemacode/bidsschematools/render/tables.py b/tools/schemacode/src/bidsschematools/render/tables.py similarity index 100% rename from tools/schemacode/bidsschematools/render/tables.py rename to tools/schemacode/src/bidsschematools/render/tables.py diff --git a/tools/schemacode/bidsschematools/render/text.py b/tools/schemacode/src/bidsschematools/render/text.py similarity index 100% rename from tools/schemacode/bidsschematools/render/text.py rename to tools/schemacode/src/bidsschematools/render/text.py diff --git a/tools/schemacode/bidsschematools/render/utils.py b/tools/schemacode/src/bidsschematools/render/utils.py similarity index 100% rename from tools/schemacode/bidsschematools/render/utils.py rename to tools/schemacode/src/bidsschematools/render/utils.py diff --git a/tools/schemacode/bidsschematools/rules.py b/tools/schemacode/src/bidsschematools/rules.py similarity index 100% rename from tools/schemacode/bidsschematools/rules.py rename to tools/schemacode/src/bidsschematools/rules.py diff --git a/tools/schemacode/bidsschematools/schema.py b/tools/schemacode/src/bidsschematools/schema.py similarity index 100% rename from tools/schemacode/bidsschematools/schema.py rename to tools/schemacode/src/bidsschematools/schema.py diff --git a/tools/schemacode/bidsschematools/tests/__init__.py b/tools/schemacode/src/bidsschematools/tests/__init__.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/__init__.py rename to tools/schemacode/src/bidsschematools/tests/__init__.py diff --git a/tools/schemacode/bidsschematools/tests/data/__init__.py b/tools/schemacode/src/bidsschematools/tests/data/__init__.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/data/__init__.py rename to tools/schemacode/src/bidsschematools/tests/data/__init__.py diff --git a/tools/schemacode/bidsschematools/tests/data/broken_dataset_description.json b/tools/schemacode/src/bidsschematools/tests/data/broken_dataset_description.json similarity index 100% rename from tools/schemacode/bidsschematools/tests/data/broken_dataset_description.json rename to tools/schemacode/src/bidsschematools/tests/data/broken_dataset_description.json diff --git a/tools/schemacode/bidsschematools/tests/data/expected_bids_validator_xs_write.log b/tools/schemacode/src/bidsschematools/tests/data/expected_bids_validator_xs_write.log similarity index 100% rename from tools/schemacode/bidsschematools/tests/data/expected_bids_validator_xs_write.log rename to tools/schemacode/src/bidsschematools/tests/data/expected_bids_validator_xs_write.log diff --git a/tools/schemacode/bidsschematools/tests/test_expressions.py b/tools/schemacode/src/bidsschematools/tests/test_expressions.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_expressions.py rename to tools/schemacode/src/bidsschematools/tests/test_expressions.py diff --git a/tools/schemacode/src/bidsschematools/tests/test_make_testdata.py b/tools/schemacode/src/bidsschematools/tests/test_make_testdata.py new file mode 100644 index 0000000000..77c6ae9d00 --- /dev/null +++ b/tools/schemacode/src/bidsschematools/tests/test_make_testdata.py @@ -0,0 +1,38 @@ +import os +import shutil + +import pytest + + +def require_env(var): + env = os.environ.get(var) + return pytest.mark.skipif( + not env, reason=f"To activate this test/feature `export {var}=1` and re-run." + ) + + +@require_env("BIDSSCHEMATOOLS_RELEASE") +def test_make_archive(tests_data_dir, bids_examples, bids_error_examples): + """ + ATTENTION! This is not a test! + Create static testdata archive containing the bidsschematools data reference whitelist. + + Notes + ----- + Due to intricacies arising from: + + (1) fixtures not working outside of pytest + (2) implicit teardown leveraging tempdata removal (while held open by yield) + (3) wrappers evaluating the yield statement + (4) the desire to not download testdata twice for archive creation + + testdata archive creation is now inconspicuously posing as a test. + """ + + ignore_git = shutil.ignore_patterns(".git*") + target_examples = tests_data_dir / "bids-examples" + target_error_examples = tests_data_dir / "bids-error-examples" + if bids_examples != target_examples: + shutil.copytree(bids_examples, target_examples, ignore=ignore_git) + if bids_error_examples != target_error_examples: + shutil.copytree(bids_error_examples, target_error_examples, ignore=ignore_git) diff --git a/tools/schemacode/bidsschematools/tests/test_render_tables.py b/tools/schemacode/src/bidsschematools/tests/test_render_tables.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_render_tables.py rename to tools/schemacode/src/bidsschematools/tests/test_render_tables.py diff --git a/tools/schemacode/bidsschematools/tests/test_render_text.py b/tools/schemacode/src/bidsschematools/tests/test_render_text.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_render_text.py rename to tools/schemacode/src/bidsschematools/tests/test_render_text.py diff --git a/tools/schemacode/bidsschematools/tests/test_render_utils.py b/tools/schemacode/src/bidsschematools/tests/test_render_utils.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_render_utils.py rename to tools/schemacode/src/bidsschematools/tests/test_render_utils.py diff --git a/tools/schemacode/bidsschematools/tests/test_rules.py b/tools/schemacode/src/bidsschematools/tests/test_rules.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_rules.py rename to tools/schemacode/src/bidsschematools/tests/test_rules.py diff --git a/tools/schemacode/bidsschematools/tests/test_schema.py b/tools/schemacode/src/bidsschematools/tests/test_schema.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_schema.py rename to tools/schemacode/src/bidsschematools/tests/test_schema.py diff --git a/tools/schemacode/bidsschematools/tests/test_validator.py b/tools/schemacode/src/bidsschematools/tests/test_validator.py similarity index 100% rename from tools/schemacode/bidsschematools/tests/test_validator.py rename to tools/schemacode/src/bidsschematools/tests/test_validator.py diff --git a/tools/schemacode/bidsschematools/types/__init__.py b/tools/schemacode/src/bidsschematools/types/__init__.py similarity index 100% rename from tools/schemacode/bidsschematools/types/__init__.py rename to tools/schemacode/src/bidsschematools/types/__init__.py diff --git a/tools/schemacode/bidsschematools/types/namespace.py b/tools/schemacode/src/bidsschematools/types/namespace.py similarity index 100% rename from tools/schemacode/bidsschematools/types/namespace.py rename to tools/schemacode/src/bidsschematools/types/namespace.py diff --git a/tools/schemacode/bidsschematools/utils.py b/tools/schemacode/src/bidsschematools/utils.py similarity index 100% rename from tools/schemacode/bidsschematools/utils.py rename to tools/schemacode/src/bidsschematools/utils.py diff --git a/tools/schemacode/bidsschematools/validator.py b/tools/schemacode/src/bidsschematools/validator.py similarity index 100% rename from tools/schemacode/bidsschematools/validator.py rename to tools/schemacode/src/bidsschematools/validator.py diff --git a/tools/schemacode/tests/data/.gitignore b/tools/schemacode/tests/data/.gitignore new file mode 100644 index 0000000000..2dc3af1b14 --- /dev/null +++ b/tools/schemacode/tests/data/.gitignore @@ -0,0 +1 @@ +bids*-examples