pyproject.toml
Rama main · réplica de lectura del repositorio original.
[project]
name = "logfire-python"
version = "0.0.0"
requires-python = ">=3.10"
dependencies = ["logfire"]
[dependency-groups]
editor-tests = [
"jedi>=0.19.2",
"mypy>=1.10.0",
"pyright!=1.1.407",
]
dev = [
{ include-group = "editor-tests" },
"httpx >= 0.27.2",
"httpx2 >= 2.0.0",
"aiohttp >= 3.10.9",
"redis >= 5.1.1",
"pymongo >= 4.10.1",
"elasticsearch >= 8.15",
"fastapi != 0.124.3, != 0.124.4",
"Flask >= 3.0.3",
"django >= 4.2.16",
"dirty-equals >= 0.8.0",
# For type checking `logfire.configure(fleet=...)` against the Fleet client (the `fleet` extra).
"logfire-fleet-otel >= 0.2.1, < 0.3; python_version >= '3.11'",
"pytest >= 8.3.4",
"pytest-django >= 4.6.0",
"pytest-pretty >= 1.2.0",
"pydantic >= 2.11.0",
"requests >= 2.31.0",
"packaging",
# requests >= 2.34 bundles inline (py.typed) annotations shaped differently from
# the types-requests stubs the code was written against. Concretely, it types
# Session.headers as CaseInsensitiveDict[str], which rejects the str|bytes header
# values requests accepts at runtime and that our DiskRetryer passes to a Session
# (exporters/otlp.py); types-requests types it as MutableMapping[str, str|bytes].
# Keep depending on types-requests so its stubs take priority; it previously came
# in transitively via openai-agents.
"types-requests",
# OTel instrumentation currently supports SQLAlchemy <2.1.
"sqlalchemy >= 1.4.54, <2.1",
"pandas>=2.1.2",
"attrs >= 23.1.0",
"openai >= 1.108.1",
"opentelemetry-instrumentation-aiohttp-client>=0.42b0",
"opentelemetry-instrumentation-aiohttp-server>=0.55b0",
"opentelemetry-instrumentation-asgi>=0.42b0",
"opentelemetry-instrumentation-wsgi>=0.42b0",
"opentelemetry-instrumentation-fastapi>=0.42b0",
"opentelemetry-instrumentation-starlette>=0.42b0",
"litestar>=2.11.0",
"opentelemetry-instrumentation-flask>=0.42b0",
"opentelemetry-instrumentation-django>=0.42b0",
"opentelemetry-instrumentation-httpx>=0.42b0",
"opentelemetry-instrumentation-requests>=0.42b0",
"opentelemetry-instrumentation-sqlalchemy>=0.42b0",
"opentelemetry-instrumentation-system-metrics>=0.42b0",
"opentelemetry-instrumentation-asyncpg>=0.42b0",
"opentelemetry-instrumentation-psycopg>=0.42b0",
"opentelemetry-instrumentation-psycopg2>=0.42b0",
"opentelemetry-instrumentation-redis>=0.42b0",
"opentelemetry-instrumentation-pymongo>=0.42b0",
"opentelemetry-instrumentation-celery>=0.42b0",
"opentelemetry-instrumentation-mysql>=0.42b0",
"opentelemetry-instrumentation-sqlite3>=0.42b0",
"opentelemetry-instrumentation-aws-lambda>=0.42b0",
"eval-type-backport >= 0.2.0",
"requests-mock >= 1.12.1",
"inline-snapshot >= 0.32.5",
"structlog >= 24.4.0",
"loguru >= 0.7.3",
"ruff >= 0.8.3",
"pre-commit>=3.5.0",
"coverage[toml]>=7.13.0",
"psycopg[binary] >= 3.2.3",
"psycopg2-binary >= 2.9.10",
"asyncpg >= 0.30.0",
"pymysql >= 1.1.1",
# >=48.0.1 ships a non-vulnerable OpenSSL (GHSA-537c-gmf6-5ccf).
"cryptography >= 48.0.1",
"cloudpickle>=3.0.0",
"anthropic>=0.27.0",
"sqlmodel>=0.0.15",
"celery>=5.4.0",
"faststream[redis]>=0.5.0",
# https://github.com/testcontainers/testcontainers-python/issues/874
"testcontainers<4.13",
"mysql-connector-python>=8.0",
"pyarrow>=17.0.0; python_version < '3.13'",
"pyarrow>=18.1.0; python_version >= '3.13'",
# pyarrow 25.0.0 dropped its py.typed marker and type stubs; pyarrow-stubs restores pyright typing.
"pyarrow-stubs>=20",
# It looks like numpy didn't use to have `requires-python`, so we need to specify the version.
"numpy>=2.0; python_version < '3.12'",
# Backport of `compression.zstd`, to test zstd export compression below Python 3.14.
"backports.zstd>=1.7.0; python_version < '3.14'",
"pytest-recording>=0.13.2",
# >=8.2.1 includes the aiohttp 3.14 compatibility fix and a fix for arbitrary
# code execution via unsafe YAML deserialization of cassettes (GHSA-rpj2-4hq8-938g).
"vcrpy>=8.2.1",
"uvicorn>=0.30.6",
"logfire-api",
"setuptools>=75.3.0",
# https://github.com/omnilib/aiosqlite/issues/369
"aiosqlite!=0.22.*",
"boto3 >= 1.28.57",
"botocore >= 1.31.57",
"opentelemetry-instrumentation-botocore >= 0.42b0",
"greenlet >= 3.1.1",
"pytest-xdist>=3.6.1",
"openai-agents[voice]>=0.14.0",
"fastmcp-slim[server]>=4",
"pydantic-ai-slim[mcp]>=2",
"pydantic-evals>=2",
"pydantic-monty>=1.5.0",
# Serves the agent sandboxes gRPC stream in tests.
"grpcio>=1.75",
# >=1.3.9 fixes path traversal / sandbox escape in file-search middleware and loaders (GHSA-gr75-jv2w-4656).
"langchain>=1.3.9",
"langchain-openai>=0.3.17",
"langgraph >= 0",
"opentelemetry-instrumentation-google-genai >= 1.0b0",
"google-genai >= 0",
"openinference-instrumentation-litellm >= 0",
"litellm >= 1.98.0; python_version >= '3.11'",
# LiteLLM 1.97 leaves its Message Pydantic model unresolved on Python 3.10, while
# 1.98 imports typing.NotRequired, which is unavailable on Python 3.10.
"litellm >= 1.96.2, != 1.97.0, != 1.98.0; python_version < '3.11'",
"openinference-instrumentation-dspy >= 0",
"dspy >= 3.1.0",
"pip >= 0",
"surrealdb >= 0",
"snowflake-connector-python >= 3",
"pytest-examples>=0.0.18",
"pytest-timeout>=2.4.0",
"pytest-asyncio>=0.24.0",
"pydantic-handlebars>=0.2.1",
"claude-agent-sdk>=0",
]
[tool.inline-snapshot]
default-flags = ["disable"]
format-command = "ruff format --stdin-filename {filename}"
[tool.uv.sources]
logfire = { workspace = true }
logfire-api = { workspace = true }
logfire-sdk = { workspace = true }
[tool.uv]
package = false
default-groups = ["dev"]
exclude-newer = "4 days"
[tool.uv.exclude-newer-package]
# Allow the security update that removes trust in compromised eMudhra certificate chains.
certifi = false
pip = false
# These are our own packages, not worth defending from supply chain attacks on them.
pydantic_ai_slim = false
pydantic-graph = false
pydantic-evals = false
pydantic = false
pydantic-core = false
pydantic-handlebars = false
genai-prices = false
logfire-cli = false
logfire-fleet-otel = false
logfire-fleet-client = false
logfire-fleet-core = false
pydantic-monty = false
pydantic-monty-client = false
pydantic-monty-runtime = false
[tool.uv.workspace]
members = ["logfire", "logfire-api", "logfire-sdk"]
# https://beta.ruff.rs/docs/configuration/
[tool.ruff]
line-length = 120
src = [".", "logfire-sdk"]
extend-exclude = ["logfire-api/logfire_api/*", "tests/auto_trace_samples/param_spec.py"]
[tool.ruff.lint]
# Ruff 0.16 greatly expanded the default rule set (59 -> 413 rules).
# Restore the pre-0.16 defaults until we deliberately migrate to the new defaults.
select = ["E4", "E7", "E9", "F"]
extend-select = [
"Q", # https://docs.astral.sh/ruff/rules/#flake8-quotes-q
"RUF100", # https://docs.astral.sh/ruff/rules/unused-noqa/
"C90", # https://docs.astral.sh/ruff/rules/#mccabe-c90
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
"I", # https://docs.astral.sh/ruff/rules/#isort-i
"D", # https://docs.astral.sh/ruff/rules/#pydocstyle-d
"DTZ005", # https://docs.astral.sh/ruff/rules/call-datetime-now-without-tzinfo/
"FA", # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa
]
flake8-quotes = { inline-quotes = "single", multiline-quotes = "double" }
isort = { combine-as-imports = true, known-first-party = [
"logfire",
"logfire_api",
] }
mccabe = { max-complexity = 14 }
ignore = [
"D107", # ignore missing docstring in __init__ methods
"D100", # ignore missing docstring in module
"D104", # ignore missing docstring in public package
"D105", # ignore missing docstring in magic methods
"D418", # allow docstrings on overloads for the sake of logfire-api stubs
"C901", # ignore too complex functions, doesn't seem to be worth it
]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["D"]
"docs/**/*.py" = ["D"]
"logfire-api/logfire_api/**/*.py" = ["D"]
[tool.ruff.format]
docstring-code-format = true
quote-style = "single"
# Ruff 0.16 formats Python code blocks in Markdown files by default,
# but that mangles the `#>` output markers checked by pytest-examples,
# which is the authority on docs code formatting.
exclude = ["*.md"]
[tool.pyright]
typeCheckingMode = "strict"
reportUnnecessaryTypeIgnoreComment = true
reportMissingTypeStubs = false
include = ["logfire-sdk/logfire", "tests"]
extraPaths = ["logfire-sdk"]
venvPath = "."
venv = ".venv"
[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "function"
xfail_strict = true
pythonpath = ["."]
markers = [
"otel_collector: requires Docker and runs against a pinned OpenTelemetry Collector",
]
# The langsmith pytest plugin messes with test_langchain.py
addopts = "-p no:langsmith_plugin"
filterwarnings = [
"error",
# fastapi uses deprecated pydantic functions
"ignore:`FieldValidationInfo` is deprecated.*:DeprecationWarning:pydantic_core:",
"ignore:`general_(before|after|wrap|plain)_validator_function` is deprecated.*:DeprecationWarning:fastapi:",
"ignore:`general_(before|after|wrap|plain)_validator_function` is deprecated.*:DeprecationWarning:pydantic_core:",
# google packages are using deprecated APIs
"ignore::DeprecationWarning:pkg_resources*:",
"ignore::DeprecationWarning:google*:",
"ignore:.* google._upb._message.*:DeprecationWarning",
# OTEL uses some deprecated APIs
"ignore:pkg_resources:DeprecationWarning:opentelemetry.instrumentation.dependencies*:",
# To be able to test numpy.matrix
"ignore:the matrix subclass is not the recommended way.*:PendingDeprecationWarning",
# See test_filter_warnings in test_testing.py
'ignore:(?s).*google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.*scheduler\.shutdown.*IndexError. tuple index out of range:pytest.PytestUnhandledThreadExceptionWarning',
'ignore:(?s).*aiosqlite/core\.py.*get_loop\(future\).call_soon_threadsafe.*RuntimeError. Event loop is closed:pytest.PytestUnhandledThreadExceptionWarning',
# This problem is fixed in https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2013, but not the warning.
"ignore:The '__version__' attribute is deprecated and will be removed in Flask 3.1:DeprecationWarning",
# kombu using deprecated redis API
"ignore:Call to 'get_connection' function with deprecated usage of input argument/s.*:DeprecationWarning",
# celery's redis backend uses redis's deprecated `setex` (deprecated in redis-py 8.0)
"ignore:Call to deprecated setex.*:DeprecationWarning",
# OpenTelemetry event logger stuff being used by Pydantic AI
"ignore:You should use `\\w*(L|l)ogger\\w*` instead. Deprecated since version 1.39.0 and will be removed in a future release.:DeprecationWarning",
# flask.__version__ is deprecated and used by OTel
"ignore:The '__version__' attribute is deprecated and will be removed in Flask 3.2.*:DeprecationWarning",
# aiohttp web.Application is deprecated and used by OTel
"ignore:Inheritance class _InstrumentedApplication from web.Application is discouraged:DeprecationWarning",
# anthropic SDK warns when using older models that are still recorded in test cassettes
"ignore:The model 'claude-.*' is deprecated.*:DeprecationWarning",
# py-key-value-aio (a pydantic-ai dependency) type-checks itself at import time with
# beartype's import hook, which is designed to warn rather than fail. Promoting those
# warnings to errors breaks `import pydantic_ai`, e.g. on pydantic 2.10 where
# `JsonSchemaValue` is still a `typing.Dict` alias, triggering beartype's PEP 585
# deprecation warning during decoration of py-key-value-aio's pydantic adapter.
"ignore::beartype.roar.BeartypeClawDecorWarning",
"ignore::beartype.roar.BeartypeDecorHintPep585DeprecationWarning",
# langsmith uses asyncio.iscoroutinefunction, deprecated on Python 3.14
"ignore:'asyncio.iscoroutinefunction' is deprecated.*:DeprecationWarning:langsmith.*",
# mcp's FastMCP Settings class has an unresolved forward reference in its `lifespan` field,
# which pydantic-settings >= 2.15 warns about (IncompleteFieldDefinitionWarning).
# No category here: naming the warning class would fail to import on jobs with older pydantic-settings.
"ignore:Field 'lifespan' has an incomplete definition.*",
# snowflake.connector.options warns about our locked pyarrow version being outside its
# declared bound on Python 3.14 (pyarrow<24, we have 25.0.1). Just an import-time warning.
"ignore:You have an incompatible version of 'pyarrow' installed.*:UserWarning:snowflake.connector.options",
]
DJANGO_SETTINGS_MODULE = "tests.otel_integrations.django_test_project.django_test_site.settings"
# https://coverage.readthedocs.io/en/latest/config.html#run
[tool.coverage.run]
branch = true
relative_files = true
source = ["logfire-sdk/logfire", "logfire-api"]
omit = [
"*/tmp/*",
"*/temp/*",
"*/.pytest_cache/*",
"*/pytest-of-*/*",
]
#
# Subprocess coverage patching is enabled to measure coverage in child processes.
# This is particularly useful for tests that spawn subprocesses (e.g., Pytester tests).
#
# Note: This previously exposed a race condition in test_sqlalchemy_async_instrumentation
# which has been fixed by using unique temporary files per parametrized test instead of
# hardcoded filenames.
#
patch = ["subprocess"]
# Use this to get the tests that are covering the code. This is disabled by default because it can be slow.
# dynamic_context = "test_function"
# https://coverage.readthedocs.io/en/latest/config.html#report
[tool.coverage.report]
skip_covered = true
show_missing = true
ignore_errors = true
precision = 2
exclude_lines = [
'def __repr__',
'pragma: no cover',
'raise NotImplementedError',
'if TYPE_CHECKING:',
'if typing.TYPE_CHECKING:',
'@overload',
'@abstractmethod',
'@abc.abstractmethod',
'@typing.overload',
'\(Protocol\):$',
'typing.assert_never',
'assert_never',
'if __name__ == .__main__.:',
]