From 1404e581847aedb292ec187c12e2c465247f4bfd Mon Sep 17 00:00:00 2001 From: eliadl Date: Sat, 10 Jun 2017 02:42:59 +0300 Subject: [PATCH 1/5] Fix game.play and its test 1. One of the test's assertion was missing the `assert`. 2. Adding the above `assert` revealed that text is translated before it is formatted. So I fixed it to translate only after formatting it. (Because formats can have variable name in them, and we don't want them translated) --- 20170613-mock/code/ggee/guessing/game.py | 6 +++--- 20170613-mock/code/ggee/tests/test_game.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/20170613-mock/code/ggee/guessing/game.py b/20170613-mock/code/ggee/guessing/game.py index ddc610b..da4d1b5 100755 --- a/20170613-mock/code/ggee/guessing/game.py +++ b/20170613-mock/code/ggee/guessing/game.py @@ -47,14 +47,14 @@ def think_of_a_number(level): def play(level): # type: (int) -> None - print(T("Level {level}: 0 to {max_num}").format( - level=level, max_num=max_number(level))) + print(T("Level {level}: 0 to {max_num}".format( + level=level, max_num=max_number(level)))) num = think_of_a_number(level) while True: print(T("Can you guess what number I am thinking about?")) guess = your_guess() if guess is None: - print(T("Just wanted you to know that I was thinking about {}").format(num)) + print(T("Just wanted you to know that I was thinking about {}".format(num))) break if guess < num: print(T("No, my number is bigger than that")) diff --git a/20170613-mock/code/ggee/tests/test_game.py b/20170613-mock/code/ggee/tests/test_game.py index 4eafeaf..76b60d8 100644 --- a/20170613-mock/code/ggee/tests/test_game.py +++ b/20170613-mock/code/ggee/tests/test_game.py @@ -120,5 +120,5 @@ def test_play(mock_stdout, mock_T, guesses, expected_messages): mock.patch('guessing.game.your_guess', side_effect=guesses): game.play(level) - mock_T.call_args_list = map(mock.call, expected_messages) + assert mock_T.call_args_list == map(mock.call, expected_messages) assert mock_stdout.getvalue() == '\n'.join(expected_messages) + '\n' From 8caa4a22246a1e4d6d43a69c35d3bc4216ce9746 Mon Sep 17 00:00:00 2001 From: eliadl Date: Sat, 10 Jun 2017 14:51:17 +0300 Subject: [PATCH 2/5] Revert to translate before format (temporary test break) --- 20170613-mock/code/ggee/guessing/game.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/20170613-mock/code/ggee/guessing/game.py b/20170613-mock/code/ggee/guessing/game.py index da4d1b5..ddc610b 100755 --- a/20170613-mock/code/ggee/guessing/game.py +++ b/20170613-mock/code/ggee/guessing/game.py @@ -47,14 +47,14 @@ def think_of_a_number(level): def play(level): # type: (int) -> None - print(T("Level {level}: 0 to {max_num}".format( - level=level, max_num=max_number(level)))) + print(T("Level {level}: 0 to {max_num}").format( + level=level, max_num=max_number(level))) num = think_of_a_number(level) while True: print(T("Can you guess what number I am thinking about?")) guess = your_guess() if guess is None: - print(T("Just wanted you to know that I was thinking about {}".format(num))) + print(T("Just wanted you to know that I was thinking about {}").format(num)) break if guess < num: print(T("No, my number is bigger than that")) From ae2d4c1631a4404e1f9ff3c12a1b53900ecb5c5e Mon Sep 17 00:00:00 2001 From: eliadl Date: Sat, 10 Jun 2017 15:32:37 +0300 Subject: [PATCH 3/5] Add PromptGGEE to prevent translate-format break --- 20170613-mock/code/ggee/guessing/game.py | 29 ++++++++++++++++++++++ 20170613-mock/code/ggee/tests/test_game.py | 7 ++++++ 2 files changed, 36 insertions(+) diff --git a/20170613-mock/code/ggee/guessing/game.py b/20170613-mock/code/ggee/guessing/game.py index ddc610b..6ad0bcb 100755 --- a/20170613-mock/code/ggee/guessing/game.py +++ b/20170613-mock/code/ggee/guessing/game.py @@ -19,6 +19,35 @@ # TODO: implement a high-score # see https://github.com/chenl/talks/issues/4 +class PromptGGEE(object): + """This class was made to work around a problem, + where a string is translated before formatting. + + E.g. a part like `{level}` might translate too, + thus breaking the formatting. + + This class allows to replace `{level}` with `{0:0}`: + >>> prompt = PromptGGEE(3, 7, 5) + >>> 'using level {0:0}'.format(prompt) + + Using a fixed mapping between indices (0) and attrs (level), + we prevent the translation of any attr. + """ + + attr_by_index = {'0': 'level', '1': 'max_num', '2': 'num'} + + def __init__(self, level, max_num, num): + self.level = str(level) + self.max_num = str(max_num) + self.num = str(num) + + def __getitem__(self, item): + attr = self.attr_by_index[item] + return getattr(self, attr) + + def __format__(self, format_spec): + return self[format_spec] + def game(): # type: () -> None intro() diff --git a/20170613-mock/code/ggee/tests/test_game.py b/20170613-mock/code/ggee/tests/test_game.py index 76b60d8..71c9bfb 100644 --- a/20170613-mock/code/ggee/tests/test_game.py +++ b/20170613-mock/code/ggee/tests/test_game.py @@ -88,6 +88,13 @@ def test_your_guess_quit(mock_stdout, mock_readline, mock_lang): ) +def test_PromptGGEE(): + prompt = game.PromptGGEE(level=3, max_num=7, num=5) + assert '{0:0} {0:1} {0:2}'.format(prompt) == '3 7 5' + assert '{a} {b:1} {c}'.format(a='a', b=prompt, c='c') == 'a 7 c' + assert 'simple'.format(prompt) == 'simple' + + @pytest.mark.parametrize('guesses,expected_messages', [ ([4, 6, 5], [ # full scenario "Level 3: 0 to 7", From a1d88d68916cbe565f2d735600b0d600c4f30415 Mon Sep 17 00:00:00 2001 From: eliadl Date: Sat, 10 Jun 2017 15:33:21 +0300 Subject: [PATCH 4/5] Use PromptGGEE in game.play (+fix test) --- 20170613-mock/code/ggee/guessing/game.py | 6 +++--- 20170613-mock/code/ggee/tests/test_game.py | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/20170613-mock/code/ggee/guessing/game.py b/20170613-mock/code/ggee/guessing/game.py index 6ad0bcb..60d6e10 100755 --- a/20170613-mock/code/ggee/guessing/game.py +++ b/20170613-mock/code/ggee/guessing/game.py @@ -76,14 +76,14 @@ def think_of_a_number(level): def play(level): # type: (int) -> None - print(T("Level {level}: 0 to {max_num}").format( - level=level, max_num=max_number(level))) num = think_of_a_number(level) + prompt = PromptGGEE(level=level, max_num=max_number(level), num=num) + print(T("Level {0:0}: 0 to {0:1}").format(prompt)) while True: print(T("Can you guess what number I am thinking about?")) guess = your_guess() if guess is None: - print(T("Just wanted you to know that I was thinking about {}").format(num)) + print(T("Just wanted you to know that I was thinking about {0:2}").format(prompt)) break if guess < num: print(T("No, my number is bigger than that")) diff --git a/20170613-mock/code/ggee/tests/test_game.py b/20170613-mock/code/ggee/tests/test_game.py index 71c9bfb..a0c15c7 100644 --- a/20170613-mock/code/ggee/tests/test_game.py +++ b/20170613-mock/code/ggee/tests/test_game.py @@ -97,7 +97,7 @@ def test_PromptGGEE(): @pytest.mark.parametrize('guesses,expected_messages', [ ([4, 6, 5], [ # full scenario - "Level 3: 0 to 7", + "Level {0:0}: 0 to {0:1}", "Can you guess what number I am thinking about?", "No, my number is bigger than that", "Can you guess what number I am thinking about?", @@ -106,12 +106,12 @@ def test_PromptGGEE(): "Yes, this is the number I was thinking about! How did you know that?", ]), ([None], [ # empty scenario - "Level 3: 0 to 7", + "Level {0:0}: 0 to {0:1}", "Can you guess what number I am thinking about?", - "Just wanted you to know that I was thinking about 5", + "Just wanted you to know that I was thinking about {0:2}", ]), ([5], [ # lucky scenario - "Level 3: 0 to 7", + "Level {0:0}: 0 to {0:1}", "Can you guess what number I am thinking about?", "Yes, this is the number I was thinking about! How did you know that?", ]), @@ -128,4 +128,8 @@ def test_play(mock_stdout, mock_T, guesses, expected_messages): game.play(level) assert mock_T.call_args_list == map(mock.call, expected_messages) - assert mock_stdout.getvalue() == '\n'.join(expected_messages) + '\n' + + prompt = game.PromptGGEE(level=level, max_num=7, num=num) + printed_messages = [msg.format(prompt) + '\n' + for msg in expected_messages] + assert mock_stdout.getvalue() == ''.join(printed_messages) From c902112a9644c850cd7d8c22dd926304ab572aad Mon Sep 17 00:00:00 2001 From: eliadl Date: Sat, 10 Jun 2017 15:44:00 +0300 Subject: [PATCH 5/5] Fix StringIO import --- 20170613-mock/code/ggee/tests/test_game.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/20170613-mock/code/ggee/tests/test_game.py b/20170613-mock/code/ggee/tests/test_game.py index a0c15c7..15c0b09 100644 --- a/20170613-mock/code/ggee/tests/test_game.py +++ b/20170613-mock/code/ggee/tests/test_game.py @@ -3,10 +3,9 @@ import pytest try: - from io import StringIO -except ImportError: - #from io import BytesIO as StringIO from StringIO import StringIO +except ImportError: + from io import StringIO try: from unittest import mock