Started on documentation
[szyfrow.git] / szyfrow / support / utilities.py
index 7319621c1fbfdfa7cf650912d288401189482057..80008e9629dfb9d06eda531406a7958fcb3a9fdc 100644 (file)
@@ -1,16 +1,18 @@
+"""A mish-mash of utility functions"""
+
 import string
 import collections
 import unicodedata
 from itertools import zip_longest
 
-# join a a list of letters into a string
 cat = ''.join
+"""join a a list of letters into a string."""
 
-# join a list of words into a string, separated by spaces
 wcat = ' '.join
+"""join a list of words into a string, separated by spaces"""
 
-# join a list of lines, separated by newline
 lcat = '\n'.join
+"""join a list of lines, separated by newline"""
 
 def pos(letter): 
     """Return the position of a letter in the alphabet (0-25)"""
@@ -25,6 +27,24 @@ def unpos(number):
     """Return the letter in the given position in the alphabet (mod 26)"""
     return chr(number % 26 + ord('a'))
 
+def pad(message_len, group_len, fillvalue):
+    """Return the padding needed to extend a message to a multiple of group_len
+    in length.
+
+    fillvalue can be a function or a literal value. If a function, it is called
+    once for each padded character. Use this with fillvalue=random_english_letter
+    to pad a message with random letters.
+    """
+    padding_length = group_len - message_len % group_len
+    if padding_length == group_len: padding_length = 0
+    padding = ''
+    if callable(fillvalue):
+        for i in range(padding_length):
+            padding += fillvalue()
+    else:
+        padding += fillvalue * padding_length
+    return padding
+
 def every_nth(text, n, fillvalue=''):
     """Returns n strings, each of which consists of every nth character, 
     starting with the 0th, 1st, 2nd, ... (n-1)th character
@@ -66,10 +86,12 @@ def chunks(text, n, fillvalue=None):
     ['abcd', 'efgh', 'i!!!']
     """
     if fillvalue:
-        padding = fillvalue[0] * (n - len(text) % n)
+        # padding = fillvalue[0] * (n - len(text) % n)
+        padding = pad(len(text), n, fillvalue)
+        padded_text = text + padding
     else:
-        padding = ''
-    return [(text+padding)[i:i+n] for i in range(0, len(text), n)]
+        padded_text = text
+    return [(padded_text)[i:i+n] for i in range(0, len(text), n)]
 
 def transpose(items, transposition):
     """Moves items around according to the given transposition
@@ -102,6 +124,9 @@ def untranspose(items, transposition):
     return transposed
 
 def deduplicate(text):
+    """Return the input string, but with second (and subsequent) occurrences
+    of a character removed.
+    """
     return list(collections.OrderedDict.fromkeys(text))
 
 
@@ -152,6 +177,9 @@ def sanitise(text):
 
 
 def index_of_coincidence(text):
+    """Index of coincidence of a string. This is low for random text, 
+    higher for natural langauge.
+    """
     stext = sanitise(text)
     counts = collections.Counter(stext)
     denom = len(stext) * (len(text) - 1) / 26