Skip to content

Commit e0e28a3

Browse files
committed
fix: address four code-review findings
add.py: _resolve_entry_version now short-circuits for archive-backed subprojects (as_vcs() is None), returning Version(revision=raw_version) instead of falling through to a VCS branch/tag lookup that always produces an empty branch fallback for archives. log.py: replace _LogRenderBase/_NoExpandLogRender class pair (each requiring a pylint too-few-public-methods suppression) with a single factory function _make_non_expanding_log_render; the only remaining suppression is the pre-existing protected-access on handler._log_render. svnsubproject.py: override latest_available_version so SVN revision-only pins (revision set, no branch, no tag) return the pinned revision with the default branch context; previously the base implementation called latest_revision_on_branch(trunk), causing dfetch check to report pinned SVN revisions as out of date. tests/test_subproject.py: MockVcsFetcher.browse_tree now returns nullcontext(lambda path="": []) so any consumer calling with subproject.as_vcs().browse_tree(...) as ls: gets a valid context manager instead of None. https://claude.ai/code/session_01BMSF8XFAxV6hABQgL7RZ3z
1 parent aef43fe commit e0e28a3

4 files changed

Lines changed: 35 additions & 19 deletions

File tree

dfetch/commands/add.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,13 @@ def _finalize_add(
273273

274274

275275
def _resolve_entry_version(ctx: _AddContext, raw_version: str) -> Version:
276-
"""Resolve a raw version string to a ``Version`` using remote branches and tags."""
276+
"""Resolve a raw version string to a ``Version`` using remote branches and tags.
277+
278+
For archive-backed subprojects ``raw_version`` is preserved as a revision
279+
identifier (URL or hash) because archives have no branch/tag semantics.
280+
"""
281+
if ctx.subproject.as_vcs() is None:
282+
return Version(revision=raw_version)
277283
branches = ctx.subproject.list_of_branches()
278284
tags = ctx.subproject.list_of_tags()
279285
choices: list[Version] = [

dfetch/log.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66
import types
77
from contextlib import nullcontext
8-
from typing import TYPE_CHECKING, Any, cast
8+
from typing import Any, cast
99

1010
from rich._log_render import LogRender # type: ignore[import-untyped]
1111
from rich.console import Console
@@ -16,26 +16,23 @@
1616

1717
from dfetch import __version__
1818

19-
if TYPE_CHECKING:
2019

21-
class _LogRenderBase: # pylint: disable=too-few-public-methods
22-
def __init__(self, **_kwargs: Any) -> None: ...
20+
def _make_non_expanding_log_render(**kwargs: Any) -> Any:
21+
"""Return a LogRender callable that disables table expansion.
2322
24-
def __call__(self, *_args: Any, **_kwargs: Any) -> Any: ...
23+
Used when recording with asciinema to prevent Rich's ``expand=True`` from
24+
padding log lines to the full terminal width, which produces spurious blank
25+
lines in the cast player.
26+
"""
27+
renderer = LogRender(**kwargs)
2528

26-
else:
27-
_LogRenderBase = LogRender
28-
29-
30-
class _NoExpandLogRender(_LogRenderBase): # pylint: disable=too-few-public-methods
31-
"""LogRender that disables table expansion to prevent blank lines in asciicasts."""
32-
33-
def __call__(self, *args: Any, **kwargs: Any) -> Any:
34-
"""Render log entry without expanding the table to the full terminal width."""
35-
table = super().__call__(*args, **kwargs)
29+
def _render(*args: Any, **kw: Any) -> Any:
30+
table = renderer(*args, **kw)
3631
table.expand = False
3732
return table
3833

34+
return _render
35+
3936

4037
def make_console(no_color: bool = False) -> Console:
4138
"""Create a Rich Console with proper color handling."""
@@ -67,9 +64,10 @@ def configure_root_logger(console: Console | None = None) -> None:
6764
# causing the subsequent newline to produce a blank line in the cast
6865
# player. Wrapping _log_render so it returns a non-expanding table
6966
# removes the trailing spaces and avoids the spurious blank lines.
70-
handler._log_render = _NoExpandLogRender( # pylint: disable=protected-access
67+
no_expand = _make_non_expanding_log_render(
7168
show_time=False, show_level=False, show_path=False
7269
)
70+
handler._log_render = no_expand # pylint: disable=protected-access
7371

7472
logging.basicConfig(
7573
level=logging.INFO,

dfetch/project/svnsubproject.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ def does_revision_exist(self, revision: str) -> bool:
6666
"In SVN only a revision is NOT enough, this should not be called!"
6767
)
6868

69+
def latest_available_version(self, wanted: Version) -> Version | None:
70+
"""Return the latest version matching *wanted*, or None if unavailable.
71+
72+
For revision-only pins (no branch, no tag) the pinned revision is
73+
returned with the default branch so version comparison works correctly.
74+
SVN revisions are globally ordered within a repository, so a bare
75+
``revision:`` in the manifest is always relative to trunk.
76+
"""
77+
if wanted.revision and not wanted.branch and not wanted.tag:
78+
return Version(revision=wanted.revision, branch=self.get_default_branch())
79+
return super().latest_available_version(wanted)
80+
6981
def browse_tree(
7082
self, version: str
7183
) -> AbstractContextManager[Callable[[str], list[tuple[str, bool]]]]:

tests/test_subproject.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# mypy: ignore-errors
44
# flake8: noqa
55

6-
from contextlib import ExitStack
6+
from contextlib import ExitStack, nullcontext
77
from typing import Optional, Union
88
from unittest.mock import MagicMock, patch
99

@@ -48,7 +48,7 @@ def does_revision_exist(self, revision: str) -> bool:
4848
return True
4949

5050
def browse_tree(self, version: str) -> object:
51-
return None
51+
return nullcontext(lambda path="": [])
5252

5353
def patch_type(self) -> PatchType:
5454
return PatchType.GIT

0 commit comments

Comments
 (0)