Skip to content

Commit a644e0b

Browse files
authored
Merge pull request #608 from uttam12331/fix/cli-missing-click-594
fix(cli): give actionable error when 'deep' runs without cli extra (#594)
2 parents e84901e + 93c9895 commit a644e0b

3 files changed

Lines changed: 67 additions & 1 deletion

File tree

deepdiff/cli.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Console-script entry point for the ``deep`` command.
2+
3+
The command line dependencies (``click``, and ``pyyaml`` for YAML files) are
4+
optional and installed via the ``cli`` extra (``pip install deepdiff[cli]``).
5+
The ``deep`` script itself is always installed, so importing
6+
:mod:`deepdiff.commands` directly raises a bare
7+
``ModuleNotFoundError: No module named 'click'`` on a default install
8+
(see https://github.com/seperman/deepdiff/issues/594). This thin wrapper checks
9+
for the dependency first and exits with an actionable message instead of a
10+
traceback.
11+
"""
12+
13+
import sys
14+
15+
16+
def main():
17+
"""Entry point for the ``deep`` console script."""
18+
try:
19+
import click # noqa: F401
20+
except ImportError:
21+
sys.exit(
22+
"The 'deep' command line tool requires extra dependencies that are "
23+
"not installed.\n"
24+
"Install them with:\n\n pip install deepdiff[cli]\n"
25+
)
26+
27+
from deepdiff.commands import cli
28+
29+
cli()

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ optimize = [
8383
]
8484

8585
[project.scripts]
86-
deep = "deepdiff.commands:cli"
86+
deep = "deepdiff.cli:main"
8787

8888
[project.urls]
8989
Homepage = "https://zepworks.com/deepdiff/"

tests/test_command.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,40 @@ def test_command_extract(self):
116116
diffed = runner.invoke(extract, ['root[2][2]', path])
117117
assert 0 == diffed.exit_code
118118
assert '0.288\n' == diffed.output
119+
120+
121+
class TestCliEntryPoint:
122+
"""Tests for the ``deep`` console-script wrapper (deepdiff/cli.py)."""
123+
124+
def test_main_runs_cli_when_click_available(self):
125+
# click is available in the test environment; invoking the entry point
126+
# with --help should print the group help and exit cleanly.
127+
from click.testing import CliRunner
128+
129+
from deepdiff.commands import cli
130+
131+
result = CliRunner().invoke(cli, ['--help'])
132+
assert result.exit_code == 0
133+
assert 'command line tool' in result.output
134+
135+
def test_main_reports_missing_click_dependency(self, monkeypatch):
136+
# Simulate a default install without the optional ``cli`` extra: the
137+
# entry point must fail with an actionable message rather than a bare
138+
# ModuleNotFoundError traceback. See issue #594.
139+
import builtins
140+
141+
from deepdiff import cli as cli_entry
142+
143+
real_import = builtins.__import__
144+
145+
def fake_import(name, *args, **kwargs):
146+
if name == 'click':
147+
raise ImportError("No module named 'click'")
148+
return real_import(name, *args, **kwargs)
149+
150+
monkeypatch.setattr(builtins, '__import__', fake_import)
151+
152+
with pytest.raises(SystemExit) as exc_info:
153+
cli_entry.main()
154+
155+
assert 'pip install deepdiff[cli]' in str(exc_info.value)

0 commit comments

Comments
 (0)