Skip to content

[codex] Fix Pydantic default third-party filtering#2054

Open
chocoHacks33 wants to merge 4 commits into
pydantic:mainfrom
chocoHacks33:codex/pydantic-default-third-party-filter
Open

[codex] Fix Pydantic default third-party filtering#2054
chocoHacks33 wants to merge 4 commits into
pydantic:mainfrom
chocoHacks33:codex/pydantic-default-third-party-filter

Conversation

@chocoHacks33

@chocoHacks33 chocoHacks33 commented Jul 6, 2026

Copy link
Copy Markdown

Summary

  • make the Pydantic plugin skip non-user modules by default when include is empty
  • keep include= as an explicit override so third-party modules can still be instrumented intentionally
  • add regression coverage for the default skip path and the include override

Why

Fixes #2053. The current implementation instruments every model outside a tiny hardcoded ignore list when include is empty, which contradicts the documented default and can create high-volume noise from third-party validation fallbacks.

Validation

  • git diff --check
  • direct regression script against the editable checkout covering:
    • default exclusion of a third-party module path
    • default inclusion of a user module path
    • include= override for an explicit third-party module
  • full pytest tests/test_pydantic_plugin.py -q is blocked in this environment before test collection by an existing OpenTelemetry/importlib deprecation warning promoted to error by the repo's pytest warning policy

Review in cubic

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@chocoHacks33
chocoHacks33 marked this pull request as ready for review July 9, 2026 01:02
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Pydantic integration now classifies modules as non-user code when they resolve to standard library, site-packages, or Logfire package paths. The default model-inclusion fallback excludes those modules unless explicitly included. Tests cover module-spec filtering, include overrides, built-in and namespace handling, and updated metric and SQLModel snapshot expectations.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: default third-party filtering for Pydantic instrumentation.
Description check ✅ Passed The description is directly aligned with the Pydantic filtering fix and regression coverage.
Linked Issues check ✅ Passed The changes implement the requested default exclusion of third-party modules while preserving explicit include overrides and adding tests.
Out of Scope Changes check ✅ Passed The diff is focused on the Pydantic plugin and related tests, with no obvious unrelated changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/test_pydantic_plugin.py (2)

202-219: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

fake_find_spec here is never exercised.

In _include_model, the include branch returns before the non-user-code fallback, so _module_is_non_user_code (and thus find_spec) isn't called when include is set. The test still validly confirms include wins, but the patch is dead weight and the name overstates what's verified. Optional to drop the patch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_pydantic_plugin.py` around lines 202 - 219, The test currently
patches importlib.util.find_spec via fake_find_spec, but that path is never
reached when include is provided because _include_model returns before the
non-user-code fallback. Update
test_pydantic_plugin_include_overrides_default_non_user_filter to remove the
unnecessary patch (and fake_find_spec setup) or otherwise adjust it so it
actually exercises the intended branch; the key behavior to keep asserting is
that _new_pydantic_plugin_result returns a non-empty result when
include={'third_party_pkg.models::ThirdPartyModel'} is set.

162-180: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

_module_is_non_user_code is lru_cached — clear it to avoid cross-test contamination.

Results are cached by module name across tests. It works today only because each test uses distinct fake module names; a future test reusing a name would silently get a stale, differently-patched result. Clear the cache in the helper (or a fixture) to keep tests hermetic.

from logfire.integrations.pydantic import _module_is_non_user_code, _non_user_code_prefixes
_module_is_non_user_code.cache_clear()
_non_user_code_prefixes.cache_clear()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_pydantic_plugin.py` around lines 162 - 180, The test helper
_new_pydantic_plugin_result is leaving cached state in _module_is_non_user_code
and _non_user_code_prefixes between test runs, which can cause cross-test
contamination. Update the helper (or a shared fixture used by it) to clear both
caches before calling LogfirePydanticPlugin.new_schema_validator, so each test
gets a fresh result regardless of reused module names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@logfire/integrations/pydantic.py`:
- Around line 397-422: _module_is_non_user_code() should not let
importlib.util.find_spec() failures abort validation when resolving module
metadata. Broaden the exception handling around the find_spec(module) call to
catch any exception, not just ImportError/ModuleNotFoundError/ValueError, and
return False so the module is treated as user code. Keep the existing behavior
in _module_is_non_user_code and preserve the caching and spec checks after a
successful lookup.

---

Nitpick comments:
In `@tests/test_pydantic_plugin.py`:
- Around line 202-219: The test currently patches importlib.util.find_spec via
fake_find_spec, but that path is never reached when include is provided because
_include_model returns before the non-user-code fallback. Update
test_pydantic_plugin_include_overrides_default_non_user_filter to remove the
unnecessary patch (and fake_find_spec setup) or otherwise adjust it so it
actually exercises the intended branch; the key behavior to keep asserting is
that _new_pydantic_plugin_result returns a non-empty result when
include={'third_party_pkg.models::ThirdPartyModel'} is set.
- Around line 162-180: The test helper _new_pydantic_plugin_result is leaving
cached state in _module_is_non_user_code and _non_user_code_prefixes between
test runs, which can cause cross-test contamination. Update the helper (or a
shared fixture used by it) to clear both caches before calling
LogfirePydanticPlugin.new_schema_validator, so each test gets a fresh result
regardless of reused module names.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 42c8ad84-2802-4080-8dc2-a6cac28c04ee

📥 Commits

Reviewing files that changed from the base of the PR and between ddaffa6 and fae2008.

📒 Files selected for processing (2)
  • logfire/integrations/pydantic.py
  • tests/test_pydantic_plugin.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • pydantic/logfire (manual)
  • pydantic/pydantic-ai (manual)
  • pydantic/pydantic (auto-detected)

Comment thread logfire/integrations/pydantic.py

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Confidence score: 4/5

  • In tests/test_pydantic_plugin.py, the inline snapshots still reference outdated code.lineno values after new tests shifted file lines, which can cause snapshot mismatches and flaky/failing test expectations even if runtime behavior is unchanged—re-record or update the affected snapshots before merging.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tests/test_pydantic_plugin.py">

<violation number="1" location="tests/test_pydantic_plugin.py:197">
P2: The new test functions added before the existing snapshot-based tests have shifted line numbers in this file, but the inline snapshots still contain the old `code.lineno: 123` values captured before the change. Since the plugin records the physical line number where validation occurs, and the `MyModel(x='a')` calls now reside at different lines (265, 341, etc.), all 23 inline snapshots with `code.lineno` will fail when the test suite runs with inline_snapshot in review mode. Run `pytest --inline-snapshot=update` to refresh the snapshot values, then commit the updated line numbers.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread logfire/integrations/pydantic.py Outdated
@@ -2,7 +2,9 @@

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The new test functions added before the existing snapshot-based tests have shifted line numbers in this file, but the inline snapshots still contain the old code.lineno: 123 values captured before the change. Since the plugin records the physical line number where validation occurs, and the MyModel(x='a') calls now reside at different lines (265, 341, etc.), all 23 inline snapshots with code.lineno will fail when the test suite runs with inline_snapshot in review mode. Run pytest --inline-snapshot=update to refresh the snapshot values, then commit the updated line numbers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_pydantic_plugin.py, line 197:

<comment>The new test functions added before the existing snapshot-based tests have shifted line numbers in this file, but the inline snapshots still contain the old `code.lineno: 123` values captured before the change. Since the plugin records the physical line number where validation occurs, and the `MyModel(x='a')` calls now reside at different lines (265, 341, etc.), all 23 inline snapshots with `code.lineno` will fail when the test suite runs with inline_snapshot in review mode. Run `pytest --inline-snapshot=update` to refresh the snapshot values, then commit the updated line numbers.</comment>

<file context>
@@ -157,6 +159,89 @@ def test_logfire_plugin_include_exclude_models(
+            return SimpleNamespace(origin=__file__, submodule_search_locations=[])
+        return None
+
+    with patch('logfire.integrations.pydantic.importlib.util.find_spec', side_effect=fake_find_spec):
+        assert _new_pydantic_plugin_result('third_party_pkg.models', 'ThirdPartyModel') == (None, None, None)
+        assert _new_pydantic_plugin_result('tests.test_pydantic_plugin', 'MyModel') != (None, None, None)
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread tests/test_pydantic_plugin.py Outdated
@chocoHacks33
chocoHacks33 force-pushed the codex/pydantic-default-third-party-filter branch from 2e628b2 to 0ec2705 Compare July 13, 2026 07:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
logfire/integrations/pydantic.py (2)

439-457: 📐 Maintainability & Code Quality | 🔵 Trivial

Fallback correctly gated on non-user-code classification.

Matches the documented default ("third party modules are not instrumented by the plugin to avoid noise") and preserves include/exclude override precedence.

Separately: linked-repo context shows pydantic/pydantic's docs describe instrument_pydantic() as logging "all Pydantic models in your project," and pydantic-ai's docs assume broad instrumentation without mentioning this filtering/override. Those external docs may now be more clearly stale as a result of this fix — worth a follow-up doc note in those repos.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@logfire/integrations/pydantic.py` around lines 439 - 457, Update the relevant
Pydantic integration documentation to note that default instrumentation excludes
third-party/non-user-code modules, while include and exclude patterns can
override this behavior. Keep the implementation in _include_model unchanged and
limit the documentation follow-up to the affected external usage descriptions.

Source: Linked repositories


375-386: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Share the non-user-code prefix logic
The non-user-code prefix logic overlaps with logfire/_internal/stack_info.py, but the sources aren’t identical (stack_info.py seeds its set from runtime package paths, while this code rebuilds it from sysconfig/site). Extract the prefix derivation into a shared helper so the two filters stay in sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@logfire/integrations/pydantic.py` around lines 375 - 386, Extract the prefix
derivation currently implemented by _non_user_code_prefixes into a shared
helper, reusing the existing runtime package-path sources from
logfire/_internal/stack_info.py rather than maintaining separate sysconfig/site
logic. Update both _non_user_code_prefixes and the stack-info filter to consume
that helper, preserving their current filtering behavior while keeping the
prefix sets synchronized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@logfire/integrations/pydantic.py`:
- Around line 439-457: Update the relevant Pydantic integration documentation to
note that default instrumentation excludes third-party/non-user-code modules,
while include and exclude patterns can override this behavior. Keep the
implementation in _include_model unchanged and limit the documentation follow-up
to the affected external usage descriptions.
- Around line 375-386: Extract the prefix derivation currently implemented by
_non_user_code_prefixes into a shared helper, reusing the existing runtime
package-path sources from logfire/_internal/stack_info.py rather than
maintaining separate sysconfig/site logic. Update both _non_user_code_prefixes
and the stack-info filter to consume that helper, preserving their current
filtering behavior while keeping the prefix sets synchronized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 272fe268-f669-465f-96cc-6b07d75875e1

📥 Commits

Reviewing files that changed from the base of the PR and between 2e628b2 and 0ec2705.

📒 Files selected for processing (2)
  • logfire/integrations/pydantic.py
  • tests/test_pydantic_plugin.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • pydantic/logfire (manual)
  • pydantic/pydantic-ai (manual)
  • pydantic/pydantic (auto-detected)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pydantic plugin: docs say third-party modules are not instrumented by default, but empty include instruments everything

1 participant