Enable ty rule 'unresolved-attribute' for test/

This commit is contained in:
Dominik Jain authored and Dominik Jain committed 2026-09-18 13:08:36 +02:00
1 parent 2a6deef838
commit 3ad4044c69
24 files changed
+67 -38

No files matched your search

-1
View File
@@ -152,7 +152,6 @@ no-matching-overload = "ignore"
not-subscriptable = "ignore"
parameter-already-assigned = "ignore"
too-many-positional-arguments = "ignore"
unresolved-attribute = "ignore"
unsupported-operator = "ignore"
[tool.poe.env]
+2 -2
View File
@@ -73,9 +73,9 @@ def test_list_dir_and_find_file(api: FsApi) -> None:
def test_search_for_pattern(api: FsApi) -> None:
matches = api.search_for_pattern("foo", relative_path="src")
assert len(matches) == 3
assert {m.source_file_path.replace("\\", "/") for m in matches.matches} == {"src/a.py", "src/b.txt"}
assert {m.source_file_path.replace("\\", "/") for m in matches.matches} == {"src/a.py", "src/b.txt"} # type: ignore
# restricting to code files excludes the text file; the rendering maps files to matched lines
code_matches = api.search_for_pattern("foo", restrict_search_to_code_files=True)
assert all(m.source_file_path.endswith("a.py") for m in code_matches.matches)
assert all(m.source_file_path.endswith("a.py") for m in code_matches.matches) # type: ignore
assert "foo(1)" in code_matches.represent()
+5 -2
View File
@@ -62,7 +62,8 @@ class FileSystemSyncTestCase:
symbol_names = [ref["name_path"].split("/")[-1] for ref in ref_symbols]
return symbol_names
else:
ls = next(iter(agent.get_active_project_or_raise().language_server_manager.iter_language_servers()))
ls_manager = agent.get_active_project_or_raise().get_language_server_manager_or_raise()
ls = next(iter(ls_manager.iter_language_servers()))
document_symbols = ls.request_document_symbols(self._TARGET_FILE).get_all_symbols_and_roots()
target = next((s for s in document_symbols[0] if s.get("name") == self._TARGET_SYMBOL), None)
assert target is not None and "selectionRange" in target, f"{self._TARGET_SYMBOL} not found in {self._TARGET_FILE}"
@@ -162,7 +163,9 @@ class SymbolPositionStaleAfterExternalEditTestCase:
with agent_for_project_context(LanguageServerId.PYTHON, str(repo_root)) as agent:
project = agent.get_active_project_or_raise()
ls = next(iter(project.language_server_manager.iter_language_servers()))
ls_manager = project.language_server_manager
assert ls_manager is not None
ls = next(iter(ls_manager.iter_language_servers()))
tool = agent.get_tool(FindSymbolTool)
# Hold the file's buffer open across the external edit, mirroring the state left
+2 -1
View File
@@ -833,7 +833,7 @@ def parse_edit_diagnostics_result(result: str) -> dict:
@contextmanager
def project_file_modification_context(serena_agent: SerenaAgent, relative_path: str) -> Iterator[None]:
"""Context manager to modify a project file and revert the changes after use."""
project = serena_agent.get_active_project()
project = serena_agent.get_active_project_or_raise()
file_path = os.path.join(project.project_root, relative_path)
# Read the original content
@@ -1455,6 +1455,7 @@ class TestPromptProvision:
# now activate another project which dynamically enables a new mode (no-onboarding)
reg_project = serena_agent.serena_config.get_registered_project(project_name2)
assert reg_project is not None
reg_project.project_config.default_modes = ["no-onboarding"]
expected_new_mode_message = "The onboarding process is not applied."
result2 = self._call_tool(serena_agent, ActivateProjectTool, project=project_name2, session_id=session1)
+3 -3
View File
@@ -251,10 +251,10 @@ class TestSymbolDictTypes:
:param key_type: the corresponding key type (Literal[...]) that the dict should have for keys
"""
dict_type_keys = dict_type.__annotations__.keys()
assert len(dict_type_keys) == len(key_type.__args__), (
f"Expected {len(key_type.__args__)} keys in {dict_type}, but got {len(dict_type_keys)}"
assert len(dict_type_keys) == len(key_type.__args__), ( # type: ignore
f"Expected {len(key_type.__args__)} keys in {dict_type}, but got {len(dict_type_keys)}" # type: ignore
)
for expected_key in key_type.__args__:
for expected_key in key_type.__args__: # type: ignore
assert expected_key in dict_type_keys, f"Expected key '{expected_key}' not found in {dict_type}"
def test_ls_symbol_dict_type(self):
+8 -8
View File
@@ -264,7 +264,7 @@ class TestALHoverInjection:
char = start.get("character", 0)
hover = language_server.request_hover(file_path, line, char)
if hover and "contents" in hover:
return hover, hover["contents"].get("value", "")
return hover, hover["contents"].get("value", "") # type: ignore
return hover, None
return None, None
@@ -286,7 +286,7 @@ class TestALHoverInjection:
char = start.get("character", 0)
hover = language_server.request_hover(file_path, line, char)
if hover and "contents" in hover:
return hover, hover["contents"].get("value", "")
return hover, hover["contents"].get("value", "") # type: ignore
return hover, None
return None, None
@@ -373,7 +373,7 @@ class TestALHoverInjection:
hover = language_server.request_hover(file_path, line, char)
assert hover is not None, "Hover should return a result for field"
value = hover.get("contents", {}).get("value", "")
value = hover.get("contents", {}).get("value", "") # type: ignore
# Field hover should NOT start with ** (no injection)
assert not value.startswith("**"), f"Field hover should not have injected name. Got: {value[:200]}"
return
@@ -445,7 +445,7 @@ class TestALPathNormalization:
hover = language_server.request_hover(file_path, line, char)
assert hover is not None, "Hover should return a result"
value = hover.get("contents", {}).get("value", "")
value = hover.get("contents", {}).get("value", "") # type: ignore
assert '**Table 50000 "TEST Customer"**' in value, f"Hover should have injection. Got: {value[:200]}"
return
@@ -466,7 +466,7 @@ class TestALPathNormalization:
hover = language_server.request_hover(file_path, line, char)
assert hover is not None, "Hover should return a result"
value = hover.get("contents", {}).get("value", "")
value = hover.get("contents", {}).get("value", "") # type: ignore
assert '**Table 50000 "TEST Customer"**' in value, f"Hover should have injection. Got: {value[:200]}"
return
@@ -491,7 +491,7 @@ class TestALPathNormalization:
# Request hover with forward slash path (different format)
hover = language_server.request_hover(file_path_forward, line, char)
assert hover is not None, "Hover should return a result"
value = hover.get("contents", {}).get("value", "")
value = hover.get("contents", {}).get("value", "") # type: ignore
assert '**Table 50000 "TEST Customer"**' in value, (
f"Hover injection should work with mixed path formats. Got: {value[:200]}"
)
@@ -518,7 +518,7 @@ class TestALPathNormalization:
# Request hover with backslash path (different format)
hover = language_server.request_hover(file_path_backslash, line, char)
assert hover is not None, "Hover should return a result"
value = hover.get("contents", {}).get("value", "")
value = hover.get("contents", {}).get("value", "") # type: ignore
assert '**Table 50000 "TEST Customer"**' in value, (
f"Hover injection should work with mixed path formats. Got: {value[:200]}"
)
@@ -553,7 +553,7 @@ class TestALPathNormalization:
# Request hover with different path format
hover = language_server.request_hover(hover_path, line, char)
assert hover is not None, f"Hover should return a result for {symbol_name}"
value = hover.get("contents", {}).get("value", "")
value = hover.get("contents", {}).get("value", "") # type: ignore
assert f"**{expected_injection}**" in value, (
f"Hover for {symbol_name} should have injection with mixed paths. Got: {value[:200]}"
)
@@ -125,6 +125,7 @@ class TestAngularLanguageServerBasics:
# +1 puts the cursor inside the identifier rather than on its leading boundary.
refs = language_server.request_references(src_path, coords.line, coords.col + 1)
ref_paths = {r.get("relativePath", "") for r in refs}
ref_paths = {p for p in ref_paths if p} # filter out any empty relativePath entries
assert any(p.endswith("app.component.html") for p in ref_paths), (
f"Expected references for setName to include its template callsite in app.component.html, got: {ref_paths}"
)
@@ -21,6 +21,7 @@ import time
import pytest
from solidlsp import SolidLanguageServer
from solidlsp.language_servers.angular_language_server import AngularLanguageServer
from solidlsp.ls_config import LanguageServerId
from solidlsp.ls_exceptions import SolidLSPException
from test.conftest import _create_ls
@@ -344,6 +345,7 @@ class TestAngularStartupCleanup:
with pytest.raises(RuntimeError, match="simulated ngserver init"):
ls.start()
assert isinstance(ls, AngularLanguageServer)
assert ls._ts_server is None, "TS companion was not cleared after startup failure"
assert ls._html_server is None, "HTML companion was not cleared after startup failure"
@@ -54,7 +54,7 @@ class TestClojureProjectIndexing:
# extra.clj contains two real call sites (in double-product and triple-product);
# they must be returned regardless of whether the file was opened beforehand
extra_refs = [r for r in refs if r.get("relativePath", "").endswith("extra.clj")]
extra_refs = [r for r in refs if r.get("relativePath", "").endswith("extra.clj")] # type: ignore
assert extra_refs, (
"Expected references to 'multiply' to include call sites from extra.clj, "
f"but got files: {sorted(ref_paths)}. "
@@ -82,7 +82,9 @@ class TestClojureProjectIndexing:
ref_paths = {r.get("relativePath", "") for r in refs}
consumer_refs = [
r for r in refs if r.get("relativePath", "").replace("\\", "/").endswith("sub_module/src/sub_module_app/consumer.clj")
r
for r in refs
if r.get("relativePath", "").replace("\\", "/").endswith("sub_module/src/sub_module_app/consumer.clj") # type: ignore
]
assert consumer_refs, (
"Expected references to 'multiply' to include call sites from the sibling module "
+3 -1
View File
@@ -14,6 +14,7 @@ import os
import pytest
from solidlsp import SolidLanguageServer
from solidlsp.language_servers.crystal_language_server import CrystalLanguageServer
from solidlsp.ls_config import LanguageServerId
from test.conftest import language_server_tests_enabled
from test.solidlsp.conftest import format_symbol_for_assert, has_malformed_name, request_all_symbols
@@ -94,7 +95,8 @@ class TestCrystalDefinition:
file_path = os.path.join("src", "main.cr")
# wait for Crystalline to compile the project
language_server.language_server._wait_for_compilation()
assert isinstance(language_server, CrystalLanguageServer)
language_server._wait_for_compilation()
# Calculator.new on line 35 (0-indexed: 34), col 13 -> Calculator class on line 3 (0-indexed: 2)
definitions = language_server.request_definition(file_path, 34, 13)
+1
View File
@@ -249,6 +249,7 @@ class TestDartLanguageServer:
# Find coordinates of 'final result = a + b;' - test position on 'result'
with language_server.open_file(file_path, open_in_ls=False) as f:
pos = find_text_coordinates(f.contents, r"final (result) = a \+ b;")
assert pos is not None
defining_symbol = language_server.request_defining_symbol(file_path, pos.line, pos.col)
@@ -4,6 +4,7 @@ from pathlib import Path
import pytest
from solidlsp import SolidLanguageServer
from solidlsp.language_servers.erlang_language_server import ErlangLanguageServer
from solidlsp.ls_config import LanguageServerId
from test.conftest import language_server_tests_enabled, start_ls_context
@@ -146,6 +147,8 @@ def test_symbol_tree_excludes_build_dirs(language_server: SolidLanguageServer):
@pytest.mark.parametrize("language_server", [LanguageServerId.ERLANG], indirect=True)
def test_ignore_compiled_files(language_server: SolidLanguageServer):
"""Test that compiled Erlang files are ignored."""
assert isinstance(language_server, ErlangLanguageServer)
# Test that beam files are ignored
assert language_server.is_ignored_filename("module.beam"), "BEAM files should be ignored"
assert language_server.is_ignored_filename("app.beam"), "BEAM files should be ignored"
@@ -164,6 +167,7 @@ def test_rebar_directories_ignored(language_server: SolidLanguageServer):
assert language_server.is_ignored_dirname(".rebar3"), "rebar3 cache should be ignored"
# Test that rebar.lock and rebar.config are not ignored (they are configuration files)
assert isinstance(language_server, ErlangLanguageServer)
assert not language_server.is_ignored_filename("rebar.config"), "rebar.config should not be ignored"
assert not language_server.is_ignored_filename("rebar.lock"), "rebar.lock should not be ignored"
+1 -1
View File
@@ -25,7 +25,7 @@ class TestFatouLanguageServer:
def test_cross_file_references(self, language_server: SolidLanguageServer) -> None:
references = language_server.request_references("src/fatou_a.jl", line=0, column=2)
locations = {(reference["relativePath"].replace("\\", "/"), reference["range"]["start"]["line"]) for reference in references}
locations = {(reference["relativePath"].replace("\\", "/"), reference["range"]["start"]["line"]) for reference in references} # type: ignore
assert locations >= {("src/fatou_a.jl", 1), ("src/fatou_b.jl", 0)}
def test_file_matching(self) -> None:
+1 -1
View File
@@ -192,7 +192,7 @@ class TestPascalLanguageServerBasics:
contents = hover.get("contents", {})
value = contents.get("value", "") if isinstance(contents, dict) else str(contents)
else:
value = hover.contents.value if hasattr(hover.contents, "value") else str(hover.contents)
value = hover.contents.value if hasattr(hover.contents, "value") else str(hover.contents) # type: ignore
# Should contain the function signature
assert "CalculateSum" in value, f"Hover should show function name. Got: {value[:500]}"
@@ -46,6 +46,7 @@ class TestLanguageServerSymbols:
with language_server.open_file(file_path, open_in_ls=False) as f:
file_content = f.contents
coords = find_text_coordinates(file_content, r"(status): str")
assert coords is not None
ref_symbols = [ref.symbol for ref in language_server.request_referencing_symbols(file_path, coords.line, coords.col)]
assert len(ref_symbols) > 0
@@ -590,7 +590,9 @@ class TestRubyLanguageServerSymbols:
pos = find_text_coordinates(fb.contents, r"user = @service\.(create_user)")
# Verify that we can find the method definition
assert pos is not None
defining_symbol = language_server.request_defining_symbol(file_path, pos.line, pos.col)
assert defining_symbol is not None
assert "name" in defining_symbol
assert "kind" in defining_symbol
assert defining_symbol.get("name") == "create_user"
+2 -2
View File
@@ -68,7 +68,7 @@ class TestRustLanguageServer:
implementations = language_server.request_implementation(os.path.join("src", "lib.rs"), *pos)
assert implementations, "Expected at least one implementation of Greeter.format_greeting"
assert any("src/lib.rs" in implementation.get("relativePath", "").replace("\\", "/") for implementation in implementations), (
assert any("src/lib.rs" in implementation.get("relativePath", "").replace("\\", "/") for implementation in implementations), ( # type: ignore
f"Expected ConsoleGreeter.format_greeting in implementations, got: {implementations}"
)
@@ -81,7 +81,7 @@ class TestRustLanguageServer:
implementing_symbols = language_server.request_implementing_symbols(os.path.join("src", "lib.rs"), *pos)
assert implementing_symbols, "Expected implementing symbols for Greeter.format_greeting"
assert any(
symbol.get("name") == "format_greeting" and "src/lib.rs" in symbol["location"].get("relativePath", "").replace("\\", "/")
symbol.get("name") == "format_greeting" and "src/lib.rs" in symbol["location"].get("relativePath", "").replace("\\", "/") # type: ignore
for symbol in implementing_symbols
), f"Expected ConsoleGreeter.format_greeting symbol, got: {implementing_symbols}"
+2
View File
@@ -130,6 +130,7 @@ class TestScssReferences:
line, col = coords.line, coords.col
refs = language_server.request_references(path, line, col + 2)
ref_paths = {r.get("relativePath", "") for r in refs}
ref_paths = {r for r in ref_paths if r} # filter out empty strings
assert any(p.endswith("buttons.scss") for p in ref_paths), (
f"Expected card-surface references to include buttons.scss, got: {ref_paths}"
)
@@ -148,6 +149,7 @@ class TestScssReferences:
line, col = coords.line, coords.col
refs = language_server.request_references(path, line, col + 2)
ref_paths = {r.get("relativePath", "") for r in refs}
ref_paths = {r for r in ref_paths if r} # filter out empty strings
assert any(p.endswith("buttons.scss") for p in ref_paths), (
f"Expected $color-primary references to include buttons.scss, got: {ref_paths}"
)
+4 -3
View File
@@ -20,7 +20,7 @@ class TestSvelteLanguageServer:
def test_svelte_language_server_root_matches_repo_path(self, language_server: SolidLanguageServer, repo_path: Path) -> None:
assert language_server.is_running()
assert repo_path.resolve() == svelte_test_conftest.repo_path.resolve()
assert Path(language_server.language_server.repo_path).resolve() == repo_path.resolve()
assert Path(language_server.repository_root_path).resolve() == repo_path.resolve()
@pytest.mark.parametrize("language_server", [LanguageServerId.SVELTE], indirect=True)
def test_svelte_and_typescript_files_in_symbol_tree(self, language_server: SolidLanguageServer) -> None:
@@ -74,12 +74,13 @@ class TestSvelteLanguageServer:
def test_definition_from_component_import_to_svelte_file(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("src", "lib", "components", "Header.svelte")
coords = find_text_coordinates(read_repo_file(language_server, file_path), r"(count)")
assert coords is not None
definitions = language_server.request_definition(file_path, coords.line, coords.col)
definition_paths = sorted(definition["relativePath"].replace("\\", "/") for definition in definitions)
definition_paths = sorted(definition["relativePath"].replace("\\", "/") for definition in definitions) # type: ignore
assert len(definitions) == 1, definition_paths
assert definitions[0]["relativePath"].replace("\\", "/") == "src/lib/components/Counter.svelte", definition_paths
assert definitions[0]["relativePath"].replace("\\", "/") == "src/lib/components/Counter.svelte", definition_paths # type: ignore
@pytest.mark.parametrize("language_server", [LanguageServerId.SVELTE], indirect=True)
def test_diagnostics_in_typescript_file(self, language_server: SolidLanguageServer) -> None:
@@ -12,7 +12,7 @@ class TestSvelteReferences:
@pytest.mark.parametrize("language_server", [LanguageServerId.SVELTE], indirect=True)
def test_references_across_svelte_and_typescript(self, language_server: SolidLanguageServer) -> None:
refs = language_server.request_references(os.path.join("src", "lib", "components", "Words.svelte"), 1, 17)
ref_paths = {ref["relativePath"].replace("\\", "/") for ref in refs}
ref_paths = {ref["relativePath"].replace("\\", "/") for ref in refs} # type: ignore
assert "src/routes/(sverdle)/words.server.ts" in ref_paths, sorted(ref_paths)
assert "src/lib/game.ts" in ref_paths, sorted(ref_paths)
@@ -21,6 +21,6 @@ class TestSvelteReferences:
@pytest.mark.parametrize("language_server", [LanguageServerId.SVELTE], indirect=True)
def test_references_from_typescript_file(self, language_server: SolidLanguageServer) -> None:
refs = language_server.request_references(os.path.join("src", "lib", "game.ts"), 3, 13)
ref_paths = {ref["relativePath"].replace("\\", "/") for ref in refs}
ref_paths = {ref["relativePath"].replace("\\", "/") for ref in refs} # type: ignore
assert "src/routes/(sverdle)/+page.server.ts" in ref_paths, sorted(ref_paths)
@@ -56,6 +56,7 @@ class TestSvelteRename:
def test_rename_svelte_export_updates_svelte_importers(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("src", "lib", "components", "Counter.svelte")
coords = find_text_coordinates(read_repo_file(language_server, file_path), r"(count)")
assert coords is not None
workspace_edit = language_server.request_rename_symbol_edit(file_path, coords.line, coords.col, "score")
@@ -69,6 +70,7 @@ class TestSvelteRename:
def test_rename_svelte_export_updates_ts_and_svelte_files(self, language_server: SolidLanguageServer) -> None:
file_path = os.path.join("src", "lib", "components", "Words.svelte")
coords = find_text_coordinates(read_repo_file(language_server, file_path), r"(words)")
assert coords is not None
workspace_edit = language_server.request_rename_symbol_edit(file_path, coords.line, coords.col, "vocabulary")
+2 -2
View File
@@ -38,7 +38,7 @@ def test_start_stops_process_when_start_server_raises_after_spawning():
with pytest.raises(RuntimeError, match="capability assertion"):
server.start()
server.server.stop.assert_called_once()
server.server.stop.assert_called_once() # type: ignore
assert server.server_started is False
@@ -51,5 +51,5 @@ def test_start_does_not_call_stop_when_start_server_raises_before_spawning():
with pytest.raises(RuntimeError, match="capability assertion"):
server.start()
server.server.stop.assert_not_called()
server.server.stop.assert_not_called() # type: ignore
assert server.server_started is False
+6 -4
View File
@@ -115,8 +115,8 @@ def test_language_server_process_survives_a_short_lived_calling_thread() -> None
text=True,
)
try:
ready_line = driver.stdout.readline()
assert ready_line.strip() == "READY", f"driver failed to start the language server: {driver.stderr.read()}"
ready_line = driver.stdout.readline() # type: ignore
assert ready_line.strip() == "READY", f"driver failed to start the language server: {driver.stderr.read()}" # type: ignore
time.sleep(2)
# The driver's own argv also contains `marker` (it's passed as sys.argv[1]), so exclude
@@ -143,8 +143,10 @@ def test_language_server_process_dies_with_a_sigkilled_serena() -> None:
text=True,
)
try:
ready_line = driver.stdout.readline()
assert ready_line.strip() == "READY", f"driver failed to start the language server: {driver.stderr.read()}"
ready_line = driver.stdout.readline() # type: ignore
stderr = driver.stderr
assert stderr is not None, "stderr should be captured"
assert ready_line.strip() == "READY", f"driver failed to start the language server: {stderr.read()}"
assert _find_marked_processes(marker), "language server process never started"
driver.kill() # SIGKILL: simulates Serena being killed without a chance to clean up
+7 -3
View File
@@ -80,7 +80,9 @@ def _spawn_ready(src: str) -> subprocess.Popen:
test_pdeathsig.py's driver pattern (deterministic sync instead of a blind sleep).
"""
proc = subprocess.Popen([sys.executable, "-c", src], start_new_session=True, stdout=subprocess.PIPE, text=True)
ready_line = proc.stdout.readline()
stdout = proc.stdout
assert stdout is not None
ready_line = stdout.readline()
assert ready_line.strip() == "READY", f"helper process failed to start: {ready_line!r}"
return proc
@@ -341,8 +343,10 @@ class TestPsutilDenialConsequences:
"""
)
proc = subprocess.Popen([sys.executable, "-c", src], start_new_session=True, stdout=subprocess.PIPE, text=True)
child_pid = int(proc.stdout.readline().strip())
ready_line = proc.stdout.readline()
stdout = proc.stdout
assert stdout is not None
child_pid = int(stdout.readline().strip())
ready_line = stdout.readline()
assert ready_line.strip() == "READY", f"helper process failed to start: {ready_line!r}"
return proc, child_pid