Skip to content

Commit

Permalink
python 3.13 compatibility (#522)
Browse files Browse the repository at this point in the history
* python 3.13 compatibility

* bump version

* fix poetry.lock for 3.13

* skip uvloop

* fix poetry

* fix ci

* fix tests

* fix ci

* fix

* fix

* fix

* no pypy 3.8

* fix
  • Loading branch information
sonic182 authored Feb 1, 2025
1 parent 284c228 commit fbdd0e2
Show file tree
Hide file tree
Showing 8 changed files with 1,019 additions and 792 deletions.
56 changes: 31 additions & 25 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

name: Python package

on:
Expand All @@ -7,21 +6,19 @@ on:

jobs:
build:


runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version:
- '3.13'
- '3.12'
- '3.11'
- '3.10'
- '3.9'
- '3.8'
- 'pypy3.10'
- 'pypy3.9'
- 'pypy3.8'
exclude:
- os: windows-latest
python-version: 'pypy3.10'
Expand All @@ -31,6 +28,12 @@ jobs:
python-version: 'pypy3.8'
- os: windows-latest
python-version: 'pypy3.7'
- os: macos-latest
python-version: 'pypy3.10'
- os: macos-latest
python-version: 'pypy3.9'
- os: macos-latest
python-version: 'pypy3.8'

steps:
- uses: actions/checkout@v4
Expand All @@ -46,39 +49,42 @@ jobs:
node-version: 20

- uses: actions/cache@v3
if: startsWith(runner.os, 'Linux')
with:
path: ~/.cache/pip
key: ${{ runner.os }}-${{matrix.python-version}}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-${{matrix.python-version}}-pip-
- uses: actions/cache@v3
if: startsWith(runner.os, 'macOS')
with:
path: ~/Library/Caches/pip
key: ${{ runner.os }}-${{matrix.python-version}}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-${{matrix.python-version}}-pip-
- uses: actions/cache@v3
if: startsWith(runner.os, 'Windows')
with:
path: ~\AppData\Local\pip\Cache
path: |
~/.cache/pip
~/Library/Caches/pip
~\AppData\Local\pip\Cache
key: ${{ runner.os }}-${{matrix.python-version}}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-${{matrix.python-version}}-pip-
- name: Install dependencies
- name: Install Rust (for PyPy)
if: ${{ startsWith(matrix.python-version, 'pypy') && runner.os == 'Linux' }}
run: |
curl https://sh.rustup.rs -sSf | sh -s -- -y
. "$HOME/.cargo/env"
- name: Install dependencies (CPython)
if: ${{ !startsWith(matrix.python-version, 'pypy') }}
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install
- name: Install dependencies (PyPy)
if: ${{ startsWith(matrix.python-version, 'pypy') && runner.os == 'Linux' }}
run: |
python -m pip install --upgrade pip
pip install poetry
# Replace Django version with "django<4.1" in pyproject.toml
sed -i '/^django = { version = /s/.*/django = { version = "<4.1" }/' pyproject.toml
poetry lock
poetry install
- name: Test with pytest
run: |
poetry run py.test --cov-append
env:
COV_CORE_SOURCE: src
COV_CORE_CONFIG: .coveragerc
COV_CORE_DATAFILE: .coverage.eager
COV_CORE_DATAFILE: .coverage.eager
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.22.1] 2025-02-01

### Added
- Python 3.13 compatibility

## [0.22.0] 2024-10-16

### Added
Expand Down Expand Up @@ -294,7 +299,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- https


[Unreleased]: https://github.com/sonic182/aiosonic/compare/0.22.0..HEAD
[Unreleased]: https://github.com/sonic182/aiosonic/compare/0.22.1..HEAD
[0.22.1]: https://github.com/sonic182/aiosonic/compare/0.22.0..0.22.1
[0.22.0]: https://github.com/sonic182/aiosonic/compare/0.21.0..0.22.0
[0.21.0]: https://github.com/sonic182/aiosonic/compare/0.20.1..0.21.0
[0.20.1]: https://github.com/sonic182/aiosonic/compare/0.20.0..0.20.1
Expand Down
41 changes: 30 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,30 @@ SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = sourcedocs
BUILDDIR = docs
DOCKER_CMD = curl -sL https://deb.nodesource.com/setup_20.x | bash && apt-get update && apt-get install nodejs -y && cd /root && cp -r /app/* . && pip install poetry && poetry install && poetry run py.test

# Default Docker command for CPython
DOCKER_CMD = curl -sL https://deb.nodesource.com/setup_20.x | bash \
&& apt-get update \
&& apt-get install -y nodejs \
&& cd /root \
&& cp -r /app/* . \
&& pip install poetry \
&& poetry install \
&& poetry run py.test

# Separate Docker command for PyPy
# Installs an up-to-date Rust toolchain with rustup (rather than older distro cargo/rustc).
# Also upgrades pip/setuptools/wheel/maturin to avoid potential parse issues.
DOCKER_CMD_PYPY = curl -sL https://deb.nodesource.com/setup_20.x | bash \
&& apt-get update \
&& apt-get install -y nodejs curl build-essential \
&& curl https://sh.rustup.rs -sSf | sh -s -- -y \
&& . /root/.cargo/env \
&& cd /root \
&& cp -r /app/* . \
&& pip install poetry \
&& poetry install \
&& poetry run py.test

# Put it first so that "make" without argument is like "make help".
help:
Expand All @@ -33,23 +56,19 @@ test312:
echo "TEST PYTHON 3.12"
docker run -i --rm -v $(shell pwd):/app python:3.12 bash -c "$(DOCKER_CMD)"

test-pypy37:
echo "TEST PYPY 3.7"
docker run -i --rm -v $(shell pwd):/app pypy:3.7 bash -c "$(DOCKER_CMD)"

test-pypy38:
echo "TEST PYPY 3.8"
docker run -i --rm -v $(shell pwd):/app pypy:3.8 bash -c "$(DOCKER_CMD)"
test313:
echo "TEST PYTHON 3.13"
docker run -i --rm -v $(shell pwd):/app python:3.13 bash -c "$(DOCKER_CMD)"

test-pypy39:
echo "TEST PYPY 3.9"
docker run -i --rm -v $(shell pwd):/app pypy:3.9 bash -c "$(DOCKER_CMD)"
docker run -i --rm -v $(shell pwd):/app pypy:3.9 bash -c "$(DOCKER_CMD_PYPY)"

test-pypy310:
echo "TEST PYPY 3.10"
docker run -i --rm -v $(shell pwd):/app pypy:3.10 bash -c "$(DOCKER_CMD)"
docker run -i --rm -v $(shell pwd):/app pypy:3.10 bash -c "$(DOCKER_CMD_PYPY)"

test: test37 test38 test39 test310 test311 test312 test-pypy37 test-pypy38 test-pypy39 test-pypy310
test: test38 test39 test310 test311 test312 test313 test-pypy39 test-pypy310
echo "OK"

clear:
Expand Down
28 changes: 15 additions & 13 deletions djangotestproj/djangotestproj/settings.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
"""
Django settings for djangotestproj project.
Generated by 'django-admin startproject' using Django 2.2.3.
Generated by 'django-admin startproject' using Django 4.2.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
https://docs.djangoproject.com/en/4.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

import os
from pathlib import Path

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Build paths inside the project like this: BASE_DIR / 'subdir'
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "+-3d9d)73gcb_4$#1x_fidxuckv!yaii-qbinm8cvl_-0+b4ph"
Expand Down Expand Up @@ -49,6 +49,7 @@
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]

# Adjust this if your URL configuration is in a different file
ROOT_URLCONF = "djangotestproj.djangotestproj.urls"

TEMPLATES = [
Expand All @@ -71,18 +72,18 @@


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
"NAME": BASE_DIR / "db.sqlite3",
}
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
Expand All @@ -101,20 +102,21 @@


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_L10N = True
# USE_L10N is deprecated in Django 4.x and removed in 5.x. Remove or comment it out:
# USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = "/static/"
7 changes: 3 additions & 4 deletions djangotestproj/djangotestproj/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""djangotestproj URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
Expand All @@ -17,8 +17,7 @@
from django.urls import path
from djangotestproj.djangotestproj import views


urlpatterns = [
# path('admin/', admin.site.urls),
path("post_file", views.upload_file),
path('admin/', admin.site.urls), # Uncomment this if admin is needed
path("post_file", views.upload_file, name='upload_file'),
]
36 changes: 23 additions & 13 deletions djangotestproj/djangotestproj/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Views."""
"""
Views module for file upload demonstration.
Compatible with Django 4.2.
"""

from django.http import HttpRequest
from django.http import HttpResponse
from django.http import HttpRequest, HttpResponse
from django.views.decorators.csrf import csrf_exempt

from django import forms


Expand All @@ -12,15 +13,24 @@ class UploadFileForm(forms.Form):


@csrf_exempt
def upload_file(request: HttpRequest):
"""Sample upload file."""
def upload_file(request: HttpRequest) -> HttpResponse:
"""
Example view for handling file uploads.
Expects:
- 'foo' as a FileField in the form
- 'field1' as a POST parameter
"""
if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
return HttpResponse(
content=form.cleaned_data["foo"].read()
+ b"-"
+ request.POST["field1"].encode()
)
return HttpResponse(content=form.errors)
return HttpResponse(content="ko")
file_content = form.cleaned_data["foo"].read()
field1_value = request.POST.get("field1", "")
response_data = file_content + b"-" + field1_value.encode()
return HttpResponse(content=response_data)

# If the form is not valid, return the errors for debug
return HttpResponse(content=form.errors, status=400)

# If not a POST request, return a simple response
return HttpResponse(content="Request method not allowed.", status=405)
Loading

0 comments on commit fbdd0e2

Please sign in to comment.