Skip to content

Commit

Permalink
Fixed bug with relative paths and improved test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
owenlamont committed Jan 6, 2025
1 parent 97fbc55 commit 14b4f6b
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ repos:
additional_dependencies:
- pydantic
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.8.5
rev: v0.8.6
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
Expand Down
2 changes: 1 addition & 1 deletion src/uv_secure/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.3.0"
__version__ = "0.3.1"
21 changes: 12 additions & 9 deletions src/uv_secure/directory_scanner/directory_scanner.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from collections.abc import Iterable
from collections.abc import Iterable, Sequence
from typing import Union

from anyio import Path
Expand All @@ -23,15 +23,17 @@ async def _find_files(
return {filename: task.value for filename, task in tasks.items()}


async def _get_root_dir(file_paths: Iterable[Path]) -> Path:
async def _resolve_paths(file_paths: Sequence[Path]) -> list[Path]:
async with create_task_group() as tg:
tasks = [tg.soonify(path.resolve)() for path in file_paths]
return [task.value for task in tasks]

resolved_paths = [task.value for task in tasks]
if len(resolved_paths) == 1:
return resolved_paths[0].parent

split_paths = [list(rp.parts) for rp in resolved_paths]
def _get_root_dir(file_paths: Sequence[Path]) -> Path:
if len(file_paths) == 1:
return file_paths[0].parent

split_paths = [list(rp.parts) for rp in file_paths]
min_length = min(len(parts) for parts in split_paths)
common_prefix_len = 0

Expand Down Expand Up @@ -61,16 +63,17 @@ async def get_lock_to_config_map(
A dictionary mapping uv.lock files to their nearest Configuration
"""
if type(file_paths) is Path:
root_dir = file_paths
root_dir = await file_paths.resolve()
config_and_lock_files = await _find_files(
root_dir, ["pyproject.toml", "uv-secure.toml", ".uv-secure.toml", "uv.lock"]
)
else:
root_dir = await _get_root_dir(file_paths)
resolved_paths = await _resolve_paths(file_paths)
root_dir = _get_root_dir(resolved_paths)
config_and_lock_files = await _find_files(
root_dir, ["pyproject.toml", "uv-secure.toml", ".uv-secure.toml"]
)
config_and_lock_files["uv.lock"] = file_paths
config_and_lock_files["uv.lock"] = resolved_paths

config_file_paths = (
config_and_lock_files["pyproject.toml"]
Expand Down
75 changes: 75 additions & 0 deletions tests/uv_secure/test_run.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import os
from pathlib import Path

from httpx import Request, RequestError
import pytest
from pytest_httpx import HTTPXMock
from typer.testing import CliRunner
Expand Down Expand Up @@ -145,6 +147,25 @@ def one_vulnerability_response_v2(httpx_mock: HTTPXMock) -> HTTPXMock:
return httpx_mock


@pytest.fixture
def package_version_not_found_response(httpx_mock: HTTPXMock) -> HTTPXMock:
httpx_mock.add_response(
url="https://pypi.org/pypi/example-package/1.0.0/json", status_code=404
)
return httpx_mock


@pytest.fixture
def missing_vulnerability_response(httpx_mock: HTTPXMock) -> HTTPXMock:
httpx_mock.add_exception(
RequestError(
"Request failed",
request=Request("GET", "https://pypi.org/pypi/example-package/1.0.0/json"),
)
)
return httpx_mock


def test_app_version() -> None:
result = runner.invoke(app, "--version")
assert result.exit_code == 0
Expand Down Expand Up @@ -175,6 +196,60 @@ def test_app_no_vulnerabilities(
assert "All dependencies appear safe!" in result.output


def test_app_no_vulnerabilities_relative_lock_file_path(
tmp_path: Path, temp_uv_lock_file: Path, no_vulnerabilities_response: HTTPXMock
) -> None:
"""Test check_dependencies with a single dependency and no vulnerabilities."""

os.chdir(tmp_path)
result = runner.invoke(app, ["uv.lock"])

assert result.exit_code == 0
assert "No vulnerabilities detected!" in result.output
assert "Checked: 1 dependency" in result.output
assert "All dependencies appear safe!" in result.output


def test_app_no_vulnerabilities_relative_no_specified_path(
tmp_path: Path, temp_uv_lock_file: Path, no_vulnerabilities_response: HTTPXMock
) -> None:
"""Test check_dependencies with a single dependency and no vulnerabilities."""

os.chdir(tmp_path)
result = runner.invoke(app)

assert result.exit_code == 0
assert "No vulnerabilities detected!" in result.output
assert "Checked: 1 dependency" in result.output
assert "All dependencies appear safe!" in result.output


def test_app_failed_vulnerability_request(
temp_uv_lock_file: Path, missing_vulnerability_response: HTTPXMock
) -> None:
"""Test check_dependencies with a single dependency and no vulnerabilities."""
result = runner.invoke(app, [str(temp_uv_lock_file)])

assert result.exit_code == 0
assert "Error fetching example-package==1.0.0: Request failed" in result.output
assert "No vulnerabilities detected!" in result.output
assert "Checked: 1 dependency" in result.output
assert "All dependencies appear safe!" in result.output


def test_app_package_not_found(
temp_uv_lock_file: Path, package_version_not_found_response: HTTPXMock
) -> None:
"""Test check_dependencies with a single dependency and no vulnerabilities."""
result = runner.invoke(app, [str(temp_uv_lock_file)])

assert result.exit_code == 0
assert "Warning: Could not fetch data for example-package==1.0.0" in result.output
assert "No vulnerabilities detected!" in result.output
assert "Checked: 1 dependency" in result.output
assert "All dependencies appear safe!" in result.output


def test_check_dependencies_with_vulnerability(
temp_uv_lock_file: Path, one_vulnerability_response: HTTPXMock
) -> None:
Expand Down
14 changes: 7 additions & 7 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 14b4f6b

Please sign in to comment.