Read Programming Python Online

Authors: Mark Lutz

Tags: #COMPUTERS / Programming Languages / Python

Programming Python (148 page)

BOOK: Programming Python
2.79Mb size Format: txt, pdf, ePub
ads
Reply and Forward buttons on view windows,
too?

Minor potential ergonomic improvement: we could include Reply
and Forward buttons on the message view windows, too, instead of
requiring these operations to be selected in mail list windows only.
As this system’s sole user, I prefer the uncluttered appearance and
conceptual simplicity of the current latter approach; GUIs have a
way of getting out of hand when persistent pop-up windows start
nesting too deeply. It would be trivial to have Reply/Forward on
view windows, too, though; they could probably fetch mail components
straight from the GUI instead of reparsing a message.

Omit Bcc header in view windows?

Minor nit: mail view windows may be better off omitting the
Bcc header even if it’s enabled in the configuration file. Since it
shouldn’t be present once a mail is sent, it really needs to be
included in composition windows only. It’s displayed as is anyhow,
to verify that Bcc is omitted on sends (the prior edition did not),
to maintain a uniform look for all mail windows, to avoid
special-casing this in the code, and to avoid making such ergonomic
decisions in the absence of actual user feedback.

Check for empty Subject lines?

Minor usability issue: it would be straightforward to add a
check for an empty Subject field on sends and to pop up a
verification dialog to give the user a second chance to fill the
field in. A blank subject is probably unintended. We could do the
same for the To field as well, though there may be valid use cases
for omitting this from mail headers (the mail is still sent to Cc
and Bcc recipients).

Removing duplicate recipients more
accurately?

As is, the send operation attempts to remove duplicate
recipients using set operations. This works, but it may be
inaccurate if the same email address appears twice with a different
name component (e.g., “
name1
,
name2
”). To do better, we could
fully parse the recipient addresses to extract and compare just the
address portion of the full email address. Arguably, though, it’s
not clear what
should
be done if the same
recipient address appears with different names. Could multiple
people be using the same email account? If not, which name should we
choose to use?

For now, end user or mail server intervention may be required
in the rare cases where this might crop up. In most cases, other
email clients will likely handle names in consistent ways that make
this a moot point. On related notes, Reply removes duplicates in Cc
prefills in the same simplistic way, and both sends and replies
could use case-insensitive string comparisons when filtering for
duplicates.

Handling newsgroup messages, too?

Because Internet
newsgroup posts are similar in structure to emails
(header lines plus body text; see the
nntplib
example in
Chapter 13
), this script could in principle
be extended to display both email messages and news articles.
Classifying such a mutation as clever generalization or diabolical
hack is left as an exercise in itself.

SMTP sends may not work in some network
configurations?

On my home/office network, SMTP works fine and as shown for
sending emails, but I have occasionally seen sends have issues on
public networks of the sort available in hotels and airports. In
some cases, mail sends can fail with exceptions and error messages
in the GUI; in worst cases, such sends might fail with no exception
at all and without reporting an error in the GUI. The mail simply
goes nowhere, which is obviously less than ideal if its content
matters.

It’s not clear if these issues are related to limitations of
the networks used, of Python’s
smtplib
, or of the
ISP-provided SMTP server I use. Unfortunately, I ran out of time to
recreate the problem and investigate further (again, a system with a
single user also has just a single tester).

Resolving any such issues is left as an exercise for the
reader, but as a caution: if you wish to use the system to send
important emails, you should first test sends in a new network
environment to ensure that they will be routed correctly. Sending an
email to yourself and verifying receipt should suffice.

Performance tuning?

Almost all of the
work done on this system to date has been related to
its functionality. The system does allow some operation threads to
run in parallel, and optimizes mail downloads by fetching just
headers initially and caching already-fetched full mail text to
avoid refetching. Apart from this, though, its performance in terms
of CPU utilization and memory requirements has not been explored in
any meaningful way at all. That’s for the best—in general we code
for utility and clarity first in Python, and deal with performance
later if and only if needed. Having said that, a broader audience
for this program might mandate some performance analysis and
improvement.

For example, although the full text of fetched mails is kept
just once in a cache, each open view of a message retains a copy of
the parsed mail in memory. For large mails, this may impact memory
growth. Caching parsed mails as well might help decrease memory
footprints, though these will still not be small for large mails,
and the cache might hold onto memory longer than required if not
intelligently designed. Storing messages or their parts in files
(perhaps as pickled objects) instead of in memory might alleviate
some growth, too, though that may also require a mechanism for
reaping temporary files. As is, Python’s garbage collector should
reclaim all such message space eventually as windows are closed, but
this can depend upon how and where we retain object references. See
also the
gc
standard library
modules for possible pointers on finer-grained garbage collection
control.

Unicode model tuning?

As discussed in
brief at the start of this chapter and in full in
Chapter 13
, PyMailGUI’s support for
Unicode encoding of message text and header components is broad, but
not necessarily as general or universally applicable as it might be.
Some Unicode limitations here stem from the limitations of the
email
package in
Python 3.1
upon which PyMailGUI
heavily depends. It may be difficult for Python-coded email clients
to support some features better until Python’s libraries do,
too.

Moreover, the Unicode support that is present in this program
has been tested neither widely nor rigorously. Just like
Chapter 11
’s PyEdit, this is currently still
a single-user system designed to work as a book example, not an open
source project. Because of that, some of the current Unicode
policies are partially heuristic in nature and may have to be honed
with time and practice.

For example, it may prove better in the end to use UTF-8
encoding (or none at all) for sends in general, instead of
supporting some of the many user options which are included in this
book for illustration purposes. Since UTF-8 can represent most
Unicode code points, it’s broadly applicable.

More subtly, we might also consider propagating the main text
part’s Unicode encoding to the embedded PyEdit component in view and
edit windows, so it can be used as a known encoding by the PyEdit
Save button. As is, users can pop up the main text’s part in view
windows to save with a known encoding automatically, but saves of
drafts for mails being edited fall back on PyEdit’s own Unicode
policies and GUI prompts. The ambiguous encoding for saved drafts
may be unavoidable, though—users might enter characters from any
character set, both while writing new mails from scratch and while
editing the text of replies and forwards (just like headers in
replies and forwards, the initial known encoding of the original
main text part may no longer apply after arbitrary edits).

In addition, there is no support for non-ASCII encodings of
full mail text, it’s not impossible that i18n encoded text might
appear in other contexts in rare emails (e.g., in attachment
filenames, whose undecoded form may or may not be valid on the
receiving platform’s filesystem, and may require renaming if allowed
at all), and although Internationalization is supported for mail
content, the GUI itself still uses English for its buttons, labels,
and titles—something that a truly location-neutral program may wish
to address.

In other words, if this program were to ever take the leap to
commercial-grade or broadly used software, its Unicode story would
probably have to be revisited. Also discussed in
Chapter 13
, a future release of the
email
package may solve some Unicode
issues automatically, though PyMailGUI may also require updates for
the solutions, as well as for incompatibilities introduced by them.
For now, this will have to stand as a useful object lesson in
itself: for both better and worse, such changes will always be a
fact of life in the constantly evolving world of software
development.

And so on—because this software is open source, it is also
necessarily open-ended. Ultimately, writing a complete email client is a
substantial undertaking, and we’ve taken this example as far as we can in
this book. To move PyMailGUI further along, we’d probably have to consider
the suitability of both the underlying Python 3.1
email
package, as well as the tkinter GUI
toolkit. Both are fully sufficient for the utility we’ve implemented here,
but they might limit further progress.

For example, the current lack of an HTML viewer widget in the base
tkinter toolkit precludes HTML mail viewing and composition in the GUI
itself. Moreover, although PyMailGUI broadly supports Internationalization
today, it must rely on workarounds to get
email
to work at all. To be fair, some of
the
email
package’s issues
described in this book will likely be fixed by the time you read about
them, and email in general is probably close to a worst case for
Internationalization issues brought into the spotlight by Unicode
prominence in Python 3.X. Still, such tool constraints might impede
further system evolution.

On the other hand, despite any limitations in the tools it deploys,
PyMailGUI does achieve all its goals—it’s an arguably full-featured and
remarkably quick desktop email client, which works surprisingly well for
my emails and preferences and performs admirably on the cases I’ve tested
to date. It may not satisfy your tastes or constraints, but it is open to
customization and imitation. Suggested exercises and further tweaking are
therefore officially delegated to your imagination; this is Python, after
all.

This concludes our tour of Python client-side protocols programming.
In the next chapter, we’ll hop the fence to the other side of the Internet
world and explore scripts that run on server machines. Such programs give
rise to the grander notion of applications that live entirely on the Web
and are launched by web browsers. As we take this leap in structure, keep
in mind that the tools we met in this and the previous chapter are often
sufficient to implement all the distributed processing that many
applications require, and they can work in harmony with scripts that run
on a server. To completely understand the Web world view, though, we need
to explore the server
realm, too.

Chapter 15. Server-Side Scripting
“Oh, What a Tangled Web We Weave”

This chapter is the fourth part of
our look at Python Internet programming. In the last three
chapters, we explored sockets and basic client-side programming interfaces
such as FTP and email. In this chapter, our main focus will be on writing
server-side scripts in Python—a type of program usually referred to as
CGI scripts
. Though something of a lowest common
denominator for web development today, such scripts still provide a simple
way to get started with implementing interactive websites in
Python.

Server-side scripting and its derivatives are at the heart of much
of the interaction that happens on the Web. This is true both when
scripting manually with CGI and when using the higher-level frameworks
that automate some of the work. Because of that, the fundamental web model
we’ll explore here in the context of CGI scripting is prerequisite
knowledge for programming the Web well, regardless of the tools you choose
to deploy.

As we’ll see, Python is an ideal language for writing scripts to
implement and customize websites, because of both its ease of use and its
library support. In the following chapter, we will use the basics we learn
in this chapter to implement a full-blown website. Here, our goal is to
understand the fundamentals of server-side scripting, before exploring
systems that deploy or build upon that basic model.

A House upon the Sand

As you read the next two chapters of this book, please keep in
mind that they focus on the fundamentals of server-side scripting and
are intended only as an introduction to programming in this domain with
Python. The web domain is large and complex, changes rapidly and
constantly, and often prescribes many ways to accomplish a given
goal—some of which can vary from browser to browser and server to
server.

For instance, the password encryption scheme of the next chapter
may be unnecessary under certain scenarios (with a suitable server, we
could use secure HTTP instead). Moreover, some of the HTML we’ll use
here may not leverage all of that language’s power, and may even not
conform to current HTML standards. In fact, much of the material added
in later editions of this book reflects recent technology shifts in this
domain.

Given such a large and dynamic field, this part of the book does
not even pretend to be a complete look at the server-side scripting
domain. That is, you should not take this text to be a final word on the
subject. To become truly proficient in this area, you should also expect
to spend some time studying other texts for additional
webmaster-y
details and techniques—for
example,
Chuck Musciano and Bill
Kennedy’s
HTML
& XHTML: The Definitive Guide
(O’Reilly).

The good news is that here you will explore the core ideas behind
server-side programming, meet Python’s CGI tool set, and learn enough to
start writing substantial websites of your own in Python. This knowledge
should apply to wherever the Web or you head next.

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

Other books

How to be a Husband by Tim Dowling
The Power of the Dead by Henry Williamson
Miracle on I-40 by Curtiss Ann Matlock
Awakening by Ella Price
Breaking the Fall by Michael Cadnum
Spy-in-Training by Jonathan Bernstein
Me and Kaminski by Daniel Kehlmann
Bared Blade by Kelly McCullough