Skip to content

Commit b5ef6c8

Browse files
authored
Merge pull request agentstack-ai#103 from tcdent/pre-commit
Run mypy and ruff on pre commit, type checking fixes
2 parents efc7b7f + ff07ecd commit b5ef6c8

File tree

8 files changed

+66
-37
lines changed

8 files changed

+66
-37
lines changed

.pre-commit-config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.3.0
4+
hooks:
5+
- id: ruff
6+
args: [--fix]
7+
- id: ruff-format
8+
- repo: https://github.com/pre-commit/mirrors-mypy
9+
rev: v1.8.0
10+
hooks:
11+
- id: mypy

CONTRIBUTING.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The best place to engage in conversation about your contribution is in the Issue
1313

1414
1. Clone the repo
1515
2. `poetry install`
16-
3. `pip install -e .`
16+
3. `pip install -e .[dev,test]`
1717
- This will install the CLI locally and in editable mode so you can use `agentstack <command>` to test your latest changes
1818

1919
## Project Structure
@@ -46,5 +46,17 @@ pip install ruff
4646
ruff format .
4747
```
4848

49+
### Type Checking
50+
AgentStack uses MyPy for type checking. To check types, run:
51+
```bash
52+
mypy agentstack
53+
```
54+
55+
### Pre-Commit Hooks
56+
Ruff and MyPy can be run as pre-commit hooks. To enable these hooks, run:
57+
```bash
58+
pre-commit install
59+
```
60+
4961
## Tests
5062
HAHAHAHAHAHAHA good one

agentstack/cli/agentstack_data.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from datetime import datetime
3-
from typing import Optional, Literal, List
3+
from typing import Optional
44

55
from agentstack.utils import clean_input, get_version
66
from agentstack.logger import log
@@ -9,8 +9,8 @@
99
class ProjectMetadata:
1010
def __init__(
1111
self,
12-
project_name: str = None,
13-
project_slug: str = None,
12+
project_name: Optional[str] = None,
13+
project_slug: Optional[str] = None,
1414
description: str = "",
1515
author_name: str = "",
1616
version: str = "",
@@ -80,7 +80,7 @@ class FrameworkData:
8080
def __init__(
8181
self,
8282
# name: Optional[Literal["crewai"]] = None
83-
name: str = None, # TODO: better framework handling, Literal or Enum
83+
name: Optional[str] = None, # TODO: better framework handling, Literal or Enum
8484
):
8585
self.name = name
8686

agentstack/cli/cli.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def init_project_builder(
122122

123123
try:
124124
packaging.install(f'{AGENTSTACK_PACKAGE}[{framework}]', path=slug_name)
125-
except Exception as e:
125+
except Exception:
126126
print(
127127
term_color(
128128
f"Failed to install dependencies for {slug_name}. Please try again by running `agentstack update`",
@@ -151,7 +151,7 @@ def configure_default_model(path: Optional[str] = None):
151151
return # Default model already set
152152

153153
print("Project does not have a default model configured.")
154-
other_msg = f"Other (enter a model name)"
154+
other_msg = "Other (enter a model name)"
155155
model = inquirer.list_input(
156156
message="Which model would you like to use?",
157157
choices=PREFERRED_MODELS + [other_msg],
@@ -279,7 +279,7 @@ def ask_design() -> dict:
279279
inquirer.List(
280280
"agent",
281281
message="Which agent should be assigned this task?",
282-
choices=[a['name'] for a in agents],
282+
choices=[a['name'] for a in agents], # type: ignore
283283
),
284284
]
285285
)
@@ -374,8 +374,8 @@ def insert_template(
374374
version="0.0.1",
375375
license="MIT",
376376
year=datetime.now().year,
377-
template=template_data['name'] if template_data else None,
378-
template_version=template_data['template_version'] if template_data else None,
377+
template=template_data['name'] if template_data else 'none',
378+
template_version=template_data['template_version'] if template_data else '0',
379379
)
380380

381381
project_structure = ProjectStructure()

agentstack/generation/files.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class ConfigFile(BaseModel):
3636
The default model to use when generating agent configurations.
3737
"""
3838

39-
framework: Optional[str] = DEFAULT_FRAMEWORK
39+
framework: str = DEFAULT_FRAMEWORK
4040
tools: list[str] = []
4141
telemetry_opt_out: Optional[bool] = None
4242
default_model: Optional[str] = None

agentstack/generation/tool_generation.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
import os, sys
2-
from typing import Optional, Any, List
3-
import importlib.resources
4-
from pathlib import Path
5-
import json
1+
import os
62
import sys
7-
from typing import Optional, List, Dict, Union
3+
from typing import Optional, List
4+
from pathlib import Path
5+
from typing import Union
86

97
from . import get_agent_names
10-
from .gen_utils import insert_code_after_tag, string_in_file, _framework_filename
8+
from .gen_utils import insert_code_after_tag, _framework_filename
119
from ..utils import open_json_file, get_framework, term_color
12-
import os
1310
import shutil
1411
import fileinput
1512
import astor
@@ -19,8 +16,6 @@
1916
from agentstack import packaging
2017
from agentstack.utils import get_package_path
2118
from agentstack.generation.files import ConfigFile, EnvFile
22-
from .gen_utils import insert_code_after_tag, string_in_file
23-
from ..utils import open_json_file, get_framework, term_color
2419

2520

2621
TOOL_INIT_FILENAME = "src/tools/__init__.py"
@@ -69,7 +64,7 @@ def from_json(cls, path: Path) -> 'ToolConfig':
6964
except ValidationError as e:
7065
print(term_color(f"Error validating tool config JSON: \n{path}", 'red'))
7166
for error in e.errors():
72-
print(f"{' '.join(error['loc'])}: {error['msg']}")
67+
print(f"{' '.join([str(loc) for loc in error['loc']])}: {error['msg']}")
7368
sys.exit(1)
7469

7570
def get_import_statement(self) -> str:
@@ -148,7 +143,7 @@ def remove_tool(tool_name: str, path: Optional[str] = None):
148143
framework = get_framework()
149144
agentstack_config = ConfigFile(path)
150145

151-
if not tool_name in agentstack_config.tools:
146+
if tool_name not in agentstack_config.tools:
152147
print(term_color(f'Tool {tool_name} is not installed', 'red'))
153148
sys.exit(1)
154149

@@ -195,7 +190,10 @@ def remove_tool_from_tools_init(tool_data: ToolConfig, path: str = ''):
195190

196191

197192
def add_tool_to_agent_definition(
198-
framework: str, tool_data: ToolConfig, path: str = '', agents: list[str] = []
193+
framework: str,
194+
tool_data: ToolConfig,
195+
path: str = '',
196+
agents: Optional[list[str]] = [],
199197
):
200198
"""
201199
Add tools to specific agent definitions using AST transformation.
@@ -285,7 +283,7 @@ def _process_tools_list(
285283
tool_data: ToolConfig,
286284
operation: str,
287285
base_name: str = 'tools',
288-
) -> List[ast.AST]:
286+
) -> List[ast.AST]: # type: ignore[return-type,arg-type]
289287
"""
290288
Process a tools list according to the specified operation.
291289
@@ -347,10 +345,9 @@ def _modify_agent_tools(
347345
if kw.arg == 'tools':
348346
if isinstance(kw.value, ast.List):
349347
# Process the tools list
350-
new_tools = _process_tools_list(kw.value.elts, tool_data, operation, base_name)
351-
348+
new_tools = _process_tools_list(kw.value.elts, tool_data, operation, base_name) # type: ignore
352349
# Replace with new list
353-
kw.value = ast.List(elts=new_tools, ctx=ast.Load())
350+
kw.value = ast.List(elts=new_tools, ctx=ast.Load()) # type: ignore
354351

355352
return node
356353

agentstack/utils.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
from typing import Optional
2-
3-
import os
42
import sys
53
import json
64
import re
@@ -35,7 +33,7 @@ def get_package_path() -> Path:
3533
"""This is the Path where agentstack is installed."""
3634
if sys.version_info <= (3, 9):
3735
return Path(sys.modules['agentstack'].__path__[0])
38-
return importlib.resources.files('agentstack')
36+
return importlib.resources.files('agentstack') # type: ignore[return-value]
3937

4038

4139
def get_framework(path: Optional[str] = None) -> str:
@@ -54,7 +52,7 @@ def get_framework(path: Optional[str] = None) -> str:
5452
sys.exit(1)
5553

5654

57-
def get_telemetry_opt_out(path: Optional[str] = None) -> str:
55+
def get_telemetry_opt_out(path: Optional[str] = None) -> bool:
5856
from agentstack.generation import ConfigFile
5957

6058
try:

pyproject.toml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,19 @@ dependencies = [
2424
"psutil==5.9.8",
2525
"astor==0.8.1",
2626
"pydantic>=2.10",
27-
"packaging>=23.2",
27+
"packaging==23.2",
2828
"requests>=2.32",
29-
"appdirs>=1.4.4"
29+
"appdirs>=1.4.4",
3030
]
3131

3232
[project.optional-dependencies]
3333
dev = [
34-
"ruff",
34+
"mypy>=1.13.0",
35+
"pre-commit>=4.0.1",
36+
"ruff>=0.8.2",
3537
]
3638
test = [
37-
"tox>=4.23.2",
39+
"tox",
3840
]
3941
crewai = [
4042
"crewai==0.83.0",
@@ -67,4 +69,13 @@ exclude = [
6769
line-length = 110
6870

6971
[tool.ruff.format]
70-
quote-style = "preserve"
72+
quote-style = "preserve"
73+
74+
[tool.mypy]
75+
exclude = [
76+
"templates/.*" # cookiecutter paths are not compatible
77+
]
78+
allow_untyped_defs = true
79+
disable_error_code = ["var-annotated", "import-untyped"]
80+
ignore_missing_imports = true
81+

0 commit comments

Comments
 (0)