Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
1fe31a31ac ⬆ Bump httpx from 0.24.1 to 0.27.2
Bumps [httpx](https://github.com/encode/httpx) from 0.24.1 to 0.27.2.
- [Release notes](https://github.com/encode/httpx/releases)
- [Changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/httpx/compare/0.24.1...0.27.2)

---
updated-dependencies:
- dependency-name: httpx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-27 22:39:35 +00:00
8 changed files with 48 additions and 96 deletions

View File

@@ -2,12 +2,6 @@
## Latest Changes
## 0.0.22
### Fixes
* 🐛 Fix support for types with `Optional[Annoated[x, f()]]`, e.g. `id: Optional[pydantic.UUID4]`. PR [#1093](https://github.com/fastapi/sqlmodel/pull/1093) by [@tiangolo](https://github.com/tiangolo).
### Docs
* ✏️ Fix a typo in `docs/virtual-environments.md`. PR [#1085](https://github.com/fastapi/sqlmodel/pull/1085) by [@tiangolo](https://github.com/tiangolo).
@@ -17,7 +11,6 @@
### Internal
* ✅ Refactor test_enums to make them independent of previous imports. PR [#1095](https://github.com/fastapi/sqlmodel/pull/1095) by [@tiangolo](https://github.com/tiangolo).
* 👷 Update `latest-changes` GitHub Action. PR [#1087](https://github.com/fastapi/sqlmodel/pull/1087) by [@tiangolo](https://github.com/tiangolo).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#1028](https://github.com/fastapi/sqlmodel/pull/1028) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump ruff from 0.4.7 to 0.6.2. PR [#1081](https://github.com/fastapi/sqlmodel/pull/1081) by [@dependabot[bot]](https://github.com/apps/dependabot).
@@ -38,7 +31,7 @@
* 💄 Add dark-mode logo. PR [#1061](https://github.com/tiangolo/sqlmodel/pull/1061) by [@tiangolo](https://github.com/tiangolo).
* 🔨 Update docs.py script to enable dirty reload conditionally. PR [#1060](https://github.com/tiangolo/sqlmodel/pull/1060) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update MkDocs previews. PR [#1058](https://github.com/tiangolo/sqlmodel/pull/1058) by [@tiangolo](https://github.com/tiangolo).
* 💄 Update Termynal line-height. PR [#1057](https://github.com/tiangolo/sqlmodel/pull/1057) by [@tiangolo](https://github.com/tiangolo).
* 💄 Update Termynal line-height. PR [#1057](https://github.com/tiangolo/sqlmodel/pull/1057) by [@tiangolo](https://github.com/tiangolo).
* 👷 Upgrade build docs configs. PR [#1047](https://github.com/tiangolo/sqlmodel/pull/1047) by [@tiangolo](https://github.com/tiangolo).
* 👷 Add alls-green for test-redistribute. PR [#1055](https://github.com/tiangolo/sqlmodel/pull/1055) by [@tiangolo](https://github.com/tiangolo).
* 👷 Update docs-previews to handle no docs changes. PR [#1056](https://github.com/tiangolo/sqlmodel/pull/1056) by [@tiangolo](https://github.com/tiangolo).

View File

@@ -6,7 +6,7 @@ mypy ==1.4.1
ruff ==0.6.2
# For FastAPI tests
fastapi >=0.103.2
httpx ==0.24.1
httpx ==0.27.2
# TODO: upgrade when deprecating Python 3.7
dirty-equals ==0.6.0
jinja2 ==3.1.4

View File

@@ -1,4 +1,4 @@
__version__ = "0.0.22"
__version__ = "0.0.21"
# Re-export from SQLAlchemy
from sqlalchemy.engine import create_engine as create_engine

View File

@@ -21,7 +21,7 @@ from typing import (
from pydantic import VERSION as P_VERSION
from pydantic import BaseModel
from pydantic.fields import FieldInfo
from typing_extensions import Annotated, get_args, get_origin
from typing_extensions import get_args, get_origin
# Reassign variable to make it reexported for mypy
PYDANTIC_VERSION = P_VERSION
@@ -177,17 +177,16 @@ if IS_PYDANTIC_V2:
return False
return False
def get_sa_type_from_type_annotation(annotation: Any) -> Any:
def get_type_from_field(field: Any) -> Any:
type_: Any = field.annotation
# Resolve Optional fields
if annotation is None:
if type_ is None:
raise ValueError("Missing field type")
origin = get_origin(annotation)
origin = get_origin(type_)
if origin is None:
return annotation
elif origin is Annotated:
return get_sa_type_from_type_annotation(get_args(annotation)[0])
return type_
if _is_union_type(origin):
bases = get_args(annotation)
bases = get_args(type_)
if len(bases) > 2:
raise ValueError(
"Cannot have a (non-optional) union as a SQLAlchemy field"
@@ -198,14 +197,9 @@ if IS_PYDANTIC_V2:
"Cannot have a (non-optional) union as a SQLAlchemy field"
)
# Optional unions are allowed
use_type = bases[0] if bases[0] is not NoneType else bases[1]
return get_sa_type_from_type_annotation(use_type)
return bases[0] if bases[0] is not NoneType else bases[1]
return origin
def get_sa_type_from_field(field: Any) -> Any:
type_: Any = field.annotation
return get_sa_type_from_type_annotation(type_)
def get_field_metadata(field: Any) -> Any:
for meta in field.metadata:
if isinstance(meta, (PydanticMetadata, MaxLen)):
@@ -450,7 +444,7 @@ else:
)
return field.allow_none # type: ignore[no-any-return, attr-defined]
def get_sa_type_from_field(field: Any) -> Any:
def get_type_from_field(field: Any) -> Any:
if isinstance(field.type_, type) and field.shape == SHAPE_SINGLETON:
return field.type_
raise ValueError(f"The field {field.name} has no matching SQLAlchemy type")

View File

@@ -71,7 +71,7 @@ from ._compat import ( # type: ignore[attr-defined]
get_field_metadata,
get_model_fields,
get_relationship_to,
get_sa_type_from_field,
get_type_from_field,
init_pydantic_private_attrs,
is_field_noneable,
is_table_model_class,
@@ -649,7 +649,7 @@ def get_sqlalchemy_type(field: Any) -> Any:
if sa_type is not Undefined:
return sa_type
type_ = get_sa_type_from_field(field)
type_ = get_type_from_field(field)
metadata = get_field_metadata(field)
# Check enums first as an enum can also be a str, needed by Pydantic/FastAPI

View File

@@ -1,26 +0,0 @@
import uuid
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine, select
from tests.conftest import needs_pydanticv2
@needs_pydanticv2
def test_annotated_optional_types(clear_sqlmodel) -> None:
from pydantic import UUID4
class Hero(SQLModel, table=True):
# Pydantic UUID4 is: Annotated[UUID, UuidVersion(4)]
id: Optional[UUID4] = Field(default_factory=uuid.uuid4, primary_key=True)
engine = create_engine("sqlite:///:memory:")
SQLModel.metadata.create_all(engine)
with Session(engine) as db:
hero = Hero()
db.add(hero)
db.commit()
statement = select(Hero)
result = db.exec(statement).all()
assert len(result) == 1
assert isinstance(hero.id, uuid.UUID)

View File

@@ -1,11 +1,10 @@
import importlib
import enum
import uuid
import pytest
from sqlalchemy import create_mock_engine
from sqlalchemy.sql.type_api import TypeEngine
from sqlmodel import SQLModel
from sqlmodel import Field, SQLModel
from . import test_enums_models
from .conftest import needs_pydanticv1, needs_pydanticv2
"""
@@ -17,6 +16,30 @@ Associated issues:
"""
class MyEnum1(str, enum.Enum):
A = "A"
B = "B"
class MyEnum2(str, enum.Enum):
C = "C"
D = "D"
class BaseModel(SQLModel):
id: uuid.UUID = Field(primary_key=True)
enum_field: MyEnum2
class FlatModel(SQLModel, table=True):
id: uuid.UUID = Field(primary_key=True)
enum_field: MyEnum1
class InheritModel(BaseModel, table=True):
pass
def pg_dump(sql: TypeEngine, *args, **kwargs):
dialect = sql.compile(dialect=postgres_engine.dialect)
sql_str = str(dialect).rstrip()
@@ -35,9 +58,7 @@ postgres_engine = create_mock_engine("postgresql://", pg_dump)
sqlite_engine = create_mock_engine("sqlite://", sqlite_dump)
def test_postgres_ddl_sql(clear_sqlmodel, capsys: pytest.CaptureFixture[str]):
assert test_enums_models, "Ensure the models are imported and registered"
importlib.reload(test_enums_models)
def test_postgres_ddl_sql(capsys):
SQLModel.metadata.create_all(bind=postgres_engine, checkfirst=False)
captured = capsys.readouterr()
@@ -45,19 +66,17 @@ def test_postgres_ddl_sql(clear_sqlmodel, capsys: pytest.CaptureFixture[str]):
assert "CREATE TYPE myenum2 AS ENUM ('C', 'D');" in captured.out
def test_sqlite_ddl_sql(clear_sqlmodel, capsys: pytest.CaptureFixture[str]):
assert test_enums_models, "Ensure the models are imported and registered"
importlib.reload(test_enums_models)
def test_sqlite_ddl_sql(capsys):
SQLModel.metadata.create_all(bind=sqlite_engine, checkfirst=False)
captured = capsys.readouterr()
assert "enum_field VARCHAR(1) NOT NULL" in captured.out, captured
assert "enum_field VARCHAR(1) NOT NULL" in captured.out
assert "CREATE TYPE" not in captured.out
@needs_pydanticv1
def test_json_schema_flat_model_pydantic_v1():
assert test_enums_models.FlatModel.schema() == {
assert FlatModel.schema() == {
"title": "FlatModel",
"type": "object",
"properties": {
@@ -78,7 +97,7 @@ def test_json_schema_flat_model_pydantic_v1():
@needs_pydanticv1
def test_json_schema_inherit_model_pydantic_v1():
assert test_enums_models.InheritModel.schema() == {
assert InheritModel.schema() == {
"title": "InheritModel",
"type": "object",
"properties": {
@@ -99,7 +118,7 @@ def test_json_schema_inherit_model_pydantic_v1():
@needs_pydanticv2
def test_json_schema_flat_model_pydantic_v2():
assert test_enums_models.FlatModel.model_json_schema() == {
assert FlatModel.model_json_schema() == {
"title": "FlatModel",
"type": "object",
"properties": {
@@ -115,7 +134,7 @@ def test_json_schema_flat_model_pydantic_v2():
@needs_pydanticv2
def test_json_schema_inherit_model_pydantic_v2():
assert test_enums_models.InheritModel.model_json_schema() == {
assert InheritModel.model_json_schema() == {
"title": "InheritModel",
"type": "object",
"properties": {

View File

@@ -1,28 +0,0 @@
import enum
import uuid
from sqlmodel import Field, SQLModel
class MyEnum1(str, enum.Enum):
A = "A"
B = "B"
class MyEnum2(str, enum.Enum):
C = "C"
D = "D"
class BaseModel(SQLModel):
id: uuid.UUID = Field(primary_key=True)
enum_field: MyEnum2
class FlatModel(SQLModel, table=True):
id: uuid.UUID = Field(primary_key=True)
enum_field: MyEnum1
class InheritModel(BaseModel, table=True):
pass