view docs/m209.rst @ 68:30aa114bb746

Added docs for StdProcedure and exceptions.
author Brian Neal <bgneal@gmail.com>
date Sun, 21 Jul 2013 14:03:55 -0500
parents a2647b9fe107
children 2173ac4c2d9b
line wrap: on
line source
M209 Class
==========

Naturally, the ``m209`` library includes a class that simulates a M-209
converter. The :class:`~m209.converter.M209` class allows you to experiment
with all moving parts of an M-209, including encrypting and decrypting
messages. Keep in mind there is a higher level class, StdProcedure, that
encapsulates all the steps of the standard encrypting and decrypting
operations, including generating indicators and placing or removing them from
messages. However if you need lower-level access or you are inventing your own
procedures, you would use the M209 class directly.

.. class:: m209.converter.M209([lugs=None[, pin_list=None]])

   The ``M209`` class takes the following optional arguments.

  :param lugs: either a lug settings list or string as per :meth:`set_drum_lugs`
  :param pin_list: a list of six strings each formatted as per :ref:`pin-settings`

``M209`` objects have the following attributes.

   .. attribute:: letter_count

      This attribute represents the *letter counter* functionality. It is an
      integer that is incremented after every letter is encrypted or decrypted.
      It may be set to any integer value or examined at any time.

``M209`` objects support the following methods.

   .. method:: set_pins(n, effective_pins)

      Sets the pin settings on the specified key wheel ``n``.

      :param n: an integer between 0-5, inclusive. Key wheel 0 is the 
         left-most wheel and wheel 5 is the right-most.

      :param effective_pins: an iterable of letters whose pins are slid to
        the "effective" position (to the right). See :ref:`pin-settings`.

   .. method:: set_all_pins(pin_list)

      Sets all key wheel pins according to the supplied pin list.

      :param pin_list: must either be ``None`` or a 6-element list of strings
         where each string element is as described in :ref:`pin-settings`.
         If ``None``, all pins in all key wheels are moved to the ineffective position.

   .. method:: set_drum_lugs(lug_list)

      Sets the drum lugs according to the given ``lug_list`` parameter.

      If ``lug_list`` is ``None`` or empty, all lugs will be placed in neutral
      positions.

      Otherwise, the ``lug_list`` can either be a list or a string.

      If ``lug_list`` is passed a list, it must be a list of 1 or 2-tuple integers,
      where each integer is between 0-5, inclusive, and represents a 0-based
      key wheel position. The list can not be longer than 27 items. Only lug
      bars with lugs in non-neutral positions need be listed. Lug bars with one
      lug in a non-neutral position are represented by a 1-tuple. Bars with
      2 non-netural lugs are represented as a 2-tuple.

      If ``lug_list`` is passed as a string, it is assumed to be in key list
      format as described in :ref:`lug-settings`.

      Example::

         m = M209()
         m.set_drum_lugs('1-0 2-0*2 0-3 0-5*3 0-6 2-4 3-6')

         # or equivalently
         m.set_drum_lugs([(0, ), (1, ), (1, ), (2, ), (4, ), (4, ), (4, ), (5, ), (1, 3), (2, 5)])


   .. method:: set_key_wheel(n, c)

      Set key wheel ``n`` to the letter ``c``.

      :param n: an integer between 0-5 where key wheel 0 is the leftmost key wheel,
         and 5 is the rightmost
      :param c: a 1-letter string valid for key wheel ``n``
      :raises KeyWheelError: if ``c`` is not valid for wheel ``n``

   .. method:: set_key_wheels(s)

      Set the key wheels from left to right to the six letter string ``s``.

      :raises KeyWheelError: if any letter in ``s`` is not valid for the corresponding key wheel

   .. method:: set_random_key_wheels()

      Sets the six key wheels to random letters.

      :returns: a string of length six representing the new key wheel settings

   .. method:: get_settings()

      Returns the current key settings.

      :returns: a named tuple of ``(lugs, pin_list)`` representing the current
         key settings. ``lugs`` will be in string format.

   .. method:: encrypt(plaintext[, group=True[, spaces=True]])

      Performs an encrypt operation on the given plaintext and returns the
      encrypted ciphertext as a string.

      :param plaintext: the text string to encrypt
      :param group: if ``True``, the ciphertext string will be grouped into 5-letter
         groups, separated by spaces
      :param spaces: if ``True``, space characters in the input plaintext will
         automatically be treated as ``Z`` characters. Otherwise spaces in the
         plaintext will raise an ``M209Error``.
      :returns: the ciphertext as a string

   .. method:: decrypt(ciphertext[, spaces=True[, z_sub=True]])

      Performs a decrypt operation on the given ciphertext and returns the
      decrypted plaintext as a string.

      :param ciphertext: the text string to decyrpt
      :param spaces: if ``True``, spaces will be allowed in the input ciphertext and
         ignored. Otherwise space characters will raise an ``M209Error``.
         This is useful if the input ciphertext is in 5-letter groups, separated
         by spaces.
      :param z_sub: if ``True``, ``Z`` characters in the output plaintext will be
         replaced by space characters, just like an actual M-209.
      :returns: the plaintext as a string

Example:

>>> from m209.converter import M209
>>> m = M209()
>>> m.set_drum_lugs('1-0 2-0*2 0-3 0-5*3 0-6 2-4 3-6')
>>> pin_list = [
...     'FGIKOPRSUVWYZ',
...     'DFGKLMOTUY',
...     'ADEFGIORTUVX',
...     'ACFGHILMRSU',
...     'BCDEFJKLPS',
...     'EFGHIJLMNP'
... ]
>>> m.set_all_pins(pin_list)
>>> m.set_key_wheels('FFEGJP')
>>> ct = m.encrypt('THE PIZZA HAS ARRIVED')
>>> ct
'QBCHU WCCDI YFNCH LOZJY G'
>>> m.set_key_wheels('FFEGJP')
>>> pt = m.decrypt(ct)
>>> pt
'THE PI  A HAS ARRIVED'