diff --git a/pyproject.toml b/pyproject.toml
index fb1e80b5..087af552 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -143,6 +143,9 @@ exclude = [
line-length = 120
target-version = "py311"
+[tool.ruff.lint]
+extend-select = ["PLC0415"]
+
[tool.isort]
profile = "black"
multi_line_output = 3
diff --git a/skyvern/cli/run_commands.py b/skyvern/cli/run_commands.py
index d4f51273..ffbc9538 100644
--- a/skyvern/cli/run_commands.py
+++ b/skyvern/cli/run_commands.py
@@ -85,7 +85,7 @@ def run_server() -> None:
"""Run the Skyvern API server."""
load_dotenv()
load_dotenv(".env")
- from skyvern.config import settings
+ from skyvern.config import settings # noqa: PLC0415
port = settings.PORT
console.print(Panel(f"[bold green]Starting Skyvern API Server on port {port}...", border_style="green"))
diff --git a/skyvern/forge/sdk/routes/streaming_verify.py b/skyvern/forge/sdk/routes/streaming_verify.py
index 21ed6296..4a74b5f7 100644
--- a/skyvern/forge/sdk/routes/streaming_verify.py
+++ b/skyvern/forge/sdk/routes/streaming_verify.py
@@ -1,4 +1,5 @@
import asyncio
+from datetime import datetime
import structlog
@@ -77,8 +78,6 @@ async def verify_workflow_run(
"""
if settings.ENV == "local":
- from datetime import datetime
-
dummy_workflow_run = WorkflowRun(
workflow_id="123",
workflow_permanent_id="wpid_123",
diff --git a/skyvern/forge/sdk/workflow/models/block.py b/skyvern/forge/sdk/workflow/models/block.py
index 5de0c4d3..4af2bf1b 100644
--- a/skyvern/forge/sdk/workflow/models/block.py
+++ b/skyvern/forge/sdk/workflow/models/block.py
@@ -49,6 +49,7 @@ from skyvern.forge.sdk.api.files import (
from skyvern.forge.sdk.api.llm.api_handler_factory import LLMAPIHandlerFactory
from skyvern.forge.sdk.artifact.models import ArtifactType
from skyvern.forge.sdk.core import skyvern_context
+from skyvern.forge.sdk.core.aiohttp_helper import aiohttp_request
from skyvern.forge.sdk.db.enums import TaskType
from skyvern.forge.sdk.schemas.files import FileInfo
from skyvern.forge.sdk.schemas.task_v2 import TaskV2Status
@@ -2474,8 +2475,8 @@ class TaskV2Block(Block):
browser_session_id: str | None = None,
**kwargs: dict,
) -> BlockResult:
- from skyvern.forge.sdk.workflow.models.workflow import WorkflowRunStatus
- from skyvern.services import task_v2_service
+ from skyvern.forge.sdk.workflow.models.workflow import WorkflowRunStatus # noqa: PLC0415
+ from skyvern.services import task_v2_service # noqa: PLC0415
workflow_run_context = self.get_workflow_run_context(workflow_run_id)
try:
@@ -2657,7 +2658,6 @@ class HttpRequestBlock(Block):
**kwargs: dict,
) -> BlockResult:
"""Execute the HTTP request and return the response"""
- from skyvern.forge.sdk.core.aiohttp_helper import aiohttp_request
workflow_run_context = self.get_workflow_run_context(workflow_run_id)
diff --git a/skyvern/services/task_v2_service.py b/skyvern/services/task_v2_service.py
index 18646dfe..b450754e 100644
--- a/skyvern/services/task_v2_service.py
+++ b/skyvern/services/task_v2_service.py
@@ -1614,7 +1614,7 @@ async def _summarize_task_v2(
async def build_task_v2_run_response(task_v2: TaskV2) -> TaskRunResponse:
"""Build TaskRunResponse object for webhook backward compatibility."""
- from skyvern.services import workflow_service
+ from skyvern.services import workflow_service # noqa: PLC0415
workflow_run_resp = None
if task_v2.workflow_run_id:
diff --git a/skyvern/webeye/actions/parse_actions.py b/skyvern/webeye/actions/parse_actions.py
index b4f5a298..af98c71f 100644
--- a/skyvern/webeye/actions/parse_actions.py
+++ b/skyvern/webeye/actions/parse_actions.py
@@ -1,4 +1,6 @@
-from typing import Any, Dict
+import ast
+import re
+from typing import Any, Dict, Match
import structlog
from openai.types.responses.response import Response as OpenAIResponse
@@ -862,8 +864,6 @@ def _parse_ui_tars_response(response_content: str, browser_window_dimension: Res
Extracts essential parsing logic from action_parser.py without the complex coordinate transformations.
"""
- import re
-
text = response_content.strip()
# Convert point format to coordinates if needed
@@ -947,7 +947,6 @@ def _parse_ui_tars_response(response_content: str, browser_window_dimension: Res
def _parse_single_action(action_str: str) -> dict[str, Any] | None:
"""Parse a single action string into structured data."""
- import ast
try:
# Clean up the action string
@@ -990,9 +989,6 @@ def _parse_single_action(action_str: str) -> dict[str, Any] | None:
def _convert_point_to_coordinates(text: str) -> str:
"""Convert x y format to (x,y) format."""
- import re
- from typing import Match
-
pattern = r"(\d+)\s+(\d+)"
def replace_match(match: Match[str]) -> str:
@@ -1154,8 +1150,6 @@ def _extract_ui_tars_coordinates(box_str: str, browser_window_dimension: Resolut
format to relative coordinates (0-1 range), then multiplied by screen dimensions
to get absolute pixel coordinates.
"""
- import ast
-
if not box_str:
return None, None
diff --git a/tests/unit_tests/test_openrouter_integration.py b/tests/unit_tests/test_openrouter_integration.py
index 5b28731e..97faa89a 100644
--- a/tests/unit_tests/test_openrouter_integration.py
+++ b/tests/unit_tests/test_openrouter_integration.py
@@ -1,4 +1,5 @@
import importlib
+import json
import types
from unittest.mock import AsyncMock
@@ -16,8 +17,6 @@ class DummyResponse(dict):
self.choices = [types.SimpleNamespace(message=types.SimpleNamespace(content=content))]
def model_dump_json(self, indent: int = 2):
- import json
-
return json.dumps(self, indent=indent)