chore: migrate to python 3.13 and update dependencies

Migrate from Python 3.11 to 3.13 with updated dependencies. Switch from PyPDF2 to pypdf library for better PDF processing. Add new U14 age groups and extract-pdf utility script.
This commit is contained in:
2025-09-29 23:05:48 +02:00
parent ce42f489bf
commit 8ae1c33b3a
7 changed files with 1267 additions and 932 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ repos:
- id: mypy - id: mypy
exclude: ^(docs/|example-plugin/) exclude: ^(docs/|example-plugin/)
args: [--ignore-missing-imports] args: [--ignore-missing-imports]
additional_dependencies: [types-requests, PyPDF2] additional_dependencies: [types-requests, pypdf]
- repo: https://github.com/adrienverge/yamllint.git - repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1 rev: v1.37.1
hooks: hooks:
+1 -1
View File
@@ -84,7 +84,7 @@ poetry run fastapi run myice/webapi.py --host 127.0.0.1
- Typer for CLI interface - Typer for CLI interface
- FastAPI for web API - FastAPI for web API
- requests for HTTP requests - requests for HTTP requests
- PyPDF2 for PDF processing - pypdf for PDF processing
- Use rich for enhanced console output - Use rich for enhanced console output
- Custom rl_ai_tools package for AI functionalities - Custom rl_ai_tools package for AI functionalities
+10 -8
View File
@@ -1,5 +1,5 @@
# Multi-stage build to create a distroless image # Multi-stage build to create a distroless image
FROM python:3.11 AS builder FROM python:3.13 AS builder
# Install poetry and the export plugin # Install poetry and the export plugin
# RUN pip install poetry poetry-plugin-export # RUN pip install poetry poetry-plugin-export
@@ -7,17 +7,21 @@ FROM python:3.11 AS builder
# Create working directory # Create working directory
WORKDIR /app WORKDIR /app
# Copy dependency files
COPY requirements.txt ./
# Export dependencies to requirements.txt # Export dependencies to requirements.txt
# RUN poetry export -f requirements.txt --output requirements.txt --without-hashes # RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
# Copy dependency files
COPY requirements.txt ./
# Install dependencies to a target directory that we can copy to the distroless image # Install dependencies to a target directory that we can copy to the distroless image
RUN pip install --no-cache-dir --target=/app/site-packages -r requirements.txt RUN pip install --no-cache-dir --target=/app/site-packages -r requirements.txt
# Create distroless image FROM python:3.13-slim
FROM gcr.io/distroless/python3-debian12
# RUN apt update \
# && apt -y upgrade \
# && apt clean \
# && rm /var/lib/apt/lists/* || true
# Copy installed packages and application from builder stage # Copy installed packages and application from builder stage
COPY --from=builder /app/site-packages /app/site-packages COPY --from=builder /app/site-packages /app/site-packages
@@ -35,7 +39,5 @@ WORKDIR /app
# Expose port # Expose port
EXPOSE 8000 EXPOSE 8000
USER nonroot
# Run the application directly with Python using the distroless entrypoint # Run the application directly with Python using the distroless entrypoint
ENTRYPOINT ["/usr/bin/python3", "-m", "uvicorn", "myice.webapi:app", "--host", "0.0.0.0", "--port", "8000"] ENTRYPOINT ["/usr/bin/python3", "-m", "uvicorn", "myice.webapi:app", "--host", "0.0.0.0", "--port", "8000"]
+10 -5
View File
@@ -14,7 +14,7 @@ from enum import Enum
from pathlib import Path from pathlib import Path
from typing import Annotated from typing import Annotated
from typing import List, Tuple from typing import List, Tuple
import PyPDF2 import pypdf
import requests import requests
import typer import typer
from rich import print from rich import print
@@ -148,6 +148,9 @@ class AgeGroup(str, Enum):
u18e = "U18 (Elite)" u18e = "U18 (Elite)"
u18el = "U18 (Elit)" u18el = "U18 (Elit)"
u21e = "U21 (ELIT)" u21e = "U21 (ELIT)"
u14t = "U14 (Top)"
u14t1 = "U14 (Top1)"
u14t2 = "U14 (Top2)"
def normalize_age_group(value: str) -> AgeGroup | None: def normalize_age_group(value: str) -> AgeGroup | None:
@@ -423,19 +426,21 @@ def os_open(file: str) -> None:
def extract_players(pdf_file: Path) -> List[str]: def extract_players(pdf_file: Path) -> List[str]:
reader = PyPDF2.PdfReader(pdf_file) reader = pypdf.PdfReader(pdf_file)
page = reader.pages[0] page = reader.pages[0]
players = [] players = []
def visitor_body(text, cm, tm, fontDict, fontSize): def visitor_body(text, cm, tm, fontDict, fontSize):
global last_text
if text:
last_text = text
(x, y) = (tm[4], tm[5]) (x, y) = (tm[4], tm[5])
# print(tm, text)
if x > 79 and x < 80 and y < 741.93: if x > 79 and x < 80 and y < 741.93:
# and y < 741.93 and y > 741.93 - 585.18: # and y < 741.93 and y > 741.93 - 585.18:
players.append(text) players.append(last_text.strip())
page.extract_text(visitor_text=visitor_body) page.extract_text(visitor_text=visitor_body, extraction_mode="plain")
return players return players
Generated
+1199 -875
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -7,12 +7,12 @@ authors = [
] ]
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.13"
dependencies = [ dependencies = [
"requests (>=2.32.3,<2.33.0)", "requests (>=2.32.3,<2.33.0)",
"typer (>=0.15.1,<0.16.0)", "typer (>=0.15.1,<0.16.0)",
"pypdf2 (>=3.0.1)", "pypdf (>=6.0.0)",
"rl-ai-tools >=1.9.0", "rl-ai-tools >=1.9.0",
"fastapi[standard] (>=0.115.11,<0.116.0)", "fastapi[standard] (>=0.115.11,<0.116.0)",
] ]
+44 -40
View File
@@ -1,42 +1,46 @@
--extra-index-url https://pypi.purple.infomaniak.ch --extra-index-url https://pypi.purple.infomaniak.ch
annotated-types==0.7.0 ; python_version >= "3.11" annotated-types==0.7.0 ; python_version >= "3.13"
anyio==4.8.0 ; python_version >= "3.11" anyio==4.11.0 ; python_version >= "3.13"
certifi==2024.12.14 ; python_version >= "3.11" certifi==2025.8.3 ; python_version >= "3.13"
charset-normalizer==3.4.1 ; python_version >= "3.11" charset-normalizer==3.4.3 ; python_version >= "3.13"
click==8.1.8 ; python_version >= "3.11" click==8.1.8 ; python_version >= "3.13"
colorama==0.4.6 ; (platform_system == "Windows" or sys_platform == "win32") and python_version >= "3.11" colorama==0.4.6 ; (platform_system == "Windows" or sys_platform == "win32") and python_version >= "3.13"
dnspython==2.7.0 ; python_version >= "3.11" dnspython==2.8.0 ; python_version >= "3.13"
email-validator==2.2.0 ; python_version >= "3.11" email-validator==2.3.0 ; python_version >= "3.13"
fastapi-cli==0.0.7 ; python_version >= "3.11" fastapi-cli==0.0.13 ; python_version >= "3.13"
fastapi==0.115.11 ; python_version >= "3.11" fastapi-cloud-cli==0.2.1 ; python_version >= "3.13"
h11==0.14.0 ; python_version >= "3.11" fastapi==0.115.14 ; python_version >= "3.13"
httpcore==1.0.7 ; python_version >= "3.11" h11==0.16.0 ; python_version >= "3.13"
httptools==0.6.4 ; python_version >= "3.11" httpcore==1.0.9 ; python_version >= "3.13"
httpx==0.28.1 ; python_version >= "3.11" httptools==0.6.4 ; python_version >= "3.13"
idna==3.10 ; python_version >= "3.11" httpx==0.28.1 ; python_version >= "3.13"
jinja2==3.1.6 ; python_version >= "3.11" idna==3.10 ; python_version >= "3.13"
markdown-it-py==3.0.0 ; python_version >= "3.11" jinja2==3.1.6 ; python_version >= "3.13"
markupsafe==3.0.2 ; python_version >= "3.11" markdown-it-py==4.0.0 ; python_version >= "3.13"
mdurl==0.1.2 ; python_version >= "3.11" markupsafe==3.0.3 ; python_version >= "3.13"
pydantic-core==2.27.2 ; python_version >= "3.11" mdurl==0.1.2 ; python_version >= "3.13"
pydantic==2.10.6 ; python_version >= "3.11" pydantic-core==2.33.2 ; python_version >= "3.13"
pygments==2.19.1 ; python_version >= "3.11" pydantic==2.11.9 ; python_version >= "3.13"
pypdf2==3.0.1 ; python_version >= "3.11" pygments==2.19.2 ; python_version >= "3.13"
python-dotenv==1.0.1 ; python_version >= "3.11" pypdf==6.1.1 ; python_version >= "3.13"
python-multipart==0.0.20 ; python_version >= "3.11" python-dotenv==1.1.1 ; python_version >= "3.13"
pyyaml==6.0.2 ; python_version >= "3.11" python-multipart==0.0.20 ; python_version >= "3.13"
requests==2.32.3 ; python_version >= "3.11" pyyaml==6.0.3 ; python_version >= "3.13"
rich-toolkit==0.13.2 ; python_version >= "3.11" requests==2.32.5 ; python_version >= "3.13"
rich==13.9.4 ; python_version >= "3.11" rich-toolkit==0.15.1 ; python_version >= "3.13"
rl-ai-tools==1.14.2 ; python_version >= "3.11" rich==14.1.0 ; python_version >= "3.13"
shellingham==1.5.4 ; python_version >= "3.11" rignore==0.6.4 ; python_version >= "3.13"
sniffio==1.3.1 ; python_version >= "3.11" rl-ai-tools==1.15.0 ; python_version >= "3.13"
starlette==0.46.1 ; python_version >= "3.11" sentry-sdk==2.39.0 ; python_version >= "3.13"
typer==0.15.1 ; python_version >= "3.11" shellingham==1.5.4 ; python_version >= "3.13"
typing-extensions==4.12.2 ; python_version >= "3.11" sniffio==1.3.1 ; python_version >= "3.13"
urllib3==2.3.0 ; python_version >= "3.11" starlette==0.46.2 ; python_version >= "3.13"
uvicorn==0.34.0 ; python_version >= "3.11" typer==0.15.4 ; python_version >= "3.13"
uvloop==0.21.0 ; sys_platform != "win32" and sys_platform != "cygwin" and platform_python_implementation != "PyPy" and python_version >= "3.11" typing-extensions==4.15.0 ; python_version >= "3.13"
watchfiles==1.0.4 ; python_version >= "3.11" typing-inspection==0.4.1 ; python_version >= "3.13"
websockets==15.0.1 ; python_version >= "3.11" urllib3==2.5.0 ; python_version >= "3.13"
uvicorn==0.37.0 ; python_version >= "3.13"
uvloop==0.21.0 ; sys_platform != "win32" and sys_platform != "cygwin" and platform_python_implementation != "PyPy" and python_version >= "3.13"
watchfiles==1.1.0 ; python_version >= "3.13"
websockets==15.0.1 ; python_version >= "3.13"