mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-04 03:45:12 -05:00
- **FIX ALL LINT/TYPE ERRORS IN AUTOGPT, FORGE, AND BENCHMARK** ### Linting - Clean up linter configs for `autogpt`, `forge`, and `benchmark` - Add type checking with Pyright - Create unified pre-commit config - Create unified linting and type checking CI workflow ### Testing - Synchronize CI test setups for `autogpt`, `forge`, and `benchmark` - Add missing pytest-cov to benchmark dependencies - Mark GCS tests as slow to speed up pre-commit test runs - Repair `forge` test suite - Add `AgentDB.close()` method for test DB teardown in db_test.py - Use actual temporary dir instead of forge/test_workspace/ - Move left-behind dependencies for moved `forge`-code to from autogpt to forge ### Notable type changes - Replace uses of `ChatModelProvider` by `MultiProvider` - Removed unnecessary exports from various __init__.py - Simplify `FileStorage.open_file` signature by removing `IOBase` from return type union - Implement `S3BinaryIOWrapper(BinaryIO)` type interposer for `S3FileStorage` - Expand overloads of `GCSFileStorage.open_file` for improved typing of read and write modes Had to silence type checking for the extra overloads, because (I think) Pyright is reporting a false-positive: https://github.com/microsoft/pyright/issues/8007 - Change `count_tokens`, `get_tokenizer`, `count_message_tokens` methods on `ModelProvider`s from class methods to instance methods - Move `CompletionModelFunction.schema` method -> helper function `format_function_def_for_openai` in `forge.llm.providers.openai` - Rename `ModelProvider` -> `BaseModelProvider` - Rename `ChatModelProvider` -> `BaseChatModelProvider` - Add type `ChatModelProvider` which is a union of all subclasses of `BaseChatModelProvider` ### Removed rather than fixed - Remove deprecated and broken autogpt/agbenchmark_config/benchmarks.py - Various base classes and properties on base classes in `forge.llm.providers.schema` and `forge.models.providers` ### Fixes for other issues that came to light - Clean up `forge.agent_protocol.api_router`, `forge.agent_protocol.database`, and `forge.agent.agent` - Add fallback behavior to `ImageGeneratorComponent` - Remove test for deprecated failure behavior - Fix `agbenchmark.challenges.builtin` challenge exclusion mechanism on Windows - Fix `_tool_calls_compat_extract_calls` in `forge.llm.providers.openai` - Add support for `any` (= no type specified) in `JSONSchema.typescript_type`
87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
""" Utility functions to process the identifiers of tests. """
|
|
import re
|
|
from typing import Iterator
|
|
|
|
from _pytest.mark.structures import Mark
|
|
from _pytest.nodes import Item
|
|
|
|
from .constants import MARKER_KWARG_ID, MARKER_NAME
|
|
|
|
REGEX_PARAMETERS = re.compile(r"\[.+\]$")
|
|
|
|
|
|
def clean_nodeid(nodeid: str) -> str:
|
|
"""
|
|
Remove any superfluous ::() from a node id.
|
|
|
|
>>> clean_nodeid('test_file.py::TestClass::()::test')
|
|
'test_file.py::TestClass::test'
|
|
>>> clean_nodeid('test_file.py::TestClass::test')
|
|
'test_file.py::TestClass::test'
|
|
>>> clean_nodeid('test_file.py::test')
|
|
'test_file.py::test'
|
|
"""
|
|
return nodeid.replace("::()::", "::")
|
|
|
|
|
|
def strip_nodeid_parameters(nodeid: str) -> str:
|
|
"""
|
|
Strip parameters from a node id.
|
|
|
|
>>> strip_nodeid_parameters('test_file.py::TestClass::test[foo]')
|
|
'test_file.py::TestClass::test'
|
|
>>> strip_nodeid_parameters('test_file.py::TestClass::test')
|
|
'test_file.py::TestClass::test'
|
|
"""
|
|
return REGEX_PARAMETERS.sub("", nodeid)
|
|
|
|
|
|
def get_absolute_nodeid(nodeid: str, scope: str) -> str:
|
|
"""
|
|
Transform a possibly relative node id to an absolute one
|
|
using the scope in which it is used.
|
|
|
|
>>> scope = 'test_file.py::TestClass::test'
|
|
>>> get_absolute_nodeid('test2', scope)
|
|
'test_file.py::TestClass::test2'
|
|
>>> get_absolute_nodeid('TestClass2::test2', scope)
|
|
'test_file.py::TestClass2::test2'
|
|
>>> get_absolute_nodeid('test_file2.py::TestClass2::test2', scope)
|
|
'test_file2.py::TestClass2::test2'
|
|
"""
|
|
parts = nodeid.split("::")
|
|
# Completely relative (test_name): add the full current scope (file::class or file)
|
|
if len(parts) == 1:
|
|
base_nodeid = scope.rsplit("::", 1)[0]
|
|
nodeid = f"{base_nodeid}::{nodeid}"
|
|
# Contains some scope already (Class::test_name), so only add the current file scope
|
|
elif "." not in parts[0]:
|
|
base_nodeid = scope.split("::", 1)[0]
|
|
nodeid = f"{base_nodeid}::{nodeid}"
|
|
return clean_nodeid(nodeid)
|
|
|
|
|
|
def get_name(item: Item) -> str:
|
|
"""
|
|
Get all names for a test.
|
|
|
|
This will use the following methods to determine the name of the test:
|
|
- If given, the custom name(s) passed to the keyword argument name on the marker
|
|
"""
|
|
name = ""
|
|
|
|
# Custom name
|
|
markers = get_markers(item, MARKER_NAME)
|
|
for marker in markers:
|
|
if MARKER_KWARG_ID in marker.kwargs:
|
|
name = marker.kwargs[MARKER_KWARG_ID]
|
|
|
|
return name
|
|
|
|
|
|
def get_markers(item: Item, name: str) -> Iterator[Mark]:
|
|
"""Get all markers with the given name for a given item."""
|
|
for marker in item.iter_markers():
|
|
if marker.name == name:
|
|
yield marker
|