Skip to content

Commit 28a51bd

Browse files
committed
fixed most linting errors
1 parent 709c0d1 commit 28a51bd

18 files changed

+294
-159
lines changed

evals/act/google_jobs.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import asyncio
22
import traceback
3-
from typing import Any, Dict, Optional
3+
from typing import Any, Optional, dict
44

55
from pydantic import BaseModel
66

@@ -10,23 +10,24 @@
1010

1111
class Qualifications(BaseModel):
1212
degree: Optional[str] = None
13-
yearsOfExperience: Optional[float] = None # Representing the number
13+
years_of_experience: Optional[float] = None # Representing the number
1414

1515

1616
class JobDetails(BaseModel):
17-
applicationDeadline: Optional[str] = None
18-
minimumQualifications: Qualifications
19-
preferredQualifications: Qualifications
17+
application_deadline: Optional[str] = None
18+
minimum_qualifications: Qualifications
19+
preferred_qualifications: Qualifications
2020

2121

22-
def is_job_details_valid(details: Dict[str, Any]) -> bool:
22+
def is_job_details_valid(details: dict[str, Any]) -> bool:
2323
"""
2424
Validates that each top-level field in the extracted job details is not None.
25-
For nested dictionary values, each sub-value must be non-null and a string or a number.
25+
For nested dictionary values, each sub-value must be non-null and a string
26+
or a number.
2627
"""
2728
if not details:
2829
return False
29-
for key, value in details.items():
30+
for _key, value in details.items():
3031
if value is None:
3132
return False
3233
if isinstance(value, dict):
@@ -53,9 +54,9 @@ async def google_jobs(model_name: str, logger, use_text_extract: bool) -> dict:
5354
4. Extracting job posting details using an AI-driven extraction schema.
5455
5556
The extraction schema requires:
56-
- applicationDeadline: The opening date until which applications are accepted.
57-
- minimumQualifications: An object with degree and yearsOfExperience.
58-
- preferredQualifications: An object with degree and yearsOfExperience.
57+
- application_deadline: The opening date until which applications are accepted.
58+
- minimum_qualifications: An object with degree and years_of_experience.
59+
- preferred_qualifications: An object with degree and years_of_experience.
5960
6061
Returns a dictionary containing:
6162
- _success (bool): Whether valid job details were extracted.
@@ -90,8 +91,9 @@ async def google_jobs(model_name: str, logger, use_text_extract: bool) -> dict:
9091
job_details = await stagehand.page.extract(
9192
ExtractOptions(
9293
instruction=(
93-
"Extract the following details from the job posting: application deadline, "
94-
"minimum qualifications (degree and years of experience), and preferred qualifications "
94+
"Extract the following details from the job posting: "
95+
"application deadline, minimum qualifications "
96+
"(degree and years of experience), and preferred qualifications "
9597
"(degree and years of experience)"
9698
),
9799
schemaDefinition=JobDetails.model_json_schema(),

evals/extract/extract_press_releases.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class PressReleases(BaseModel):
1919

2020
async def extract_press_releases(model_name: str, logger, use_text_extract: bool):
2121
"""
22-
Extract press releases from the dummy press releases page using the Stagehand client.
22+
Extract press releases from the dummy press releases page using the Stagehand
23+
client.
2324
2425
Args:
2526
model_name (str): Name of the AI model to use.
@@ -56,7 +57,10 @@ async def extract_press_releases(model_name: str, logger, use_text_extract: bool
5657
# TODO - FAILING - extract is likely timing out
5758
raw_result = await stagehand.page.extract(
5859
ExtractOptions(
59-
instruction="extract the title and corresponding publish date of EACH AND EVERY press releases on this page. DO NOT MISS ANY PRESS RELEASES.",
60+
instruction=(
61+
"extract the title and corresponding publish date of EACH AND EVERY "
62+
"press releases on this page. DO NOT MISS ANY PRESS RELEASES."
63+
),
6064
schemaDefinition=PressReleases.model_json_schema(),
6165
useTextExtract=use_text_extract,
6266
)

evals/init_stagehand.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
async def init_stagehand(model_name: str, logger, dom_settle_timeout_ms: int = 3000):
88
"""
9-
Initialize a Stagehand client with the given model name, logger, and DOM settle timeout.
9+
Initialize a Stagehand client with the given model name, logger, and DOM settle
10+
timeout.
1011
11-
This function creates a configuration from environment variables, initializes the Stagehand client,
12-
and returns a tuple of (stagehand, init_response). The init_response contains debug and session URLs.
12+
This function creates a configuration from environment variables, initializes
13+
the Stagehand client, and returns a tuple of (stagehand, init_response).
14+
The init_response contains debug and session URLs.
1315
1416
Args:
1517
model_name (str): The name of the AI model to use.
@@ -37,7 +39,8 @@ async def init_stagehand(model_name: str, logger, dom_settle_timeout_ms: int = 3
3739
model_client_options={"apiKey": os.getenv("MODEL_API_KEY")},
3840
)
3941

40-
# Create a Stagehand client with the configuration; server_url is taken from environment variables.
42+
# Create a Stagehand client with the configuration; server_url is taken from
43+
# environment variables.
4144
stagehand = Stagehand(
4245
config=config, server_url=os.getenv("STAGEHAND_SERVER_URL"), verbose=2
4346
)

examples/example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ async def main():
8787
if len(observed) > 0:
8888
element = observed[0]
8989
console.print("✅ [success]Found element:[/] News button")
90-
console.print(f"\n▶️ [highlight] Performing action on observed element")
90+
console.print("\n▶️ [highlight] Performing action on observed element")
9191
await page.act(element)
9292
console.print("✅ [success]Performing Action:[/] Action completed successfully")
9393

examples/example_sync.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from rich.panel import Panel
77
from rich.theme import Theme
88

9-
from stagehand.sync import Stagehand
109
from stagehand.config import StagehandConfig
10+
from stagehand.sync import Stagehand
1111

1212
# Create a custom theme for consistent styling
1313
custom_theme = Theme(
@@ -60,6 +60,7 @@ def main():
6060
)
6161

6262
import time
63+
6364
time.sleep(2)
6465

6566
console.print("\n▶️ [highlight] Navigating[/] to Google")
@@ -112,4 +113,4 @@ def main():
112113
padding=(1, 10),
113114
),
114115
)
115-
main()
116+
main()

format.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
# Define source directories (adjust as needed)
4+
SOURCE_DIRS="evals stagehand"
5+
6+
# Apply Black formatting only to source directories
7+
echo "Applying Black formatting..."
8+
black $SOURCE_DIRS
9+
10+
# Fix import sorting (addresses I001 errors)
11+
echo "Sorting imports..."
12+
isort $SOURCE_DIRS
13+
14+
# Apply Ruff with autofix for remaining issues
15+
echo "Applying Ruff autofixes..."
16+
ruff check --fix $SOURCE_DIRS
17+
18+
echo "Checking for remaining issues..."
19+
ruff check $SOURCE_DIRS
20+
21+
echo "Done! Code has been formatted and linted."

pyproject.toml

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
[tool.ruff]
22
# Enable flake8-comprehensions, flake8-bugbear, naming, etc.
33
select = ["E", "F", "B", "C4", "UP", "N", "I", "C"]
4-
ignore = []
4+
# Ignore line length errors - let Black handle those
5+
ignore = ["E501"]
56

67
# Same as Black
78
line-length = 88
@@ -46,4 +47,40 @@ classmethod-decorators = ["classmethod", "validator"]
4647

4748
# Add more customizations if needed
4849
[tool.ruff.lint.pydocstyle]
49-
convention = "google"
50+
convention = "google"
51+
52+
# Black configuration
53+
[tool.black]
54+
line-length = 88
55+
target-version = ["py39"]
56+
include = '\.pyi?$'
57+
exclude = '''
58+
/(
59+
\.git
60+
| \.hg
61+
| \.mypy_cache
62+
| \.tox
63+
| \.venv
64+
| _build
65+
| buck-out
66+
| build
67+
| dist
68+
| __pycache__
69+
| python-sdk
70+
)/
71+
'''
72+
# Ensure Black will wrap long strings and docstrings
73+
skip-string-normalization = false
74+
preview = true
75+
76+
# isort configuration to work with Black
77+
[tool.isort]
78+
profile = "black"
79+
line_length = 88
80+
multi_line_output = 3
81+
include_trailing_comma = true
82+
force_grid_wrap = 0
83+
use_parentheses = true
84+
ensure_newline_before_comments = true
85+
skip_gitignore = true
86+
skip_glob = ["**/venv/**", "**/.venv/**", "**/__pycache__/**"]

requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ pytest-mock>=3.10.0
44
pytest-cov>=4.1.0
55
black>=23.3.0
66
isort>=5.12.0
7-
mypy>=1.3.0
7+
mypy>=1.3.0
8+
ruff

stagehand/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from .config import StagehandConfig
33
from .page import StagehandPage
44

5-
65
__version__ = "0.2.2"
76

87
__all__ = ["Stagehand", "StagehandConfig", "StagehandPage"]
9-

stagehand/base.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
import logging
2+
import os
3+
import time
14
from abc import ABC, abstractmethod
2-
from typing import Any, Callable, Dict, Optional, Union
3-
from playwright.async_api import Page
5+
from typing import Any, Callable, Optional
46

57
from .config import StagehandConfig
68
from .page import StagehandPage
79
from .utils import default_log_handler
8-
import os
9-
import time
10-
import logging
1110

1211
logger = logging.getLogger(__name__)
1312

@@ -17,6 +16,7 @@ class StagehandBase(ABC):
1716
Base class for Stagehand client implementations.
1817
Defines the common interface and functionality for both sync and async versions.
1918
"""
19+
2020
def __init__(
2121
self,
2222
config: Optional[StagehandConfig] = None,
@@ -25,30 +25,46 @@ def __init__(
2525
browserbase_api_key: Optional[str] = None,
2626
browserbase_project_id: Optional[str] = None,
2727
model_api_key: Optional[str] = None,
28-
on_log: Optional[Callable[[Dict[str, Any]], Any]] = default_log_handler,
28+
on_log: Optional[Callable[[dict[str, Any]], Any]] = default_log_handler,
2929
verbose: int = 1,
3030
model_name: Optional[str] = None,
3131
dom_settle_timeout_ms: Optional[int] = None,
3232
debug_dom: Optional[bool] = None,
3333
timeout_settings: Optional[float] = None,
3434
stream_response: Optional[bool] = None,
35-
model_client_options: Optional[Dict[str, Any]] = None,
35+
model_client_options: Optional[dict[str, Any]] = None,
3636
):
3737
"""
3838
Initialize the Stagehand client with common configuration.
3939
"""
4040
self.server_url = server_url or os.getenv("STAGEHAND_SERVER_URL")
4141

4242
if config:
43-
self.browserbase_api_key = config.api_key or browserbase_api_key or os.getenv("BROWSERBASE_API_KEY")
44-
self.browserbase_project_id = config.project_id or browserbase_project_id or os.getenv("BROWSERBASE_PROJECT_ID")
43+
self.browserbase_api_key = (
44+
config.api_key
45+
or browserbase_api_key
46+
or os.getenv("BROWSERBASE_API_KEY")
47+
)
48+
self.browserbase_project_id = (
49+
config.project_id
50+
or browserbase_project_id
51+
or os.getenv("BROWSERBASE_PROJECT_ID")
52+
)
4553
self.session_id = config.browserbase_session_id or session_id
4654
self.model_name = config.model_name or model_name
47-
self.dom_settle_timeout_ms = config.dom_settle_timeout_ms or dom_settle_timeout_ms
48-
self.debug_dom = config.debug_dom if config.debug_dom is not None else debug_dom
55+
self.dom_settle_timeout_ms = (
56+
config.dom_settle_timeout_ms or dom_settle_timeout_ms
57+
)
58+
self.debug_dom = (
59+
config.debug_dom if config.debug_dom is not None else debug_dom
60+
)
4961
else:
50-
self.browserbase_api_key = browserbase_api_key or os.getenv("BROWSERBASE_API_KEY")
51-
self.browserbase_project_id = browserbase_project_id or os.getenv("BROWSERBASE_PROJECT_ID")
62+
self.browserbase_api_key = browserbase_api_key or os.getenv(
63+
"BROWSERBASE_API_KEY"
64+
)
65+
self.browserbase_project_id = browserbase_project_id or os.getenv(
66+
"BROWSERBASE_PROJECT_ID"
67+
)
5268
self.session_id = session_id
5369
self.model_name = model_name
5470
self.dom_settle_timeout_ms = dom_settle_timeout_ms
@@ -61,7 +77,9 @@ def __init__(
6177
self.model_client_options["apiKey"] = self.model_api_key
6278

6379
# Handle streaming response setting directly
64-
self.streamed_response = stream_response if stream_response is not None else True
80+
self.streamed_response = (
81+
stream_response if stream_response is not None else True
82+
)
6583

6684
self.on_log = on_log
6785
self.verbose = verbose
@@ -74,9 +92,13 @@ def __init__(
7492
# Validate essential fields if session_id was provided
7593
if self.session_id:
7694
if not self.browserbase_api_key:
77-
raise ValueError("browserbase_api_key is required (or set BROWSERBASE_API_KEY in env).")
95+
raise ValueError(
96+
"browserbase_api_key is required (or set BROWSERBASE_API_KEY in env)."
97+
)
7898
if not self.browserbase_project_id:
79-
raise ValueError("browserbase_project_id is required (or set BROWSERBASE_PROJECT_ID in env).")
99+
raise ValueError(
100+
"browserbase_project_id is required (or set BROWSERBASE_PROJECT_ID in env)."
101+
)
80102

81103
@abstractmethod
82104
def init(self):
@@ -106,4 +128,4 @@ def _log(self, message: str, level: int = 1):
106128
elif level == 2:
107129
logger.warning(formatted_msg)
108130
else:
109-
logger.debug(formatted_msg)
131+
logger.debug(formatted_msg)

0 commit comments

Comments
 (0)