Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add testing for Python 3.12 #361

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: khanlab/actions/.github/actions/[email protected]
id: setup
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
needs: [ 'quality' ]
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: khanlab/actions/.github/actions/[email protected]
id: setup
Expand All @@ -55,7 +55,7 @@ jobs:
needs: [ 'build-cache-env' ]
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
split: ['1', '2', '3', '4', '5']
fail-fast: false
steps:
Expand Down
1,097 changes: 581 additions & 516 deletions poetry.lock

Large diffs are not rendered by default.

91 changes: 45 additions & 46 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,21 @@ style = "pep440"
bump = true

[tool.poetry-dynamic-versioning.substitution]
files = [
'snakebids/__init__.py',
]
files = ['snakebids/__init__.py']
patterns = [
"(^\\s+\"snakebids_version\":\\s*\")[^'\"]*(\")",
"(^__version__\\s*(?::.*?)?=\\s*['\"])[^'\"]*(['\"])",
]

[tool.poetry.dependencies]
# upper cap imposed by scipy
python = ">=3.8,<3.13"
# upper cap imposed by pytest-split
python = ">=3.8,<4.0"
# core dep with high breakage potential given plans for redesign, so
# keep upper limit
pybids = ">=0.16.0,<0.17"
snakemake = [
{ version = ">=5.28.0", python = ">=3.8" },
{ version = ">=7.18.2", python = ">=3.11" },
{ version = ">=5.28.0,<8", python = ">=3.8" },
{ version = ">=7.18.2,<8", python = ">=3.11" },
]
PyYAML = ">=6"
typing-extensions = ">=3.10.0"
Expand All @@ -63,6 +61,10 @@ scipy = [
{ version = ">=1.10.0,<=1.10.1", python = "<3.9" },
{ version = ">=1.10.0", python = ">=3.9" },
]
pandas = [
{ version = "<=2.0.3", python = "<3.9" },
{ version = ">=2.1.1", python = ">=3.12" },
]
# minimum 8.2.0 to use post-copy mesages
copier = ">=8.2.0"
jinja2-time = ">=0.2.0"
Expand Down Expand Up @@ -127,8 +129,8 @@ expr = "platform.python_version()"
args = [{ name = "container_id", positional = true, required = true }]
uses = { VERSION = "_get_version" }
cmd = """
docker build 'containers/${container_id}' \
--tag 'snakebids/${container_id}:${VERSION}' \
docker build "containers/${container_id}" \
--tag "snakebids/${container_id}:${VERSION}" \
--build-arg="PYTHON_VERSION=${VERSION}"
"""

Expand All @@ -138,18 +140,15 @@ markers = [
]

[tool.coverage.run]
omit = [
"snakebids/project_template/**",
"snakebids/tests/**",
]
omit = ["snakebids/project_template/**", "snakebids/tests/**"]

[tool.coverage.report]
exclude_lines = [
"pragma: not covered",
"@overload",
'class [a-zA-Z0-9_]+\([^)]*Protocol.*\)',
'if TYPE_CHECKING',
"def __dir__"
"def __dir__",
]

[tool.isort]
Expand All @@ -165,31 +164,31 @@ reportImportCycles = false

[tool.ruff]
select = [
"E", # pycodestyle error
"W", # pycodestyle warning
"F", # pyflakes
"N", # pep8-naming
"UP", # pyupgrade
"YTT", # flake8-2020
"S", # flake8-bandit
"BLE", # flake8-blind-except
"B", # flake8-bugbear
"A", # flake8-builtins
"COM", # flake8-commas
"C4", # flake8-comprehensions
"T10", # flake8-debugger
"EM", # flake8-errmsg
"FA", # flake8-future-annotations
"ISC", # flake8-implicit-str-concat
"ICN", # flake8-import-conventions
"G", # flake8-logging-format
"INP", # flake8-no-pep420
"PIE", # flake8-pie
"PT", # flake8-pytest-style
"RSE", # flake8-raise
"RET", # flake8-return
"SLF", # flake8-self
"SIM", # flake8-simplify
"E", # pycodestyle error
"W", # pycodestyle warning
"F", # pyflakes
"N", # pep8-naming
"UP", # pyupgrade
"YTT", # flake8-2020
"S", # flake8-bandit
"BLE", # flake8-blind-except
"B", # flake8-bugbear
"A", # flake8-builtins
"COM", # flake8-commas
"C4", # flake8-comprehensions
"T10", # flake8-debugger
"EM", # flake8-errmsg
"FA", # flake8-future-annotations
"ISC", # flake8-implicit-str-concat
"ICN", # flake8-import-conventions
"G", # flake8-logging-format
"INP", # flake8-no-pep420
"PIE", # flake8-pie
"PT", # flake8-pytest-style
"RSE", # flake8-raise
"RET", # flake8-return
"SLF", # flake8-self
"SIM", # flake8-simplify
# We use os.path a lot in "legitimate" ways, so this ruleset has too many
# false positives
# "PTH", # flake8-use-pathlib
Expand All @@ -205,11 +204,11 @@ select = [
]
ignore = [
"PLR0913",
"D105", # missing docstring in magic method
"D100", # Require docstring in public modules
"D104", # Require docstring in public packages
"S603", # Subprocess without shell equals true
"S607", # start-process-with-partial-path
"D105", # missing docstring in magic method
"D100", # Require docstring in public modules
"D104", # Require docstring in public packages
"S603", # Subprocess without shell equals true
"S607", # start-process-with-partial-path
# recommended ignores for ruff format
"W191",
"E111",
Expand All @@ -236,8 +235,8 @@ namespace-packages = ["snakebids/plugins"]
"snakebids/project_template/**" = ["N999"]
"snakebids/tests/**" = [
"D",
"S101", # assert
"S307", # Use of eval
"S101", # assert
"S307", # Use of eval
"SLF",
]

Expand Down
38 changes: 12 additions & 26 deletions snakebids/project_template/copier.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ bids_version:
when: false

python_version:
default: ">=3.8,<3.12"
default: ">=3.8,<3.13"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be set to the range as currently set on pypi. Next release we'll need to remember to update this to >=3.8,<4.0

when: false

snakebids_version:
Expand Down Expand Up @@ -96,27 +96,16 @@ _message_after_copy: >

$ cd {{ _copier_conf.dst_path }}

{% if build_system == "poetry" -%}
{{ Fore.BLUE }}2.{{ Fore.RESET }} Install dependencies.

{% if build_system == "poetry" %}
$ poetry install

{%- else -%}
{{ Fore.BLUE + "2." + Fore.RESET + """ Install dependencies. This may vary
depending on your tooling. The following are examples (the first example
should work on any python environment; the others require 3rd party tools):
""" | wordwrap(80)}}

* {{Fore.YELLOW}}Virtual Environment and setuptools:{{Fore.RESET}}
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install .

* {{Fore.YELLOW}}Hatch:{{Fore.RESET}}
$ hatch env create

* {{Fore.YELLOW}}PDM:{{Fore.RESET}}
$ pdm install
{%- elif build_system == "hatch" %}
$ hatch env create
{%- else %}
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install .
{%- endif %}


Expand All @@ -125,15 +114,12 @@ _message_after_copy: >
{% if build_system == "poetry" %}
$ poetry run {{ test_run_cmd }}

{%- else %}
* {{Fore.YELLOW}}Virtual Environment and setuptools:{{Fore.RESET}}
$ {{ test_run_cmd }}
{%- elif build_system == "hatch" %}
$ hatch env run -- {{ test_run_cmd }}

* {{Fore.YELLOW}}Hatch:{{Fore.RESET}}
$ hatch env run -- {{ test_run_cmd }}
{%- else %}
$ {{ test_run_cmd }}

* {{Fore.YELLOW}}PDM:{{Fore.RESET}}
$ pdm run {{ test_run_cmd }}
{%- endif %}

_jinja_extensions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,8 @@ classifiers = [

requires-python = "{{ python_version }}"
dependencies = [
"snakemake >= {{ snakemake_version }}",
"snakemake >= {{ snakemake_version }},<8",
"snakebids >= {{ snakebids_version }}",
{# Explicitly specify numpy version for py38 until snakebids 0.10.x to
work around specification bug causing numpys too high for py38 to be
locked by pdm -#}
"numpy <=1.24.4; python_version < \"3.9\"",
]

[project.scripts]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ classifiers = [

[tool.poetry.dependencies]
python = "{{ python_version }}"
snakemake = ">={{ snakemake_version }}"
snakemake = ">={{ snakemake_version }},<8"
snakebids = ">={{ snakebids_version }}"
pandas = [
{ version = "<=2.0.3", python = "<3.9" },
{ version = ">=2.1.1", python = ">=3.12" },
]

[tool.poetry.scripts]
{{ name_slug }} = "{{ name_slug }}.run:main"
Expand Down
2 changes: 1 addition & 1 deletion snakebids/tests/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def test_pyproject_correctly_formatted(
("setuptools", "setuptools"),
("poetry", "poetry"),
("hatch", "hatch"),
("flit", "pdm"),
("flit", "setuptools"),
],
)
def test_template_dry_runs_successfully(tmp_path: Path, build: BuildBackend, venv: str):
Expand Down
16 changes: 4 additions & 12 deletions snakebids/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,32 +474,24 @@ def __getitem__(self, index: int | slice) -> _T_co | Self:
return self._data[index]

def __lt__(self, value: tuple[_T_co, ...] | Self, /) -> bool:
if isinstance(value, tuple):
return self._data < value
if isinstance(value, ImmutableList):
return self._data < value._data
return False
return self._data < value

def __le__(self, value: tuple[_T_co, ...] | Self, /) -> bool:
if isinstance(value, tuple):
return self._data <= value
if isinstance(value, ImmutableList):
return self._data <= value._data
return False
return self._data <= value

def __gt__(self, value: tuple[_T_co, ...] | Self, /) -> bool:
if isinstance(value, tuple):
return self._data > value
if isinstance(value, ImmutableList):
return self._data > value._data
return False
return self._data > value

def __ge__(self, value: tuple[_T_co, ...] | Self, /) -> bool:
if isinstance(value, tuple):
return self._data >= value
if isinstance(value, ImmutableList):
return self._data >= value._data
return False
return self._data >= value

@override
def __eq__(self, value: object, /) -> bool:
Expand Down