Skip to content

Commit adfa656

Browse files
yeldarbyclaude
andcommitted
fix(cli): add backwards-compat re-exports to roboflowpy.py shim
The old roboflowpy.py exported _argparser and other functions that external scripts (including tests/manual/debugme.py) may import. Re-export _argparser as an alias for build_parser so existing code like `from roboflow.roboflowpy import _argparser` continues to work. Add dedicated backwards-compatibility test suite verifying the shim exports, parser construction, and legacy command name parsing. 283 tests pass, all linting clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 11a2de2 commit adfa656

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

roboflow/roboflowpy.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44
The CLI implementation has moved to :mod:`roboflow.cli`. This module
55
re-exports ``main`` so that the ``setup.py`` entry-point
66
(``roboflow=roboflow.roboflowpy:main``) continues to work without changes.
7+
8+
It also re-exports legacy function names so that existing scripts doing
9+
``from roboflow.roboflowpy import _argparser`` (etc.) continue to work.
710
"""
811

9-
from roboflow.cli import main
12+
from roboflow.cli import build_parser, main
13+
14+
# Legacy alias: some scripts import _argparser directly
15+
_argparser = build_parser
1016

11-
__all__ = ["main"]
17+
__all__ = ["main", "_argparser"]
1218

1319
if __name__ == "__main__":
1420
main()

tests/cli/test_backwards_compat.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""Tests that the roboflowpy.py backwards-compatibility shim works.
2+
3+
Ensures that existing scripts and integrations that import from the old
4+
monolithic module continue to work after the CLI modularization.
5+
"""
6+
7+
import unittest
8+
9+
10+
class TestRoboflowpyShim(unittest.TestCase):
11+
"""Verify the roboflowpy.py shim re-exports work."""
12+
13+
def test_main_importable(self) -> None:
14+
from roboflow.roboflowpy import main
15+
16+
self.assertTrue(callable(main))
17+
18+
def test_argparser_importable(self) -> None:
19+
"""debugme.py imports _argparser — this must not break."""
20+
from roboflow.roboflowpy import _argparser
21+
22+
self.assertTrue(callable(_argparser))
23+
24+
def test_argparser_returns_parser(self) -> None:
25+
import argparse
26+
27+
from roboflow.roboflowpy import _argparser
28+
29+
parser = _argparser()
30+
self.assertIsInstance(parser, argparse.ArgumentParser)
31+
32+
def test_argparser_has_subcommands(self) -> None:
33+
"""The parser returned by _argparser should have the new CLI subcommands."""
34+
from roboflow.roboflowpy import _argparser
35+
36+
parser = _argparser()
37+
# Parse a known new-style command (--json must come before subcommand
38+
# when using parse_args directly; _reorder_argv handles end-position
39+
# in the real main() entry point)
40+
args = parser.parse_args(["--json", "project", "list"])
41+
self.assertTrue(args.json)
42+
43+
def test_argparser_has_legacy_aliases(self) -> None:
44+
"""Legacy command names should still parse."""
45+
from roboflow.roboflowpy import _argparser
46+
47+
parser = _argparser()
48+
49+
# 'login' was a top-level command in the old CLI
50+
args = parser.parse_args(["login"])
51+
self.assertIsNotNone(args.func)
52+
53+
# 'whoami' was a top-level command
54+
args = parser.parse_args(["whoami"])
55+
self.assertIsNotNone(args.func)
56+
57+
# 'download' was a top-level command
58+
args = parser.parse_args(["download", "ws/proj/1"])
59+
self.assertIsNotNone(args.func)
60+
61+
62+
if __name__ == "__main__":
63+
unittest.main()

0 commit comments

Comments
 (0)