Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import typer

from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies, build_dep_tree_path
from cycode.cli.files_collector.sca.python.restore_poetry_dependencies import POETRY_LOCK_FILE_NAME
from cycode.cli.files_collector.sca.python.restore_uv_dependencies import UV_LOCK_FILE_NAME
from cycode.cli.models import Document
from cycode.cli.utils.path_utils import get_file_content
from cycode.logger import get_logger
Expand All @@ -15,6 +17,7 @@

_POETRY_TOOL_SECTION = '[tool.poetry]'
_UV_TOOL_SECTION = '[tool.uv]'
_OTHER_TOOL_LOCK_FILE_NAMES = (UV_LOCK_FILE_NAME, POETRY_LOCK_FILE_NAME)


def _indicates_plain_pip(pyproject_content: str | None) -> bool:
Expand All @@ -41,6 +44,11 @@ def is_project(self, document: Document) -> bool:
if manifest_dir and (Path(manifest_dir) / PIP_LOCK_FILE_NAME).is_file():
return True

# uv and Poetry don't require a [tool.*] section, so their lockfile is the reliable signal.
# Those handlers already claim this manifest; running `pip lock` on it too is redundant.
Comment on lines +47 to +48

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# uv and Poetry don't require a [tool.*] section, so their lockfile is the reliable signal.
# Those handlers already claim this manifest; running `pip lock` on it too is redundant.

if manifest_dir and any((Path(manifest_dir) / name).is_file() for name in _OTHER_TOOL_LOCK_FILE_NAMES):
return False

return _indicates_plain_pip(document.content)

def try_restore_dependencies(self, document: Document) -> Document | None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,31 @@ def test_pyproject_toml_with_existing_pylock_matches(
)
assert restore_pip.is_project(doc) is True

@pytest.mark.parametrize('lock_file_name', ['uv.lock', 'poetry.lock'])
def test_pyproject_toml_with_uv_or_poetry_lock_does_not_match(
self, restore_pip: RestorePipDependencies, tmp_path: Path, lock_file_name: str
) -> None:
# No [tool.uv] / [tool.poetry] section, but the sibling lockfile shows another tool owns it
content = '[project]\nname = "test"\ndependencies = ["requests"]\n'
(tmp_path / 'pyproject.toml').write_text(content)
(tmp_path / lock_file_name).write_text('version = 1\n')
doc = Document(
str(tmp_path / 'pyproject.toml'),
content,
absolute_path=str(tmp_path / 'pyproject.toml'),
)
assert restore_pip.is_project(doc) is False

def test_requirements_txt_with_uv_lock_matches(self, restore_pip: RestorePipDependencies, tmp_path: Path) -> None:
(tmp_path / 'requirements.txt').write_text('requests==2.31.0\n')
(tmp_path / 'uv.lock').write_text('version = 1\n')
doc = Document(
str(tmp_path / 'requirements.txt'),
'requests==2.31.0\n',
absolute_path=str(tmp_path / 'requirements.txt'),
)
assert restore_pip.is_project(doc) is True

def test_requirements_txt_matches(self, restore_pip: RestorePipDependencies) -> None:
doc = Document('requirements.txt', 'requests==2.31.0\n')
assert restore_pip.is_project(doc) is True
Expand Down