Skip to content

Latest commit

 

History

History
100 lines (76 loc) · 4.85 KB

AGENTS.md

File metadata and controls

100 lines (76 loc) · 4.85 KB

Working with the Codebase

Tox

  • Run tox via uv: uv run tox -e <env>
  • tox + tox-uv are declared as the project's default dev dependencies in pyproject.toml, so uv installs them automatically into .venv.

Package Manager

Use tox for testing (not pytest directly):

  • Test matrix configuration is in tox.ini
  • Integration tests: uv run tox -e py3.14-{integration}-v{version}
  • Common tests: uv run tox -e py3.14-common
  • Run specific test file: TESTPATH=tests/integrations/logging/test_logging.py uv run tox -e py3.14-common
  • Run single test: TESTPATH=tests/path/to/test_file.py uv run tox -e py3.14-common -- -k "test_name"

Type Checking

Mypy and its type stubs live in the opt-in typing dependency group:

  • Run uv run --group typing mypy sentry_sdk before committing (must pass with zero errors)
  • Strict mode enabled (check_untyped_defs, disallow_untyped_defs)

Linting & Formatting

Use ruff for linting and formatting:

  • uv run ruff check --fix tests sentry_sdk
  • uv run ruff format tests sentry_sdk

Auto-Generated Files

Do NOT edit these directly — modify source scripts instead:

  • tox.ini — generated by scripts/populate_tox/populate_tox.py from scripts/populate_tox/tox.jinja
  • .github/workflows/test-integrations-*.yml — generated by scripts/split_tox_gh_actions/split_tox_gh_actions.py
  • Regenerate all: scripts/generate-test-files.sh

Adding Integrations to Test Suite

  1. Add minimum version to _MIN_VERSIONS in sentry_sdk/integrations/__init__.py
  2. Add config to TEST_SUITE_CONFIG in scripts/populate_tox/config.py
  3. Add to group in scripts/split_tox_gh_actions/split_tox_gh_actions.py
  4. Run scripts/generate-test-files.sh

SDK Implementation Guidelines

General Guidelines

  • Don't crash applications. SDK-caused exceptions should always be handled with capture_internal_exceptions.
  • Don't swallow exceptions not caused by the SDK. The user's app should behave the same as it would without the SDK. If exceptions would bubble all the way up and crash the app, they should do that.
  • Don't submit huge PRs. If a big feature can be meaningfully split into several PRs, split it. If the PRs depend on each other, stack them.
  • No side effects. Don't make extra DB or HTTP requests or leak file descriptors.
  • The user is instructed to initialize the SDK as early as possible. You may assume this is the case.

Maintainability & Code Structure

  • Don't fragment code unnecessarily:
    • Only extract code into a function if it's used in multiple places or if it's overly complex and distracts from understanding the flow of the neighboring code.
    • Prefer one file over splitting implementation into multiple files. Having to follow the flow of code by jumping through several files is not good style.
  • Keep constants at the top of the file, under imports.
  • Don't inline imports in functions. Strongly prefer adding imports to the top of the file, on the top level.

Integration Guidelines

When integrating with a package:

  • Prefer the following approaches, in this order of preference:
    1. Signals, hooks, callbacks provided by the package
    2. Monkeypatching public functions
    3. Monkeypatching private functions (the more integral to the package, the better, as they're less likely to change)
    4. Other approaches only if the above fails
  • A mix of the approaches above is also acceptable.
  • Minimize state.
    • If you need to store state (for instance, a running span), prefer storing it on an object of the package that gets passed around "for free".
    • Keeping state manually (e.g., implementing lookup tables) should be a last resort option.
  • Write code for the most common usecase. Keep scope small. Features can always be added later, if requested. Don't design for special cases.
  • Don't mutate object references or alter function signatures.
  • Take into account that packages evolve and change.
    • When monkeypatching a function, unless it's public, allow for it changing the order of arguments, or adding an argument, in the future.
      # Bad monkeypatching
      def patched_func(arg_you_need, another_arg, third_arg):
          # Don't spell out all arguments. If a new argument is added or an argument
          # we don't use is renamed, the patch breaks.
          ...
      
      # Good monkeypatching
      def patched_func(arg_you_need, *args, **kwargs):
          # Only assume the argument you need is there. Leave the rest of the
          # arguments flexible, so that we don't break if they change.
          ...

Test Guidelines

  • Don't use mocks unless it can't be avoided.
  • Use end-to-end tests, not unit tests.
  • Avoid testing integration helpers or private methods directly.
  • Avoid testing things that can't realistically break.
  • Avoid duplicating tests (extend an existing one or use parametrize).
  • Assert on what Sentry captures with capture_events/capture_items.