Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"include": ["src/", "tests/"],
"exclude": [".venv/", "build/", "dist/", ".pytest_cache/", ".hypothesis/"],
"pythonVersion": "3.14",
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.

medium

The pythonVersion is set to "3.14", which is not a released or planned version of Python. This could lead to unexpected behavior from pyright as it might not interpret this version correctly. It's recommended to use the actual Python version the project is targeting, for example "3.12" or "3.13", to ensure accurate type checking based on a real language version.

Suggested change
"pythonVersion": "3.14",
"pythonVersion": "3.13",

"venvPath": ".",
"venv": ".venv",
"typeCheckingMode": "standard",
"reportUnknownArgumentType": false,
"reportUnknownMemberType": false,
"reportUnknownVariableType": false,
"reportUnknownParameterType": false,
"reportUnknownLambdaType": false,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

reportCallIssue: false is broad

reportCallIssue covers any error related to calling a non-callable or passing arguments to a call expression — it's not limited to Pydantic-dynamic patterns. Disabling it globally could silently hide real call-site bugs in non-Pydantic code throughout src/ and tests/. The PR description justifies the other reportUnknown* suppressions as Pydantic noise, but reportCallIssue is harder to attribute purely to Pydantic. Consider using per-file or per-line # pyright: ignore[reportCallIssue] ignores at the handful of actual offending sites, or at minimum document here why this global suppression is safe.

Prompt To Fix With AI
This is a comment left during a code review.
Path: pyrightconfig.json
Line: 12

Comment:
**`reportCallIssue: false` is broad**

`reportCallIssue` covers any error related to calling a non-callable or passing arguments to a call expression — it's not limited to Pydantic-dynamic patterns. Disabling it globally could silently hide real call-site bugs in non-Pydantic code throughout `src/` and `tests/`. The PR description justifies the other `reportUnknown*` suppressions as Pydantic noise, but `reportCallIssue` is harder to attribute purely to Pydantic. Consider using per-file or per-line `# pyright: ignore[reportCallIssue]` ignores at the handful of actual offending sites, or at minimum document here why this global suppression is safe.

How can I resolve this? If you propose a fix, please make it concise.

"reportCallIssue": false,
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.

🧹 Nitpick | 🔵 Trivial

Consider the implications of disabling reportCallIssue.

Disabling reportCallIssue suppresses all call-site type mismatches, which could hide legitimate type errors beyond the intended Pydantic/structlog noise. Since mypy strict is the authoritative checker in CI, this may be acceptable for editor ergonomics, but be aware that some genuine issues might be silently skipped in the IDE.

If you find real type errors slipping through, consider re-enabling this and using targeted # pyright: ignore[reportCallIssue] comments on specific false-positive lines instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyrightconfig.json` at line 13, The pyright config currently disables
reportCallIssue by setting "reportCallIssue": false which silences all call-site
type mismatch warnings; to avoid hiding real issues either re-enable
reportCallIssue (set it back to true) and address any noisy Pydantic/structlog
false positives with targeted inline ignores (use "# pyright:
ignore[reportCallIssue]" on the specific functions or call sites), or keep it
disabled for editor ergonomics but add a short repo-level comment explaining
that mypy strict in CI is authoritative and to revert to per-line ignores if
real type errors are observed; reference the "reportCallIssue" setting in
pyrightconfig.json when making this change.

"reportPrivateUsage": false,
"reportMissingTypeStubs": false
}
2 changes: 1 addition & 1 deletion src/synthorg/api/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async def capture_send(message: Any) -> None:
and message.get("type") == "http.response.start"
):
status_code = message.get("status", 500)
await original_send(message)
await original_send(message) # pyright: ignore[reportArgumentType]

try:
await self.app(scope, receive, capture_send)
Expand Down
7 changes: 4 additions & 3 deletions src/synthorg/config/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,10 @@ def _parse_yaml_string(
except yaml.YAMLError as exc:
line: int | None = None
col: int | None = None
if hasattr(exc, "problem_mark") and exc.problem_mark is not None:
line = exc.problem_mark.line + 1
col = exc.problem_mark.column + 1
mark = getattr(exc, "problem_mark", None)
if mark is not None:
line = mark.line + 1
col = mark.column + 1
msg = f"YAML syntax error in {source_name}: {exc}"
logger.warning(
CONFIG_PARSE_FAILED,
Expand Down
2 changes: 1 addition & 1 deletion src/synthorg/memory/backends/mem0/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ async def connect(self) -> None:
)
msg = f"Failed to connect to Mem0: {exc}"
raise MemoryConnectionError(msg) from exc
self._client = client
self._client = client # pyright: ignore[reportAttributeAccessIssue]
self._connected = True
logger.info(MEMORY_BACKEND_CONNECTED, backend="mem0")

Expand Down
1 change: 1 addition & 0 deletions src/synthorg/memory/org/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ async def query(
clauses.append(f"category IN ({placeholders})")
params.extend(c.value for c in categories)

escaped = ""
if text is not None:
escaped = text.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_")
clauses.append("content LIKE ? ESCAPE '\\'")
Expand Down
1 change: 1 addition & 0 deletions src/synthorg/observability/events/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
TEMPLATE_RENDER_JINJA2_ERROR: Final[str] = "template.render.jinja2_error"
TEMPLATE_RENDER_YAML_ERROR: Final[str] = "template.render.yaml_error"
TEMPLATE_RENDER_VALIDATION_ERROR: Final[str] = "template.render.validation_error"
TEMPLATE_PERSONALITY_PRESET_INVALID: Final[str] = "template.personality_preset.invalid"
TEMPLATE_PERSONALITY_PRESET_UNKNOWN: Final[str] = "template.personality_preset.unknown"
TEMPLATE_PASS1_FLOAT_FALLBACK: Final[str] = "template.pass1.float_fallback"
TEMPLATE_INHERIT_RESOLVE_START: Final[str] = "template.inherit.resolve_start"
Expand Down
25 changes: 17 additions & 8 deletions src/synthorg/templates/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from synthorg.core.agent import PersonalityConfig
from synthorg.observability import get_logger
from synthorg.observability.events.template import (
TEMPLATE_PERSONALITY_PRESET_INVALID,
TEMPLATE_PERSONALITY_PRESET_UNKNOWN,
)

Expand Down Expand Up @@ -428,14 +429,22 @@ def get_personality_preset(name: str) -> dict[str, Any]:


# Validate all presets at import time to catch key typos immediately.
for _preset_name, _preset_dict in PERSONALITY_PRESETS.items():
try:
PersonalityConfig(**_preset_dict)
except (ValidationError, TypeError) as _exc:
msg = f"Invalid personality preset {_preset_name!r}: {_exc}"
raise ValueError(msg) from _exc
if PERSONALITY_PRESETS:
del _preset_name, _preset_dict
def _validate_presets() -> None:
for name, preset in PERSONALITY_PRESETS.items():
try:
PersonalityConfig(**preset)
except (ValidationError, TypeError) as exc:
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify tuple-style multi-except usages that violate the repository rule.
# Expected: this file/line should appear until fixed.
rg -nP --type=py 'except\s*\([^)]*,[^)]*\)\s*(as\s+\w+)?\s*:' src tests

Repository: Aureliolo/synthorg

Length of output: 11555


Change to PEP 758 except syntax (no parentheses).

Line 435 uses except (ValidationError, TypeError) as exc:, which violates the enforced exception syntax rule. Must use except ValidationError, TypeError as exc: instead per PEP 758 (enforced by ruff on Python 3.14).

Proposed fix
-        except (ValidationError, TypeError) as exc:
+        except ValidationError, TypeError as exc:
📝 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
except (ValidationError, TypeError) as exc:
except ValidationError, TypeError as exc:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/synthorg/templates/presets.py` at line 435, Replace the tuple-style
exception clause "except (ValidationError, TypeError) as exc:" with the PEP
758-compliant syntax without parentheses: "except ValidationError, TypeError as
exc:"; update the except line where ValidationError and TypeError are caught
(keeping the exception variable name exc) so ruff on Python 3.14 accepts it.

logger.warning(
TEMPLATE_PERSONALITY_PRESET_INVALID,
preset_name=name,
error=str(exc),
)
msg = f"Invalid personality preset {name!r}: {exc}"
raise ValueError(msg) from exc
Comment thread
coderabbitai[bot] marked this conversation as resolved.


_validate_presets()
del _validate_presets


def generate_auto_name(role: str, *, seed: int | None = None) -> str:
Expand Down
9 changes: 9 additions & 0 deletions src/synthorg/tools/mcp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
no dependency on the tool base classes.
"""

from typing import TYPE_CHECKING

from .config import MCPConfig, MCPServerConfig
from .errors import (
MCPConnectionError,
Expand All @@ -15,6 +17,13 @@
)
from .models import MCPRawResult, MCPToolInfo

if TYPE_CHECKING:
from .bridge_tool import MCPBridgeTool
from .cache import MCPResultCache
from .client import MCPClient
from .factory import MCPToolFactory
from .result_mapper import map_call_tool_result

__all__ = [
"MCPBridgeTool",
"MCPClient",
Expand Down
9 changes: 5 additions & 4 deletions src/synthorg/tools/sandbox/docker_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typing import TYPE_CHECKING, Any, Final

import aiodocker
import aiodocker.containers

from synthorg.observability import get_logger
from synthorg.observability.events.docker import (
Expand Down Expand Up @@ -353,7 +354,7 @@ async def _run_container( # noqa: PLR0913
)

try:
container = await docker.containers.create(config)
container = await docker.containers.create(config) # pyright: ignore[reportAttributeAccessIssue]
except Exception as exc:
msg = f"Failed to create container: {exc}"
logger.exception(
Expand Down Expand Up @@ -409,7 +410,7 @@ async def _start_and_wait(
Returns:
A ``SandboxResult``.
"""
container_obj = docker.containers.container(container_id)
container_obj = docker.containers.container(container_id) # pyright: ignore[reportAttributeAccessIssue]
try:
await container_obj.start()
except Exception as exc:
Expand Down Expand Up @@ -558,7 +559,7 @@ async def _stop_container(
container_id: Container ID to stop.
"""
try:
container_obj = docker.containers.container(container_id)
container_obj = docker.containers.container(container_id) # pyright: ignore[reportAttributeAccessIssue]
await container_obj.stop(
t=_STOP_TIMEOUT_SECONDS,
)
Expand All @@ -585,7 +586,7 @@ async def _remove_container(
container_id: Container ID to remove.
"""
try:
container_obj = docker.containers.container(container_id)
container_obj = docker.containers.container(container_id) # pyright: ignore[reportAttributeAccessIssue]
await container_obj.delete(force=True)
logger.debug(
DOCKER_CONTAINER_REMOVED,
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/memory/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ def test_backend_init_validation_error_wraps(self) -> None:
class _Dummy(BaseModel):
x: int

side_effect: ValidationError | None = None
try:
_Dummy(x="not-an-int") # type: ignore[arg-type]
except ValidationError as ve:
side_effect: ValidationError = ve
side_effect = ve
assert side_effect is not None # always set — narrows type for pyright

config = CompanyMemoryConfig(backend="mem0")
with (
Expand Down
Loading