HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Unix-to-Unix Encoding (Uuencoding)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
unixuuencodingencoding

Problem

Uuencoding is historically used to encode emails. Instructions for creating a Uuencoder are:

  • Start with 3 bytes from the source, 24 bits in total.



  • Split into 4 6-bit groupings, each representing a value in the range 0 to 63: bits (00-05), (06-11), (12-17) and (18-23).



  • Add 32 to each of the values. With the addition of 32 this means that the possible results can be between 32 (" " space) and 95 ("_" underline). 96 ("`" grave accent) as the "special character" is a logical extension of this range.



  • Output the ASCII equivalent of these numbers.



import platform

def dec_to_bin(int):
    return bin(int).replace('0b', '')

def uuencode(string, filename):
    if platform.system() == 'Windows':
        mode = '644'
    elif platform.system() == 'Linux':
        mode = '744'

    trail = 'begin ' + mode + ' ' + filename + '\n'
    string_values = []
    char_list = list(string)
    bytes = ''

    for char in char_list:
        string_values.append(ord(char))

    for ascii in string_values:
        bytes += dec_to_bin(ascii)

    three_byte = [bytes[p:p+24] for p in range(0, len(bytes), 24)]
    if len(three_byte[-1]) < 24:
        three_byte[-1] += (24 - len(three_byte[-1])) * '0'

    four_six_bits = [three_byte[n][m:m+6] for n in range(len(three_byte)) for m in range(0, 24, 6)]
    four_six_bits = [four_six_bits[k:k+4] for k in range(0, len(four_six_bits), 4)]

    decimal_list = []
    for x in range(len(four_six_bits)):
        for z in range(4):
            decimal_list.append(int(four_six_bits[x][z], 2))

    for index, decimal in enumerate(decimal_list):
        decimal_list[index] += 32

    encoded_chars = [chr(decimal_list[o]) for o in range(len(decimal_list))]

    length_char = chr(len(encoded_chars) + 32)
    trail += length_char

    for newchar in encoded_chars:
        trail += newchar

    trail += '\n' + '`' + '\n' + 'end' + '\n'

    return trail

Solution

This is somewhat unstructured, but here are a few recommendations:

Be careful when shadowing built-ins

In dec_to_bin(), the int parameter shadows the Python core int type keyword. This works fine, but it's usually clearer to avoid redefining builtins when you can. Maybe call it num.

bytes is also a builtin. It's ok to redefine them, just be aware.

Variables not always defined

if platform.system() == 'Windows':
    mode = '644'
elif platform.system() == 'Linux':
    mode = '744'

trail = 'begin ' + mode + ' ' + filename + '\n'


What happens if platform.system() is neither Windows or Linux? (For example: on Mac it returns 'Darwin'.) mode will be undefined, raising UnboundLocalError.

Unnecessary conversion to list

char_list = list(string)
...
for char in char_list: ...


Strings are iterable just like lists, so for char in string: works fine.

In fact, consider removing string_values and char_list entirely. You can condense them into:

bytes = ''.join(dec_to_bin(ord(char)) for char in string)


Unused variable

A common convention is to use _ to represent unused vars:

for index, _ in enumerate(decimal_list):
    decimal_list[index] += 32


This shows that you are deliberately ignoring the second value from enumerate.

Code Snippets

if platform.system() == 'Windows':
    mode = '644'
elif platform.system() == 'Linux':
    mode = '744'

trail = 'begin ' + mode + ' ' + filename + '\n'
char_list = list(string)
...
for char in char_list: ...
bytes = ''.join(dec_to_bin(ord(char)) for char in string)
for index, _ in enumerate(decimal_list):
    decimal_list[index] += 32

Context

StackExchange Code Review Q#139488, answer score: 6

Revisions (0)

No revisions yet.