# HG changeset patch # User Brian Neal # Date 1385601317 21600 # Node ID 46e1c1e6b56404571c362ab7c66332a6f3d7b06e # Parent 9e44ad188f4aaae04dd3deb42665b7f48f66f7d9 Added from_key_sheet constructor and tests. diff -r 9e44ad188f4a -r 46e1c1e6b564 purple/machine.py --- a/purple/machine.py Wed Nov 27 18:31:48 2013 -0600 +++ b/purple/machine.py Wed Nov 27 19:15:17 2013 -0600 @@ -116,4 +116,48 @@ self.alphabet = alphabet + @classmethod + def from_key_sheet(cls, switches, alphabet=None): + """This class method allows one to construct a Purple97 using + a shorthand notation used by US codebreakers. + switches: must be a string of the form 'a-b,c,d-ef' where + a - starting position of the sixes switch (1-25) + b - starting position of the twenties switch #1 (1-25) + c - starting position of the twenties switch #2 (1-25) + d - starting position of the twenties switch #3 (1-25) + e - which switch is the fast switch (1-3) + f - which switch is the middle switch (1-3) + + Example: '9-1,24,6-23' + + Note that the starting positions here are 1-based since that is the + notation the US codebreakers seemed to have used. + + alphabet: the daily alphabet, same format as in the __init__ function + + """ + try: + sixes, twenties, speed = switches.split('-') + except ValueError: + raise Purple97Error('invalid switches string (-)') + + twenties = twenties.split(',') + if len(twenties) != 3: + raise Purple97Error('invalid twenties position') + + try: + switches_pos = [int(s) - 1 for s in [sixes] + twenties] + except ValueError: + raise Purple97Error('switch positions must be numeric') + + if len(speed) != 2: + raise Purple97Error('invalid switch speed settings') + + try: + fast_switch, middle_switch = int(speed[0]), int(speed[1]) + except ValueError: + raise Purple97Error('switch speed settings must be numeric') + + return cls(switches_pos, fast_switch, middle_switch, alphabet) + diff -r 9e44ad188f4a -r 46e1c1e6b564 purple/tests/test_machine.py --- a/purple/tests/test_machine.py Wed Nov 27 18:31:48 2013 -0600 +++ b/purple/tests/test_machine.py Wed Nov 27 19:15:17 2013 -0600 @@ -64,3 +64,30 @@ self.assertRaises(Purple97Error, Purple97, alpha) alpha = 'M' * 26 self.assertRaises(Purple97Error, Purple97, alpha) + + def test_from_key_sheet(self): + + Purple97.from_key_sheet('9-1,2,3-23') + Purple97.from_key_sheet('1-1,1,1-13') + Purple97.from_key_sheet('25-25,25,25-31') + Purple97.from_key_sheet('5-20,7,18-21', alphabet=string.ascii_uppercase) + + def test_bad_from_key_sheet(self): + + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '0-1,2,3-13') + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '26-1,2,3-13') + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '1-1,0,3-13') + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '1-1,2,26-13') + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '1-1,2,26-03') + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '1-1,2,26-00') + self.assertRaises(SteppingSwitchError, Purple97.from_key_sheet, '1-1,2,26-14') + + self.assertRaises(Purple97Error, Purple97.from_key_sheet, 'bad string') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-2-1,2,26-14') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, 'a-9,2,20-13') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-a,2,20-13') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,a,20-13') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,a-13') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-a3') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-1a') + self.assertRaises(Purple97Error, Purple97.from_key_sheet, '1-9,2,20-123')