[build-system]
requires = [
    "setuptools_scm[toml]>=4",
    "cython",
    "cmake>=3.24.2,<3.28; python_version>='3.8'",
    "setuptools-rust<2",
    "patchelf>=0.17.0.0; sys_platform == 'linux'",
]
build-backend = "setuptools.build_meta"

[project]
name = "ddtrace"
# DEV: to directly override the version specifier, comment this...
dynamic = ["version"]
# ...and uncomment this
# version = "4.0.0.dev0"
description = "Datadog APM client library"
readme = "README.md"
license = { text = "LICENSE.BSD3" }
requires-python = ">=3.8"
authors = [
    { name = "Datadog, Inc.", email = "dev@datadoghq.com" },
]
classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Programming Language :: Python :: 3.14",
]
dependencies = [
    "bytecode>=0.17.0,<1; python_version>='3.14.0'",
    "bytecode>=0.16.0,<1; python_version>='3.13.0'",
    "bytecode>=0.15.1,<1; python_version~='3.12.0'",
    "bytecode>=0.14.0,<1; python_version~='3.11.0'",
    "bytecode>=0.13.0,<1; python_version<'3.11'",
    "envier~=0.6.1",
    "opentelemetry-api>=1,<2",
    "wrapt>=1,<3",
]

[project.optional-dependencies]
opentracing = [
    "opentracing>=2,<3",
]
opentelemetry = [
    "opentelemetry-exporter-otlp>=1,<2",
]

[project.scripts]
ddtrace-run = "ddtrace.commands.ddtrace_run:main"
_dd_crashtracker_receiver = "ddtrace.commands._dd_crashtracker_receiver:main"

[project.entry-points.opentelemetry_context]
ddcontextvars_context = "ddtrace.internal.opentelemetry.context:DDRuntimeContext"

[project.entry-points.pytest11]
ddtrace = "ddtrace.contrib.internal.pytest.plugin"
"ddtrace.pytest_bdd" = "ddtrace.contrib.internal.pytest_bdd.plugin"
"ddtrace.pytest_benchmark" = "ddtrace.contrib.internal.pytest_benchmark.plugin"

[project.entry-points.'ddtrace.products']
"apm-tracing-rc" = "ddtrace.internal.remoteconfig.products.apm_tracing"
"code-origin-for-spans" = "ddtrace.debugging._products.code_origin.span"
"dynamic-instrumentation" = "ddtrace.debugging._products.dynamic_instrumentation"
"exception-replay" = "ddtrace.debugging._products.exception_replay"
"live-debugger" = "ddtrace.debugging._products.live_debugger"
"error-tracking" = "ddtrace.errortracking.product"
"remote-configuration" = "ddtrace.internal.remoteconfig.products.client"
"symbol-database" = "ddtrace.internal.symbol_db.product"
"appsec" = "ddtrace.internal.appsec.product"
"iast" = "ddtrace.internal.iast.product"
"tracer" = "ddtrace._trace.product"

[project.urls]
"Bug Tracker" = "https://github.com/DataDog/dd-trace-py/issues"
Changelog = "https://github.com/DataDog/dd-trace-py/releases"
Documentation = "https://ddtrace.readthedocs.io/en/stable/"
Homepage = "https://github.com/DataDog/dd-trace-py"
"Source Code" = "https://github.com/DataDog/dd-trace-py/"

[tool.setuptools_scm]
version_scheme = "release-branch-semver"  # Must be "release-branch-semver" for now in main, see https://github.com/DataDog/dd-trace-py/issues/8801
write_to = "ddtrace/_version.py"

[tool.cython-lint]
max-line-length = 120
exclude = '''
(
  \.worktrees/
  | .venv*
  | \.sg
  | \.riot
  | ddtrace/profiling/
  | test_ci_visibility_api_client_skippable_real_world_responses\.py
)
'''

[tool.black]
line-length = 120
target_version = ['py37', 'py38', 'py39', 'py310', 'py311', 'py312']
include = '''\.py[ix]?$'''
exclude = '''
(
  \.worktrees/
  | .venv*
  | \.sg
  | \.riot/
  | ddtrace/appsec/_ddwaf.pyx$
  | ddtrace/internal/_encoding.pyx$
  | ddtrace/internal/_rand.pyx$
  | ddtrace/internal/_tagset.pyx$
  | ddtrace/internal/telemetry/metrics_namespaces.pyx$
  | ddtrace/profiling/collector/_traceback.pyx$
  | ddtrace/profiling/collector/_task.pyx$
  | ddtrace/profiling/_threading.pyx$
  | ddtrace/profiling/collector/stack.pyx$
  | ddtrace/profiling/exporter/pprof.pyx$
  | ddtrace/internal/datadog/profiling/ddup/_ddup.pyx$
  | ddtrace/vendor/
  | ddtrace/appsec/_iast/_taint_tracking/_vendor/
  | ddtrace/appsec/_iast/_taint_tracking/cmake-build-debug/
  | ddtrace/_version.py
  | \.eggs
  | \.git
  | \.hg
  | \.mypy_cache
  | \.nox
  | \.tox
  | \.venv
  | _build/
  | buck-out/
  | build/
  | dist/
  | tests/lib-injection/dd-lib-python-init-test-protobuf-old/addressbook_pb2.py$
  | tests/profiling/collector/pprof_.*_pb2.py$
)
'''

[tool.pyright]
exclude = [
  "**/__pycache__",
  ".git",
  ".ddriot",
  ".ddtox",
  ".riot",
  ".sg",
  ".tox",
  ".venv",
  ".worktrees",
]

[tool.slotscheck]
exclude-modules = '''
(
  ^ddtrace.(contrib|vendor)
  | ^tests.(contrib|vendor)
  # avoid sitecustomize modules as they start services
  | ddtrace.bootstrap.sitecustomize
  | ddtrace.openfeature
  | ddtrace.internal.openfeature
  | ddtrace.profiling.bootstrap.sitecustomize
  | ddtrace.profiling.auto
  # also ignore preload module to avoid exception after moving ddtrace.tracing module
  | ddtrace.bootstrap.preload
  # protobuf file fails to import
  | tests.profiling.collector.pprof_3_pb2
  | tests.profiling.collector.pprof_312_pb2
  | tests.profiling.collector.pprof_319_pb2
  | tests.profiling.collector.pprof_421_pb2
  # TODO: resolve slot inheritance issues with profiling
  | ddtrace.profiling.collector
  | ddtrace.profiling._gevent
  | ddtrace,appsec,iast,_taint_tracking.vendor
  | ddtrace.appsec._ddwaf.ddwaf_types
  | ddtrace.appsec._iast._taint_tracking
  | ddtrace.appsec._iast._ast.aspects
  | ddtrace.appsec._iast._taint_utils
  | ddtrace.appsec._iast.taint_sinks.sql_injection
  # DSM specific contribs
  | ddtrace.internal.datastreams.kafka
  # libdd_wrapper is a common native dependency, not a module
  | ddtrace.internal.datadog.profiling.libdd_wrapper
  # _ddup and _stack_v2 miss a runtime dependency in slotscheck, but ddup and stack_v2 are fine
  | ddtrace.internal.datadog.profiling.ddup._ddup
  | ddtrace.internal.datadog.profiling.stack_v2._stack_v2
  # coverage has version-specific checks that prevent import
  | ddtrace.internal.coverage.instrumentation_py3_8
  | ddtrace.internal.coverage.instrumentation_py3_10
  | ddtrace.internal.coverage.instrumentation_py3_11
  | ddtrace.internal.coverage.instrumentation_py3_12
  | ddtrace.internal.coverage.instrumentation_py3_13
  | ddtrace.internal.coverage.instrumentation_py3_14
)
'''

[tool.bandit]
targets = ["ddtrace/"]

# TODO: Remove excludes
exclude_dirs = [
  "ddtrace/vendor/",
  "ddtrace/appsec/_iast/_taint_tracking/_vendor/",
  "ddtrace/commands/ddtrace_run.py",
  "ddtrace/ext/git.py",
  "ddtrace/ext/test.py",
  "ddtrace/internal/datadog/profiling/ddup/test/interface.py",
  "ddtrace/internal/module.py",
  "ddtrace/internal/processor/stats.py",
  "ddtrace/internal/rate_limiter.py",
  "ddtrace/internal/uwsgi.py",
  "ddtrace/sourcecode/_utils.py",
]

[tool.ruff]
exclude = [
    ".riot",
    ".ddriot",
    ".venv*",
    ".git",
    ".worktrees",
    "__pycache__",
    ".eggs",
    "*.egg",
    ".sg",
    "build",
    "ddtrace/__init__.py",
    "ddtrace/vendor/*",
    "ddtrace/appsec/_iast/_taint_tracking/_vendor/*",
    "tests/profiling/collector/pprof_*pb2.py",
    "tests/profiling/simple_program_gevent.py",
    "tests/contrib/grpc/hello_pb2.py",
    "tests/contrib/django_celery/app/*",
    "tests/contrib/protobuf/schemas/**/*.py",
    "tests/appsec/iast/fixtures/ast/str/non_utf8_content.py",
    "tests/appsec/iast/fixtures/aspects/str/non_utf8_content.py",
    "tests/lib-injection/dd-lib-python-init-test-protobuf-old/addressbook_pb2.py"
]
lint.ignore = [
    "A003",
    "D100",
    "D101",
    "D102",
    "D103",
    "D104",
    "D105",
    "D106",
    "D107",
    "D200",
    "D202",
    "D204",
    "D205",
    "D208",
    "D210",
    "D300",
    "D400",
    "D401",
    "D403",
    "D404",
    "D413",
    "E203",
    "E231",
    "E721",
    "G201",
]
line-length = 120
lint.select = [
    "A",
    "D",
    "E",
    "F",
    "G",
    "I",
    "W",
]
lint.unfixable =[
  "F401",
]

[tool.ruff.lint.pydocstyle]
convention = "pep257"

[tool.ruff.lint.isort]
force-single-line = true
lines-after-imports = 2
force-sort-within-sections = true
known-first-party = [ "ddtrace" ]
relative-imports-order = "furthest-to-closest"

[tool.ruff.lint.per-file-ignores]
# Exclude typing stubs as vertical line spacing incompatibility with black
# See: https://github.com/astral-sh/ruff/pull/6501
"*.pyi" = ["I001"]
