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

deps!(python): drop Python 3.7 support and mark some arguments as positional-only #162

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
42 changes: 20 additions & 22 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.7 - 3.13"
python-version: "3.8 - 3.13"
update-environment: true

- name: Upgrade pip
Expand Down Expand Up @@ -88,21 +88,24 @@ jobs:
matrix:
runner: [ubuntu-latest, windows-latest, macos-latest]
python-version:
["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.13t", "pypy-3.9", "pypy-3.10"]
archs: [
# Generic
"auto",
# Linux
"aarch64",
"ppc64le",
"s390x",
# Windows
"ARM64",
]
include:
- runner: macos-13
python-version: "3.7"
archs: "auto"
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.13t"
- "pypy-3.9"
- "pypy-3.10"
archs:
# Generic
- "auto"
# Linux
- "aarch64"
- "ppc64le"
- "s390x"
# Windows
- "ARM64"
exclude:
- runner: ubuntu-latest
python-version: "pypy-3.9"
Expand All @@ -116,9 +119,6 @@ jobs:
- runner: ubuntu-latest
python-version: "pypy-3.10"
archs: "s390x"
- runner: windows-latest
python-version: "3.7"
archs: "ARM64"
- runner: windows-latest
python-version: "3.8"
archs: "ARM64"
Expand All @@ -128,8 +128,6 @@ jobs:
- runner: windows-latest
python-version: "pypy-3.10"
archs: "ARM64"
- runner: macos-latest
python-version: "3.7" # Python 3.7 does not support macOS ARM64

# Exclude archs of other platforms
- runner: ubuntu-latest
Expand Down Expand Up @@ -271,7 +269,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
uses: actions/setup-python@v5
with:
python-version: "3.7 - 3.13"
python-version: "3.8 - 3.13"
update-environment: true

- name: Upgrade pip
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/tests-with-pydebug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ jobs:
strategy:
matrix:
runner: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
python-abiflags: ["d", "td"]
exclude:
- python-version: "3.7"
python-abiflags: "td"
- python-version: "3.8"
python-abiflags: "td"
- python-version: "3.9"
Expand Down
20 changes: 8 additions & 12 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ jobs:
matrix:
runner: [ubuntu-latest, windows-latest, macos-latest]
python-version:
["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "pypy-3.9", "pypy-3.10"]
include:
- runner: macos-13
python-version: "3.7"
exclude:
- runner: macos-latest
python-version: "3.7" # Python 3.7 does not support macOS ARM64
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "pypy-3.9"
- "pypy-3.10"
fail-fast: false
timeout-minutes: 90
steps:
Expand All @@ -62,11 +63,6 @@ jobs:
run: |
python -m pip install --upgrade pip setuptools wheel

- name: Set `SETUPTOOLS_ENABLE_FEATURES`
if: ${{ matrix.python-version == '3.7' && runner.os == 'Windows' }}
run: |
Write-Output 'SETUPTOOLS_ENABLE_FEATURES=legacy-editable' | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append

- name: Install test dependencies
shell: bash
run: |
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ repos:
hooks:
- id: black
- repo: https://github.com/asottile/pyupgrade
rev: v3.18.0
rev: v3.19.0
hooks:
- id: pyupgrade
args: [--py37-plus]
args: [--py38-plus]
- repo: https://github.com/pycqa/flake8
rev: 7.1.1
hooks:
Expand Down
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

-
- Mark some arguments as positional-only by [@XuehaiPan](https://github.com/XuehaiPan) in [#161](https://github.com/metaopt/optree/pull/161).

### Fixed

-

### Removed

-
- Drop Python 3.6 support by [@XuehaiPan](https://github.com/XuehaiPan) in [#161](https://github.com/metaopt/optree/pull/161).

------

Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ python3 -m cibuildwheel --platform=linux --output-dir=wheelhouse --config-file=p
It will build wheel binaries for all supported CPython versions. The outputs will be placed in the `wheelhouse` directory.

To build a wheel for a specific CPython version, you can use the [`CIBW_BUILD`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-skip) environment variable.
For example, the following command will build a wheel for Python 3.7:
For example, the following command will build a wheel for Python 3.9:

```bash
CIBW_BUILD="cp37*manylinux*" python3 -m cibuildwheel --platform=linux --output-dir=wheelhouse --config-file=pyproject.toml
CIBW_BUILD="cp39*manylinux*" python3 -m cibuildwheel --platform=linux --output-dir=wheelhouse --config-file=pyproject.toml
```

You can change `cp37*` to `cp310*` to build for Python 3.10. See <https://cibuildwheel.readthedocs.io/en/stable/options> for more options.
You can change `cp39*` to `cp312*` to build for Python 3.12. See <https://cibuildwheel.readthedocs.io/en/stable/options> for more options.

## Documentation

Expand Down
6 changes: 1 addition & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,7 @@ pre-commit-install:
.PHONY: docs-install
docs-install:
$(call check_pip_install_extra,pydocstyle,pydocstyle[toml])
$(call check_pip_install_extra,doc8,"doc8<1.0.0a0") # unpin this when we drop support for Python 3.7
if ! $(PYTHON) -c "import sys; exit(sys.version_info < (3, 8))"; then \
$(PYTHON) -m pip uninstall --yes importlib-metadata; \
$(call check_pip_install_extra,importlib-metadata,"importlib-metadata<5.0.0a0"); \
fi
$(call check_pip_install,doc8)
$(call check_pip_install,sphinx)
$(call check_pip_install,sphinx-rtd-theme)
$(call check_pip_install,sphinx-autoapi)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# OpTree

![Python 3.7+](https://img.shields.io/badge/Python-3.7%2B-brightgreen)
![Python 3.8+](https://img.shields.io/badge/Python-3.8%2B-brightgreen)
[![PyPI](https://img.shields.io/pypi/v/optree?logo=pypi)](https://pypi.org/project/optree)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/metaopt/optree/build.yml?label=build&logo=github)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/metaopt/optree/tests.yml?label=tests&logo=github)
Expand Down Expand Up @@ -67,7 +67,7 @@ cd optree
pip3 install .
```

Compiling from the source requires Python 3.7+, a compiler (`gcc` / `clang` / `icc` / `cl.exe`) that supports C++20 and a `cmake` installation.
Compiling from the source requires Python 3.8+, a compiler (`gcc` / `clang` / `icc` / `cl.exe`) that supports C++20 and a `cmake` installation.

--------------------------------------------------------------------------------

Expand Down
72 changes: 41 additions & 31 deletions optree/_C.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ GLIBCXX_USE_CXX11_ABI: bool

def flatten(
tree: PyTree[T],
/,
leaf_predicate: Callable[[T], bool] | None = None,
node_is_leaf: bool = False,
namespace: str = '',
) -> tuple[list[T], PyTreeSpec]: ...
def flatten_with_path(
tree: PyTree[T],
/,
leaf_predicate: Callable[[T], bool] | None = None,
node_is_leaf: bool = False,
namespace: str = '',
Expand All @@ -63,29 +65,32 @@ def make_none(
) -> PyTreeSpec: ...
def make_from_collection(
collection: Collection[PyTreeSpec],
/,
node_is_leaf: bool = False,
namespace: str = '',
) -> PyTreeSpec: ...
def is_leaf(
obj: T,
/,
leaf_predicate: Callable[[T], bool] | None = None,
node_is_leaf: bool = False,
namespace: str = '',
) -> bool: ...
def all_leaves(
iterable: Iterable[T],
/,
leaf_predicate: Callable[[T], bool] | None = None,
node_is_leaf: bool = False,
namespace: str = '',
) -> bool: ...
def is_namedtuple(obj: object | type) -> bool: ...
def is_namedtuple_instance(obj: object) -> bool: ...
def is_namedtuple_class(cls: type) -> bool: ...
def namedtuple_fields(obj: tuple | type[tuple]) -> tuple[str, ...]: ...
def is_structseq(obj: object | type) -> bool: ...
def is_structseq_instance(obj: object) -> bool: ...
def is_structseq_class(cls: type) -> bool: ...
def structseq_fields(obj: tuple | type[tuple]) -> tuple[str, ...]: ...
def is_namedtuple(obj: object | type, /) -> bool: ...
def is_namedtuple_instance(obj: object, /) -> bool: ...
def is_namedtuple_class(cls: type, /) -> bool: ...
def namedtuple_fields(obj: tuple | type[tuple], /) -> tuple[str, ...]: ...
def is_structseq(obj: object | type, /) -> bool: ...
def is_structseq_instance(obj: object, /) -> bool: ...
def is_structseq_class(cls: type, /) -> bool: ...
def structseq_fields(obj: tuple | type[tuple], /) -> tuple[str, ...]: ...

class PyTreeKind(enum.IntEnum):
CUSTOM = 0 # a custom type
Expand All @@ -108,54 +113,58 @@ class PyTreeSpec:
namespace: str
type: builtins.type | None
kind: PyTreeKind
def unflatten(self, leaves: Iterable[T]) -> PyTree[T]: ...
def flatten_up_to(self, full_tree: PyTree[T]) -> list[PyTree[T]]: ...
def broadcast_to_common_suffix(self, other: PyTreeSpec) -> PyTreeSpec: ...
def compose(self, inner_treespec: PyTreeSpec) -> PyTreeSpec: ...
def unflatten(self, leaves: Iterable[T], /) -> PyTree[T]: ...
def flatten_up_to(self, full_tree: PyTree[T], /) -> list[PyTree[T]]: ...
def broadcast_to_common_suffix(self, other: Self, /) -> Self: ...
def compose(self, inner_treespec: Self, /) -> Self: ...
def walk(
self,
/,
f_node: Callable[[tuple[U, ...], MetaData], U],
f_leaf: Callable[[T], U] | None,
leaves: Iterable[T],
) -> U: ...
def paths(self) -> list[tuple[Any, ...]]: ...
def accessors(self) -> list[PyTreeAccessor]: ...
def entries(self) -> list[Any]: ...
def entry(self, index: int) -> Any: ...
def children(self) -> list[PyTreeSpec]: ...
def child(self, index: int) -> PyTreeSpec: ...
def is_leaf(self, strict: bool = True) -> bool: ...
def is_prefix(self, other: PyTreeSpec, strict: bool = False) -> bool: ...
def is_suffix(self, other: PyTreeSpec, strict: bool = False) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __lt__(self, other: object) -> bool: ...
def __le__(self, other: object) -> bool: ...
def __gt__(self, other: object) -> bool: ...
def __ge__(self, other: object) -> bool: ...
def __hash__(self) -> int: ...
def __len__(self) -> int: ...
def paths(self, /) -> list[tuple[Any, ...]]: ...
def accessors(self, /) -> list[PyTreeAccessor]: ...
def entries(self, /) -> list[Any]: ...
def entry(self, index: int, /) -> Any: ...
def children(self, /) -> list[Self]: ...
def child(self, index: int, /) -> Self: ...
def is_leaf(self, /, strict: bool = True) -> bool: ...
def is_prefix(self, other: Self, /, strict: bool = False) -> bool: ...
def is_suffix(self, other: Self, /, strict: bool = False) -> bool: ...
def __eq__(self, other: object, /) -> bool: ...
def __ne__(self, other: object, /) -> bool: ...
def __lt__(self, other: object, /) -> bool: ...
def __le__(self, other: object, /) -> bool: ...
def __gt__(self, other: object, /) -> bool: ...
def __ge__(self, other: object, /) -> bool: ...
def __hash__(self, /) -> int: ...
def __len__(self, /) -> int: ...

class PyTreeIter(Iterator[T]):
def __init__(
self,
tree: PyTree[T],
/,
leaf_predicate: Callable[[T], bool] | None = None,
node_is_leaf: bool = False,
namespace: str = '',
) -> None: ...
def __iter__(self) -> Self: ...
def __next__(self) -> T: ...
def __iter__(self, /) -> Self: ...
def __next__(self, /) -> T: ...

def register_node(
cls: type[Collection[T]],
/,
flatten_func: FlattenFunc[T],
unflatten_func: UnflattenFunc[T],
path_entry_type: type[PyTreeEntry],
namespace: str = '',
) -> None: ...
def unregister_node(
cls: type,
/,
namespace: str = '',
) -> None: ...
def is_dict_insertion_ordered(
Expand All @@ -164,5 +173,6 @@ def is_dict_insertion_ordered(
) -> bool: ...
def set_dict_insertion_ordered(
mode: bool,
/,
namespace: str = '',
) -> None: ...
Loading
Loading