Skip to content

Commit

Permalink
Added UserSelection class.
Browse files Browse the repository at this point in the history
  • Loading branch information
von committed Nov 10, 2010
1 parent f7dcd27 commit e7a1697
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -64,6 +64,7 @@ profiles:
# List in order to be tested
UNITTESTS = \
test-testing \
test-Utils \
test-Action \
test-Bitfield \
test-Cards \
Expand Down
69 changes: 68 additions & 1 deletion pyPoker/Utils.py
@@ -1,6 +1,8 @@
"""Internal utility functions"""

import collections
import itertools
import sys

def assertInstance(obj, cls):
if obj is None:
Expand Down Expand Up @@ -49,4 +51,69 @@ def combinations(set, n):
else:
for comb in itertools.combinations(set, n):
yield set.__class__(comb)


class UserSelection(object):
"""Present a user with a menu of options, each selectable with a single
keystroke. Get and return the user's selection."""

_Option = collections.namedtuple('_Option', "description return_value")

def __init__(self,
input_stream=None,
output_stream=None,
prompt="Selection?",
selection_format="({})"):
"""input_stream is the stream from which to receive input
from the user.
output_stream is the stream to which to send output to the user.
prompt is the string presented to the user to prompt for
their selection.
selection_format is the string used to present the selection
format to the user. It must include one '{}' string which will
be replaced by the selection character.
"""
self.input_stream = input_stream \
if input_stream is not None else sys.stdin
self.output_stream = output_stream \
if output_stream is not None else sys.stdout
self.prompt = prompt
self.selection_format = selection_format
self.options = {}

def add_option(self, char, description, return_value):
"""Add an option.
char is the character the user should use to select the option.
description is the string displayed to the user for the option.
return_value is the value returned if the user selects the option.
"""
if char in self.options.keys():
raise ValueError(\
"Selection character \"{}\" already in use".format(char))
self.options[char] = self._Option(description=description,
return_value=return_value)

def get_user_selection(self):
"""Present user with options and get their selection.
Returns selection's associated return_value."""
for char, option in self.options.items():
self.output_stream.write(\
self.selection_format.format(char) +
" {}\n".format(option.description))
self.output_stream.write(self.prompt)
self.output_stream.flush()
while True:
selection = self.input_stream.read(1)
if selection in self.options.keys():
break
# Just ignore non-legal selections
self.output_stream.write("\n")
self.output_stream.flush()
return self.options[selection].return_value

60 changes: 60 additions & 0 deletions unittests/test-Utils.py
@@ -0,0 +1,60 @@
#!/usr/bin/env python
"""Unittests for Utils module"""

import StringIO

import testing

from pyPoker.Utils import UserSelection

class TestSequenceFunctions(testing.TestCase):

def test_UserSelection(self):
"""Test basic UserSelction functionality"""
with self.pipe_to_stdin() as input:
with self.stdout_to_pipe() as output:
user_selection = UserSelection()
self.assertIsNotNone(user_selection)
user_selection.add_option('p',
description="Play",
return_value=0)
user_selection.add_option('q',
description="Quit",
return_value=1)
user_selection.add_option('r',
description="Reset",
return_value=2)
input.write("pyrq")
# 'p' should return 0
self.assertEqual(user_selection.get_user_selection(), 0)
# 'y' should be ignored, 'r' should return 2
self.assertEqual(user_selection.get_user_selection(), 2)
# 'q' should return 1
self.assertEqual(user_selection.get_user_selection(), 1)
lines = output.readlines()
# (Three options plus prompt) times 3 calls to get_user_selection()
# meands we should have 12 lines in output buffer.
self.assertEqual(len(lines), 12)

def test_UserSelection_with_streams(self):
"""Test basic UserSelction with specified streams"""
input_buffer = StringIO.StringIO("pyrq")
output_buffer = StringIO.StringIO()
user_selection = UserSelection(input_stream=input_buffer,
output_stream=output_buffer)
self.assertIsNotNone(user_selection)
user_selection.add_option('p', description="Play", return_value=0)
user_selection.add_option('q', description="Quit", return_value=1)
user_selection.add_option('r', description="Reset", return_value=2)
# 'p' should return 0
self.assertEqual(user_selection.get_user_selection(), 0)
output_buffer.seek(0)
lines = output_buffer.readlines()
self.assertEqual(len(lines), 4) # 3 options plus prompt
# 'y' should be ignored, 'r' should return 2
self.assertEqual(user_selection.get_user_selection(), 2)
# 'q' should return 1
self.assertEqual(user_selection.get_user_selection(), 1)

if __name__ == "__main__":
testing.main()

0 comments on commit e7a1697

Please sign in to comment.