changeset 31:853542100fc6

Hooking up main to generate_key_list(). Added logging.
author Brian Neal <bgneal@gmail.com>
date Fri, 21 Jun 2013 15:57:30 -0500
parents 908510c6d02a
children 70673126c158
files m209/keylist/generate.py m209/keylist/key_list.py m209/main.py
diffstat 3 files changed, 55 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/m209/keylist/generate.py	Wed Jun 19 21:09:48 2013 -0500
+++ b/m209/keylist/generate.py	Fri Jun 21 15:57:30 2013 -0500
@@ -6,6 +6,7 @@
 
 import collections
 import itertools
+import logging
 import random
 
 from .key_list import KeyList
@@ -15,6 +16,8 @@
 from .data import GROUP_A, GROUP_B
 
 
+logger = logging.getLogger(__name__)
+
 # Maximum number of attempts to generate valid settings before giving up and
 # raising a M209Error:
 MAX_ATTEMPTS = 128
@@ -60,6 +63,8 @@
     1942, and TM-11-380B, 20 September 1943."
 
     """
+    logger.info("Creating key list %s", indicator)
+
     lugs = generate_lugs()
     pin_list = generate_pin_list()
     letter_check = generate_letter_check(lugs=lugs, pin_list=pin_list)
@@ -124,6 +129,8 @@
     else:
         raise M209Error("generate_pin_list: too many attempts")
 
+    logger.info("Pin list generated in %s iteration(s)", n + 1)
+
     return pin_list
 
 
@@ -147,18 +154,21 @@
     ratio = num_eff / TOTAL_PINS
 
     if not (0.4 <= ratio <= 0.6):
+        logger.info("Pin list ratio check failed: %s", ratio)
         return False
 
     # Check for more than 6 consecutive effective pins on a wheel
 
     for n, pins in enumerate(pin_list):
         if check_consecutive(n, pins):
+            logger.debug("Pin list consecutive effective check failed")
             return False
 
     # Check for more than 6 consecutive ineffective pins on a wheel
 
     for n, pins in enumerate(pin_list):
         if check_consecutive(n, invert_pins(n, pins)):
+            logger.debug("Pin list consecutive ineffective check failed")
             return False
 
     return True
--- a/m209/keylist/key_list.py	Wed Jun 19 21:09:48 2013 -0500
+++ b/m209/keylist/key_list.py	Fri Jun 21 15:57:30 2013 -0500
@@ -2,9 +2,19 @@
 # This file is part of m209, the M-209 simulation.
 # m209 is released under the MIT License (see LICENSE.txt).
 
-"""key_list.py - This module defines the KeyList class."""
+"""This module defines the KeyList class and related functions"""
 
 import collections
+import re
+
+
+VALID_IND_RE = re.compile('^[A-Z]{2}$')
+
 
 KeyList = collections.namedtuple('KeyList',
                 ['indicator', 'lugs', 'pin_list', 'letter_check'])
+
+
+def valid_indicator(indicator):
+    """Returns True if the given indicator is valid and False otherwise."""
+    return True if VALID_IND_RE.match(indicator) else False
--- a/m209/main.py	Wed Jun 19 21:09:48 2013 -0500
+++ b/m209/main.py	Fri Jun 21 15:57:30 2013 -0500
@@ -7,6 +7,11 @@
 
 """
 import argparse
+import logging
+import sys
+
+from .keylist.generate import generate_key_list
+from .keylist.key_list import valid_indicator
 
 
 DESC = "M-209 simulator and utility program"
@@ -23,11 +28,22 @@
     print('Decrypting!', args)
 
 
+def keygen(args):
+    """Key list generation subcommand processor"""
+    print('Creating key list!', args)
+    if not valid_indicator(args.keylist_indicator):
+        sys.exit("Invalid key list indicator\n")
+
+    print(generate_key_list(args.keylist_indicator))
+
+
 def main(argv=None):
     """Entry point for the m209 command-line utility."""
 
     # create the top-level parser
     parser = argparse.ArgumentParser(description=DESC)
+    parser.add_argument('-v', '--verbose', action='store_true',
+        help='enable verbose output')
     subparsers = parser.add_subparsers(title='list of commands',
         description='type %(prog)s {command} -h for help on {command}')
 
@@ -47,15 +63,29 @@
     enc_parser.set_defaults(subcommand=encrypt)
 
     # create the parser for decrypt
-    enc_parser = subparsers.add_parser('decrypt', aliases=['de'],
+    dec_parser = subparsers.add_parser('decrypt', aliases=['de'],
         help='decrypt text')
-    enc_parser.add_argument('-k', '--keylist', default=DEFAULT_KEY_LIST,
+    dec_parser.add_argument('-k', '--keylist', default=DEFAULT_KEY_LIST,
         help='path to key list file [default: %(default)s]')
-    enc_parser.add_argument('-c', '--ciphertext',
+    dec_parser.add_argument('-c', '--ciphertext',
         help='ciphertext string to decrypt; prompted if omitted')
-    enc_parser.set_defaults(subcommand=decrypt)
+    dec_parser.set_defaults(subcommand=decrypt)
+
+    # create the parser for generating key lists
+
+    kg_parser = subparsers.add_parser('keygen', aliases=['kg'],
+        help='generate key list')
+    kg_parser.add_argument('-k', '--keylist', default=DEFAULT_KEY_LIST,
+        help='path to key list file [default: %(default)s]')
+    kg_parser.add_argument('-i', '--keylist-indicator',
+        help='2 letter key list indicator')
+    kg_parser.set_defaults(subcommand=keygen)
 
     args = parser.parse_args(args=argv)
+
+    level = logging.DEBUG if args.verbose else logging.WARNING
+    logging.basicConfig(level=level, format='%(levelname)s:%(message)s')
+
     args.subcommand(args)