
Screenshot of the Tkinter GUI.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Base64 File Converter
=====================
This module offers a command line interface as well as a Tkinter-based
graphical interface to convert files to and from Base64 encoding. It uses the
``base64`` module that is included in the Python distribution. See
`RFC 1521`_ for more information on Base64 encoding.
.. _RFC 1521: http://www.faqs.org/rfcs/rfc1521.html
:Copyright: 2004-2008 Jochen Kupperschmidt
:Date: 19-Nov-2008 (previous release: 11-Oct-2004)
:License: GNU General Public License
"""
from __future__ import with_statement
import base64
import binascii
from optparse import OptionParser
import os.path
import sys
import Tkinter as tk
import tkFileDialog
import tkMessageBox
def convert(filename_in, filename_out, decode=False):
"""Read from ``filename_in`` and write to ``filename_out``.
Encode the data if ``decode`` is false (the default), decode if it is true.
"""
with open(filename_in, 'rb') as f_in:
if filename_out is None:
f_out = sys.stdout
else:
f_out = open(filename_out, 'wb')
func = base64.decode if decode else base64.encode
try:
func(f_in, f_out)
except binascii.Error, errstr:
print >> sys.stderr, errstr
if filename_out is not None:
f_out.close()
class GUI(tk.Tk):
"""A Tkinter frontend."""
def __init__(self):
"""Create and lay out widgets."""
tk.Tk.__init__(self)
self.title('Base64 File Converter')
# Set up filename and mode variables.
self.filename_in = tk.StringVar()
self.filename_out = tk.StringVar()
self.decode = tk.BooleanVar()
self.decode.set(False)
# Create filename widgets.
for row, (label, var, cmd) in enumerate((
('Input', self.filename_in, self.get_in_filename),
('Output', self.filename_out, self.get_out_filename),
)):
tk.Label(self, text=label + ' File:') \
.grid(row=row, column=0, sticky=tk.W)
tk.Entry(self, textvariable=var) \
.grid(row=row, column=1, sticky=tk.W + tk.E)
tk.Button(self, text='Browse', command=cmd) \
.grid(row=row, column=2)
# Create mode selection and execution widgets.
tk.Label(self, text='Mode:').grid(row=2, column=0, sticky=tk.W)
modes = (('encode', False), ('decode', True))
for row, (label, value) in enumerate(modes):
tk.Radiobutton(self, text=label, variable=self.decode, value=value,
anchor=tk.W).grid(row=(row + 2), column=1, sticky=tk.W)
tk.Button(self, text='Convert', command=self.convert) \
.grid(row=2, column=2, rowspan=2)
self.columnconfigure(1, weight=1)
self.rowconfigure(4, weight=1)
def get_in_filename(self):
"""Ask user for the input filename."""
self.filename_in.set(tkFileDialog.askopenfilename())
def get_out_filename(self):
"""Ask user for the output filename."""
self.filename_out.set(tkFileDialog.askopenfilename())
def convert(self):
"""Execute the conversion."""
if not self.filename_in.get():
tkMessageBox.showerror('Error', 'No input filename specified.')
return
if not self.filename_out.get():
tkMessageBox.showerror('Error', 'No output filename specified.')
return
print '%s from %s to %s ...' % (
(self.decode.get() and 'Decoding' or 'Encoding'),
os.path.basename(self.filename_in.get()),
os.path.basename(self.filename_out.get())
)
try:
convert(self.filename_in.get(), self.filename_out.get(),
self.decode.get())
tkMessageBox.showinfo('Info', 'Conversion complete.')
except IOError, exc:
tkMessageBox.showerror('Error', exc)
def main():
parser = OptionParser()
parser.add_option('-c', '--cli', dest='gui',
action='store_false', help='use the command line interface (default)')
parser.add_option('-d', '--decode', dest='decode',
action='store_true', help='decode the data')
parser.add_option('-e', '--encode', dest='decode',
action='store_false', help='encode the data (default)')
parser.add_option('-g', '--gui', dest='gui',
action='store_true', help='use the user graphical interface')
parser.add_option('-i', '--input', dest='input',
metavar='FILE', help='input filename')
parser.add_option('-o', '--output', dest='output',
metavar='FILE', help='output filename')
parser.set_defaults(decode=False, gui=False)
opts, args = parser.parse_args()
if opts.gui:
# Use the graphical user interface.
GUI().mainloop()
return
# Use the command line interface.
if not opts.input:
parser.error('Please specify an input filename.')
parser.print_help()
parser.exit()
try:
convert(opts.input, opts.output, opts.decode)
except IOError, (errno, errstr):
print >> sys.stderr, 'Error:', errstr
if __name__ == '__main__':
main()