Skip to content

Conversation

@NiveditJain
Copy link
Member

This pull request contains changes generated by Cursor background composer.

Co-authored-by: nivedit <nivedit@aikin.club>
@cursor
Copy link

cursor bot commented Aug 17, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 17, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Automated test coverage reporting for the Python SDK in CI.
  • Bug Fixes
    • Improved runtime validation with clearer, consistent error handling.
  • Tests
    • Added unit tests for node execution, runtime validation, and state manager input checks.
    • Generates coverage and test result artifacts.
  • Chores
    • Introduced a dedicated “Python SDK Tests” workflow for pushes and pull requests.
    • Added a test step to the publish workflow to run the suite before build/publish.
    • Included pytest and coverage tools in development dependencies.

Walkthrough

Adds a dedicated test workflow for the Python SDK, injects a test step into the publish workflow, introduces dev test dependencies, revises Runtime node validation to guard for non-BaseModel schemas and raise ValueError, and adds unit tests for BaseNode execution, Runtime validation, and StateManager.trigger argument checks.

Changes

Cohort / File(s) Summary
CI: Test and Publish Workflows
.github/workflows/test-python-sdk.yml, .github/workflows/publish-python-sdk.yml
New test workflow runs pytest with coverage and uploads results to Codecov; publish workflow now runs tests (uvx pytest) between dependency sync and build.
Runtime Validation Logic
python-sdk/exospherehost/runtime.py
Reworks node validation: checks Inputs/Outputs/Secrets exist and inherit from BaseModel, guards field inspections, aggregates errors, and switches raised exceptions from ValidationError to ValueError.
Dev/Test Dependencies
python-sdk/pyproject.toml
Adds pytest and pytest-cov to the dev dependency group.
New Tests
python-sdk/tests/test_base_node.py, python-sdk/tests/test_runtime_validation.py, python-sdk/tests/test_state_manager.py
Adds tests for BaseNode execution behavior, Runtime configuration/node validation (including duplicate names), and StateManager.trigger parameter validation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer
  participant GH as GitHub Actions
  participant Py as Python/uv
  participant PT as Pytest
  participant CC as Codecov

  Dev->>GH: Push/PR under python-sdk/**
  GH->>Py: Setup Python 3.12 and uv
  GH->>Py: uv sync --group dev
  GH->>Py: uv pip install -e .
  GH->>PT: pytest with coverage (xml, junit)
  PT-->>GH: Test results, coverage.xml, junit.xml
  GH->>CC: Upload coverage (codecov-action)
  GH->>GH: Upload pytest results artifact
Loading
sequenceDiagram
  autonumber
  participant App as Application
  participant RT as Runtime
  participant NV as Node Validation

  App->>RT: new Runtime(nodes=[...], config)
  RT->>NV: _validate_nodes(nodes)
  NV->>NV: Check Inputs/Outputs/Secrets exist
  NV->>NV: Verify each inherits BaseModel
  NV->>NV: If BaseModel, inspect model_fields types
  NV-->>RT: Collect errors or success
  RT-->>App: Success or raise ValueError
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

Thump-thump goes my tiny heart—test time!
I hop through workflows, ears in rhyme.
Nodes checked twice, BaseModels right,
ValueErrors nibble at the night.
With carrots of coverage, I cheer and grin—
CI burrows green, let the merges begin! 🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/add-python-sdk-unit-tests-and-ci-8804

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.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @NiveditJain, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on enhancing the Python SDK by introducing comprehensive unit tests and configuring the testing environment. It also includes a minor refinement to the runtime node validation logic, improving its robustness and error handling.

Highlights

  • New Test Infrastructure: Introduction of pytest.ini to configure the testing environment for the Python SDK.
  • BaseNode Unit Tests: Added tests to verify the correct execution and input/output handling of BaseNode implementations.
  • Runtime Validation Tests: Comprehensive tests for the Runtime class, ensuring proper validation of node definitions (e.g., BaseModel inheritance, correct field types) and configuration parameters, as well as handling of duplicate node names.
  • StateManager Trigger Tests: New tests to validate the StateManager's trigger method, specifically checking for correct usage of state and states arguments.
  • Runtime Validation Refinement: Modified runtime.py to improve the robustness of node validation by conditionally checking model_fields only if Inputs, Outputs, or Secrets are indeed BaseModel subclasses, and changed the raised exception type from ValidationError to ValueError.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive suite of unit tests for the Python SDK, covering the base node, runtime validation, and state manager components. The changes also include a necessary refactoring in the runtime's node validation logic to handle edge cases correctly. My review focuses on improving the maintainability of the validation logic and cleaning up the new test code. Overall, this is a great addition that significantly improves the robustness of the SDK.

Comment on lines 43 to 45
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This helper function _set_required_env is defined but never called in the test suite. It appears to be dead code and should be removed to improve code clarity.

@NiveditJain NiveditJain marked this pull request as ready for review August 17, 2025 09:11
Copy link
Member Author

@NiveditJain NiveditJain left a comment

Choose a reason for hiding this comment

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

Also tests are failing, here are the errors:

==================================== ERRORS ====================================
___________________ ERROR collecting tests/test_base_node.py ___________________
ImportError while importing test module '/home/runner/work/exospherehost/exospherehost/python-sdk/tests/test_base_node.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../../../.local/share/uv/python/cpython-3.12.11-linux-x86_64-gnu/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_base_node.py:1: in <module>
    from exospherehost.node.BaseNode import BaseNode
exospherehost/__init__.py:38: in <module>
    from .runtime import Runtime
exospherehost/runtime.py:6: in <module>
    from pydantic import BaseModel, ValidationError
E   ModuleNotFoundError: No module named 'pydantic'
______________ ERROR collecting tests/test_runtime_validation.py _______________
ImportError while importing test module '/home/runner/work/exospherehost/exospherehost/python-sdk/tests/test_runtime_validation.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../../../.local/share/uv/python/cpython-3.12.11-linux-x86_64-gnu/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_runtime_validation.py:3: in <module>
    from pydantic import BaseModel
E   ModuleNotFoundError: No module named 'pydantic'
_________________ ERROR collecting tests/test_state_manager.py _________________
ImportError while importing test module '/home/runner/work/exospherehost/exospherehost/python-sdk/tests/test_state_manager.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../../../.local/share/uv/python/cpython-3.12.11-linux-x86_64-gnu/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_state_manager.py:3: in <module>
    from exospherehost.statemanager import StateManager, TriggerState
exospherehost/__init__.py:38: in <module>
    from .runtime import Runtime
exospherehost/runtime.py:6: in <module>
    from pydantic import BaseModel, ValidationError
E   ModuleNotFoundError: No module named 'pydantic'
=========================== short test summary info ============================

@cursoragent fix all the review comments, along with that also fix the failing tests.

- main
paths:
- "python-sdk/exospherehost/_version.py"
- "python-sdk/**"
Copy link
Member Author

Choose a reason for hiding this comment

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

this pipeline publishes only when _version.py is updated because we need to publish only when _version.py is updated. Lets revert it back?

For normal commit when just python-sdk/** is updated, we should probably write another yml file or merge with the pull_request file

Copy link
Member Author

Choose a reason for hiding this comment

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

send report to codecov also, like we are doing in api-server

Copy link
Member Author

Choose a reason for hiding this comment

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

function never used

Comment on lines 1 to 3
Copy link
Member Author

Choose a reason for hiding this comment

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

should this point to path of python-sdk?

get-pip.py Outdated
Copy link
Member Author

Choose a reason for hiding this comment

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

why this file? we don't need it

Copy link
Member Author

Choose a reason for hiding this comment

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

@cursoragent remove this file

Copy link

@cursor cursor bot Aug 17, 2025

Choose a reason for hiding this comment

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

Open in Cursor Open in Web

Learn more about Cursor Agents

@NiveditJain
Copy link
Member Author

@cursoragent fix the review comments and also fix the failing tests

@cursor
Copy link

cursor bot commented Aug 17, 2025

I refactored the Python SDK's CI/CD workflows, primarily enhancing the test pipeline to include comprehensive test execution with coverage reporting and artifact uploads. I also refined the SDK's pyproject.toml and adjusted the publish workflow trigger for better control.

  • I updated the publish-python-sdk.yml workflow to trigger only on changes to python-sdk/exospherehost/_version.py, ensuring releases are tied to explicit version bumps.
  • I significantly revamped the test-python-sdk.yml workflow:
    • Configured it to run on push and pull_request events targeting the main branch within the python-sdk/ directory.
    • Standardized Python setup to 3.12 and uv installation.
    • Implemented pytest execution with pytest-cov to generate coverage reports (coverage.xml) and JUnit XML test results (pytest-report.xml).
    • Integrated Codecov for automatic coverage report uploads and actions/upload-artifact for test result artifacts.
  • I modified python-sdk/pyproject.toml to include pytest and pytest-cov in the dev dependency group, supporting the new testing setup.
  • I removed the python-sdk/pytest.ini file, as its configurations are now managed directly in the CI workflow or are no longer necessary.
  • I cleaned up python-sdk/tests/test_runtime_validation.py by removing an unused helper function _set_required_env.

Open in Cursor Open in Web

Learn more about Cursor Agents

…R CI with coverage upload to Codecov; revert publish trigger to _version.py and run tests before publish; remove unused helper and pytest.ini; add pytest/pytest-cov to dev deps
Copy link
Member Author

@NiveditJain NiveditJain left a comment

Choose a reason for hiding this comment

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

remove get-pip file

get-pip.py Outdated
Copy link
Member Author

Choose a reason for hiding this comment

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

@cursoragent remove this file

@NiveditJain
Copy link
Member Author

@cursoragent ruff checks are failing with issue:

401 [*] `pydantic.ValidationError` imported but unused
 --> python-sdk/exospherehost/runtime.py:6:33
  |
4 | from typing import List, Dict
5 |
6 | from pydantic import BaseModel, ValidationError
  |                                 ^^^^^^^^^^^^^^^
7 | from .node.BaseNode import BaseNode
8 | from aiohttp import ClientSession
  |
help: Remove unused import: `pydantic.ValidationError`

F401 [*] `os` imported but unused
 --> python-sdk/tests/test_runtime_validation.py:1:8
  |
1 | import os
  |        ^^
2 | import pytest
3 | from pydantic import BaseModel
  |
help: Remove unused import: `os`

Found 2 errors.

Tests are still failing in CI/CD pipeline with issue:

==================================== ERRORS ====================================
___________________ ERROR collecting tests/test_base_node.py ___________________
ImportError while importing test module '/home/runner/work/exospherehost/exospherehost/python-sdk/tests/test_base_node.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_base_node.py:1: in <module>
    from exospherehost.node.BaseNode import BaseNode
E   ModuleNotFoundError: No module named 'exospherehost'
______________ ERROR collecting tests/test_runtime_validation.py _______________
ImportError while importing test module '/home/runner/work/exospherehost/exospherehost/python-sdk/tests/test_runtime_validation.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_runtime_validation.py:4: in <module>
    from exospherehost.runtime import Runtime
E   ModuleNotFoundError: No module named 'exospherehost'
_________________ ERROR collecting tests/test_state_manager.py _________________
ImportError while importing test module '/home/runner/work/exospherehost/exospherehost/python-sdk/tests/test_state_manager.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_state_manager.py:3: in <module>
    from exospherehost.statemanager import StateManager, TriggerState
E   ModuleNotFoundError: No module named 'exospherehost'
- generated xml file: /home/runner/work/exospherehost/exospherehost/python-sdk/pytest-report.xml -
=========================== short test summary info ============================
ERROR tests/test_base_node.py
ERROR tests/test_runtime_validation.py
ERROR tests/test_state_manager.py
!!!!!!!!!!!!!!!!!!! Interrupted: 3 errors during collection !!!!!!!!!!!!!!!!!!!!
============================== 3 errors in 0.59s ===============================

probably we need to check paths and check if we updated uv.lock file, also run tests locally first before commiting

@cursor
Copy link

cursor bot commented Aug 17, 2025

I enhanced the Python SDK's CI pipeline by ensuring the package is installed in editable mode before testing, and I performed minor code cleanups by removing unused imports across several files. These changes improve test reliability and code maintainability.

  • I added a new step to .github/workflows/test-python-sdk.yml to install the python-sdk package in editable mode (uv pip install -e .). This ensures the package is correctly installed and discoverable for testing within the CI environment.
  • I removed the unused ValidationError import from python-sdk/exospherehost/runtime.py, simplifying the module's dependencies.
  • I cleaned up python-sdk/tests/test_runtime_validation.py by removing the unused import os and ValidationError imports, streamlining the test file.

Open in Cursor Open in Web

Learn more about Cursor Agents

Copy link
Contributor

@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: 13

♻️ Duplicate comments (2)
.github/workflows/test-python-sdk.yml (1)

45-54: Codecov upload present (addresses prior request).

You’ve added Codecov upload as requested in prior review comments.

python-sdk/tests/test_runtime_validation.py (1)

1-5: Unused helper function from prior review is removed.

The earlier dead _set_required_env helper is no longer present, addressing the prior comment about unused code.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
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 7038dc2 and 6752dbb.

📒 Files selected for processing (7)
  • .github/workflows/publish-python-sdk.yml (1 hunks)
  • .github/workflows/test-python-sdk.yml (1 hunks)
  • python-sdk/exospherehost/runtime.py (3 hunks)
  • python-sdk/pyproject.toml (1 hunks)
  • python-sdk/tests/test_base_node.py (1 hunks)
  • python-sdk/tests/test_runtime_validation.py (1 hunks)
  • python-sdk/tests/test_state_manager.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
python-sdk/tests/test_base_node.py (1)
python-sdk/exospherehost/node/BaseNode.py (6)
  • BaseNode (6-100)
  • _execute (70-83)
  • execute (86-100)
  • Outputs (37-43)
  • Inputs (29-35)
  • Secrets (45-68)
python-sdk/tests/test_runtime_validation.py (2)
python-sdk/exospherehost/runtime.py (1)
  • Runtime (13-367)
python-sdk/exospherehost/node/BaseNode.py (2)
  • BaseNode (6-100)
  • Inputs (29-35)
python-sdk/exospherehost/runtime.py (3)
python-sdk/tests/test_runtime_validation.py (11)
  • Inputs (8-9)
  • Inputs (32-33)
  • Inputs (85-86)
  • Outputs (11-12)
  • Outputs (23-24)
  • Outputs (34-35)
  • Outputs (87-88)
  • Secrets (14-15)
  • Secrets (25-26)
  • Secrets (36-37)
  • Secrets (89-90)
python-sdk/exospherehost/node/BaseNode.py (3)
  • Inputs (29-35)
  • Outputs (37-43)
  • Secrets (45-68)
state-manager/app/tasks/verify_graph.py (1)
  • verify_inputs (94-148)
🪛 YAMLlint (1.37.1)
.github/workflows/test-python-sdk.yml

[warning] 3-3: truthy value should be one of [false, true]

(truthy)


[error] 61-61: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (11)
python-sdk/pyproject.toml (1)

34-35: LGTM! Test dependencies added appropriately.

The addition of pytest>=8.3.0 and pytest-cov>=5.0.0 as development dependencies is appropriate for enabling the unit test suite and coverage reporting.

python-sdk/tests/test_base_node.py (1)

20-29: Test correctly validates BaseNode behavior.

The test properly validates that _execute sets inputs and secrets attributes and returns the expected outputs. Good coverage of the BaseNode contract.

Note: Consider fixing the indentation in this function as well:

 def test_base_node_execute_sets_inputs_and_returns_outputs():
-	node = EchoNode()
-	inputs = EchoNode.Inputs(text="hello")
-	secrets = EchoNode.Secrets(token="tkn")
-	outputs = asyncio.run(node._execute(inputs, secrets))
+    node = EchoNode()
+    inputs = EchoNode.Inputs(text="hello")
+    secrets = EchoNode.Secrets(token="tkn")
+    outputs = asyncio.run(node._execute(inputs, secrets))

-	assert isinstance(outputs, EchoNode.Outputs)
-	assert outputs.message == "hello:tkn"
-	assert node.inputs == inputs
-	assert node.secrets == secrets
+    assert isinstance(outputs, EchoNode.Outputs)
+    assert outputs.message == "hello:tkn"
+    assert node.inputs == inputs
+    assert node.secrets == secrets
python-sdk/tests/test_state_manager.py (3)

6-11: Test correctly validates the trigger requirement.

The test properly verifies that calling trigger without providing either state or states raises a ValueError.

Note: Consider fixing the indentation to follow PEP 8 (4 spaces instead of tabs):

 def test_trigger_requires_either_state_or_states(monkeypatch):
-	monkeypatch.setenv("EXOSPHERE_STATE_MANAGER_URI", "http://sm")
-	monkeypatch.setenv("EXOSPHERE_API_KEY", "k")
-	sm = StateManager(namespace="ns")
-	with pytest.raises(ValueError):
-		asyncio.run(sm.trigger("g"))
+    monkeypatch.setenv("EXOSPHERE_STATE_MANAGER_URI", "http://sm")
+    monkeypatch.setenv("EXOSPHERE_API_KEY", "k")
+    sm = StateManager(namespace="ns")
+    with pytest.raises(ValueError):
+        asyncio.run(sm.trigger("g"))

14-20: Test correctly validates mutual exclusivity.

The test properly verifies that providing both state and states arguments raises a ValueError.

Note: Consider fixing the indentation:

 def test_trigger_rejects_both_state_and_states(monkeypatch):
-	monkeypatch.setenv("EXOSPHERE_STATE_MANAGER_URI", "http://sm")
-	monkeypatch.setenv("EXOSPHERE_API_KEY", "k")
-	sm = StateManager(namespace="ns")
-	state = TriggerState(identifier="id", inputs={})
-	with pytest.raises(ValueError):
-		asyncio.run(sm.trigger("g", state=state, states=[state]))
+    monkeypatch.setenv("EXOSPHERE_STATE_MANAGER_URI", "http://sm")
+    monkeypatch.setenv("EXOSPHERE_API_KEY", "k")
+    sm = StateManager(namespace="ns")
+    state = TriggerState(identifier="id", inputs={})
+    with pytest.raises(ValueError):
+        asyncio.run(sm.trigger("g", state=state, states=[state]))

23-28: Test correctly validates empty list rejection.

The test properly verifies that providing an empty states list raises a ValueError.

Note: Consider fixing the indentation:

 def test_trigger_rejects_empty_states_list(monkeypatch):
-	monkeypatch.setenv("EXOSPHERE_STATE_MANAGER_URI", "http://sm")
-	monkeypatch.setenv("EXOSPHERE_API_KEY", "k")
-	sm = StateManager(namespace="ns")
-	with pytest.raises(ValueError):
-		asyncio.run(sm.trigger("g", states=[]))
+    monkeypatch.setenv("EXOSPHERE_STATE_MANAGER_URI", "http://sm")
+    monkeypatch.setenv("EXOSPHERE_API_KEY", "k")
+    sm = StateManager(namespace="ns")
+    with pytest.raises(ValueError):
+        asyncio.run(sm.trigger("g", states=[]))
python-sdk/exospherehost/runtime.py (4)

274-284: Robust validation of BaseModel inheritance.

The added validation correctly checks that Inputs, Outputs, and Secrets classes inherit from pydantic.BaseModel before attempting to access their model_fields. This prevents runtime errors and provides clear error messages.


287-298: Field type validation properly guarded.

The field type checks are now correctly guarded by the *_is_basemodel flags, preventing attribute errors when the classes don't inherit from BaseModel.


307-307: Error type correctly changed to ValueError.

The switch from ValidationError to ValueError is appropriate and consistent with the error handling throughout the class.


6-6: Remove unused import to fix Ruff lint error.

The ValidationError import from pydantic is no longer used after switching to ValueError for error signaling.

Since ValidationError is no longer used in the code (replaced with ValueError), the import should be removed. However, I notice that ValidationError was already removed from the imports in line 6. The Ruff error mentioned in the PR comments appears to be about a different import. Let me verify the actual issue.

python-sdk/tests/test_runtime_validation.py (2)

7-19: Solid “happy path” node fixture.

GoodNode follows the BaseNode contract and returns Outputs using validated inputs; appropriate for constructor-level tests without I/O.


81-95: Duplicate-name check is clear and side-effect free.

Overriding name locally to simulate duplicates is a neat way to validate the check without polluting global state.

@NiveditJain NiveditJain merged commit 5b7076d into main Aug 17, 2025
5 checks passed
@NiveditJain NiveditJain deleted the cursor/add-python-sdk-unit-tests-and-ci-8804 branch August 21, 2025 08:24
@coderabbitai coderabbitai bot mentioned this pull request Sep 4, 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