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
29 changes: 29 additions & 0 deletions deepdiff/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Console-script entry point for the ``deep`` command.

The command line dependencies (``click``, and ``pyyaml`` for YAML files) are
optional and installed via the ``cli`` extra (``pip install deepdiff[cli]``).
The ``deep`` script itself is always installed, so importing
:mod:`deepdiff.commands` directly raises a bare
``ModuleNotFoundError: No module named 'click'`` on a default install
(see https://github.com/seperman/deepdiff/issues/594). This thin wrapper checks
for the dependency first and exits with an actionable message instead of a
traceback.
"""

import sys


def main():
"""Entry point for the ``deep`` console script."""
try:
import click # noqa: F401
except ImportError:
sys.exit(
"The 'deep' command line tool requires extra dependencies that are "
"not installed.\n"
"Install them with:\n\n pip install deepdiff[cli]\n"
)

from deepdiff.commands import cli

cli()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ optimize = [
]

[project.scripts]
deep = "deepdiff.commands:cli"
deep = "deepdiff.cli:main"

[project.urls]
Homepage = "https://zepworks.com/deepdiff/"
Expand Down
37 changes: 37 additions & 0 deletions tests/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,40 @@ def test_command_extract(self):
diffed = runner.invoke(extract, ['root[2][2]', path])
assert 0 == diffed.exit_code
assert '0.288\n' == diffed.output


class TestCliEntryPoint:
"""Tests for the ``deep`` console-script wrapper (deepdiff/cli.py)."""

def test_main_runs_cli_when_click_available(self):
# click is available in the test environment; invoking the entry point
# with --help should print the group help and exit cleanly.
from click.testing import CliRunner

from deepdiff.commands import cli

result = CliRunner().invoke(cli, ['--help'])
assert result.exit_code == 0
assert 'command line tool' in result.output

def test_main_reports_missing_click_dependency(self, monkeypatch):
# Simulate a default install without the optional ``cli`` extra: the
# entry point must fail with an actionable message rather than a bare
# ModuleNotFoundError traceback. See issue #594.
import builtins

from deepdiff import cli as cli_entry

real_import = builtins.__import__

def fake_import(name, *args, **kwargs):
if name == 'click':
raise ImportError("No module named 'click'")
return real_import(name, *args, **kwargs)

monkeypatch.setattr(builtins, '__import__', fake_import)

with pytest.raises(SystemExit) as exc_info:
cli_entry.main()

assert 'pip install deepdiff[cli]' in str(exc_info.value)