Read Programming Python Online

Authors: Mark Lutz

Tags: #COMPUTERS / Programming Languages / Python

Programming Python (146 page)

BOOK: Programming Python
9.28Mb size Format: txt, pdf, ePub
ads
textConfig: Customizing Pop-Up PyEdit Windows

The prior
section’s
mailconfig
module provides user settings for tailoring the PyEdit component used to
view and edit main mail text, but PyMailGUI also uses PyEdit to display
other kinds of pop-up text, including raw mail text, some text
attachments, and source code in its help system. To customize display
for these pop ups, PyMailGUI relies on PyEdit’s own utility, which
attempts to load a module like that in
Example 14-10
from the client
application’s own directory. By contrast, PyEdit’s Unicode settings are
loaded from the single
textConfig
module in its own package’s directory since they are not expected to
vary across a platform (see
Chapter 11
for
more details).

Example 14-10. PP4E\Internet\Email\PyMailGui\textConfig.py

"""
customize PyEdit pop-up windows other than the main mail text component;
this module (not its package) is assumed to be on the path for these settings;
PyEdit Unicode settings come from its own package's textConfig.py, not this;
"""
bg = 'beige' # absent=white; colorname or RGB hexstr
fg = 'black' # absent=black; e.g., 'beige', '#690f96'
# etc -- see PP4E\Gui\TextEditor\textConfig.py
# font = ('courier', 9, 'normal')
# height = 20 # Tk default: 24 lines
# width = 80 # Tk default: 80 characters
PyMailGUIHelp: User Help Text and Display

Finally,
Example 14-11
lists the
module that defines the text displayed in PyMailGUI’s help
pop up as one triple-quoted string, as well as a function for displaying
the HTML rendition of this text. The HTML version of help itself is in a
separate file not listed in full here but included in the book’s
examples package.

In fact, I’ve omitted most of the help text string, too, to
conserve space here (it spanned 11 pages in the prior edition, and would
be longer in this one!). For the full story, see this module in the
examples package, or run PyMailGUI live and click the help bar at the
top of its main server list window to learn more about how PyMailGUI’s
interface operates. If fact, you probably should; the help display may
explain some properties of PyMailGUI not introduced by the demo and
other material earlier in this chapter.

The HTML rendition of help includes section links, and is popped
up in a web browser. Because the text version also is able to pop up
source files and minimizes external dependencies (HTML fails if no
browser can be located), both the text and HTML versions are provided
and selected by users in the
mailconfig
module. Other schemes are possible
(e.g., converting HTML to text by parsing as a fallback option), but
they are left as suggested improvements.

Example 14-11. PP4E\Internet\PyMailGui\PyMailGuiHelp.py (partial)

"""
##########################################################################
PyMailGUI help text string and HTML display function;
History: this display began as an info box pop up which had to be
narrow for Linux; it later grew to use scrolledtext with buttons
instead; it now also displays an HTML rendition in a web browser;
2.1/3E: the help string is stored in this separate module to avoid
distracting from executable code. As coded, we throw up this text
in a simple scrollable text box; in the future, we might instead
use an HTML file opened with a browser (use webbrowser module, or
run a "browser help.html" or DOS "start help.html" with os.system);
3.0/4E: the help text is now also popped up in a web browser in HTML
form, with lists, section links, and separators; see the HTML file
PyMailGuiHelp.html in the examples package for the simple HTML
translation of the help text string here, popped up in a browser;
both the scrolled text widget and HTML browser forms are currently
supported: change mailconfig.py to use the flavor(s) you prefer;
##########################################################################
"""
# new HTML help for 3.0/4E
helpfile = 'PyMailGuiHelp.html' # see book examples package
def showHtmlHelp(helpfile=helpfile):
"""
3.0: popup HTML version of help file in a local web browser via webbrowser;
this module is importable, but html file might not be in current working dir
"""
import os, webbrowser
mydir = os.path.dirname(__file__) # dir of this module's filename
mydir = os.path.abspath(mydir) # make absolute: may be .., etc
webbrowser.open_new('file://' + os.path.join(mydir, helpfile))
##########################################################################
# string for older text display: client responsible for GUI construction
##########################################################################
helptext = """PyMailGUI, version 3.0
May, 2010 (2.1 January, 2006)
Programming Python, 4th Edition
Mark Lutz, for O'Reilly Media, Inc.
PyMailGUI is a multiwindow interface for processing email, both online and
offline. Its main interfaces include one list window for the mail server,
zero or more list windows for mail save files, and multiple view windows for
composing or viewing emails selected in a list window. On startup, the main
(server) list window appears first, but no mail server connection is attempted
until a Load or message send request. All PyMailGUI windows may be resized,
which is especially useful in list windows to see additional columns.
Note: To use PyMailGUI to read and write email of your own, you must change
the POP and SMTP server names and login details in the file mailconfig.py,
located in PyMailGUI's source-code directory. See section 11 for details.
Contents:
0) VERSION ENHANCEMENTS
1) LIST WINDOW ACTIONS
2) VIEW WINDOW ACTIONS
3) OFFLINE PROCESSING
4) VIEWING TEXT AND ATTACHMENTS
5) SENDING TEXT AND ATTACHMENTS
6) MAIL TRANSFER OVERLAP
7) MAIL DELETION
8) INBOX MESSAGE NUMBER SYNCHRONIZATION
9) LOADING EMAIL
10) UNICODE AND INTERNATIONALIZATION SUPPORT
11) THE mailconfig CONFIGURATION MODULE
12) DEPENDENCIES
13) MISCELLANEOUS HINTS ("Cheat Sheet")
...rest of file omitted...
13) MISCELLANEOUS HINTS ("Cheat Sheet")
- Use ',' between multiple addresses in To, Cc, and Bcc headers.
- Addresses may be given in the full '"name" ' form.
- Payloads and headers are decoded on fetches and encoded on sends.
- HTML mails show extracted plain text plus HTML in a web browser.
- To, Cc, and Bcc receive composed mail, but no Bcc header is sent.
- If enabled in mailconfig, Bcc is prefilled with sender address.
- Reply and Fwd automatically quote the original mail text.
- If enabled, replies prefill Cc with all original recipients.
- Attachments may be added for sends and are encoded as required.
- Attachments may be opened after View via Split or part buttons.
- Double-click a mail in the list index to view its raw text.
- Select multiple mails to process as a set: Ctrl|Shift + click, or All.
- Sent mails are saved to a file named in mailconfig: use Open to view.
- Save pops up a dialog for selecting a file to hold saved mails.
- Save always appends to the chosen save file, rather than erasing it.
- Split asks for a save directory; part buttons save in ./TempParts.
- Open and save dialogs always remember the prior directory.
- Use text editor's Save to save a draft of email text being composed.
- Passwords are requested if/when needed, and not stored by PyMailGUI.
- You may list your password in a file named in mailconfig.py.
- To print emails, "Save" to a text file and print with other tools.
- See the altconfigs directory for using with multiple email accounts.
- Emails are never deleted from the mail server automatically.
- Delete does not reload message headers, unless it fails.
- Delete checks your inbox to make sure it deletes the correct mail.
- Fetches detect inbox changes and may automatically reload the index.
- Any number of sends and disjoint fetches may overlap in time.
- Click this window's Source button to view PyMailGUI source-code files.
- Watch http://www.rmi.net/~lutz for updates and patches
- This is an Open Source system: change its code as you like.
"""
if __name__ == '__main__':
print(helptext) # to stdout if run alone
input('Press Enter key') # pause in DOS console pop ups

See the examples package for the HTML help file, the first few
lines of which are shown in
Example 14-12
; it’s a simple
translation of the module’s help text string (adding a bit more pizzazz
to this page is left in the suggested exercise column).

Example 14-12. PP4E\Internet\PyMailGui\PyMailGuiHelp.html (partial)


PyMailGUI 3.0 Help


PyMailGUI, Version 3.0



May, 2010 (2.1 January, 2006)

Programming Python, 4th Edition

Mark Lutz, for O'Reilly Media, Inc.


PyMailGUI is a multiwindow interface for processing email, both online and
...rest of file omitted...

altconfigs: Configuring for Multiple Accounts

Though
not an “official” part of the system, I use a few
additional short files to launch and test it. If you have multiple email
accounts, it can be inconvenient to change a configuration file every
time you want to open one in particular. Moreover, if you open multiple
PyMailGUI sessions for your accounts at the same time, it would be
better if they could use custom appearance and behavior schemes to make
them distinct.

To address this, the
altconfigs
directory in the examples source directory provides a simple way to
select an account and configurations for it at start-up time. It defines
a new top-level script which tailors the module import search path,
along with a
mailconfig
that prompts
for and loads a custom configuration module whose suffix is named by
console input. A launcher script is also provided to run without module
search path configurations—from PyGadgets or a desktop shortcut, for
example, without requiring PYTHONPATH settings for the PP4E root.
Examples
14-13
through
14-17
list the files involved.

Example 14-13. PP4E\Internet\PyMailGui\altconfigs\PyMailGui.py

import sys                             # ..\PyMailGui.py or 'book' for book configs
sys.path.insert(1, '..') # add visibility for real dir
exec(open('../PyMailGui.py').read()) # do this, but get mailconfig here

Example 14-14. PP4E\Internet\PyMailGui\altconfigs\mailconfig.py

above = open('../mailconfig.py').read()       # copy version above here (hack?)
open('mailconfig_book.py', 'w').write(above) # used for 'book' and as others' base
acct = input('Account name?') # book, rmi, train
exec('from mailconfig_%s import *' % acct) # . is first on sys.path

Example 14-15. PP4E\Internet\PyMailGui\altconfigs\mailconfig_rmi.py

from mailconfig_book import *                 # get base in . (copied from ..)
popservername = 'pop.rmi.net' # this is a big inbox: 4800 emails!
popusername = 'lutz'
myaddress = '[email protected]'
listbg = 'navy'
listfg = 'white'
listHeight = 20 # higher initially
viewbg = '#dbbedc'
viewfg = 'black'
wrapsz = 80 # wrap at 80 cols
fetchlimit = 300 # load more headers

Example 14-16. PP4E\Internet\PyMailGui\altconfigs\mailconfig_train.py

from mailconfig_book import *                 # get base in . (copied from ..)
popusername = '[email protected]'
myaddress = '[email protected]'
listbg = 'wheat' # goldenrod, dark green, beige
listfg = 'navy' # chocolate, brown,...
viewbg = 'aquamarine'
viewfg = 'black'
wrapsz = 80
viewheaders = None # no Bcc
fetchlimit = 100 # load more headers

Example 14-17. PP4E\Internet\PyMailGui\altconfigs\launch_PyMailGui.py

# to run without PYTHONPATH setup (e.g., desktop)
import os # Launcher.py is overkill
os.environ['PYTHONPATH'] = r'..\..\..\..\..' # hmm; generalize me
os.system('PyMailGui.py') # inherits path env var

Account files like those in Examples
14-15
and
14-16
can import the base “book” module (to
extend it) or not (to replace it entirely). To use these alternative
account configurations, run a command line like the following or run the
self
-
configuring
launcher script in
Example 14-17
from any location.
Either way, you can open these account’s windows to view the included
saved mails, but be sure to change configurations for your own email
accounts and preferences first if you wish to fetch or send mail from
these clients:

C:\...\PP4E\Internet\Email\PyMailGui\altconfigs>
PyMailGui.py
Account name?
rmi

Add a “start” to the beginning of this command to keep your
console alive on Windows so you can open multiple accounts (try a
“&” at the end on Unix).
Figure 14-45
earlier shows the
scene with all three of my accounts open in PyMailGUI. I keep them open
perpetually on my desktop, since a Load fetches just newly arrived
headers no matter how long the GUI may have sat dormant, and a Send
requires nothing to be loaded at all. While they’re open, the
alternative color schemes make the accounts’ windows distinct. A desktop
shortcut to the launcher script makes opening my accounts even
easier.

As is, account names are only requested when this special
PyMailGui.py
file is run directly,
and not when the original file is run directly or by program launchers
(in which case there may be no
stdin
to read). Extending a module like
mailconfig
which might be imported in multiple
places this way turns out to be an interesting task (which is largely
why I don’t consider its quick solution here to be an official end-user
feature). For instance, there are other ways to allow for multiple
accounts, including:

  • Changing the single
    mailconfig
    module in-place

  • Importing alternative modules and storing them as key
    “mailconfig” in
    sys.modules

  • Copying alternative module variables to
    mailconfig
    attributes using
    __dict__
    and
    setattr

  • Using a class for configuration to better support
    customization in subclasses

  • Issuing a pop-up in the GUI to prompt for an account name
    after or before the main window appears

And so on. The separate subdirectory scheme used here was chosen
to minimize impacts on existing code in general; to avoid changes to the
existing
mailconfig
module
specifically (which works fine for the single account case); to avoid
requiring extra user input of any kind in single account cases; and to
allow for the fact that an “import module1 as module2” statement doesn’t
prevent “module1” from being imported directly later. This last point is
more fraught with peril than you might expect—importing a customized
version of a module is not merely a matter of using the “as” renaming
extension:

import m1 as m2      # custom import: load m1 as m2 alternative
print(m2.attr) # prints attr in m1.py
import m2 # later imports: loads m2.py anyhow!
print(m2.attr) # prints attr in m2.py

In other words, this is a quick-and-dirty solution that I
originally wrote for testing purposes, and it seems a prime candidate
for improvement—along with the other ideas in the next section’s chapter
wrap up.

BOOK: Programming Python
9.28Mb size Format: txt, pdf, ePub
ads

Other books

Thank You, Goodnight by Andy Abramowitz
Backstreet Child by Harry Bowling
Tomorrow’s World by Davie Henderson
Blood and Ashes by Matt Hilton
Sensual Danger by Tina Folsom
The Cortés Enigma by John Paul Davis
A Classic Crime Collection by Edgar Allan Poe
The Fever by Megan Abbott