Skip to content

Support Python 3.13 #227

New issue

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

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

Already on GitHub? # to your account

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d3434ce
Support Python 3.13 without torch
chezou Dec 8, 2024
66a57b3
Update GH Action
chezou Dec 8, 2024
e7fb4f3
Bump up mypy, black, and pytest
chezou Dec 10, 2024
216c5e2
Fix for RTD
chezou Dec 10, 2024
38472c9
Stabilize knn i2i test
chezou Dec 10, 2024
d37e414
Address deprecation of typing.Hashable
chezou Dec 10, 2024
e999f88
Skip doctests for Python 3.13 incompatible modules
chezou Dec 10, 2024
2d5ccf3
Avoid returing numpy.float64 in calc_metrics
chezou Dec 11, 2024
63481d2
Update CHANGELOG
chezou Dec 11, 2024
3b5e594
Apply review feedback
chezou Dec 11, 2024
9010381
Use docs group instead
chezou Dec 11, 2024
bd36f52
Merge branch 'main' into feature/py313
chezou Dec 11, 2024
aaaf0ac
Precise scipy version
chezou Dec 11, 2024
aee7b22
Fix lint
chezou Dec 11, 2024
d6bc4fb
Update pyproject.toml
chezou Dec 12, 2024
183b365
Poetry lock
chezou Dec 12, 2024
7402772
Update CHANGELOG
chezou Dec 12, 2024
1fc04a8
Merge branch 'main' into feature/py313
chezou Jan 14, 2025
ea6f854
Merge branch 'main' into feature/py313
chezou Jan 16, 2025
a249d4f
Merge branch 'main' into feature/py313
chezou Feb 3, 2025
b4ee1a9
Update CHANGELOG
chezou Feb 3, 2025
7717990
poetry lock --no-update
chezou Feb 3, 2025
42028f2
Fix patch order
chezou Feb 3, 2025
73d5d21
Merge remote-tracking branch 'origin/main' into feature/py313
chezou Feb 4, 2025
309a88c
Add comment for numpy.argpartition behavioral change
chezou Feb 4, 2025
8b97751
Merge remote-tracking branch 'origin/main' into feature/py313
chezou Mar 14, 2025
5e67d9c
Skip more torch
chezou Mar 14, 2025
0381da0
Support cupy for Python 3.13
chezou Mar 20, 2025
d596436
Support PyTorch 2.6
chezou Mar 20, 2025
c952fec
Bump fastrlock for cupy with Python 3.13
chezou Mar 20, 2025
dd3360a
Supress lint errors
chezou Mar 20, 2025
03e525a
poetry lock --no-update
chezou Mar 20, 2025
697fe39
Remove unused test skip conditions
chezou Mar 20, 2025
33ccf5f
Support pytorch_lightning with torch 2.6
chezou Mar 20, 2025
a4e5418
Resurrect doctest
chezou Mar 20, 2025
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
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
python-version: "3.10"

- name: Install poetry
run: pip install urllib3==1.26.15 poetry==1.8.3
run: pip install urllib3==1.26.15 poetry==1.8.5

- name: Load cached venv
id: cached-poetry-dependencies
Expand All @@ -43,7 +43,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [ "3.9", "3.10", "3.11", "3.12" ]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]

steps:
- uses: actions/checkout@v4
Expand All @@ -54,7 +54,7 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Install poetry
run: pip install urllib3==1.26.15 poetry==1.4.0
run: pip install urllib3==1.26.15 poetry==1.8.5

- name: Load cached venv
id: cached-poetry-dependencies
Expand Down
10 changes: 3 additions & 7 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,15 @@ build:
jobs:
pre_build:
- cp -r examples docs/source/
post_create_environment:
- pip install poetry
post_install:
- pip install --no-cache-dir poetry==1.8.5
- poetry export -f requirements.txt -o requirements.txt -E all --without-hashes
- pip install --no-cache-dir -r requirements.txt
- VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install -E all --no-root --with docs

sphinx:
builder: html
configuration: docs/source/conf.py
fail_on_warning: false

python:
install:
- requirements: docs/requirements.txt

formats:
- pdf
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Python 3.13 support ([#227](https://github.com/MobileTeleSystems/RecTools/pull/227))

## [0.12.0] - 24.02.2025

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ install: .venv .reports
poetry run pytest ${TESTS} --cov=${SOURCES} --cov-report=xml

.doctest:
poetry run pytest --doctest-modules ${SOURCES} --ignore=rectools/models/lightfm.py
poetry run pytest --doctest-modules ${SOURCES} --ignore=rectools/tools/ann.py

coverage: .venv .reports
poetry run coverage run --source ${SOURCES} --module pytest
Expand Down
1,167 changes: 976 additions & 191 deletions poetry.lock

Large diffs are not rendered by default.

46 changes: 34 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3",
"Topic :: Software Development :: Libraries :: Python Modules",
"Intended Audience :: Science/Research",
Expand All @@ -52,13 +53,20 @@ packages = [


[tool.poetry.dependencies]
python = ">=3.9, <3.13"
python = ">=3.9, <3.14"
numpy = [
{version = ">=1.22, <2.0.0", python = "<3.12"},
{version = ">=1.26, <2.0.0", python = "3.12"} # numpy <1.26 fails to install on Python 3.12
{version = ">=1.26, <2.0.0", python = "3.12"}, # numpy <1.26 fails to install on Python 3.12
{version = ">=2.1.0, <3.0.0", python = ">=3.13"} # numpy <2.1 fails to install on Python 3.13
]
pandas = [
{version = ">=1.5.0, <3.0.0", python = "<3.13"},
{version = ">=2.2.3, <3.0.0", python = ">=3.13"} # pandas <2.2.3 fails to install on Python 3.13
]
scipy = [
{version = "^1.10.1, <1.13", python = "<3.10"}, # there is a bug in 1.13* https://github.com/scipy/scipy/issues/20670
{version = ">=1.14.1, <2.0.0", python = ">=3.10"} # scipy >=1.14.1 fails to install on Python 3.9
]
pandas = ">=1.5.0, <3.0.0"
scipy = "^1.10.1, <1.13" # in 1.13 were introduced significant changes breaking our logic
tqdm = "^4.27.0"
implicit = "^0.7.1"
attrs = ">=19.1.0,<24.0.0"
Expand All @@ -76,16 +84,23 @@ nmslib-metabrainz = {version = "^2.1.3", python = ">=3.11, <3.13", optional = tr

# The latest torch version available for MacOSX + x86_64 is 2.2.2
torch = [
{version = ">=1.6.0, <2.3.0", markers = "sys_platform == 'darwin' and platform_machine == 'x86_64'", optional = true},
{version = ">=1.6.0, <3.0.0", optional = true}
{version = ">=1.6.0, <2.3.0", python = "<3.13", markers = "sys_platform == 'darwin' and platform_machine == 'x86_64'", optional = true},
{version = ">=1.6.0, <3.0.0", python = "<3.13", optional = true},
{version = ">=2.6.0, <3.0.0", python = ">=3.13", optional = true},
]
pytorch-lightning = [
{version = ">=1.6.0, <3.0.0", python = "<3.13", optional = true},
{version = ">=2.5.1, <3.0.0", python = ">=3.13", optional = true},
]
pytorch-lightning = {version = ">=1.6.0, <3.0.0", optional = true}

ipywidgets = {version = ">=7.7,<8.2", optional = true}
plotly = {version="^5.22.0", optional = true}
nbformat = {version = ">=4.2.0", optional = true}
cupy-cuda12x = {version = "^13.3.0", python = "<3.13", optional = true}

cupy-cuda12x = [
{version = "^13.3.0", python = "<3.13", optional = true},
{version = "^13.4.0", python = ">=3.13", optional = true},
]
fastrlock = {version = "^0.8.3", optional = true}

[tool.poetry.extras]
lightfm = ["rectools-lightfm"]
Expand All @@ -103,13 +118,13 @@ all = [


[tool.poetry.group.dev.dependencies]
black = "24.4.2"
black = "24.10.0"
isort = "5.13.2"
pylint = "3.1.0"
mypy = "1.13.0"
flake8 = "7.0.0"
bandit = "1.7.8"
pytest = "8.1.1"
pytest = "8.3.3"
radon = "6.0.1"
coverage = "7.5.0"
autopep8 = "2.1.0"
Expand All @@ -122,10 +137,17 @@ pytest-mock = "3.14.0"
click = "8.1.7"
gitpython = "3.1.43"

[tool.poetry.group.docs]
optional = true

[tool.poetry.group.docs.dependencies]
sphinx = "5.1.1"
nbsphinx = "0.8.9"
sphinx-rtd-theme = "1.0.0"

[tool.black]
line-length = 120
target-version = ["py39", "py310", "py311", "py312"]
target-version = ["py39", "py310", "py311", "py312", "py313"]


[build-system]
Expand Down
2 changes: 1 addition & 1 deletion rectools/metrics/scoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,4 @@ def calc_metrics( # noqa # pylint: disable=too-many-branches,too-many-locals,t
if len(results) < expected_results_len:
warnings.warn("Custom metrics are not supported.")

return results
return {k: v.item() if hasattr(v, "item") else v for k, v in results.items()}
4 changes: 2 additions & 2 deletions rectools/models/nn/transformers/lightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,9 @@ def _calc_bce_loss(cls, logits: torch.Tensor, y: torch.Tensor, w: torch.Tensor)
def _calc_gbce_loss(
self, logits: torch.Tensor, y: torch.Tensor, w: torch.Tensor, negatives: torch.Tensor
) -> torch.Tensor:
n_actual_items = self.torch_model.item_model.n_items - len(self.item_extra_tokens)
n_actual_items = self.torch_model.item_model.n_items - len(self.item_extra_tokens) # type: ignore
n_negatives = negatives.shape[2]
logits = self._get_reduced_overconfidence_logits(logits, n_actual_items, n_negatives)
logits = self._get_reduced_overconfidence_logits(logits, n_actual_items, n_negatives) # type: ignore
loss = self._calc_bce_loss(logits, y, w)
return loss

Expand Down
7 changes: 6 additions & 1 deletion tests/models/nn/test_dssm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import numpy as np
import pandas as pd
import pytest
import pytorch_lightning # noqa # pylint: disable=unused-import
from lightning_fabric import seed_everything

from rectools.columns import Columns
Expand All @@ -29,8 +30,12 @@

from ..data import INTERACTIONS

filter_warnings_decorator = pytest.mark.filterwarnings(
"ignore::pytorch_lightning.utilities.warnings.PossibleUserWarning"
)

@pytest.mark.filterwarnings("ignore::pytorch_lightning.utilities.warnings.PossibleUserWarning")

@filter_warnings_decorator
@pytest.mark.filterwarnings("ignore::UserWarning")
class TestDSSMModel:
def setup_method(self) -> None:
Expand Down
30 changes: 26 additions & 4 deletions tests/models/test_implicit_knn.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def test_with_whitelist(self, dataset: Dataset, filter_viewed: bool, expected: p
pd.DataFrame(
{
Columns.TargetItem: [11, 11, 12, 12],
Columns.Item: [12, 15, 11, 14],
Columns.Item: [12, 14, 11, 14],
Columns.Rank: [1, 2, 1, 2],
}
),
Expand All @@ -154,10 +154,32 @@ def test_with_whitelist(self, dataset: Dataset, filter_viewed: bool, expected: p
),
),
)
def test_i2i(
self, dataset: Dataset, filter_itself: bool, whitelist: tp.Optional[np.ndarray], expected: pd.DataFrame
) -> None:
def test_i2i(self, filter_itself: bool, whitelist: tp.Optional[np.ndarray], expected: pd.DataFrame) -> None:
base_model = TFIDFRecommender(K=5, num_threads=2)
# Recreate dataset to prevent same co-occurrence count between (11, 14) and (11, 15)
# which leads to different results in the test in Python 3.13
# This is because numpy.argpartition behavior was changed.
# See also: https://github.com/MobileTeleSystems/RecTools/pull/227#discussion_r1941872699
interactions = pd.DataFrame(
[
[10, 11],
[10, 12],
[10, 14],
[20, 11],
[20, 12],
[20, 13],
[30, 11],
[30, 12],
[30, 14],
[40, 11],
[40, 15],
[40, 17],
],
columns=Columns.UserItem,
)
interactions[Columns.Weight] = 1
interactions[Columns.Datetime] = "2021-09-09"
dataset = Dataset.construct(interactions)
model = ImplicitItemKNNWrapperModel(model=base_model).fit(dataset)
actual = model.recommend_to_items(
target_items=np.array([11, 12]),
Expand Down
2 changes: 1 addition & 1 deletion tests/models/test_pure_svd.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,8 @@ def test_from_config(self, mocker: MockerFixture, use_gpu: bool) -> None:
def test_get_config(
self, mocker: MockerFixture, random_state: tp.Optional[int], simple_types: bool, use_gpu: bool
) -> None:
mocker.patch("rectools.models.pure_svd.cp.cuda.is_available", return_value=True)
mocker.patch("rectools.models.pure_svd.cp", return_value=True)
mocker.patch("rectools.models.pure_svd.cp.cuda.is_available", return_value=True)
model = PureSVDModel(
factors=100,
tol=1.0,
Expand Down
10 changes: 9 additions & 1 deletion tests/tools/test_ann.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,22 @@
# limitations under the License.

import pickle
import sys
from collections.abc import Hashable
from typing import Callable, Dict, List, Union

import numpy as np
import pytest

from rectools.dataset import IdMap
from rectools.tools import ItemToItemAnnRecommender, UserToItemAnnRecommender

try:
from rectools.tools import ItemToItemAnnRecommender, UserToItemAnnRecommender
except ImportError:
pass


pytestmark = pytest.mark.skipif(sys.version_info >= (3, 13), reason="`nsmlib` is not compatible with Python >= 3.13")


class TestItemToItemAnnRecommender:
Expand Down