Mercurial > public > enigma
view enigma/main.py @ 40:e7b2424704c1
Document pyenigma.py. Fix bug in keyfile.py.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Mon, 04 Jun 2012 20:05:51 -0500 |
parents | e328fcb6659b |
children |
line wrap: on
line source
# Copyright (C) 2012 by Brian Neal. # This file is part of Py-Enigma, the Enigma Machine simulation. # Py-Enigma is released under the MIT License (see License.txt). """Provide an example command-line app that can setup an EnigmaMachine and process text. """ import argparse import sys from .machine import EnigmaMachine, EnigmaError from .rotors import RotorError from .keyfile import KeyFileError PROG_DESC = 'Encrypt/decrypt text according to Enigma machine key settings' HELP_EPILOG = """\ Key settings can either be specified by command-line arguments, or read from a key file. If reading from a key file, the line labeled with the current day number is used unless the --day argument is provided. Text to process can be supplied 3 ways: if --text=TEXT is present TEXT is processed if --file=FILE is present the contents of FILE are processed otherwise the text is read from standard input Examples: $ %(prog)s --key-file=enigma.keys -s XYZ -t HELLOXWORLDX $ %(prog)s -r III IV V -i 1 2 3 -p AB CD EF GH IJ KL MN -u B -s XYZ $ %(prog)s -r Beta III IV V -i A B C D -p 1/2 3/4 5/6 -u B-Thin -s WXYZ """ def create_from_key_file(filename, day=None): """Create an EnigmaMachine from a daily key sheet.""" with open(filename, 'r') as f: return EnigmaMachine.from_key_file(f, day) def create_from_args(parser, args): """Create an EnigmaMachine from command-line specs.""" if args.rotors is None: parser.error("Please specify 3 or 4 rotors; e.g. II IV V") elif len(args.rotors) not in [3, 4]: parser.error("Expecting 3 or 4 rotors; %d supplied" % len(args.rotors)) if args.text and args.file: parser.error("Please specify --text or --file, but not both") ring_settings = ' '.join(args.ring_settings) if args.ring_settings else None plugboard = ' '.join(args.plugboard) if args.plugboard else None return EnigmaMachine.from_key_sheet(rotors=args.rotors, ring_settings=ring_settings, plugboard_settings=plugboard, reflector=args.reflector) def main(): parser = argparse.ArgumentParser(description=PROG_DESC, epilog=HELP_EPILOG, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-k', '--key-file', help='path to key file for daily settings') parser.add_argument('-d', '--day', type=int, default=None, help='use the settings for day DAY when reading key file') parser.add_argument('-r', '--rotors', nargs='+', metavar='ROTOR', help='rotor list ordered from left to right; e.g III IV I') parser.add_argument('-i', '--ring-settings', nargs='+', metavar='RING_SETTING', help='ring setting list from left to right; e.g. A A J') parser.add_argument('-p', '--plugboard', nargs='+', metavar='PLUGBOARD', help='plugboard settings') parser.add_argument('-u', '--reflector', help='reflector name') parser.add_argument('-s', '--start', help='starting position') parser.add_argument('-t', '--text', help='text to process') parser.add_argument('-f', '--file', help='input file to process') parser.add_argument('-x', '--replace-char', default='X', help=('if the input text contains chars not found on the enigma' ' keyboard, replace with this char [default: %(default)s]')) parser.add_argument('-z', '--delete-chars', default=False, action='store_true', help=('if the input text contains chars not found on the enigma' ' keyboard, delete them from the input')) parser.add_argument('-v', '--verbose', action='store_true', default=False, help='provide verbose output; include final rotor positions') args = parser.parse_args() if args.key_file and (args.rotors or args.ring_settings or args.plugboard or args.reflector): parser.error("Please specify either a key file or command-line key " "settings, but not both") if args.start is None: parser.error("Please specify a start position") if args.key_file: machine = create_from_key_file(args.key_file, args.day) else: machine = create_from_args(parser, args) if args.text: text = args.text elif args.file: with open(args.file, 'r') as f: text = f.read() else: text = input('--> ') replace_char = args.replace_char if not args.delete_chars else None machine.set_display(args.start) s = machine.process_text(text, replace_char=replace_char) if args.verbose: print('Final rotor positions:', machine.get_display()) print('Rotor rotation counts:', machine.get_rotor_counts()) print('Output:') print(s) def console_main(): try: main() except (IOError, EnigmaError, RotorError, KeyFileError) as ex: sys.stderr.write("%s\n" % ex) if __name__ == '__main__': console_main()