Skip to content
Closed
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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Unreleased

### Bug fixes

* The `s7` command now prints an install hint and exits when the optional `click` dependency is missing, instead of
failing with an `ImportError` traceback, so `click` stays an optional `cli` extra (#954).
* `get_string` and `get_wstring` now raise `ValueError` when the buffer is shorter than the declared current length,
instead of silently returning a truncated value (#945).
* USERDATA responses whose last-data-unit byte is neither `0x00` nor `0x01` are rejected with `S7ProtocolError`
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ include = ["snap7*", "s7*"]

[project.scripts]
snap7-server = "snap7.server:mainloop"
s7 = "snap7.cli:main"
s7 = "snap7._console:main"

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
19 changes: 19 additions & 0 deletions snap7/_console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
Console entry point for the ``s7`` command.

The CLI depends on the optional ``click`` package (``pip install python-snap7[cli]``). This wrapper checks for it before
importing :mod:`snap7.cli`, so a plain install prints an install hint instead of an ``ImportError`` traceback.
"""

import importlib.util
import sys


def main() -> None:
if importlib.util.find_spec("click") is None:
print("The s7 command requires the CLI dependencies. Install them with: pip install python-snap7[cli]", file=sys.stderr)
sys.exit(1)

from snap7.cli import main as cli_main

cli_main()
35 changes: 35 additions & 0 deletions tests/test_console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Tests for the s7 console entry point wrapper."""

import importlib.util
from typing import Any
from unittest.mock import patch

import pytest

from snap7 import _console


@pytest.mark.client
def test_missing_click_prints_install_hint(capsys: pytest.CaptureFixture[str]) -> None:
real_find_spec = importlib.util.find_spec

def find_spec(name: str, *args: Any, **kwargs: Any) -> Any:
if name == "click":
return None
return real_find_spec(name, *args, **kwargs)

with patch.object(importlib.util, "find_spec", find_spec):
with pytest.raises(SystemExit) as exc_info:
_console.main()

assert exc_info.value.code == 1
assert "pip install python-snap7[cli]" in capsys.readouterr().err


@pytest.mark.client
def test_runs_cli_when_click_installed() -> None:
pytest.importorskip("click")
with patch("sys.argv", ["s7", "--help"]):
with pytest.raises(SystemExit) as exc_info:
_console.main()
assert exc_info.value.code == 0