Skip to content

SNOW-2912540: add IS_V5_DRIVER constant; use it for SecretDetector/TelemetryData imports and pandas/pyarrow/numpy resolution - #4313

Open
sfc-gh-fpawlowski wants to merge 15 commits into
SNOW-2912540-decouple-oob-telemetryfrom
SNOW-2912540-secret-detector-import
Open

SNOW-2912540: add IS_V5_DRIVER constant; use it for SecretDetector/TelemetryData imports and pandas/pyarrow/numpy resolution#4313
sfc-gh-fpawlowski wants to merge 15 commits into
SNOW-2912540-decouple-oob-telemetryfrom
SNOW-2912540-secret-detector-import

Conversation

@sfc-gh-fpawlowski

@sfc-gh-fpawlowski sfc-gh-fpawlowski commented Aug 12, 2026

Copy link
Copy Markdown

Summary

  • Adds a module-level IS_V5_DRIVER: bool = connector_version[0] >= 5 to _internal/utils.py — a single canonical place for code that needs to branch on connector generation (legacy v3/v4 vs Universal Driver v5+). Originally opened as its own PR (SNOW-2912540: add IS_V5_DRIVER constant for version-conditioned connector imports #4310); folded in here since every other change in this PR is gated on it.
  • snowflake.connector.secret_detector does not exist in v5 (UD) — SecretDetector lives at snowflake.connector._common.secret_detector. Fixed with an IS_V5_DRIVER-gated conditional import in mock/_telemetry.py.
  • snowflake.connector.options already provides MissingOptionalDependency, ModuleLikeObject, and pyarrow on both driver generations — no gap to fill. Re-import these from the connector, gated on IS_V5_DRIVER, instead of redefining them locally in _internal/utils.py. installed_pyarrow is now imported directly on v5 (UD PR [Local Testing] SNOW-904981 Support Column bitwise operations and unary minus expression #1151 fixed it to check pyarrow independently instead of mirroring installed_pandas) but still derived locally via isinstance on v4 (not exported there at all). MissingPandas is imported only on v4 (UD PR [Local Testing] SNOW-904981 Support Column bitwise operations and unary minus expression #1151 deleted it outright on v5 — no replacement, per BehaviorDifferences.yaml Fix drop columns of dataframe join #66); a _missing_pandas() helper builds the sentinel with whichever construction style each driver generation supports, so callers don't need their own IS_V5_DRIVER branch.
  • Removes _internal/utils.py's pre-existing _pandas_importer() (a second, independent pandas-resolution attempt that predates this whole effort) in favor of sourcing pandas/installed_pandas from the same IS_V5_DRIVER-gated import as the rest of these names. Dedups mock/_options.py's numpy handling against connector._common.extras.numpy on v5 (confirmed pure duplicate; v4 keeps its own MissingNumpy since v4's options.py has no numpy handling to delegate to). Originally opened as a separate PR (SNOW-2912540: remove _pandas_importer(), dedup mock/_options.py numpy handling #4317); folded in here since the diff was small.
  • _internal/telemetry.py's TelemetryData import previously hedged with a try/except between two locations, neither of which actually has TelemetryData.TRUE/.FALSE on the real current UD source. Fixed to import unconditionally from _internal.telemetry on v5, matching UD PR SNOW-946900: Add internal parameter in stored proc registration to allow forcing inline code #1106 (open, not draft) which adds exactly that surface to match Snowpark's usage.
  • Part of the SNOW-2912540 Graphite stack decoupling Snowpark from the connector compat shim.

Still open: UD PRs #1151, #1152, and #1106 are unmerged. This PR's IS_V5_DRIVER=True paths are written against their current source but unverifiable end-to-end until they merge.

Test plan

Checklist

  • If adding any arguments to public Snowpark APIs or creating new public Snowpark APIs, I acknowledge that I have ensured my changes include AST support.
  • I acknowledge that I have ensured my changes to be thread-safe

Stack (via Graphite)

🤖 Generated with Claude Code

sfc-gh-fpawlowski and others added 2 commits August 6, 2026 15:46
…ctor imports

connector_version is already imported in utils.py; this one-liner exposes a
boolean flag so callers can gate imports or behavior that differs between the
legacy connector (v3/v4) and the Universal Driver (v5+).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In v5 (Universal Driver), SecretDetector lives at
snowflake.connector._common.secret_detector; the legacy top-level
snowflake.connector.secret_detector module no longer exists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sfc-gh-fpawlowski
sfc-gh-fpawlowski requested a review from a team as a code owner August 12, 2026 16:10
@sfc-gh-fpawlowski
sfc-gh-fpawlowski requested review from sfc-gh-aling, sfc-gh-bkogan and sfc-gh-jzeng and removed request for a team August 12, 2026 16:10

@snowflake-security-bot snowflake-security-bot 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.

Snowflake Security Review

Security grade: A — Passed

This PR was classified as LOW risk by the automated pre-screen.

…; drop connector.options imports

snowflake.connector.options is a backward-compat shim in v5 (UD) that
will eventually be removed.  Define MissingOptionalDependency,
MissingPandas, MissingPyarrow, ModuleLikeObject, pandas, pyarrow,
installed_pandas, and installed_pyarrow directly in _internal/utils.py
and redirect all thirteen source-file imports there.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@snowflake-security-bot snowflake-security-bot 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.

Snowflake Security Review

Security grade: A — Passed

This PR was classified as LOW risk by the automated pre-screen.

from snowflake.connector import ProgrammingError
from snowflake.connector.cursor import SnowflakeCursor
from snowflake.connector.options import pyarrow
from snowflake.snowpark._internal.utils import pyarrow

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

should be _internal.options

from snowflake.snowpark._internal.error_message import SnowparkClientExceptionMessages


class MissingOptionalDependency:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This should be in driver - from there imported here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Or shouldnt it be from class MissingOptionalDependency in _internal.extras?

sfc-gh-fpawlowski and others added 3 commits August 12, 2026 20:25
The v5 (Universal Driver) public snowflake.connector.telemetry shim does not
always expose TelemetryData.TRUE/.FALSE (present on _internal.telemetry in some
UD builds), which made every telemetry-sending Snowpark test raise
AttributeError: type object 'TelemetryData' has no attribute 'FALSE'. Gate the
TelemetryData import on IS_V5_DRIVER: on v5 prefer _internal.telemetry and fall
back to the public shim; on v4 keep the legacy public import.

Co-authored-by: Cursor <cursoragent@cursor.com>
…D build

The previous commit's IS_V5_DRIVER branch assumed the v5 (UD) build
exposes SecretDetector at snowflake.connector._common.secret_detector.
Verified against the actually-installed UD build (2026.0.0) that this
module does not exist there — SecretDetector is only ever at the
top-level snowflake.connector.secret_detector path, same as v4. Switch
to a try/except fallback so it works against both the current UD build
and a possible future build that drops the top-level compat shim,
without hardcoding a version assumption that doesn't hold today.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edefinition; re-source from connector

04c82d2 assumed connector.options had a gap and redefined MissingOptionalDependency,
MissingPandas, MissingPyarrow, ModuleLikeObject, pyarrow, and installed_pyarrow locally.
connector.options already provides all of these except installed_pyarrow (verified
against the actually-installed v4.7.2 connector, which only exposes pyarrow itself and
couples its availability to pandas's import tuple, not a standalone name). Re-import the
four names that do exist there, gated on IS_V5_DRIVER so this keeps working once UD's
connector._common.extras lands, and derive installed_pyarrow locally via isinstance
instead of maintaining an independent, unprecedented MissingPyarrow resolution.

pandas/installed_pandas (produced by the pre-existing _pandas_importer(), unrelated to
04c82d2) are intentionally left untouched -- unifying those is a separate follow-up.
@sfc-gh-fpawlowski
sfc-gh-fpawlowski marked this pull request as draft August 14, 2026 17:29

@snowflake-security-bot snowflake-security-bot 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.

Snowflake Security Review

Security grade: A — Passed

This PR was classified as LOW risk by the automated pre-screen.

…rent shape

UD PR #1151 was updated since cb9f590 landed: MissingPandas is deleted
outright from _common/extras.py (BehaviorDifferences.yaml #66), not kept as a
deprecated re-export. Its suggested replacement, MissingOptionalDependency("pandas"),
only works on v5 -- the real v4 connector's MissingOptionalDependency defines no
__init__ override, so it only supports the no-arg-subclass pattern.

Import MissingPandas only where it's real (v4). Add _missing_pandas() to build
the sentinel with whichever construction style the active driver generation
supports, centralizing the branch in _internal/utils.py rather than spreading
IS_V5_DRIVER awareness to callers. Fix _pandas_importer() and mock/_options.py,
both of which referenced MissingPandas directly and would otherwise NameError/
ImportError under IS_V5_DRIVER=True.

installed_pyarrow also moves to a direct v5 import: #1151 fixed it to check
pyarrow independently instead of mirroring installed_pandas, so it's now
correct to import there instead of re-deriving locally. v4 still doesn't
export it at all, so the local isinstance derivation stays there.
…n v5

The previous try/except hedged between two locations, neither of which
actually has TelemetryData.TRUE/.FALSE on the current UD main: the public
snowflake.connector.telemetry shim's TelemetryData has no TRUE/FALSE at all,
and _internal.telemetry currently has no TelemetryData class either. The
fallback branch was silently reachable and silently wrong.

UD PR #1106 (open, not draft) adds TelemetryData/TelemetryField to
_internal/telemetry.py specifically to match Snowpark's exact usage
(PCTelemetryData(message=..., timestamp=...), .TRUE/.FALSE) -- confirmed by
reading its actual diff. Import from there unconditionally on v5, no
try/except: both branches now import from one definite, verified location.
…as from connector

_pandas_importer() predates this whole effort and duplicated resolution the
connector already does correctly on both driver generations -- including the
"relative imports without dots" DataFrame workaround, now folded into UD's
own _common.extras.pandas (confirmed on the not-yet-merged UD PR #1151/#1152;
v4's options.py already had it). Add pandas/installed_pandas to the existing
IS_V5_DRIVER-gated import block and delete the local resolution entirely.

Verified the workaround isn't needed on Snowpark's side by running the exact
invocation style its comment called out (pytest with tests/unit/ as cwd) --
no failure, consistent with both driver generations now handling it
internally.
….extras

mock/_options.py's MissingNumpy/numpy try-except was functionally identical
to _common/extras.py's own numpy resolution (confirmed: pure duplicate, no
fix to merge, per UD PR #1152's investigation). Import numpy from
_common.extras on v5; v4 keeps its own MissingNumpy class since v4's
options.py has no numpy handling to delegate to.

Does not touch the pandas try/except in this file -- Local Testing
deliberately never resolves pyarrow, unlike every other pandas-resolution
path in this codebase (commit #1628).
@sfc-gh-fpawlowski
sfc-gh-fpawlowski changed the base branch from SNOW-2912540-is-v5-driver-constant to SNOW-2912540-decouple-oob-telemetry August 17, 2026 18:33
@sfc-gh-fpawlowski
sfc-gh-fpawlowski marked this pull request as ready for review August 17, 2026 18:34
Removing the function left only one blank line before class TempObjectType; black requires two before a top-level class definition.
@sfc-gh-fpawlowski sfc-gh-fpawlowski changed the title SNOW-2912540: use IS_V5_DRIVER for SecretDetector import path SNOW-2912540: add IS_V5_DRIVER constant; use it for SecretDetector/TelemetryData imports and pandas/pyarrow/numpy resolution Aug 17, 2026
…block

- F401: pandas is imported purely for other modules to re-import from
  here, so it's never referenced elsewhere in this file. Split into
  its own import with a noqa, rather than noqa-ing a name inside a
  multi-line parenthesized import (which flake8 attributes to the
  opening line, not the name's own line).
- E402: the IS_V5_DRIVER conditional-import block and _missing_pandas()
  ended up sitting between the top-of-file imports and two later ones
  (Row, VERSION). Moved those two imports up to stay contiguous.
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.00000% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.33%. Comparing base (c202a6b) to head (69382c5).

Files with missing lines Patch % Lines
src/snowflake/snowpark/_internal/utils.py 45.45% 5 Missing and 1 partial ⚠️
src/snowflake/snowpark/_internal/telemetry.py 33.33% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@                           Coverage Diff                            @@
##           SNOW-2912540-decouple-oob-telemetry    #4313       +/-   ##
========================================================================
- Coverage                                80.99%   67.33%   -13.67%     
========================================================================
  Files                                      170      170               
  Lines                                    44663    44666        +3     
  Branches                                  7677     7680        +3     
========================================================================
- Hits                                     36174    30075     -6099     
- Misses                                    6969    11874     +4905     
- Partials                                  1520     2717     +1197     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

2 participants