diff --git a/src/solidlsp/language_servers/csharp_language_server.py b/src/solidlsp/language_servers/csharp_language_server.py index b8f0cc38..da65cb83 100644 --- a/src/solidlsp/language_servers/csharp_language_server.py +++ b/src/solidlsp/language_servers/csharp_language_server.py @@ -388,11 +388,7 @@ class CSharpLanguageServer(SolidLanguageServer): package_extract_dir.mkdir(exist_ok=True) # Use SafeZipExtractor to handle long paths and skip errors - extractor = SafeZipExtractor( - archive_path=nupkg_file, - extract_dir=package_extract_dir, - verbose=False - ) + extractor = SafeZipExtractor(archive_path=nupkg_file, extract_dir=package_extract_dir, verbose=False) extractor.extract_all() # Clean up the nupkg file diff --git a/src/solidlsp/util/zip.py b/src/solidlsp/util/zip.py index ae0c3183..d93d9421 100644 --- a/src/solidlsp/util/zip.py +++ b/src/solidlsp/util/zip.py @@ -1,13 +1,14 @@ +import fnmatch import logging import os import sys import zipfile from pathlib import Path -from typing import Optional, List -import fnmatch +from typing import Optional log = logging.getLogger(__name__) + class SafeZipExtractor: """ A utility class for extracting ZIP archives safely. @@ -24,8 +25,8 @@ class SafeZipExtractor: archive_path: Path, extract_dir: Path, verbose: bool = True, - include_patterns: Optional[List[str]] = None, - exclude_patterns: Optional[List[str]] = None + include_patterns: Optional[list[str]] = None, + exclude_patterns: Optional[list[str]] = None, ) -> None: """ Initialize the SafeZipExtractor. @@ -113,7 +114,7 @@ class SafeZipExtractor: :return: Normalized path """ if sys.platform.startswith("win"): - return Path(r"\\?\{}".format(os.path.abspath(path))) + return Path(rf"\\?\{os.path.abspath(path)}") return path diff --git a/test/solidlsp/util/test_zip.py b/test/solidlsp/util/test_zip.py index 4498781a..5fa545ba 100644 --- a/test/solidlsp/util/test_zip.py +++ b/test/solidlsp/util/test_zip.py @@ -1,8 +1,7 @@ -import io -import os import sys import zipfile from pathlib import Path + import pytest from solidlsp.util.zip import SafeZipExtractor @@ -33,9 +32,7 @@ def test_extract_all_success(temp_zip_file: Path, tmp_path: Path) -> None: def test_include_patterns(temp_zip_file: Path, tmp_path: Path) -> None: """Only files matching include_patterns should be extracted.""" dest_dir = tmp_path / "extracted" - extractor = SafeZipExtractor( - temp_zip_file, dest_dir, verbose=False, include_patterns=["*.txt"] - ) + extractor = SafeZipExtractor(temp_zip_file, dest_dir, verbose=False, include_patterns=["*.txt"]) extractor.extract_all() assert (dest_dir / "file1.txt").exists() @@ -46,9 +43,7 @@ def test_include_patterns(temp_zip_file: Path, tmp_path: Path) -> None: def test_exclude_patterns(temp_zip_file: Path, tmp_path: Path) -> None: """Files matching exclude_patterns should be skipped.""" dest_dir = tmp_path / "extracted" - extractor = SafeZipExtractor( - temp_zip_file, dest_dir, verbose=False, exclude_patterns=["file2.txt"] - ) + extractor = SafeZipExtractor(temp_zip_file, dest_dir, verbose=False, exclude_patterns=["file2.txt"]) extractor.extract_all() assert (dest_dir / "file1.txt").exists() @@ -81,7 +76,7 @@ def test_skip_on_error(monkeypatch, temp_zip_file: Path, tmp_path: Path) -> None def failing_open(self, member, *args, **kwargs): if member.filename == "file2.txt": - raise IOError("Simulated failure") + raise OSError("Simulated failure") return original_open(self, member, *args, **kwargs) # Patch the method on the class, not on an instance @@ -94,9 +89,10 @@ def test_skip_on_error(monkeypatch, temp_zip_file: Path, tmp_path: Path) -> None assert not (dest_dir / "file2.txt").exists() assert (dest_dir / "folder" / "file3.txt").exists() + @pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows-only test") def test_long_path_normalization(temp_zip_file: Path, tmp_path: Path) -> None: - """Ensure _normalize_path adds \\?\ prefix on Windows.""" + r"""Ensure _normalize_path adds \\?\\ prefix on Windows.""" dest_dir = tmp_path / ("a" * 250) # Simulate long path extractor = SafeZipExtractor(temp_zip_file, dest_dir, verbose=False) norm_path = extractor._normalize_path(dest_dir / "file.txt")