Skip to content

Commit

Permalink
Fix and test unmapped SQLModels (#286)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmojaki authored Jun 29, 2024
1 parent bf5d860 commit 26ab2d5
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 36 deletions.
10 changes: 7 additions & 3 deletions logfire/_internal/json_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,16 @@ def logfire_json_dumps(obj: Any) -> str:


def is_sqlalchemy(obj: Any) -> bool:
if not hasattr(obj, '__mapper__'):
# A SQLModel without `table=True` will pass `isinstance(obj.__class__, DeclarativeMeta)` (I don't know how)
# but will fail when retrieving data, specifically when calling `sqlalchemy.inspect`
# or when getting the `__mapper__` attribute.
return False

try:
from sqlalchemy.orm import DeclarativeBase, DeclarativeMeta

if isinstance(obj, DeclarativeBase):
return True
return isinstance(obj.__class__, DeclarativeMeta)
return isinstance(obj, DeclarativeBase) or isinstance(obj.__class__, DeclarativeMeta)
except ImportError: # pragma: no cover
return False

Expand Down
2 changes: 1 addition & 1 deletion logfire/_internal/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def _span(
if json_schema_properties := attributes_json_schema_properties(attributes):
otlp_attributes[ATTRIBUTES_JSON_SCHEMA_KEY] = attributes_json_schema(json_schema_properties)

tags = cast('tuple[str, ...]', (self._tags or ()) + tuple(_tags or ()))
tags = (self._tags or ()) + tuple(_tags or ())
if tags:
otlp_attributes[ATTRIBUTES_TAGS_KEY] = uniquify_sequence(tags)

Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ dev-dependencies = [
"asyncpg",
"cloudpickle>=3.0.0",
"anthropic>=0.27.0",
# Can remove this when https://github.com/python/typing_extensions/commit/53bcdded534494674f893112f71d3be344d65363 is released
"typing-extensions<4.12",
"sqlmodel",
]

[tool.rye.scripts]
Expand Down Expand Up @@ -191,7 +190,7 @@ quote-style = "single"
typeCheckingMode = "strict"
reportUnnecessaryTypeIgnoreComment = true
reportMissingTypeStubs = false
exclude = ["docs/**/*.py", "site/**/*.py", ".venv", "venv*"]
exclude = ["docs/**/*.py", "site/**/*.py", ".venv", "venv*", "ignoreme"]
venvPath = ".venv"

[tool.pytest.ini_options]
Expand Down
53 changes: 28 additions & 25 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ aiosignal==1.3.1
# via aiohttp
annotated-types==0.7.0
# via pydantic
anthropic==0.28.0
anthropic==0.30.0
anyio==4.3.0
# via anthropic
# via httpx
Expand Down Expand Up @@ -55,7 +55,7 @@ cloudpickle==3.0.0
colorama==0.4.6
# via griffe
# via mkdocs-material
coverage==7.5.3
coverage==7.5.4
deprecated==1.2.14
# via opentelemetry-api
# via opentelemetry-exporter-otlp-proto-http
Expand All @@ -69,7 +69,7 @@ django==5.0.6
dnspython==2.6.1
# via email-validator
# via pymongo
email-validator==2.1.1
email-validator==2.2.0
# via fastapi
eval-type-backport==0.2.0
executing==2.0.1
Expand All @@ -78,20 +78,20 @@ executing==2.0.1
fastapi==0.111.0
fastapi-cli==0.0.4
# via fastapi
filelock==3.14.0
filelock==3.15.4
# via huggingface-hub
# via virtualenv
flask==3.0.3
frozenlist==1.4.1
# via aiohttp
# via aiosignal
fsspec==2024.6.0
fsspec==2024.6.1
# via huggingface-hub
ghp-import==2.1.0
# via mkdocs
googleapis-common-protos==1.63.1
googleapis-common-protos==1.63.2
# via opentelemetry-exporter-otlp-proto-http
griffe==0.45.2
griffe==0.47.0
# via mkdocstrings-python
h11==0.14.0
# via httpcore
Expand All @@ -104,7 +104,7 @@ httpx==0.27.0
# via anthropic
# via fastapi
# via openai
huggingface-hub==0.23.3
huggingface-hub==0.23.4
# via tokenizers
identify==2.5.36
# via pre-commit
Expand All @@ -128,7 +128,7 @@ jinja2==3.1.4
# via mkdocs
# via mkdocs-material
# via mkdocstrings
jiter==0.4.1
jiter==0.5.0
# via anthropic
loguru==0.7.2
markdown==3.6
Expand Down Expand Up @@ -159,12 +159,12 @@ mkdocs-autorefs==1.0.1
mkdocs-get-deps==0.2.0
# via mkdocs
mkdocs-glightbox==0.4.0
mkdocs-material==9.5.25
mkdocs-material==9.5.27
mkdocs-material-extensions==1.3.1
# via mkdocs-material
mkdocstrings==0.25.1
# via mkdocstrings-python
mkdocstrings-python==1.10.3
mkdocstrings-python==1.10.5
multidict==6.0.5
# via aiohttp
# via yarl
Expand All @@ -173,9 +173,9 @@ mypy-extensions==1.0.0
nodeenv==1.9.1
# via pre-commit
# via pyright
numpy==1.26.4
numpy==2.0.0
# via pandas
openai==1.31.1
openai==1.35.7
opentelemetry-api==1.25.0
# via opentelemetry-exporter-otlp-proto-http
# via opentelemetry-instrumentation
Expand Down Expand Up @@ -276,9 +276,9 @@ opentelemetry-util-http==0.46b0
# via opentelemetry-instrumentation-requests
# via opentelemetry-instrumentation-starlette
# via opentelemetry-instrumentation-wsgi
orjson==3.10.3
orjson==3.10.5
# via fastapi
packaging==24.0
packaging==24.1
# via black
# via huggingface-hub
# via mkdocs
Expand Down Expand Up @@ -309,10 +309,11 @@ psycopg==3.1.19
psycopg-binary==3.1.19
# via psycopg
psycopg2-binary==2.9.9
pydantic==2.7.3
pydantic==2.7.4
# via anthropic
# via fastapi
# via openai
# via sqlmodel
pydantic-core==2.18.4
# via pydantic
pygments==2.18.0
Expand All @@ -321,8 +322,8 @@ pygments==2.18.0
pymdown-extensions==10.8.1
# via mkdocs-material
# via mkdocstrings
pymongo==4.7.3
pyright==1.1.365
pymongo==4.8.0
pyright==1.1.369
pytest==8.2.2
# via pytest-django
# via pytest-pretty
Expand All @@ -348,7 +349,7 @@ pyyaml==6.0.1
# via uvicorn
pyyaml-env-tag==0.1
# via mkdocs
redis==5.0.4
redis==5.0.7
regex==2024.5.15
# via mkdocs-material
requests==2.32.3
Expand All @@ -362,8 +363,8 @@ rich==13.7.1
# via logfire
# via pytest-pretty
# via typer
ruff==0.4.8
setuptools==70.0.0
ruff==0.5.0
setuptools==70.1.1
# via opentelemetry-instrumentation
shellingham==1.5.4
# via typer
Expand All @@ -375,7 +376,9 @@ sniffio==1.3.1
# via anyio
# via httpx
# via openai
sqlalchemy==2.0.30
sqlalchemy==2.0.31
# via sqlmodel
sqlmodel==0.0.19
sqlparse==0.5.0
# via django
starlette==0.37.2
Expand All @@ -392,7 +395,7 @@ typer==0.12.3
# via fastapi-cli
types-toml==0.10.8.20240310
# via inline-snapshot
typing-extensions==4.11.0
typing-extensions==4.12.2
# via anthropic
# via fastapi
# via huggingface-hub
Expand All @@ -408,13 +411,13 @@ tzdata==2024.1
# via pandas
ujson==5.10.0
# via fastapi
urllib3==2.2.1
urllib3==2.2.2
# via requests
uvicorn==0.30.1
# via fastapi
uvloop==0.19.0
# via uvicorn
virtualenv==20.26.2
virtualenv==20.26.3
# via pre-commit
watchdog==4.0.1
# via mkdocs
Expand Down
8 changes: 4 additions & 4 deletions requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ deprecated==1.2.14
# via opentelemetry-exporter-otlp-proto-http
executing==2.0.1
# via logfire
googleapis-common-protos==1.63.1
googleapis-common-protos==1.63.2
# via opentelemetry-exporter-otlp-proto-http
idna==3.7
# via requests
Expand Down Expand Up @@ -57,12 +57,12 @@ requests==2.32.3
# via opentelemetry-exporter-otlp-proto-http
rich==13.7.1
# via logfire
setuptools==70.0.0
setuptools==70.1.1
# via opentelemetry-instrumentation
typing-extensions==4.11.0
typing-extensions==4.12.2
# via logfire
# via opentelemetry-sdk
urllib3==2.2.1
urllib3==2.2.2
# via requests
wrapt==1.16.0
# via deprecated
Expand Down
11 changes: 11 additions & 0 deletions tests/test_json_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column, relationship
from sqlalchemy.orm.decl_api import MappedAsDataclass
from sqlalchemy.sql.schema import ForeignKey
from sqlmodel import SQLModel

import logfire
from logfire.testing import TestExporter
Expand Down Expand Up @@ -70,6 +71,10 @@ class MyPydanticComplexDataclass:
t: MyPydanticDataclass


class MySQLModel(SQLModel):
s: int


class Generator:
def __repr__(self) -> str:
return 'Generator()'
Expand Down Expand Up @@ -513,6 +518,12 @@ class StrSubclass(str):
},
id='pydantic_model_with_extra',
),
pytest.param(
MySQLModel(s=10),
's=10',
'{"s":10}',
{'type': 'object', 'title': 'MySQLModel', 'x-python-datatype': 'PydanticModel'},
),
pytest.param(
MyDataclass(10),
'MyDataclass(t=10)',
Expand Down

0 comments on commit 26ab2d5

Please sign in to comment.