diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..e6ec6ccb --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others’ private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project’s leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..a1db846c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,94 @@ +name: Bug Report +description: File a bug report. +title: "[Bug]: " +labels: ["bug"] + +body: + - type: markdown + attributes: + value: | + # Thanks for taking the time to fill out this bug report! + ### The following information will help us resolve your issue. + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to Reproduce + description: | + Please copy and paste the code you were trying to run that caused the error. + + Feel free to include as little or as much as you think is relevant. This section will be automatically formatted into code, so no need for backticks. + render: shell + validations: + required: true + - type: textarea + id: traceback + attributes: + label: Traceback + description: | + Please copy and paste the full traceback produced by the error. + + This section will be automatically formatted into code, so no need for backticks. + render: shell + validations: + required: true + - type: dropdown + id: os + attributes: + label: Operating System + options: + - Windows + - macOS + - Linux + validations: + required: true + - type: dropdown + id: executable + attributes: + label: Python Executable + options: + - Conda + - Python + validations: + required: true + - type: dropdown + id: python_version + attributes: + label: Python Version + options: + - "3.7" + - "3.8" + - "3.9" + - "3.10" + - "3.11" + validations: + required: true + - type: textarea + id: package_versions + attributes: + label: Package Versions + description: | + Please share your currently installed Python package versions by calling `pip freeze > environment_for_issue.txt` and uploading the text file along with this issue. + + This helps us determine if there are any secondary or tertiary issues caused by other dependencies. + + You can attach images or log files by clicking this area to highlight it and then dragging files in. + If GitHub upload is not working, you can also copy and paste the output into this section. + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/.github/CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's [Code of Conduct](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/.github/CODE_OF_CONDUCT.md) + required: true + - label: Have you checked the [Contributing](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/docs/CONTRIBUTING.rst) document? + required: true + - label: Have you ensured this bug was not already [reported](https://github.com/hdmf-dev/hdmf-zarr/issues)? + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..9a5863af --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Read the Documentation + url: https://hdmf-zarr.readthedocs.io/en/latest/ + about: Check out the full documentation. diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 00000000..1558a13e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,46 @@ +name: Documentation +description: Is the documentation of something missing, unclear, or lacking? This is the place. +title: "[Documentation]: " +labels: "documentation" +body: + - type: markdown + attributes: + value: | + ## Thank you for your suggestion! + + We welcome any ideas about how to make **HDMF-ZARR** better for the community. + + Please keep in mind that new or improved documentation may not get implemented immediately. + - type: textarea + id: summary + attributes: + label: What would you like changed or added to the documentation and why? + description: Do you have any suggestions for the documents? + validations: + required: true + - type: dropdown + id: interest + attributes: + label: Do you have any interest in helping write or edit the documentation? + description: | + We appreciate any help you can offer! + + For information on how to contribute, please refer to our [contributing guidelines](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/docs/CONTRIBUTING.rst). + options: + - Yes. + - Yes, but I would need guidance. + - No. + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/.github/CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's [Code of Conduct](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/.github/CODE_OF_CONDUCT.md) + required: true + - label: Have you checked the [Contributing](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/docs/CONTRIBUTING.rst) document? + required: true + - label: Have you ensured this change was not already [requested](https://github.com/hdmf-dev/hdmf-zarr/issues)? + required: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..85462b52 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,64 @@ +name: Feature Request +description: Suggest an idea for a brand new feature, or a change to an existing one. +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + ## Thank you for your suggestion! + + We welcome any ideas about how to make **HDMF-ZARR** better for the community. + + Please keep in mind that new features may not get implemented immediately. + - type: textarea + id: summary + attributes: + label: What would you like to see added to HDMF-ZARR? + description: | + What are you trying to achieve with **HDMF-ZARR**? + + Is this a more convenient way to do something that is already possible, or is a workaround currently unfeasible? + validations: + required: true + - type: textarea + id: problem + attributes: + label: Is your feature request related to a problem? + description: A clear and concise description of what the problem is. + - type: textarea + id: solution + attributes: + label: What solution would you like? + description: | + A clear and concise description of what you want to happen. + + Describe alternative solutions you have considered. + validations: + required: true + - type: dropdown + id: interest + attributes: + label: Do you have any interest in helping implement the feature? + description: | + We appreciate any help you can offer! + + For information on how to contribute, please refer to our [contributing guidelines](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/docs/CONTRIBUTING.rst). + options: + - Yes. + - Yes, but I would need guidance. + - No. + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/.github/CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's [Code of Conduct](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/.github/CODE_OF_CONDUCT.md) + required: true + - label: Have you checked the [Contributing](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/docs/CONTRIBUTING.rst) document? + required: true + - label: Have you ensured this change was not already [requested](https://github.com/hdmf-dev/hdmf-zarr/issues)? + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE/release.md b/.github/PULL_REQUEST_TEMPLATE/release.md new file mode 100644 index 00000000..a26798e0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/release.md @@ -0,0 +1,24 @@ +Prepare for release of HDMF-Zarr [version] + +### Before merging: +- [ ] Major and minor releases: Update package versions in `requirements.txt`, `requirements-dev.txt`, + `requirements-doc.txt`, `requirements-min.txt`, and `setup.py` as needed +- [ ] Check legal file dates and information in `Legal.txt`, `license.txt`, `README.rst`, `docs/source/conf.py`, + and any other locations as needed +- [ ] Update `setup.py` as needed +- [ ] Update `README.rst` as needed +- [ ] Update changelog (set release date) in `CHANGELOG.md` and any other docs as needed +- [ ] Run tests locally including gallery tests, and inspect all warnings and outputs + (`pytest && python test_gallery.py`) +- [ ] Test docs locally by going into the `docs` directory and running the following: `make clean && make html` +- [ ] Push changes to this PR and make sure all PRs to be included in this release have been merged +- [ ] Check that the readthedocs build for this PR succeeds (build latest to pull the new branch, then activate and + build docs for new branch): https://readthedocs.org/projects/hdmf-zarr/builds/ + +### After merging: +1. Create release by following steps in `docs/source/make_a_release.rst` or use alias `git pypi-release [tag]` if set up +2. After the CI bot creates the new release (wait ~10 min), update the release notes on the + [GitHub releases page](https://github.com/hdmf-dev/hdmf-zarr/releases) with the changelog +3. Check that the readthedocs "latest" and "stable" builds run and succeed +4. Update [conda-forge/hdmf_zarr-feedstock](https://github.com/conda-forge/hdmf_zarr-feedstock) with the latest version number + and SHA256 retrieved from PyPI > HDMF-Zarr > Download Files > View hashes for the `.tar.gz` file. Re-render as needed diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..8435ea82 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +## Motivation + +What was the reasoning behind this change? Please explain the changes briefly. + +## How to test the behavior? +``` +Show how to reproduce the new behavior (can be a bug fix or a new feature) +``` + +## Checklist + +- [ ] Did you update CHANGELOG.md with your changes? +- [ ] Have you checked our [Contributing](https://github.com/hdmf-dev/hdmf-zarr/blob/dev/docs/CONTRIBUTING.rst) document? +- [ ] Have you ensured the PR clearly describes the problem and the solution? +- [ ] Is your contribution compliant with our coding style? This can be checked running `ruff` from the source directory. +- [ ] Have you checked to ensure that there aren't other open [Pull Requests](https://github.com/hdmf-dev/hdmf-zarr/pulls) for the same change? +- [ ] Have you included the relevant issue number using "Fix #XXX" notation where XXX is the issue number? By including "Fix #XXX" you allow GitHub to close issue #XXX when the PR is merged. diff --git a/.github/workflows/check_external_links.yml b/.github/workflows/check_external_links.yml index c084c229..1fbf0ee0 100644 --- a/.github/workflows/check_external_links.yml +++ b/.github/workflows/check_external_links.yml @@ -22,7 +22,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install Sphinx dependencies and package run: | diff --git a/.github/workflows/deploy_release.yml b/.github/workflows/deploy_release.yml index 1287944f..7a3e7399 100644 --- a/.github/workflows/deploy_release.yml +++ b/.github/workflows/deploy_release.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install build dependencies run: | @@ -28,11 +28,11 @@ jobs: - name: Run tox tests run: | - tox -e py310-upgraded + tox -e py311-upgraded - name: Build wheel and source distribution run: | - tox -e build-py310-upgraded + tox -e build-py311-upgraded ls -1 dist - name: Test installation from a wheel diff --git a/.github/workflows/run_all_tests.yml b/.github/workflows/run_all_tests.yml index 2eb6a9d7..e58226f3 100644 --- a/.github/workflows/run_all_tests.yml +++ b/.github/workflows/run_all_tests.yml @@ -26,23 +26,26 @@ jobs: - { name: linux-python3.8 , test-tox-env: py38 , build-tox-env: build-py38 , python-ver: "3.8" , os: ubuntu-latest } - { name: linux-python3.9 , test-tox-env: py39 , build-tox-env: build-py39 , python-ver: "3.9" , os: ubuntu-latest } - { name: linux-python3.10 , test-tox-env: py310 , build-tox-env: build-py310 , python-ver: "3.10", os: ubuntu-latest } - - { name: linux-python3.10-optional , test-tox-env: py310-optional , build-tox-env: build-py310-optional , python-ver: "3.10", os: ubuntu-latest } - - { name: linux-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: ubuntu-latest } - - { name: linux-python3.10-prerelease , test-tox-env: py310-prerelease, build-tox-env: build-py310-prerelease, python-ver: "3.10", os: ubuntu-latest } + - { name: linux-python3.11 , test-tox-env: py311 , build-tox-env: build-py311 , python-ver: "3.11", os: ubuntu-latest } + - { name: linux-python3.11-optional , test-tox-env: py311-optional , build-tox-env: build-py311-optional , python-ver: "3.11", os: ubuntu-latest } + - { name: linux-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: ubuntu-latest } + - { name: linux-python3.11-prerelease , test-tox-env: py311-prerelease, build-tox-env: build-py311-prerelease, python-ver: "3.11", os: ubuntu-latest } - { name: windows-python3.7-minimum , test-tox-env: py37-minimum , build-tox-env: build-py37-minimum , python-ver: "3.7" , os: windows-latest } - { name: windows-python3.8 , test-tox-env: py38 , build-tox-env: build-py38 , python-ver: "3.8" , os: windows-latest } - { name: windows-python3.9 , test-tox-env: py39 , build-tox-env: build-py39 , python-ver: "3.9" , os: windows-latest } - { name: windows-python3.10 , test-tox-env: py310 , build-tox-env: build-py310 , python-ver: "3.10", os: windows-latest } - - { name: windows-python3.10-optional , test-tox-env: py310-optional , build-tox-env: build-py310-optional , python-ver: "3.10", os: windows-latest } - - { name: windows-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: windows-latest } - - { name: windows-python3.10-prerelease, test-tox-env: py310-prerelease, build-tox-env: build-py310-prerelease, python-ver: "3.10", os: windows-latest } + - { name: windows-python3.11 , test-tox-env: py311 , build-tox-env: build-py311 , python-ver: "3.11", os: windows-latest } + - { name: windows-python3.11-optional , test-tox-env: py311-optional , build-tox-env: build-py311-optional , python-ver: "3.11", os: windows-latest } + - { name: windows-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: windows-latest } + - { name: windows-python3.11-prerelease, test-tox-env: py311-prerelease, build-tox-env: build-py311-prerelease, python-ver: "3.11", os: windows-latest } - { name: macos-python3.7-minimum , test-tox-env: py37-minimum , build-tox-env: build-py37-minimum , python-ver: "3.7" , os: macos-latest } - { name: macos-python3.8 , test-tox-env: py38 , build-tox-env: build-py38 , python-ver: "3.8" , os: macos-latest } - { name: macos-python3.9 , test-tox-env: py39 , build-tox-env: build-py39 , python-ver: "3.9" , os: macos-latest } - { name: macos-python3.10 , test-tox-env: py310 , build-tox-env: build-py310 , python-ver: "3.10", os: macos-latest } - - { name: macos-python3.10-optional , test-tox-env: py310-optional , build-tox-env: build-py310-optional , python-ver: "3.10", os: macos-latest } - - { name: macos-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: macos-latest } - - { name: macos-python3.10-prerelease , test-tox-env: py310-prerelease, build-tox-env: build-py310-prerelease, python-ver: "3.10", os: macos-latest } + - { name: macos-python3.11 , test-tox-env: py311 , build-tox-env: build-py311 , python-ver: "3.11", os: macos-latest } + - { name: macos-python3.11-optional , test-tox-env: py311-optional , build-tox-env: build-py311-optional , python-ver: "3.11", os: macos-latest } + - { name: macos-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: macos-latest } + - { name: macos-python3.11-prerelease , test-tox-env: py311-prerelease, build-tox-env: build-py311-prerelease, python-ver: "3.11", os: macos-latest } steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -86,14 +89,14 @@ jobs: matrix: include: - { name: linux-gallery-python3.7-minimum , test-tox-env: gallery-py37-minimum , python-ver: "3.7" , os: ubuntu-latest } - - { name: linux-gallery-python3.10-upgraded , test-tox-env: gallery-py310-upgraded , python-ver: "3.10", os: ubuntu-latest } - - { name: linux-gallery-python3.10-prerelease , test-tox-env: gallery-py310-prerelease, python-ver: "3.10", os: ubuntu-latest } + - { name: linux-gallery-python3.11-upgraded , test-tox-env: gallery-py311-upgraded , python-ver: "3.11", os: ubuntu-latest } + - { name: linux-gallery-python3.11-prerelease , test-tox-env: gallery-py311-prerelease, python-ver: "3.11", os: ubuntu-latest } - { name: windows-gallery-python3.7-minimum , test-tox-env: gallery-py37-minimum , python-ver: "3.7" , os: windows-latest } - - { name: windows-gallery-python3.10-upgraded , test-tox-env: gallery-py310-upgraded , python-ver: "3.10", os: windows-latest } - - { name: windows-gallery-python3.10-prerelease, test-tox-env: gallery-py310-prerelease, python-ver: "3.10", os: windows-latest } + - { name: windows-gallery-python3.11-upgraded , test-tox-env: gallery-py311-upgraded , python-ver: "3.11", os: windows-latest } + - { name: windows-gallery-python3.11-prerelease, test-tox-env: gallery-py311-prerelease, python-ver: "3.11", os: windows-latest } - { name: macos-gallery-python3.7-minimum , test-tox-env: gallery-py37-minimum , python-ver: "3.7" , os: macos-latest } - - { name: macos-gallery-python3.10-upgraded , test-tox-env: gallery-py310-upgraded , python-ver: "3.10", os: macos-latest } - - { name: macos-gallery-python3.10-prerelease , test-tox-env: gallery-py310-prerelease, python-ver: "3.10", os: macos-latest } + - { name: macos-gallery-python3.11-upgraded , test-tox-env: gallery-py311-upgraded , python-ver: "3.11", os: macos-latest } + - { name: macos-gallery-python3.11-prerelease , test-tox-env: gallery-py311-prerelease, python-ver: "3.11", os: macos-latest } steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -133,9 +136,10 @@ jobs: - { name: conda-linux-python3.8 , test-tox-env: py38 , build-tox-env: build-py38 , python-ver: "3.8" , os: ubuntu-latest } - { name: conda-linux-python3.9 , test-tox-env: py39 , build-tox-env: build-py39 , python-ver: "3.9" , os: ubuntu-latest } - { name: conda-linux-python3.10 , test-tox-env: py310 , build-tox-env: build-py310 , python-ver: "3.10", os: ubuntu-latest } - - { name: conda-linux-python3.10-optional , test-tox-env: py310-optional , build-tox-env: build-py310-optional , python-ver: "3.10", os: ubuntu-latest } - - { name: conda-linux-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: ubuntu-latest } - - { name: conda-linux-python3.10-prerelease, test-tox-env: py310-prerelease, build-tox-env: build-py310-prerelease, python-ver: "3.10", os: ubuntu-latest } + - { name: conda-linux-python3.11 , test-tox-env: py311 , build-tox-env: build-py311 , python-ver: "3.11", os: ubuntu-latest } + - { name: conda-linux-python3.11-optional , test-tox-env: py311-optional , build-tox-env: build-py311-optional , python-ver: "3.11", os: ubuntu-latest } + - { name: conda-linux-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: ubuntu-latest } + - { name: conda-linux-python3.11-prerelease, test-tox-env: py311-prerelease, build-tox-env: build-py311-prerelease, python-ver: "3.11", os: ubuntu-latest } steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -152,23 +156,30 @@ jobs: uses: conda-incubator/setup-miniconda@v2 with: auto-update-conda: true - auto-activate-base: true - activate-environment: true python-version: ${{ matrix.python-ver }} - name: Install build dependencies run: | conda config --set always_yes yes --set changeps1 no conda info - conda install -c conda-forge tox - conda list + # the conda dependency resolution for tox under python 3.7 can install the wrong importlib_metadata + conda install -c conda-forge tox "importlib_metadata>4" + + - name: Conda reporting + run: | + conda info + conda config --show-sources + conda list --show-channel-urls + - name: Run tox tests run: | tox -e ${{ matrix.test-tox-env }} + - name: Build wheel and source distribution run: | tox -e ${{ matrix.build-tox-env }} ls -1 dist + - name: Test installation from a wheel run: | tox -e wheelinstall --recreate --installpkg dist/*-none-any.whl diff --git a/.github/workflows/run_coverage.yml b/.github/workflows/run_coverage.yml index ae075ae1..142b0868 100644 --- a/.github/workflows/run_coverage.yml +++ b/.github/workflows/run_coverage.yml @@ -28,7 +28,7 @@ jobs: - { os: macos-latest , opt_req: false } env: OS: ${{ matrix.os }} - PYTHON: '3.10' + PYTHON: '3.11' steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -43,7 +43,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: ${{ env.PYTHON }} - name: Install dependencies run: | diff --git a/.github/workflows/run_flake8.yml b/.github/workflows/run_flake8.yml index bc31c994..042b9379 100644 --- a/.github/workflows/run_flake8.yml +++ b/.github/workflows/run_flake8.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Install flake8 run: | diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 84add80c..857b4159 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -20,13 +20,13 @@ jobs: matrix: include: - { name: linux-python3.7-minimum , test-tox-env: py37-minimum , build-tox-env: build-py37-minimum , python-ver: "3.7" , os: ubuntu-latest } - - { name: linux-python3.10 , test-tox-env: py310 , build-tox-env: build-py310 , python-ver: "3.10", os: ubuntu-latest } + - { name: linux-python3.11 , test-tox-env: py311 , build-tox-env: build-py311 , python-ver: "3.11", os: ubuntu-latest } # NOTE config below with "upload-wheels: true" specifies that wheels should be uploaded as an artifact - - { name: linux-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: ubuntu-latest , upload-wheels: true } + - { name: linux-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: ubuntu-latest , upload-wheels: true } - { name: windows-python3.7-minimum , test-tox-env: py37-minimum , build-tox-env: build-py37-minimum , python-ver: "3.7" , os: windows-latest } - - { name: windows-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: windows-latest } + - { name: windows-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: windows-latest } - { name: macos-python3.7-minimum , test-tox-env: py37-minimum , build-tox-env: build-py37-minimum , python-ver: "3.7" , os: macos-latest } - - { name: macos-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: macos-latest } + - { name: macos-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: macos-latest } steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -77,9 +77,9 @@ jobs: matrix: include: - { name: linux-gallery-python3.7-minimum , test-tox-env: gallery-py37-minimum , python-ver: "3.7" , os: ubuntu-latest } - - { name: linux-gallery-python3.10-upgraded , test-tox-env: gallery-py310-upgraded, python-ver: "3.10", os: ubuntu-latest } + - { name: linux-gallery-python3.11-upgraded , test-tox-env: gallery-py311-upgraded, python-ver: "3.11", os: ubuntu-latest } - { name: windows-gallery-python3.7-minimum , test-tox-env: gallery-py37-minimum , python-ver: "3.7" , os: windows-latest } - - { name: windows-gallery-python3.10-upgraded, test-tox-env: gallery-py310-upgraded, python-ver: "3.10", os: windows-latest } + - { name: windows-gallery-python3.11-upgraded, test-tox-env: gallery-py311-upgraded, python-ver: "3.11", os: windows-latest } steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -115,7 +115,7 @@ jobs: matrix: include: - { name: conda-linux-python3.7-minimum , test-tox-env: py37-minimum , build-tox-env: build-py37-minimum , python-ver: "3.7" , os: ubuntu-latest } - - { name: conda-linux-python3.10-upgraded , test-tox-env: py310-upgraded , build-tox-env: build-py310-upgraded , python-ver: "3.10", os: ubuntu-latest } + - { name: conda-linux-python3.11-upgraded , test-tox-env: py311-upgraded , build-tox-env: build-py311-upgraded , python-ver: "3.11", os: ubuntu-latest } steps: - name: Cancel non-latest runs uses: styfle/cancel-workflow-action@0.11.0 @@ -172,7 +172,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Download wheel and source distributions from artifact uses: actions/download-artifact@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index e2efee95..1cccebeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,17 @@ # HDMF-ZARR Changelog -## 0.3.0 (Upcoming) +## 0.3.1 (Upcoming) + +### Bug fixes +* Fixed error in deploy workflow. @mavaylon1 [#109](https://github.com/hdmf-dev/hdmf-zarr/pull/109) +* Fixed build error for ReadtheDocs by degrading numpy for python 3.7 support. @mavaylon1 [#115](https://github.com/hdmf-dev/hdmf-zarr/pull/115) + + +## 0.3.0 (July 21, 2023) ### New Features * Added support, tests, and docs for using ``DirectoryStore``, ``TempStore``, and - ``NestedDirectoryStore`` Zarr storage backends with ``ZarrIO`` and ``NWBZarrIO`` + ``NestedDirectoryStore`` Zarr storage backends with ``ZarrIO`` and ``NWBZarrIO``. @oruebel [#62](https://github.com/hdmf-dev/hdmf-zarr/pull/62) * Added support for using ``SQLiteStore`` Zarr storage backend with ``ZarrIO`` @oruebel [#66](https://github.com/hdmf-dev/hdmf-zarr/pull/66) @@ -15,14 +22,20 @@ ### Minor enhancements * Updated handling of references on read to simplify future integration of file-based Zarr - stores (e.g., ZipStore or database stores) @oruebel [#62](https://github.com/hdmf-dev/hdmf-zarr/pull/62) + stores (e.g., ZipStore or database stores). @oruebel [#62](https://github.com/hdmf-dev/hdmf-zarr/pull/62) +* Added ``can_read`` classmethod to ``ZarrIO``. @bendichter [#97](https://github.com/hdmf-dev/hdmf-zarr/pull/97) ### Test suite enhancements -* Modularized unit tests to simplify running tests for multiple Zarr storage backends +* Modularized unit tests to simplify running tests for multiple Zarr storage backends. @oruebel [#62](https://github.com/hdmf-dev/hdmf-zarr/pull/62) +* Fixed CI testing of minimum and optional installation requirement. @rly + [#99](https://github.com/hdmf-dev/hdmf-zarr/pull/99) +* Updated tests to handle upcoming changes to ``HDMFIO``. @rly + [#102](https://github.com/hdmf-dev/hdmf-zarr/pull/102) + ### Docs -* Added developer documentation on how to integrate new storage backends with ZarrIO +* Added developer documentation on how to integrate new storage backends with ZarrIO. @oruebel [#62](https://github.com/hdmf-dev/hdmf-zarr/pull/62) ### Internal changes @@ -31,6 +44,9 @@ @oruebel [#66](https://github.com/hdmf-dev/hdmf-zarr/pull/66) +### Bug fixes +* Fixed error in nightly CI. @rly [#93](https://github.com/hdmf-dev/hdmf-zarr/pull/93) + ## 0.2.0 (January 6, 2023) ### Bugs diff --git a/docs/CONTRIBUTING.rst b/docs/CONTRIBUTING.rst new file mode 100644 index 00000000..4daeaf54 --- /dev/null +++ b/docs/CONTRIBUTING.rst @@ -0,0 +1,132 @@ +Contributing Guide +================== + +.. _sec-code-of-conduct: + +Code of Conduct +--------------- + +This project and everyone participating in it is governed by our `code of conduct guidelines `_. By participating, you are expected to uphold this code. Please report unacceptable behavior. + +.. _sec-contribution-types: + +Types of Contributions +---------------------- + +Did you find a bug? or Do you intend to add a new feature or change an existing one? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* **Submit issues and requests** using our `issue tracker `_ + +* **Ensure the feature or change was not already reported** by searching on GitHub under `HDMF-ZARR Issues `_ + +* If you are unable to find an open issue addressing the problem then open a new issue on the respective repository. Be sure to use our issue templates and include: + + * **brief and descriptive title** + * **clear description of the problem you are trying to solve**. Describing the use case is often more important than proposing a specific solution. By describing the use case and problem you are trying to solve gives the development team community a better understanding for the reasons of changes and enables others to suggest solutions. + * **context** providing as much relevant information as possible and if available a **code sample** or an **executable test case** demonstrating the expected behavior and/or problem. + +* Be sure to select the appropriate label (bug report or feature request) for your tickets so that they can be processed accordingly. + +* HDMF-ZARR is currently being developed primarily by staff at scientific research institutions and industry, most of which work on many different research projects. Please be patient, if our development team is not able to respond immediately to your issues. In particular issues that belong to later project milestones may not be reviewed or processed until work on that milestone begins. + +Did you write a patch that fixes a bug or implements a new feature? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +See the :ref:`sec-contributing` section below for details. + +Did you fix whitespace, format code, or make a purely cosmetic patch in source code? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Source code changes that are purely cosmetic in nature and do not add anything substantial to the stability, functionality, or testability will generally not be accepted unless they have been approved beforehand. One of the main reasons is that there are a lot of hidden costs in addition to writing the code itself, and with the limited resources of the project, we need to optimize developer time. E.g,. someone needs to test and review PRs, backporting of bug fixes gets harder, it creates noise and pollutes the git repo and many other cost factors. + +Do you have questions about HDMF-ZARR? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +See our `hdmf-dev.github.io `_ website for details. + +Informal discussions between developers and users? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The https://nwb-users.slack.com slack is currently used for informal discussions between developers and users. + +.. _sec-contributing: + +Contributing Patches and Changes +-------------------------------- + +To contribute to HDMF-ZARR you must submit your changes to the ``dev`` branch via a `Pull Request `_. + +From your local copy directory, use the following commands. + +1) First create a new branch to work on + +.. code-block:: bash + + $ git checkout -b + +2) Make your changes. + +3) Push your feature branch to origin (i.e. GitHub) + +.. code-block:: bash + + $ git push origin + +4) Once you have tested and finalized your changes, create a pull request targeting ``dev`` as the base branch. Be sure to use our `pull request template `_ and: + + * Ensure the PR description clearly describes the problem and solution. + * Include the relevant issue number if applicable. + * Before submitting, please ensure that: + * The proposed changes include an addition to ``CHANGELOG.md`` describing your changes. To label the change with the PR number, you will have to first create the PR, then edit the ``CHANGELOG.md`` with the PR number, and push that change. + * The code follows our coding style. This can be checked running ``ruff`` from the source directory. + * **NOTE:** Contributed branches will be removed by the development team after the merge is complete and should, hence, not be used after the pull request is complete. + +.. _sec-styleguides: + +Style Guides +------------ + +Python Code Styleguide +^^^^^^^^^^^^^^^^^^^^^^ + +Before you create a Pull Request, make sure you are following the HDMF-ZARR style guide (PEP8_). +To check whether your code conforms to the HDMF-ZARR style guide, simply run the flake8_ tool in the project's root +directory. + +.. _flake8: https://flake8.pycqa.org/en/latest/ +.. _PEP8: https://peps.python.org/pep-0008/ + +.. code:: + + $ flake8 + +Git Commit Message Styleguide +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Use the present tense ("Add feature" not "Added feature") +* The first should be short and descriptive. +* Additional details may be included in further paragraphs. +* If a commit fixes an issue, then include "Fix #X" where X is the number of the issue. +* Reference relevant issues and pull requests liberally after the first line. + +Documentation Styleguide +^^^^^^^^^^^^^^^^^^^^^^^^ + +All documentations is written in reStructuredText (RST) using Sphinx. + +Endorsement +----------- + +Please do not take working with an organization (e.g., during a hackathon or via GitHub) as an endorsement of your work or your organization. It's okay to say e.g., “We worked with XXXXX to advance science” but not e.g., “XXXXX supports our work on HDMF-ZARR”.” + +License and Copyright +--------------------- + +See the `license `_ files for details about the copyright and license. + +As indicated in the HDMF-ZARR license: *“You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form.”* + +Contributors to the HDMF-ZARR code base are expected to use a permissive, non-copyleft open source license. Typically 3-clause BSD is used, but any compatible license is allowed, the MIT and Apache 2.0 licenses being good alternative choices. The GPL and other copyleft licenses are not allowed due to the consternation it generates across many organizations. + +Also, make sure that you are permitted to contribute code. Some organizations, even academic organizations, have agreements in place that discuss IP ownership in detail (i.e., address IP rights and ownership that you create while under the employ of the organization). These are typically signed documents that you looked at on your first day of work and then promptly forgot. We don't want contributed code to be yanked later due to IP issues. diff --git a/docs/source/conf.py b/docs/source/conf.py index de6ff8cc..d612aade 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -43,7 +43,7 @@ project = 'hdmf_zarr' copyright = '2022, Oliver Ruebel' -author = 'Oliver Ruebel' +author = 'Oliver Ruebel, Matthew Avaylon' # The short X.Y version. version = '{}'.format(get_versions()['version']) @@ -75,7 +75,7 @@ } intersphinx_mapping = { - 'python': ('https://docs.python.org/3.10', None), + 'python': ('https://docs.python.org/3.11', None), 'numpy': ('https://numpy.org/doc/stable/', None), 'scipy': ('https://docs.scipy.org/doc/scipy/', None), 'matplotlib': ('https://matplotlib.org/stable/', None), @@ -88,9 +88,9 @@ # Use this for mapping to external links extlinks = { - 'pynwb-docs': ('https://pynwb.readthedocs.io/en/stable/', '%s'), - 'hdmf-docs': ('https://hdmf.readthedocs.io/en/stable/', '%s'), - 'zarr-docs': ('https://zarr.readthedocs.io/en/stable/', '%s') + 'pynwb-docs': ('https://pynwb.readthedocs.io/en/stable/%s', '%s'), + 'hdmf-docs': ('https://hdmf.readthedocs.io/en/stable/%s', '%s'), + 'zarr-docs': ('https://zarr.readthedocs.io/en/stable/%s', '%s') } # Add any paths that contain templates here, relative to this directory. diff --git a/requirements-dev.txt b/requirements-dev.txt index fec71b98..cb72d345 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,5 @@ # pinned dependencies to reproduce an entire development environment to use HDMF, run HDMF tests, check code style, # compute coverage, and create test environments -codecov==2.1.12 coverage==6.4.2 flake8==5.0.4 flake8-debugger==4.1.2 diff --git a/requirements-min.txt b/requirements-min.txt index bf4d276f..f5de79ad 100644 --- a/requirements-min.txt +++ b/requirements-min.txt @@ -1,5 +1,6 @@ -hdmf==3.5.0 +hdmf==3.5.4 zarr==2.11.0 numcodecs==0.9.1 -pynwb==2.0.0 +pynwb==2.3.2 setuptools +importlib_resources;python_version<'3.9' # Remove when python 3.9 becomes the new minimum diff --git a/requirements.txt b/requirements.txt index 69d3947b..20a92d6d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,8 @@ # pinned dependencies to reproduce an entire development environment to use HDMF-ZARR -hdmf==3.5.0 +hdmf==3.5.4 zarr==2.11.0 -numcodecs==0.9.1 -pynwb==2.0.1 \ No newline at end of file +pynwb==2.3.2 +numpy==1.21; python_version < "3.8" +numpy==1.23; python_version >= "3.8" +numcodecs==0.10.2; python_version < "3.8" +numcodecs==0.11.0; python_version >= "3.8" diff --git a/setup.py b/setup.py index 50953471..5b155ecb 100755 --- a/setup.py +++ b/setup.py @@ -17,12 +17,15 @@ reqs = [ - 'hdmf>=3.5.0', + 'hdmf==3.5.4', # temporary 'zarr>=2.11.0', + 'numpy<1.22; python_version < "3.8"', + 'numpy>=1.22; python_version >= "3.8"', 'numcodecs>=0.9.1', - 'pynwb>=2.0.0', + 'numcodecs==0.10.2; python_version < "3.8"', + 'numcodecs==0.11.0; python_version >= "3.8"', + 'pynwb>=2.3.2', 'setuptools', - 'numpy>=1.22, <1.24; python_version>"3.7"' ] print(reqs) @@ -49,6 +52,7 @@ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "License :: OSI Approved :: BSD License", "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", diff --git a/src/hdmf_zarr/backend.py b/src/hdmf_zarr/backend.py index 91083669..2c3d2da4 100644 --- a/src/hdmf_zarr/backend.py +++ b/src/hdmf_zarr/backend.py @@ -79,6 +79,14 @@ class ZarrIO(HDMFIO): + @staticmethod + def can_read(path): + try: + zarr.open(path, mode="r") + return True + except Exception: + return False + @docval({'name': 'path', 'type': (str, *SUPPORTED_ZARR_STORES), 'doc': 'the path to the Zarr file or a supported Zarr store'}, @@ -723,6 +731,7 @@ def __setup_chunked_dataset__(cls, parent, name, data, options=None): io_settings['dtype'] = cls.__dtypes.get(io_settings['dtype']) try: dset = parent.create_dataset(name, **io_settings) + dset.attrs['zarr_dtype'] = np.dtype(io_settings['dtype']).str except Exception as exc: raise Exception("Could not create dataset %s in %s" % (name, parent.name)) from exc return dset @@ -1152,11 +1161,18 @@ def __read_dataset(self, zarr_obj, name): if ret is not None: return ret - if 'zarr_dtype' not in zarr_obj.attrs: + if 'zarr_dtype' in zarr_obj.attrs: + zarr_dtype = zarr_obj.attrs['zarr_dtype'] + elif hasattr(zarr_obj, 'dtype'): # Fallback for invalid files that are mssing zarr_type + zarr_dtype = zarr_obj.dtype + warnings.warn( + "Inferred dtype from zarr type. Dataset missing zarr_dtype: " + str(name) + " " + str(zarr_obj) + ) + else: raise ValueError("Dataset missing zarr_dtype: " + str(name) + " " + str(zarr_obj)) kwargs = {"attributes": self.__read_attrs(zarr_obj), - "dtype": zarr_obj.attrs['zarr_dtype'], + "dtype": zarr_dtype, "maxshape": zarr_obj.shape, "chunks": not (zarr_obj.shape == zarr_obj.chunks), "source": self.source} diff --git a/test.py b/test.py deleted file mode 100644 index a5a55603..00000000 --- a/test.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python - -# NOTE this script is currently used in CI *only* to test the sphinx gallery examples using python test.py -e -import warnings -import re -import argparse -import logging -import os.path -import os -import sys -import traceback -import unittest - -flags = {'hdmf_zarr': 1, 'example': 4} - -TOTAL = 0 -FAILURES = 0 -ERRORS = 0 - - -class SuccessRecordingResult(unittest.TextTestResult): - '''A unittest test result class that stores successful test cases as well - as failures and skips. - ''' - - def addSuccess(self, test): - if not hasattr(self, 'successes'): - self.successes = [test] - else: - self.successes.append(test) - - def get_all_cases_run(self): - '''Return a list of each test case which failed or succeeded - ''' - cases = [] - - if hasattr(self, 'successes'): - cases.extend(self.successes) - cases.extend([failure[0] for failure in self.failures]) - - return cases - - -def run_test_suite(directory, description="", verbose=True): - global TOTAL, FAILURES, ERRORS - logging.info("running %s" % description) - directory = os.path.join(os.path.dirname(__file__), directory) - runner = unittest.TextTestRunner(verbosity=verbose, resultclass=SuccessRecordingResult) - test_result = runner.run(unittest.TestLoader().discover(directory)) - - TOTAL += test_result.testsRun - FAILURES += len(test_result.failures) - ERRORS += len(test_result.errors) - - return test_result - - -def _import_from_file(script): - import imp - return imp.load_source(os.path.basename(script), script) - - -warning_re = re.compile("Parent module '[a-zA-Z0-9]+' not found while handling absolute import") - - -def run_example_tests(): - global TOTAL, FAILURES, ERRORS - logging.info('running example tests') - - # get list of example scripts - examples_scripts = list() - for root, dirs, files in os.walk(os.path.join(os.path.dirname(__file__), "docs", "gallery")): - for f in files: - if f.endswith(".py"): - examples_scripts.append(os.path.join(root, f)) - - TOTAL += len(examples_scripts) - curr_dir = os.getcwd() - for script in examples_scripts: - os.chdir(curr_dir) # Reset the working directory - script_abs = os.path.abspath(script) # Determine the full path of the script - # Set the working dir to be relative to the script to allow the use of relative file paths in the scripts - os.chdir(os.path.dirname(script_abs)) - try: - logging.info("Executing %s" % script) - ws = list() - with warnings.catch_warnings(record=True) as tmp: - # Import/run the example gallery - _import_from_file(script_abs) - for w in tmp: # ignore RunTimeWarnings about importing - if isinstance(w.message, RuntimeWarning) and not warning_re.match(str(w.message)): - ws.append(w) - for w in ws: - warnings.showwarning(w.message, w.category, w.filename, w.lineno, w.line) - except Exception: - print(traceback.format_exc()) - FAILURES += 1 - ERRORS += 1 - # Make sure to reset the working directory at the end - os.chdir(curr_dir) - - -def main(): - warnings.warn( - "python test.py is deprecated. Please use pytest to run unit tests and run python test_gallery.py to " - "test Sphinx Gallery files.", - DeprecationWarning - ) - - # setup and parse arguments - parser = argparse.ArgumentParser('python test.py [options]') - parser.set_defaults(verbosity=1, suites=[]) - parser.add_argument('-v', '--verbose', const=2, dest='verbosity', action='store_const', help='run in verbose mode') - parser.add_argument('-q', '--quiet', const=0, dest='verbosity', action='store_const', help='run disabling output') - parser.add_argument('-u', '--unit', action='append_const', const=flags['hdmf_zarr'], dest='suites', - help='run unit tests for hdmf_zarr package') - parser.add_argument('-e', '--example', action='append_const', const=flags['example'], dest='suites', - help='run example tests') - args = parser.parse_args() - if not args.suites: - args.suites = list(flags.values()) - args.suites.pop(args.suites.index(flags['example'])) # remove example as a suite run by default - - # set up logger - root = logging.getLogger() - root.setLevel(logging.INFO) - ch = logging.StreamHandler(sys.stdout) - ch.setLevel(logging.INFO) - formatter = logging.Formatter('======================================================================\n' - '%(asctime)s - %(levelname)s - %(message)s') - ch.setFormatter(formatter) - root.addHandler(ch) - - warnings.simplefilter('always') - - # Run unit tests for hdmf_zarr package - if flags['hdmf_zarr'] in args.suites: - run_test_suite("tests/unit", "hdmf_zarr unit tests", verbose=args.verbosity) - - # Run example tests - if flags['example'] in args.suites: - run_example_tests() - - final_message = 'Ran %s tests' % TOTAL - exitcode = 0 - if ERRORS > 0 or FAILURES > 0: - exitcode = 1 - _list = list() - if ERRORS > 0: - _list.append('errors=%d' % ERRORS) - if FAILURES > 0: - _list.append('failures=%d' % FAILURES) - final_message = '%s - FAILED (%s)' % (final_message, ','.join(_list)) - else: - final_message = '%s - OK' % final_message - - logging.info(final_message) - - return exitcode - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/test_gallery.py b/test_gallery.py index 731a9f0d..77613a89 100644 --- a/test_gallery.py +++ b/test_gallery.py @@ -23,6 +23,14 @@ def _import_from_file(script): spec.loader.exec_module(module) +_pkg_resources_warning_re = ( + "pkg_resources is deprecated as an API" +) + +_pkg_resources_declare_warning_re = ( + r"Deprecated call to `pkg_resources\.declare_namespace.*" +) + _numpy_warning_re = ( "numpy.ufunc size changed, may indicate binary incompatibility. Expected 216, got 192" ) @@ -111,6 +119,14 @@ def run_gallery_tests(): # against a different version of numpy than the one installed "ignore", message=_numpy_warning_re, category=RuntimeWarning ) + warnings.filterwarnings( + # this warning is triggered when downstream code such as pynwb uses pkg_resources>=5.13 + "ignore", message=_pkg_resources_warning_re, category=DeprecationWarning + ) + warnings.filterwarnings( + # this warning is triggered when downstream code such as pynwb uses pkg_resources>=5.13 + "ignore", message=_pkg_resources_declare_warning_re, category=DeprecationWarning + ) _import_from_file(script_abs) except Exception: print(traceback.format_exc()) diff --git a/tests/unit/base_tests_zarrio.py b/tests/unit/base_tests_zarrio.py index 6bd97edb..78c39d18 100644 --- a/tests/unit/base_tests_zarrio.py +++ b/tests/unit/base_tests_zarrio.py @@ -209,6 +209,9 @@ def createReferenceCompoundBuilder(self): 'ref_dataset': dataset_ref}) return builder + def test_cannot_read(self): + assert not ZarrIO.can_read("incorrect_path") + def read_test_dataset(self): reader = ZarrIO(reopen_store(self.store), manager=self.manager, mode='r') self.root = reader.read_builder() @@ -251,6 +254,7 @@ def test_write_int(self, test_data=None): writer = ZarrIO(self.store, manager=self.manager, mode='a') writer.write_builder(self.builder) writer.close() + assert ZarrIO.can_read(self.store) def test_write_compound(self, test_data=None): """ @@ -1488,6 +1492,10 @@ def test_non_manager_container(self): class OtherIO(HDMFIO): + @staticmethod + def can_read(path): + pass + def read_builder(self): pass @@ -1520,6 +1528,10 @@ class OtherIO(HDMFIO): def __init__(self, manager): super().__init__(manager=manager) + @staticmethod + def can_read(path): + pass + def read_builder(self): pass diff --git a/tox.ini b/tox.ini index f8e7798e..b79471ed 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py37, py38, py39, py310 +envlist = py37, py38, py39, py310, py311 requires = pip >= 22.0 [testenv] @@ -14,7 +14,7 @@ setenv = PYTHONDONTWRITEBYTECODE = 1 VIRTUALENV_python -m pip = 22.3.1 install_command = - python -m pip install -U {opts} {packages} + python -m pip install {opts} {packages} deps = -rrequirements-dev.txt @@ -26,36 +26,39 @@ commands = # Env to create coverage report locally [testenv:localcoverage] -basepython = python3.10 +basepython = python3.11 commands = pytest --cov=hdmf_zarr coverage html -d tests/coverage/htmlcov -# Test with python 3.10; pinned dev and optional reqs -[testenv:py310-optional] -basepython = python3.10 +# Test with python 3.11; pinned dev and optional reqs +[testenv:py311-optional] +basepython = python3.11 install_command = python -m pip install {opts} {packages} deps = - -rrequirements-dev.txt + {[testenv]deps} + # -rrequirements-opt.txt commands = {[testenv]commands} -# Test with python 3.10; pinned dev and optional reqs; upgraded run reqs -[testenv:py310-upgraded] -basepython = python3.10 +# Test with python 3.11; pinned dev and optional reqs; upgraded run reqs +[testenv:py311-upgraded] +basepython = python3.11 install_command = python -m pip install -U {opts} {packages} deps = -rrequirements-dev.txt + # -rrequirements-opt.txt commands = {[testenv]commands} -# Test with python 3.10; pinned dev and optional reqs; upgraded, pre-release run reqs -[testenv:py310-prerelease] -basepython = python3.10 +# Test with python 3.11; pinned dev and optional reqs; upgraded, pre-release run reqs +[testenv:py311-prerelease] +basepython = python3.11 install_command = python -m pip install -U --pre {opts} {packages} deps = -rrequirements-dev.txt + # -rrequirements-opt.txt commands = {[testenv]commands} # Test with python 3.7; pinned dev reqs; minimum run reqs @@ -88,26 +91,33 @@ commands = {[testenv:build]commands} basepython = python3.10 commands = {[testenv:build]commands} -[testenv:build-py310-optional] -basepython = python3.10 +[testenv:build-py311] +basepython = python3.11 +commands = {[testenv:build]commands} + +[testenv:build-py311-optional] +basepython = python3.11 deps = - -rrequirements-dev.txt + {[testenv]deps} + # -rrequirements-opt.txt commands = {[testenv:build]commands} -[testenv:build-py310-upgraded] -basepython = python3.10 +[testenv:build-py311-upgraded] +basepython = python3.11 install_command = python -m pip install -U {opts} {packages} deps = -rrequirements-dev.txt + # -rrequirements-opt.txt commands = {[testenv:build]commands} -[testenv:build-py310-prerelease] -basepython = python3.10 +[testenv:build-py311-prerelease] +basepython = python3.11 install_command = python -m pip install -U --pre {opts} {packages} deps = -rrequirements-dev.txt + # -rrequirements-opt.txt commands = {[testenv:build]commands} [testenv:build-py37-minimum] @@ -125,7 +135,7 @@ commands = python -c "import hdmf_zarr" # Envs that will execute gallery tests [testenv:gallery] install_command = - python -m pip install -U {opts} {packages} + python -m pip install {opts} {packages} deps = -rrequirements-dev.txt @@ -135,11 +145,6 @@ deps = commands = python test_gallery.py -[testenv:gallery-py37] -basepython = python3.7 -deps = {[testenv:gallery]deps} -commands = {[testenv:gallery]commands} - [testenv:gallery-py38] basepython = python3.8 deps = {[testenv:gallery]deps} @@ -155,24 +160,31 @@ basepython = python3.10 deps = {[testenv:gallery]deps} commands = {[testenv:gallery]commands} -# Test with python 3.10; pinned dev, doc, and optional reqs; upgraded run reqs -[testenv:gallery-py310-upgraded] -basepython = python3.10 +[testenv:gallery-py311] +basepython = python3.11 +deps = {[testenv:gallery]deps} +commands = {[testenv:gallery]commands} + +# Test with python 3.11; pinned dev, doc, and optional reqs; upgraded run reqs +[testenv:gallery-py311-upgraded] +basepython = python3.11 install_command = python -m pip install -U {opts} {packages} deps = -rrequirements-dev.txt -rrequirements-doc.txt + # -rrequirements-opt.txt commands = {[testenv:gallery]commands} -# Test with python 3.10; pinned dev, doc, and optional reqs; pre-release run reqs -[testenv:gallery-py310-prerelease] -basepython = python3.10 +# Test with python 3.11; pinned dev, doc, and optional reqs; pre-release run reqs +[testenv:gallery-py311-prerelease] +basepython = python3.11 install_command = python -m pip install -U --pre {opts} {packages} deps = -rrequirements-dev.txt -rrequirements-doc.txt + # -rrequirements-opt.txt commands = {[testenv:gallery]commands} # Test with python 3.7; pinned dev and doc reqs; minimum run reqs