From d1966fbbc5e637993974d3e6c6b3742c5a6bfc32 Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:01:47 -0300 Subject: [PATCH 1/7] Updates supported versions of Python and Django --- CHANGELOG.md | 8 +++++++ django_virtual_models/__init__.py | 2 +- django_virtual_models/py.typed | 0 .../query_capture/capture.py | 12 +++++++++- pyproject.toml | 24 +++++++++---------- 5 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 django_virtual_models/py.typed diff --git a/CHANGELOG.md b/CHANGELOG.md index 110755b..f2abc2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ 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). +## [0.3.0] + +- Include `py.typed` file for type hints +- Add support to Python 3.12 and 3.13 +- Drop support to Python 3.8 and 3.9 +- Add support to Django 5.0, 5.1, and 5.2 +- Drop support to Django 3.2, 4.0, and 4.1 + ## [0.2.0] - Add support to nested prefetch lookups like `v.VirtualModel(manager=User.objects, lookup="course__facilitators")` diff --git a/django_virtual_models/__init__.py b/django_virtual_models/__init__.py index c65a20a..aa36853 100644 --- a/django_virtual_models/__init__.py +++ b/django_virtual_models/__init__.py @@ -1,7 +1,7 @@ """Top-level package for django_virtual_models.""" import logging -__version__ = "0.2.0" +__version__ = "0.3.0" # Good practice: https://docs.python-guide.org/writing/logging/#logging-in-a-library logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/django_virtual_models/py.typed b/django_virtual_models/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/django_virtual_models/query_capture/capture.py b/django_virtual_models/query_capture/capture.py index 7addb14..256f4e1 100644 --- a/django_virtual_models/query_capture/capture.py +++ b/django_virtual_models/query_capture/capture.py @@ -7,11 +7,21 @@ import time import typing from contextlib import ContextDecorator, ExitStack -from distutils.sysconfig import get_python_lib from django.conf import settings from django.db import connection +try: + from distutils.sysconfig import get_python_lib +except ImportError: + from sysconfig import get_paths + + def get_python_lib(): + """ + Get the path to the Python library directory. + """ + return get_paths()["purelib"] + class CapturedQuery(typing.TypedDict): """ diff --git a/pyproject.toml b/pyproject.toml index 5537b6e..4d69d19 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,10 +21,10 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dependencies = [ "django >=3.2", @@ -57,7 +57,7 @@ test = [ "model_bakery >=1.11.0,<2.0.0", ] example = [ - "django >= 3.2,<4.0", + "django >= 4.2,<6.0", "pyyaml >= 6.0,<7.0", ] @@ -112,31 +112,31 @@ testpaths = [ [tool.tox] legacy_tox_ini = """ [tox] -envlist = {linux}-py{38,39,310,311}-django{32,40,41,42} +envlist = {linux}-py{310,311,312,313}-django{42,50,51,52} isolated_build = True [gh-actions] python = - 3.8: py38 - 3.9: py39 3.10: py310 3.11: py311 + 3.12: py312 + 3.13: py313 [gh-actions:env] OS = ubuntu-latest: linux DJANGO = - 3.2: django32 - 4.0: django40 - 4.1: django41 4.2: django42 + 5.0: django50 + 5.1: django51 + 5.2: django52 [testenv] deps = - django32: django~=3.2 - django40: django~=4.0 - django41: django~=4.1 django42: django~=4.2 + django50: django~=5.0 + django51: django~=5.1 + django52: django~=5.2 .[test] commands = coverage run -m pytest --basetemp={envtmpdir} From ceebfb42752dec38c5c87c18d6550044824505e6 Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:07:25 -0300 Subject: [PATCH 2/7] Adjust platform versions matrix --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 738377f..bb8bd37 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,8 +12,8 @@ jobs: strategy: matrix: os: [ubuntu-latest] - python-version: ['3.8', '3.9', '3.10', '3.11'] - django-version: ['3.2', '4.0', '4.1', '4.2'] + python-version: ['3.10', '3.11', '3.12', '3.13'] + django-version: ['4.2', '5.0', '5.1', '5.2'] steps: - name: Checkout code From c9972eda0ecfa189691270445a44372c8b685841 Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:11:33 -0300 Subject: [PATCH 3/7] Fix GH actions config --- .github/workflows/pre-commit.yml | 6 +++--- .github/workflows/tests.yml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 976b6cd..85cb398 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -9,6 +9,6 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - - uses: pre-commit/action@v3.0.0 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bb8bd37..c243c05 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,13 +17,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Cache installed requirements - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ env.pythonLocation }} key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v01 @@ -43,7 +43,7 @@ jobs: python -m pytest example - name: Generate coverage.xml if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' && matrix.django-version == '3.2' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tox-gh-actions-coverage path: coverage.xml From 43e36656fdf98e0a36b51c77876920e46c0fcb12 Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:23:01 -0300 Subject: [PATCH 4/7] Improve code based on sourcery suggestions --- django_virtual_models/query_capture/capture.py | 18 ++++++++++++++---- pyproject.toml | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/django_virtual_models/query_capture/capture.py b/django_virtual_models/query_capture/capture.py index 256f4e1..99b8f60 100644 --- a/django_virtual_models/query_capture/capture.py +++ b/django_virtual_models/query_capture/capture.py @@ -16,11 +16,17 @@ except ImportError: from sysconfig import get_paths - def get_python_lib(): + def get_python_lib(plat_specific=False): """ Get the path to the Python library directory. + If plat_specific is True, return platform-specific directory, + otherwise return platform-independent directory. + To match distutils behavior, return both paths when called without arguments. """ - return get_paths()["purelib"] + paths = get_paths() + if plat_specific: + return paths["platlib"] + return [paths["purelib"], paths["platlib"]] class CapturedQuery(typing.TypedDict): @@ -89,11 +95,15 @@ def _save_queries(self, execute, sql, params, many, context): """ if settings.DEBUG: # only calculate stack in DEBUG or TEST mode, to avoid production impact - python_library_directory = get_python_lib() + python_lib_paths = get_python_lib() + # Handle both single string and list return values + if isinstance(python_lib_paths, str): + python_lib_paths = [python_lib_paths] + stack = [ stack for stack in inspect.stack() - if not stack.filename.startswith(python_library_directory) + if not any(stack.filename.startswith(path) for path in python_lib_paths) and not stack.filename.startswith("/usr/local/lib/") and not stack.filename.endswith("query_capture/capture.py") ] diff --git a/pyproject.toml b/pyproject.toml index 4d69d19..c1c98d9 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,7 @@ build-backend = "flit_core.buildapi" [tool.flit.module] name = "django_virtual_models" +py-typed = true [project] name = "django-virtual-models" From d7e8e9ecbe8fb2df788b395d8f7162311796d23a Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:27:19 -0300 Subject: [PATCH 5/7] Fixes old version checks on CI --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c243c05..b1c81cb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,19 +37,19 @@ jobs: DJANGO: ${{ matrix.django-version }} run: tox - name: Run tests for example - if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' && matrix.django-version == '3.2' }} + if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10' && matrix.django-version == '4.2' }} run: | python -m pip install .[test,example] python -m pytest example - name: Generate coverage.xml - if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' && matrix.django-version == '3.2' }} + if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10' && matrix.django-version == '4.2' }} uses: actions/upload-artifact@v4 with: name: tox-gh-actions-coverage path: coverage.xml if-no-files-found: error - name: Upload coverage.xml to Coveralls - if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.8' && matrix.django-version == '3.2' }} + if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10' && matrix.django-version == '4.2' }} run: coveralls --service=github env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 8b8920ac28d99f1cc3984583e4011d7230437f7d Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:37:45 -0300 Subject: [PATCH 6/7] Migrate index_together to indexes --- ...ovie_order_movies_pers_movie_i_957f84_idx.py | 17 +++++++++++++++++ example/movies/models.py | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 example/movies/migrations/0002_rename_persondirector_movie_order_movies_pers_movie_i_957f84_idx.py diff --git a/example/movies/migrations/0002_rename_persondirector_movie_order_movies_pers_movie_i_957f84_idx.py b/example/movies/migrations/0002_rename_persondirector_movie_order_movies_pers_movie_i_957f84_idx.py new file mode 100644 index 0000000..8367469 --- /dev/null +++ b/example/movies/migrations/0002_rename_persondirector_movie_order_movies_pers_movie_i_957f84_idx.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2 on 2025-05-14 01:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("movies", "0001_initial"), + ] + + operations = [ + migrations.RenameIndex( + model_name="persondirector", + new_name="movies_pers_movie_i_957f84_idx", + old_fields=("movie", "order"), + ), + ] diff --git a/example/movies/models.py b/example/movies/models.py index 3a4b46c..36c2d19 100644 --- a/example/movies/models.py +++ b/example/movies/models.py @@ -20,7 +20,7 @@ class PersonDirector(models.Model): order = models.PositiveSmallIntegerField() class Meta: - index_together = [("movie", "order")] + indexes = [models.Index(fields=["movie", "order"])] ordering = ["movie", "order"] From b056505b80ba819b81896b91e36ab82a4dcf6c40 Mon Sep 17 00:00:00 2001 From: Hugo bessa Date: Tue, 13 May 2025 22:41:18 -0300 Subject: [PATCH 7/7] Fix Django min version in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c1c98d9..6f9386b 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ "Programming Language :: Python :: 3.13", ] dependencies = [ - "django >=3.2", + "django >=4.2", "djangorestframework >=3.13.1", "typing-extensions >=4.3.0", ]