diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c4fdb911a8..fb01245f45 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,9 +26,8 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] - python-version: [ "3.13" ] + python-version: [ "3.14" ] pydantic-version: - - pydantic-v1 - pydantic-v2 include: - os: macos-latest @@ -47,7 +46,10 @@ jobs: python-version: "3.12" pydantic-version: pydantic-v1 - os: ubuntu-latest - python-version: "3.12" + python-version: "3.13" + pydantic-version: pydantic-v1 + - os: macos-latest + python-version: "3.13" pydantic-version: pydantic-v2 fail-fast: false runs-on: ${{ matrix.os }} diff --git a/pyproject.toml b/pyproject.toml index 902fffdc9f..cd47f5ecd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Database", "Topic :: Database :: Database Engines/Servers", "Topic :: Internet", diff --git a/sqlmodel/_compat.py b/sqlmodel/_compat.py index dc806d381b..230f8cc362 100644 --- a/sqlmodel/_compat.py +++ b/sqlmodel/_compat.py @@ -1,3 +1,4 @@ +import sys import types from contextlib import contextmanager from contextvars import ContextVar @@ -123,7 +124,20 @@ def init_pydantic_private_attrs(new_object: InstanceOrType["SQLModel"]) -> None: object.__setattr__(new_object, "__pydantic_private__", None) def get_annotations(class_dict: Dict[str, Any]) -> Dict[str, Any]: - return class_dict.get("__annotations__", {}) # type: ignore[no-any-return] + raw_annotations: Dict[str, Any] = class_dict.get("__annotations__", {}) + if sys.version_info >= (3, 14) and "__annotations__" not in class_dict: + # See https://github.com/pydantic/pydantic/pull/11991 + from annotationlib import ( + Format, + call_annotate_function, + get_annotate_from_class_namespace, + ) + + if annotate := get_annotate_from_class_namespace(class_dict): + raw_annotations = call_annotate_function( + annotate, format=Format.FORWARDREF + ) + return raw_annotations def is_table_model_class(cls: Type[Any]) -> bool: config = getattr(cls, "model_config", {})