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
20 changes: 17 additions & 3 deletions shakespearelang/_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,39 @@ def consume_numeric_input(self):
try:
self._ensure_input_buffer()
except EOFError:
raise ShakespeareRuntimeError("End of file encountered.") from None
return -2

sign = self._consume_sign_if_present()
number = self._consume_digits()

if number is None:
if sign:
self._input_buffer = sign + self._input_buffer
return -1

self._consume_newline_if_present()

return number
return -number if sign == "-" else number

def _consume_newline_if_present(self):
if self._input_buffer and self._input_buffer[0] == "\n":
self._input_buffer = self._input_buffer[1:]

def _consume_sign_if_present(self):
if self._input_buffer and (sign := self._input_buffer[0]) in ["+", "-"]:
self._input_buffer = self._input_buffer[1:]
return sign

return ""

def _consume_digits(self):
number_input = ""
while self._input_buffer and self._input_buffer[0].isdigit():
number_input += self._input_buffer[0]
self._input_buffer = self._input_buffer[1:]

if len(number_input) == 0:
raise ShakespeareRuntimeError("No numeric input was given.")
return None

return int(number_input)

Expand Down
41 changes: 20 additions & 21 deletions shakespearelang/tests/test_numeric_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ def test_correctly_parses_number(monkeypatch, capsys):
s.run_event("[Enter Romeo and Juliet]")
s.run_sentence("Listen to your heart!", "Juliet")
assert s.state.character_by_name("Romeo").value == 4257

monkeypatch.setattr("sys.stdin", StringIO("-3211"))
s = Shakespeare("Foo. Juliet, a test. Romeo, a test.")
s.run_event("[Enter Romeo and Juliet]")
s.run_sentence("Listen to your heart!", "Juliet")
assert s.state.character_by_name("Romeo").value == -3211

monkeypatch.setattr("sys.stdin", StringIO("+2"))
s = Shakespeare("Foo. Juliet, a test. Romeo, a test.")
s.run_event("[Enter Romeo and Juliet]")
s.run_sentence("Listen to your heart!", "Juliet")
assert s.state.character_by_name("Romeo").value == 2

captured = capsys.readouterr()
assert captured.out == ""
assert captured.err == ""
Expand Down Expand Up @@ -42,39 +55,24 @@ def test_consumes_trailing_newline(monkeypatch, capsys):
assert s.state.character_by_name("Romeo").value == -1


def test_errors_without_digits(monkeypatch, capsys):
def test_no_digits_consumed(monkeypatch, capsys):
monkeypatch.setattr("sys.stdin", StringIO("a123"))
s = Shakespeare("Foo. Juliet, a test. Romeo, a test.")
s.run_event("[Enter Romeo and Juliet]")

with pytest.raises(ShakespeareRuntimeError) as exc:
s.run_sentence("Listen to your heart!", "Juliet")
assert "no numeric input" in str(exc.value).lower()
assert ">>Listen to your heart!<<" in str(exc.value)
assert exc.value.interpreter == s
assert s.state.character_by_name("Romeo").value == 0

monkeypatch.setattr("sys.stdin", StringIO("a123"))
with pytest.raises(ShakespeareRuntimeError) as exc:
s.run_sentence("Listen to your heart!", "Juliet")
assert "no numeric input" in str(exc.value).lower()
assert ">>Listen to your heart!<<" in str(exc.value)
assert exc.value.interpreter == s
s.state.character_by_name("Romeo").value = 24
s.run_sentence("Listen to your heart!", "Juliet")
assert s.state.character_by_name("Romeo").value == 0
captured = capsys.readouterr()
assert captured.out == ""
assert captured.err == ""


def test_errors_on_eof(monkeypatch, capsys):
def test_eof(monkeypatch, capsys):
monkeypatch.setattr("sys.stdin", StringIO(""))
s = Shakespeare("Foo. Juliet, a test. Romeo, a test.")
s.run_event("[Enter Romeo and Juliet]")
with pytest.raises(ShakespeareRuntimeError) as exc:
s.run_sentence("Listen to your heart!", "Juliet")
assert "end of file" in str(exc.value).lower()
assert ">>Listen to your heart!<<" in str(exc.value)
assert exc.value.interpreter == s
s.state.character_by_name("Romeo").value = 42
s.run_sentence("Listen to your heart!", "Juliet")
assert s.state.character_by_name("Romeo").value == 0
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert presumably needs to change to -2 to pass?

captured = capsys.readouterr()
assert captured.out == ""
Expand Down Expand Up @@ -106,6 +104,7 @@ def test_conditional(monkeypatch, capsys):
assert captured.out == ""
assert captured.err == ""


def test_interactive_style(monkeypatch, capsys):
monkeypatch.setattr("sys.stdin", StringIO("4257\n3211"))
s = Shakespeare("Foo. Juliet, a test. Romeo, a test.", input_style="interactive")
Expand Down
Loading