Skip to content

fix(replicate): defer replicate import#3126

Open
timkpaine wants to merge 1 commit intotraceloop:mainfrom
timkpaine:timkpaine-patch-1
Open

fix(replicate): defer replicate import#3126
timkpaine wants to merge 1 commit intotraceloop:mainfrom
timkpaine:timkpaine-patch-1

Conversation

@timkpaine
Copy link
Copy Markdown

@timkpaine timkpaine commented Jul 13, 2025

xref: conda-forge/opentelemetry-instrumentation-replicate-feedstock#20

import: 'opentelemetry.instrumentation.replicate'
Traceback (most recent call last):
  File "/home/conda/feedstock_root/build_artifacts/opentelemetry-instrumentation-replicate_1752448577076/test_tmp/run_test.py", line 2, in <module>
    import opentelemetry.instrumentation.replicate
  File "/home/conda/feedstock_root/build_artifacts/opentelemetry-instrumentation-replicate_1752448577076/_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placeh/lib/python3.9/site-packages/opentelemetry/instrumentation/replicate/__init__.py", line 11, in <module>
    from opentelemetry.instrumentation.replicate.event_emitter import (
  File "/home/conda/feedstock_root/build_artifacts/opentelemetry-instrumentation-replicate_1752448577076/_test_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placeh/lib/python3.9/site-packages/opentelemetry/instrumentation/replicate/event_emitter.py", line 19, in <module>
    from replicate.prediction import Prediction
ModuleNotFoundError: No module named 'replicate'
  • I have added tests that cover my changes.
  • If adding a new instrumentation or changing an existing one, I've added screenshots from some observability platform showing the change.
  • PR name follows conventional commits format: feat(instrumentation): ... or fix(instrumentation): ....
  • (If applicable) I have updated the documentation accordingly.

Important

Move replicate to runtime dependencies in pyproject.toml to fix import error.

  • Dependency Management:
    • Move replicate from [tool.poetry.group.dev.dependencies] to [tool.poetry.dependencies] in pyproject.toml.
    • Ensures replicate is available at runtime to prevent ModuleNotFoundError during import in event_emitter.py.

This description was created by Ellipsis for 053b35a. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Bug Fixes

    • Avoids unintended runtime imports of optional dependencies by restricting certain imports to type-checking, improving startup reliability and compatibility.
    • Ensures import behavior doesn't introduce stray top-level modules in the runtime environment.
  • Tests

    • Added an import-safety test to verify no unintended top-level module is created during package import.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jul 13, 2025

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 053b35a in 52 seconds. Click for details.
  • Reviewed 20 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/opentelemetry-instrumentation-replicate/pyproject.toml:27
  • Draft comment:
    Good move: replicating dependency is now correctly listed as a runtime dependency. Ensure that the version range (>=0.23.1,<0.27.0) is intended.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
2. packages/opentelemetry-instrumentation-replicate/pyproject.toml:38
  • Draft comment:
    Removing replicate from the dev dependencies is appropriate now since it's required at runtime.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, as it states that removing 'replicate' from the dev dependencies is appropriate. It doesn't provide a suggestion, ask for confirmation, or point out a potential issue. It simply informs about the appropriateness of the change, which violates the rules.

Workflow ID: wflow_8rIvy0XtIogSGTuW

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Comment thread packages/opentelemetry-instrumentation-replicate/pyproject.toml Outdated
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 14, 2025

Walkthrough

Adds TYPE_CHECKING-guarded typing for replicate's Prediction, changes emit_choice_events to use a forward-referenced "Prediction" in annotations and adjusts its isinstance check to the quoted form, and adds a test ensuring importing the instrumentation package does not populate a top-level replicate entry in sys.modules.

Changes

Cohort / File(s) Summary of Changes
Instrumentation typing and runtime check
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py
Introduced TYPE_CHECKING guard for typing imports; changed emit_choice_events signature to use Union[str, list, "Prediction"] and event_logger: Union[EventLogger, None]; replaced isinstance(response, Prediction) with isinstance(response, "Prediction").
Import-side-effect test
packages/opentelemetry-instrumentation-replicate/tests/test_import.py
Added test that imports opentelemetry.instrumentation.replicate and asserts no top-level "replicate" key appears in sys.modules.

Sequence Diagram(s)

(omitted — changes are type/import and a unit test; no control-flow modifications to visualize)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I twitch my whiskers at a guarded type,
Quoted names tiptoe through the night.
Imports clean, no stray module found,
Events still hum without a sound.
A little hop, a test — all right! 🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@timkpaine timkpaine changed the title fix: Move replicate to runtime dependency fix: defer replicate import Aug 14, 2025
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (1)

39-40: Optional: Broaden list typing and clarify None-able logger.

If you’re open to minor typing polish:

  • Prefer Sequence[str] over list for the replicate.run responses (it’s more general).
  • Prefer Optional[EventLogger] over Union[EventLogger, None] (stylistic; equivalent).

If you decide to proceed, add Sequence/Optional to imports and update the annotation:

-from typing import Union, TYPE_CHECKING
+from typing import Optional, Sequence, Union, TYPE_CHECKING
@@
-def emit_choice_events(
-    response: Union[str, list, "Prediction"], event_logger: Union[EventLogger, None]
-):
+def emit_choice_events(
+    response: Union[str, Sequence[str], "Prediction"], event_logger: Optional[EventLogger]
+):
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 50be41d and e85c396.

📒 Files selected for processing (2)
  • packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (4 hunks)
  • packages/opentelemetry-instrumentation-replicate/tests/test_import.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit Inference Engine (CLAUDE.md)

**/*.py: Python code must conform to Flake8 linting rules
Do not hardcode API keys in source code; read them from environment variables or a secure vault

Files:

  • packages/opentelemetry-instrumentation-replicate/tests/test_import.py
  • packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py
🪛 Ruff (0.12.2)
packages/opentelemetry-instrumentation-replicate/tests/test_import.py

4-4: opentelemetry.instrumentation.replicate imported but unused

Remove unused import: opentelemetry.instrumentation.replicate

(F401)

🪛 Flake8 (7.2.0)
packages/opentelemetry-instrumentation-replicate/tests/test_import.py

[error] 4-4: 'opentelemetry.instrumentation.replicate' imported but unused

(F401)

🔇 Additional comments (1)
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (1)

19-20: Good: Gate typing-only import to avoid runtime dependency.

Using TYPE_CHECKING to avoid importing replicate at runtime is correct and aligns with the goal of not requiring replicate to be installed just to import the instrumentation package.

)
# Handle replicate.predictions.create responses
elif isinstance(response, Prediction):
elif isinstance(response, "Prediction"):
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

Bug: isinstance() cannot take a string as the type argument.

isinstance(response, "Prediction") raises TypeError at runtime. Since we intentionally avoid importing Prediction at module import time, use a duck-typed and module-aware check instead.

Apply this diff:

-    elif isinstance(response, "Prediction"):
+    elif hasattr(response, "output") and getattr(response.__class__, "__module__", "").startswith("replicate."):

This preserves the no-import-at-import-time behavior while correctly detecting Replicate Prediction-like objects at runtime.

📝 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
elif isinstance(response, "Prediction"):
elif hasattr(response, "output") and getattr(response.__class__, "__module__", "").startswith("replicate."):
🤖 Prompt for AI Agents
In
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py
around line 51, the code uses isinstance(response, "Prediction") which raises
TypeError because isinstance cannot take a string; replace this with a
duck-typed and module-aware runtime check that does not import Prediction at
module load: inspect the response's class name and module (e.g. class.__name__
== "Prediction" and class.__module__ startswith the replicate package/module)
and/or check for a small set of Prediction-specific attributes/methods to
reliably identify Prediction-like objects at runtime, then branch accordingly.

Comment on lines +3 to +7
def test_import():
import opentelemetry.instrumentation.replicate

assert "replicate" not in sys.modules
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

Fix F401 (unused import) and make the assertion robust to pre-existing imports.

  • Flake8/Ruff flags Line 4 as an unused import.
  • The current assertion fails if some other test already imported the top-level "replicate" module.

Switch to importlib for side-effect import and assert that importing the instrumentation didn’t newly add "replicate" to sys.modules.

Apply this diff:

-import sys
-
-def test_import():
-    import opentelemetry.instrumentation.replicate
-
-    assert "replicate" not in sys.modules
+import importlib
+import sys
+
+def test_import():
+    before = set(sys.modules.keys())
+    importlib.import_module("opentelemetry.instrumentation.replicate")
+    after = set(sys.modules.keys())
+
+    # Ensure importing the instrumentation does not import the top-level "replicate" package
+    assert "replicate" not in (after - before)
📝 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 test_import():
import opentelemetry.instrumentation.replicate
assert "replicate" not in sys.modules
import importlib
import sys
def test_import():
before = set(sys.modules.keys())
importlib.import_module("opentelemetry.instrumentation.replicate")
after = set(sys.modules.keys())
# Ensure importing the instrumentation does not import the top-level "replicate" package
assert "replicate" not in (after - before)
🧰 Tools
🪛 Ruff (0.12.2)

4-4: opentelemetry.instrumentation.replicate imported but unused

Remove unused import: opentelemetry.instrumentation.replicate

(F401)

🪛 Flake8 (7.2.0)

[error] 4-4: 'opentelemetry.instrumentation.replicate' imported but unused

(F401)

🤖 Prompt for AI Agents
In packages/opentelemetry-instrumentation-replicate/tests/test_import.py around
lines 3 to 6, the test currently does a direct import which triggers a Flake8
F401 unused-import and can fail if the top-level "replicate" module was already
imported by other tests; change it to take a snapshot of sys.modules before the
import, use importlib.import_module("opentelemetry.instrumentation.replicate")
for the side-effect import (so there is no unused local), then assert that
"replicate" is not newly present in sys.modules by comparing the post-import
modules to the snapshot (or explicitly assert "replicate" not in
sys.modules_difference).

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (1)

51-57: Bug: isinstance() cannot take a string as the type argument. Replace with a duck-typed, module-aware check.

isinstance(response, "Prediction") raises TypeError at runtime. Keep the no-import-at-import-time behavior by checking shape and module metadata.

Apply this diff:

-    elif isinstance(response, "Prediction"):
+    elif (
+        hasattr(response, "output")
+        and getattr(response.__class__, "__name__", "") == "Prediction"
+        and getattr(response.__class__, "__module__", "").startswith("replicate")
+    ):

Notes:

  • This avoids importing replicate at module import time.
  • When replicate is installed and a real Prediction instance is passed, this branch will match.
  • As an alternative, you could perform a lazy import inside this branch, but only if you first prove it’s likely a Prediction to avoid importing replicate for non-Prediction responses.

If helpful, I can add a unit test that stubs a Prediction-like object to exercise this branch without importing replicate.

🧹 Nitpick comments (2)
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (2)

3-3: Nit: import Optional and Sequence for cleaner annotations.

Prepping for clearer type hints below. No behavior change.

-from typing import Union, TYPE_CHECKING
+from typing import Union, Optional, Sequence, TYPE_CHECKING

39-40: Clarify and broaden annotations: Optional[EventLogger] and Sequence[str].

  • Using Optional[EventLogger] is idiomatic vs Union[EventLogger, None].
  • Sequence[str] communicates intent better than bare list and accepts tuples, etc.
-def emit_choice_events(
-    response: Union[str, list, "Prediction"], event_logger: Union[EventLogger, None]
-):
+def emit_choice_events(
+    response: Union[str, Sequence[str], "Prediction"], event_logger: Optional[EventLogger]
+):

For consistency, consider updating the helper signatures similarly (no behavior change):

def emit_event(event: Union[MessageEvent, ChoiceEvent], event_logger: Optional[EventLogger]) -> None: ...
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e85c396 and 5222abb.

📒 Files selected for processing (2)
  • packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (4 hunks)
  • packages/opentelemetry-instrumentation-replicate/tests/test_import.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opentelemetry-instrumentation-replicate/tests/test_import.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py
🔇 Additional comments (1)
packages/opentelemetry-instrumentation-replicate/opentelemetry/instrumentation/replicate/event_emitter.py (1)

19-20: LGTM: TYPE_CHECKING-guarded import avoids runtime import side effects.

This correctly prevents importing replicate at module import time, aligning with the goal of not populating sys.modules solely from importing the instrumentation package.

@timkpaine timkpaine changed the title fix: defer replicate import fix(replicate): defer replicate import Aug 21, 2025
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.

3 participants