Skip to content

test: guard import footprint (no heavy deps, fast cold start)#9

Merged
hampsterx merged 1 commit into
masterfrom
test/import-footprint
Jun 19, 2026
Merged

test: guard import footprint (no heavy deps, fast cold start)#9
hampsterx merged 1 commit into
masterfrom
test/import-footprint

Conversation

@hampsterx

@hampsterx hampsterx commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • The small install and fast cold start are this client's core value prop (serverless / Lambda), but nothing failed CI if a future change imported pandas at module top or ballooned import time.
  • Add tests/test_import_footprint.py: a fresh subprocess installs a recording meta-path finder and asserts a bare import snowflake_sql_api makes no attempt to import heavy optional deps (pandas/pyarrow/numpy). Stubbing the forbidden names makes the check deterministic in any env, a module-top import is caught even when guarded by try/except and even where pandas is not installed. A second test asserts the import stays under a generous 2.5s budget (best of 3 samples, to stay non-flaky on shared runners).
  • Add scripts/benchmark.py: a dependency-free manual tool reporting cold-import time and package source size (excludes bytecode/deps). Informational, not a gate, not shipped in the wheel; locates the package relative to itself so it runs from a raw checkout.

Review

External (Codex agentic, Kimi-agentic): first pass flagged three findings (non-deterministic leak check, single-sample timing, benchmark size/validation), all applied. Codex re-review of the amended diff: clean. Claude reviewer skipped (same harness).

Changes

  • tests/test_import_footprint.py (new, +120)
  • scripts/benchmark.py (new, +82)

Test plan

  • coverage run -m pytest && coverage report: 178 passed, 5 skipped, total 94% (>= 89% gate)
  • pre-commit run --all-files clean (ruff, black, mypy, yaml/toml, private-key)
  • Negative proof: a guarded module-top import pandas is detected with pandas absent
  • python scripts/benchmark.py: import ~450ms median, 90 KiB source; --runs 0 rejected

Summary by CodeRabbit

  • Tests

    • Added import-footprint tests ensuring the package doesn't pull heavy dependencies on bare import and meets startup-time requirements.
  • Chores

    • Added performance benchmarking tool for measuring cold-import time and package source size.

- The small install and fast cold start are this client's core value prop
  (serverless / Lambda), but nothing failed CI if a future change imported
  pandas at module top or ballooned import time.
- Add tests/test_import_footprint.py: a fresh subprocess installs a recording
  meta-path finder and asserts a bare `import snowflake_sql_api` makes no attempt
  to import heavy optional deps (pandas/pyarrow/numpy). Stubbing the forbidden
  names makes the check deterministic in any env: a module-top import is caught
  even when guarded by try/except and even where pandas is not installed. A
  second test asserts the import stays under a generous 2.5s budget (best of 3
  samples, to stay non-flaky on shared runners).
- Add scripts/benchmark.py: a dependency-free manual tool reporting cold-import
  time and package source size (excludes bytecode/deps). Informational, not a
  gate, not shipped in the wheel; locates the package relative to itself so it
  runs from a raw checkout.
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds scripts/benchmark.py, a CLI tool measuring cold-import time and source size of snowflake_sql_api via subprocesses, and tests/test_import_footprint.py, a pytest module enforcing that a bare import pulls no heavy dependencies (pandas, pyarrow, numpy) and completes within a time budget.

Changes

Import Footprint Tooling

Layer / File(s) Summary
Benchmark CLI script
scripts/benchmark.py
Adds cold_import_seconds(runs) spawning fresh Python subprocesses to record elapsed import time, source_size_bytes() summing package files excluding __pycache__/.pyc, and main() parsing --runs, computing median/min/max in ms and size in KiB.
Import footprint test suite
tests/test_import_footprint.py
Defines FORBIDDEN_ON_BARE_IMPORT, IMPORT_BUDGET_SECONDS, TIMING_SAMPLES constants and _run() helper; test_bare_import_pulls_no_heavy_deps() installs a sys.meta_path stub recorder in a subprocess and asserts no forbidden modules are attempted; test_bare_import_is_fast() takes the minimum of TIMING_SAMPLES subprocess runs and asserts it stays under budget.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop, a subprocess springs to life,
Timing imports with a stopwatch keen,
No pandas sneaking in to cause strife,
The leanest package you have ever seen.
Milliseconds measured, kilobytes weighed —
A benchmark script to keep slow imports afraid! 🕐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding tests to guard the library's import footprint by preventing heavy dependencies and ensuring fast cold start times.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/import-footprint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@hampsterx

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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 (1)
scripts/benchmark.py (1)

42-48: ⚡ Quick win

Add a timeout to each benchmark subprocess run.

Without a timeout, a stuck child process can hang the benchmark indefinitely. Bound execution so failures are deterministic.

Proposed patch
         result = subprocess.run(
             [sys.executable, "-c", _TIMING_SCRIPT],
             capture_output=True,
             text=True,
             check=True,
             cwd=_REPO_ROOT,
+            timeout=30,
         )
🤖 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 `@scripts/benchmark.py` around lines 42 - 48, Add a timeout parameter to the
subprocess.run() call that executes _TIMING_SCRIPT to prevent the benchmark from
hanging indefinitely if the child process gets stuck. Set an appropriate timeout
value that allows normal execution while ensuring failures are deterministic
rather than causing the benchmark to hang.
🤖 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 `@tests/test_import_footprint.py`:
- Around line 79-82: The _run() function needs to be modified to ensure
subprocess execution is deterministic and time-bounded. Add a cwd parameter to
the subprocess.run() call to explicitly set the working directory to the
repository root (ensuring the checked-out snowflake_sql_api is used instead of
any installed version), and add a timeout parameter to set a time limit on
subprocess execution to prevent CI hangs. Both parameters should be passed
directly to the subprocess.run() call along with the existing arguments.

---

Nitpick comments:
In `@scripts/benchmark.py`:
- Around line 42-48: Add a timeout parameter to the subprocess.run() call that
executes _TIMING_SCRIPT to prevent the benchmark from hanging indefinitely if
the child process gets stuck. Set an appropriate timeout value that allows
normal execution while ensuring failures are deterministic rather than causing
the benchmark to hang.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 63cb416b-a430-44f0-a364-e885ae36e4f4

📥 Commits

Reviewing files that changed from the base of the PR and between 9137d4e and d3feb47.

📒 Files selected for processing (2)
  • scripts/benchmark.py
  • tests/test_import_footprint.py

Comment on lines +79 to +82
def _run(script: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, "-c", script], capture_output=True, text=True
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make subprocess execution deterministic to the checked-out repo and time-bounded.

_run() inherits caller cwd, so these tests can accidentally validate an installed snowflake_sql_api instead of this checkout. It also has no timeout, so CI can hang on a stuck child import.

Proposed patch
 import subprocess
 import sys
+from pathlib import Path
@@
 TIMING_SAMPLES = 3
+_REPO_ROOT = Path(__file__).resolve().parent.parent
@@
 def _run(script: str) -> subprocess.CompletedProcess:
     return subprocess.run(
-        [sys.executable, "-c", script], capture_output=True, text=True
+        [sys.executable, "-c", script],
+        capture_output=True,
+        text=True,
+        cwd=_REPO_ROOT,
+        timeout=30,
     )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _run(script: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, "-c", script], capture_output=True, text=True
)
import subprocess
import sys
from pathlib import Path
# ... existing code ...
TIMING_SAMPLES = 3
_REPO_ROOT = Path(__file__).resolve().parent.parent
# ... existing code ...
def _run(script: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
cwd=_REPO_ROOT,
timeout=30,
)
🧰 Tools
🪛 ast-grep (0.43.0)

[error] 79-81: Command coming from incoming request
Context: subprocess.run(
[sys.executable, "-c", script], capture_output=True, text=True
)
Note: [CWE-20].

(subprocess-from-request)

🤖 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_import_footprint.py` around lines 79 - 82, The _run() function
needs to be modified to ensure subprocess execution is deterministic and
time-bounded. Add a cwd parameter to the subprocess.run() call to explicitly set
the working directory to the repository root (ensuring the checked-out
snowflake_sql_api is used instead of any installed version), and add a timeout
parameter to set a time limit on subprocess execution to prevent CI hangs. Both
parameters should be passed directly to the subprocess.run() call along with the
existing arguments.

@hampsterx hampsterx merged commit 3863b3c into master Jun 19, 2026
7 checks passed
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.

1 participant