Commits

br...@SilentBob.domain.actdsltmp  committed 6f0754f

Moved all development files into src directory

  • Participants
  • Parent commits 3e36a78

Comments (0)

Files changed (156)

File CanonicalScript.rst

-..  index::
-    triple: script; command-line; canonical form
-
-****************************************************************************
-A Canonical Form for Command-Line Programs
-****************************************************************************
-
-Creating Python programs for command-line use involves a certain amount of
-repetitious coding, which can often be left off or forgotten. Here is a form
-which includes everthing.
-
-Note that if you are using Windows, you can add Python programs to your "File
-New" menu and automatically include the above text in the new file. `This
-article <http://articles.techrepublic.com.com/5100-10878_11-5034852.html>`_
-shows you how. Other operating systems have their own automation features.

File CodeManager.py

-# CodeManager.py
-"""
-Extracts, checks and updates code examples in ReST files.
-
-You can just put in the codeMarker and the (indented) first line (containing the
-file path) into your ReST file, then run the update program to automatically
-insert the rest of the file.
-"""
-import os, re, sys, shutil, inspect, difflib
-
-restFiles = [os.path.join(d[0], f) for d in os.walk(".") if not "_test" in d[0]
-             for f in d[2] if f.endswith(".rst")]
-
-class Languages:
-    "Strategy design pattern"
-
-    class Python:
-        codeMarker = "::\n\n"
-        commentTag = "#"
-        listings = re.compile("::\n\n( {4}#.*(?:\n+ {4}.*)*)")
-
-    class Java:
-        codeMarker = "..  code-block:: java\n\n"
-        commentTag = "//"
-        listings = \
-            re.compile(".. *code-block:: *java\n\n( {4}//.*(?:\n+ {4}.*)*)")
-
-def shift(listing):
-    "Shift the listing left by 4 spaces"
-    return [x[4:] if x.startswith("    ") else x for x in listing.splitlines()]
-
-# TEST makes duplicates of the rst files in a test directory to test update():
-dirs = set([os.path.join("_test", os.path.dirname(f)) for f in restFiles])
-if [os.makedirs(d) for d in dirs if not os.path.exists(d)]:
-    [shutil.copy(f, os.path.join("_test", f)) for f in restFiles]
-testFiles = [os.path.join(d[0], f) for d in os.walk("_test")
-             for f in d[2] if f.endswith(".rst")]
-
-class Commands:
-    """
-    Each static method can be called from the command line. Add a new static
-    method here to add a new command to the program.
-    """
-
-    @staticmethod
-    def display(language):
-        "Print all the code listings"
-        for f in restFiles:
-            listings = language.listings.findall(open(f).read())
-            if not listings: continue
-            print '=' * 60 + "\n" + f + "\n" + '=' * 60
-            for n, l in enumerate(listings):
-                print "\n".join(shift(l))
-                if n < len(listings) - 1:
-                    print '-' * 60
-
-    @staticmethod
-    def extract(language):
-        """Pull the code listings from the ReST files and write each
-        listing into its own file"""
-        for f in restFiles:
-            for listing in language.listings.findall(open(f).read()):
-                listing = shift(listing)
-                path = listing[0][len(language.commentTag):].strip()
-                path = os.path.join("_code", path)
-                dirname = os.path.dirname(path)
-                if dirname:
-                    if not os.path.exists(dirname):
-                        os.makedirs(dirname)
-                file(path, 'w').write("\n".join(listing))
-
-    @staticmethod
-    def check(language):
-        "Ensure that external code files exist"
-        missing = []
-        for path in [code.splitlines()[0] for f in restFiles for code in
-                     language.listings.findall(open(f).read())]:
-            path = path.strip()[len(language.commentTag):].strip()
-            path = os.path.normpath(os.path.join("_code", path))
-            if not os.path.exists(path):
-                missing.append(path)
-        if missing:
-            print "Missing", language.__name__, "files:"
-            for p in missing:
-                print p
-        return missing
-
-    @staticmethod
-    def update(language): # Test until it is trustworthy
-        "Refresh external code files into ReST files"
-        if Commands.check(language):
-            print language.__name__, "update aborted"
-            return
-        def _update(matchobj):
-            listing = shift(matchobj.group(1))
-            path = listing[0].strip()[len(language.commentTag):].strip()
-            filename = os.path.basename(path).split('.')[0]
-            path = os.path.join("_code", path)
-            code = open(path).read().splitlines()
-            #diff = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
-            #for delta in diff.compare(listing, code):
-            #    print delta
-            #d = difflib.Differ()
-            d = difflib.HtmlDiff()
-            if not os.path.exists("_deltas"):
-                os.makedirs("_deltas")
-            open(os.path.join("_deltas", filename + ".html"), 'w'). write(
-                d.make_file(listing, code) + d.make_table(listing,code))
-            #print '\n'.join(list(diff))
-            #sys.exit()
-            return language.codeMarker + "\n".join(["    " + line for line in listing])
-        for f in testFiles:
-            updated = language.listings.sub(_update, open(f).read())
-            #open(f, 'w').write(updated)
-
-if __name__ == "__main__":
-    commands = dict(inspect.getmembers(Commands, inspect.isfunction))
-    if len(sys.argv) < 2 or sys.argv[1] not in commands:
-        print "Command line options:"
-        for name in commands:
-            print name + ":", commands[name].__doc__
-    else:
-        for language in inspect.getmembers(Languages, inspect.isclass):
-            commands[sys.argv[1]](language[1])

File Comprehensions.rst

-.. index::
-   pair: list; comprehension
-   pair: generator; comprehension
-
-********************************************************************************
-Comprehensions
-********************************************************************************
-
-History: where did they come from?
-
-They require a mind shift.
-
-What makes them so compelling (once you 'get it')?
-
-A two-level list comprehension using ``os.walk()``::
-
-    # Comprehensions/os_walk_comprehension.py
-    import os
-    restFiles = [os.path.join(d[0], f) for d in os.walk(".")
-                 for f in d[2] if f.endswith(".rst")]
-    for r in restFiles:
-        print(r)
-

File Contributors.rst

-*******************************************************************************
-Contributors
-*******************************************************************************
-
-Contributors ordered by the number of Launchpad.net Karma points.
-
-.. rubric:: Karma List
-
-..  note:: Launchpad.net now has a web services interface; we need to figure
-    out how to automatically download the Karma list.
-
-Thanks To
-===============================================================================
-
-  * Launchpad.net
-
-  * Creator(s) of Sphinx
-
-  * And of course, Guido and the team for their incessant improvement of Python,
-    especially for taking the risk in breaking backward compatibility in Python
-    3.0 to refactor the language.

File CoroutinesAndConcurrency.rst

-.. index::
-   coroutines
-   concurrency
-   threads
-   parallelism
-   multiprocessing
-   GIL: Global Interpreter Lock
-
-********************************************************************************
-Coroutines & Concurrency
-********************************************************************************
-
-Primary focus should be on:
-
-1) Using ``yield`` to create coroutines
-
-2) Using the new ``multiprocessing`` module
-
-and then showing some alternative techniques.
-
-foo bar :func:`input` baz.

File DeveloperGuide.rst

-*******************************************************************************
-Developer Guide
-*******************************************************************************
-
-Details for people participating in the book development process.
-
-For Windows Users
-===============================================================================
-
-You need to install Cygwin; go to:
-
-    http://www.cygwin.com
-
-You need to install at least the ``make`` utility, but I find that ``chere``
-(command prompt here) is also very useful.
-
-Also install ``openssh`` (under **Net**), so you can create your RSA key
-for Bazaar.
-
-I've discovered that it's best if you *don't* install Python as part of
-Cygwin; instead use a single Python installation under windows. Cygwin will
-find the installation if it is on your Windows PATH.
-
-Because of this, you shouldn't select "mercurial" or "bazaar" when you're
-installing Cygwin because that will cause Python to be installed. Instead,
-install them as Windows applications (see below).
-
-Installing Sphinx
-===============================================================================
-
-Because we are sometimes pushing the boundaries of Sphinx, you'll need to get
-the very latest development version (a.k.a. the "tip").
-
-#. Get mercurial:
-
-    http://www.selenic.com/mercurial
-
-    Avoid installing the tortoiseHG part - it has caused trouble w/ Python
-    debuggers.
-
-#. To get the Sphinx trunk, start with:
-
-    ``$ hg clone http://www.bitbucket.org/birkenfeld/sphinx/``
-
-    and to update, use:
-
-    ``$ hg pull``
-
-    Once you update, run
-
-    ``$ python setup.py install``
-
-    We may talk about minimum version numbers to process the book. Check your
-    version with:
-
-    ``$ hg identify -n``
-
-The full anouncement from Georg (Sphinx creator) is here:
-
-    http://groups.google.com/group/sphinx-dev/browse_thread/thread/6dd415847e5cbf7c
-
-Mercurial Cheat sheets & quick starts should be enough to answer your questions:
-
-    - http://edong.net/2008v1/docs/dongwoo-Hg-120dpi.png
-    - http://www.ivy.fr/mercurial/ref/v1.0/
-
-Getting the Development Branch of the Book
-===============================================================================
-
-This book uses Launchpad.net tools, and additional tools if necessary.
-
-#.  Sign up for an account at http://Launchpad.net.
-
-#.  Install the Bazaar distributed version control system (DVCS):
-
-    https://launchpad.net/bzr
-
-    It's helpful to follow this Bazaar mini-tutorial:
-
-    http://doc.bazaar-vcs.org/latest/en/mini-tutorial/index.html
-
-    And here's the complete Bazaar user guide:
-
-    http://doc.bazaar-vcs.org/latest/en/user-guide/index.html
-
-#.  You must create an rsa key. Under OSX and Linux, and if you installed
-    ``openssh with`` Cygwin under windows, you run ``ssh-keygen`` to generate
-    the key, and then add it to your Launchpad account.
-
-#.  Go to https://code.launchpad.net/python3patterns, and you'll see
-    instructions for getting a branch for development.
-
-#.  Work on your branch and make local commits.
-
-Building the Book
-===============================================================================
-
-To ensure you have Cygwin installed correctly (if you're using windows) and
-to see what the options are, type:
-
-    ``make``
-
-at a shell prompt. Then you can use ``make html`` to build the HTML version of
-the book, or ``make htmlhelp`` to make the windows help version, etc.
-
-You can also use the ``build`` system I've created (as a book example; it is
-part of the distribution). This will call ``make`` and it simplifies many of the
-tasks involved. Type:
-
-    ``build help``
-
-to see the options.
-
-Working with Launchpad and Bazaar
-===============================================================================
-
-(Adapted from a posting by Yarko T)
-
-This assumes that you have created a local branch on your private machine where
-you do work, and keep it merged with the trunk.
-
-That is, you've done:
-
-   - ``bzr branch lp:python3patterns``
-   - ``bzr commit -m 'initial checkout'``
-   - (hack, hack, hack....)
-   - ``bzr merge``   (pull new updates)
-   - ``bzr commit -m 'checkin after merge...'``
-   - ... and so on...
-
-When you have a new function idea, or think you've found a bug, ask Bruce
-on the group.
-
-   -  If you have a new feature, register a blueprint on Launchpad and
-      describe what you're going to do.
-   -  If you have found a bug, make a bug report on Launchpad (later assign
-      it to yourself, and link your branch to it);
-   -  If you want to work on a project, look for an unassigned bug and try to
-      work it out - then proceed as below...
-
-When you are ready to share your work have others review, register a branch.
-
-.. note:: Once you create a branch, there is no easy way to remove it.
-
-.. note:: You can re-use one branch for multiple bug fixes.
-
-1.  Sign up for an account on launchpad.net
-
-2.  Go to the project and select "register branch"
-    (``https://code.launchpad.net/python3patterns/+addbranch``). Suggest you
-    create a hosted branch, then you can work locally, and pull/push as you make
-    progress (see
-    http://doc.bazaar-vcs.org/latest/en/user-guide/index.html#organizing).
-
-3.  Once you have registered your branch, launchpad will provide you with
-    instructions on how to pull and push to your personal development copy.
-
-4.  Link your bug report or blueprint to your branch.
-
-5.  Merge from your "parent" (the trunk, or others you are working with) as needed.
-
-6.  Push your working copy to launchpad as your work is ready for others to
-    review or  test.
-
-7.  Once you are done making your changes, have completed testing, and are
-    ready for the project team to inspect & test, please select "propose for
-    merging"
-
-8.  Somebody on the core team will make a test merge (it may include
-    merging with other patches). Once tests pass, and your branch is accepted,
-    it will be merged into the trunk.
-
-
-Branch Registration Details
-===============================================================================
-Register a branch on http://code.launchpad.net/python3patterns/.  Since your login
-will identify your branch, ``devel`` is a good choice for a general development branch.
-If you're unsure, select ``Hosted`` branching.
-
-You must submit a public key - this will get you there:
-
-    https://launchpad.net/people/+me/+editsshkeys
-
-When you create your branch, Launchpad will show you the command to push to your branch.
-It will look something like this.
-
-.. image:: _images/pushPath.*
-
-A good local setup is to keep an updated copy of the current trunk
-and a separate local development branch.
-
-Tips for Merging
-===============================================================================
-
-..  note:: I want to eventually move to the mode where submissions are
-    reviewed by another member of the team, rather than me reviewing everything.
-
--   Make a merge using a local test branch
-
--   Consider using kdiff3: http://kdiff3.sourceforge.net/
-
--   You can use ``bzr diff --using=kdiff3`` to browse differences, and use a bazaar
-    plugin to merge conflicts:
-
-       ``bzr extmerge --all``
-
--    More here:  http://dev.mysql.com/tech-resources/articles/advanced-bazaar.html
-

File GeneratorsIterators.rst

-.. index::
-   generators
-   iterators
-   itertools
-
-********************************************************************************
-Generators, Iterators, and Itertools
-********************************************************************************
-

File Introduction.rst

-*******************************************************************************
-Introduction
-*******************************************************************************
-
-.. raw:: html
-
-   <font size="+1">The vision for this book.</font>
-
-A Team Effort
-===============================================================================
-
-This book is an experiment to see if we can combine everyone's best efforts to
-create something great.
-
-You can find the contributors right before this introduction. They are listed
-in order of *Karma Points*, a system Launchpad.net uses to keep track of
-contributions from everyone working on an open-source project.
-
-In my case, I will write new material, as well as rewriting other contributions
-to clarify and give voice, setting up the architecture and being the *Benevolent
-Dictator* for the book. But I definitely won't be doing everything; my goal is
-that this is a team project and that everyone who wants to will have something
-useful to contribute.
-
-We'll be using Launchpad.net's "Blueprints" facility to add "features" to the
-book, so that's where you'll find the main repository of things to do.
-
-What can you contribute? Anything as small as spelling and grammatical
-correctons, and as large as a whole chapter. Research into new topics and
-creating examples is what takes me the most time, so if you know something
-already or are willing to figure it out, don't worry if your writing or
-programming isn't perfect -- contribute it and I and the rest of the group will
-improve it.
-
-You may also have talents in figuring things out. Sphinx formatting, for
-example, or how to produce camera-ready formatting. These are all very useful
-things which will not only benefit this book but also any future book built on
-this template (every bit of the build system for the book will be out in the
-open, so if you want to take what we've done here and start your own book, you
-can).
-
-Of course, not everything can make it into the final print book, but things that
-don't fit into the main book can be moved into an "appendix book" or a "volume
-2" book or something like that.
-
-Not an Introductory Book
-===============================================================================
-
-Although there is an introduction for programmers, this book is not intended to
-be introductory. There are already lots of good introductory books out there.
-
-You can think of it as an "intermediate" or "somewhat advanced" book, but the
-"somewhat" modifier is very important here. Because it is not introductory, two
-difficult constraints are removed.
-
-#.  In an introductory book you are forced to describe everything in lock step,
-    never mentioning anything before it has been thoroughly introduced. That's
-    still a good goal, but we don't have to agonize over it when it doesn't
-    happen (just cross-reference the material).
-
-#.  In addition, the topics are not restricted; in this book topics are chosen
-    based on whether they are interesting and/or useful, not on whether they are
-    introductory or not.
-
-That said, people will still be coming to a topic without knowing about it and
-it will need to be introduced, as much as possible, as if they have never seen
-it before.
-
-The License
-===============================================================================
-
-Unless otherwise specified, the material in this book is published under a
-`Creative Commons Attribution-Share Alike 3.0 license
-<http://creativecommons.org/licenses/by-sa/3.0/>`_.
-
-If you make contributions, you must own the rights to your material and be able
-to place them under this license. Please don't contribute something unless you
-are sure this is the case (read your company's employment contract -- these
-often specify that anything you think of or create at any time of day or night
-belongs to the company).
-
-The Printed Book
-===============================================================================
-
-Because of the creative commons license, the electronic version of the book as
-well as all the sources are available, can be reproduced on other web sites,
-etc. (again, as long as you attribute it).
-
-You can print your own version of the book. I will be creating a printed version
-of the book for sale, with a nice cover and binding. Many people do like to have
-a print version of the book, and part of the motivation for doing a print
-version is to make some income off the effort I put into the book.
-
-But buying my particular print version of the book is optional. All of the tools
-will be downloadable so that you can print it yourself, or send it to a copy
-shop and have it bound, etc. The only thing you won't get is my cover and
-binding.
-
-Translations
-===============================================================================
-
-Launchpad.net, where this project is hosted, has support for doing translations
-and this gave me an idea. I had just come back from speaking at the Python
-conference in Brazil, and was thinking about the user group there and how I
-might support them. (We had done a seminar while I was there in order to help
-pay for my trip and support the organization).
-
-If the book can be kept in a Sphinx restructured text format that can be turned
-directly into camera-ready PDF (the basic form is there but it will take
-somebody messing about with it to get it into camera-ready layout), then the job
-of translation can be kept to something that could be done by user groups during
-sprints. The user group could then use a print-on-demand service to print the
-book, and get the group members to take them to local bookstores and do other
-kinds of promotions. The profits from the book could go to the user group (who
-knows, just like the Brazillian group, your group may end up using some of those
-profits to bring me to speak at your conference!).
-
-If possible, I would like a royalty from these translations. To me, 5% of the
-cover price sounds reasonable. If the user group would like to use my cover,
-then they could pay this royalty. If they wanted to go their own way, it's
-creative commons so as long as the book is attributed that's their choice.
-
-My Motives
-===============================================================================
-
-Just so it's clear, I have the following motives for creating this book:
-
-#.  Learn more about Python and contribute to the Python community, to help
-    create more and better Python programmers.
-
-#.  Develop more Python consulting and training clients through the publicity
-    generated by the book (see
-    `here <http://www.mindviewinc.com/Consulting/Index.php>`_).
-
-#.  Experiment with group creation of teaching materials for the book, which
-    will benefit me in my own training (see the previous point) but will also
-    benefit anyone choosing to use the book as a text in a course or training
-    seminar. (See :ref:`TeachingSupport`).
-
-#.  Generate profits by selling printed books. (But see above about the ability
-    to print the book yourself).
-
-#.  Help raise money for non-U.S. Python user groups via translations, from
-    which I might gain a small percentage.

File LanguageChanges.rst

-.. index::
-   pair: Language differences; Python 3
-
-********************************************************************************
-Python 3 Language Changes
-********************************************************************************
-
-Covers language features that don't require their own chapters.
-
-.. note:: If a section in this chapter grows too large it may require its own chapter.

File MachineDiscovery.rst

-********************************************************************************
-Discovering the Details About Your Platform
-********************************************************************************
-
-The Python library XXX will give you some information about your machine,
-but it falls short. Here's a rather messy, but useful way to figure out
-everything else.
-
-Just a starting point::
-
-    def detectCPUs():
-        """
-        Detects the number of CPUs on a system. Cribbed from pp.
-        """
-        # Linux, Unix and MacOS:
-        if hasattr(os, "sysconf"):
-            if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"):
-                # Linux & Unix:
-                ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
-                if isinstance(ncpus, int) and ncpus > 0:
-                    return ncpus
-            else: # OSX:
-                return int(os.popen2("sysctl -n hw.ncpu")[1].read())
-        # Windows:
-        if os.environ.has_key("NUMBER_OF_PROCESSORS"):
-                ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]);
-                if ncpus > 0:
-                    return ncpus
-        return 1 # Default
-        

File Makefile

-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
-
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
-
-help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  html      to make standalone HTML files"
-	@echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
-	@echo "  htmlhelp  to make HTML files and a HTML help project"
-	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  changes   to make an overview over all changed/added/deprecated items"
-	@echo "  linkcheck to check all external links for integrity"
-
-clean:
-	-rm -rf _build/*
-
-html:
-	mkdir -p _build/html _build/doctrees
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
-	@echo
-	@echo "Build finished. The HTML pages are in _build/html."
-
-pickle:
-	mkdir -p _build/pickle _build/doctrees
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files or run"
-	@echo "  sphinx-web _build/pickle"
-	@echo "to start the sphinx-web server."
-
-web: pickle
-
-htmlhelp:
-	mkdir -p _build/htmlhelp _build/doctrees
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in _build/htmlhelp."
-
-latex:
-	mkdir -p _build/latex _build/doctrees
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in _build/latex."
-	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
-	      "run these through (pdf)latex."
-
-changes:
-	mkdir -p _build/changes _build/doctrees
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
-	@echo
-	@echo "The overview file is in _build/changes."
-
-linkcheck:
-	mkdir -p _build/linkcheck _build/doctrees
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in _build/linkcheck/output.txt."

File NoteToReaders.rst

-*******************************************************************************
-A Note To Readers
-*******************************************************************************
-
-What you see here is an early version of the book. We have yet to get everything
-working right and rewritten for Python. Or even to get the book testing systems
-in place.
-
-If you're here because you're curious, that's great. But please don't expect too
-much from the book just yet. When we get it to a point where everything compiles
-and all the Java references, etc. have been rewritten out, then this note will
-disappear. Until then, *caveat emptor*.

File Part1.rst

-###############################################################################
-Part I: Foundations
-###############################################################################
-

File Part2.rst

-###############################################################################
-Part II: Idioms
-###############################################################################

File Part3.rst

-###############################################################################
-Part III: Patterns
-###############################################################################

File PythonDecorators.rst

-.. index::
-   decorator: Python decorators
-   @: Python decorators
-
-************************************************************************************
-Decorators
-************************************************************************************
-
-.. note:: This chapter is a work in progress; it's probably better if you don't
-          begin making changes until I've finished the original version, which
-          is being posted as a series on my weblog.
-
-This amazing feature appeared in the language almost apologetically and with
-concern that it might not be that useful.
-
-I predict that in time it will be seen as one of the more powerful features in
-the language. The problem is that all the introductions to decorators that I
-have seen have been rather confusing, so I will try to rectify that here.
-
-Decorators vs. the Decorator Pattern
-=============================================
-
-First, you need to understand that the word "decorator" was used with some
-trepidation in Python, because there was concern that it would be completely
-confused with the *Decorator* pattern from the `Design Patterns book
-<http://www.amazon.com/gp/product/0201633612/ref=ase_bruceeckelA/>`_. At one
-point other terms were considered for the feature, but "decorator" seems to be
-the one that sticks.
-
-Indeed, you can use Python decorators to implement the *Decorator* pattern, but
-that's an extremely limited use of it. Python decorators, I think, are best
-equated to macros.
-
-History of Macros
-==========================
-
-The macro has a long history, but most people will probably have had experience
-with C preprocessor macros. The problems with C macros were (1) they were in a
-different language (not C) and (2) the behavior was sometimes bizarre, and often
-inconsistent with the behavior of the rest of C.
-
-Both Java and C# have added *annotations*, which allow you to do some things to
-elements of the language. Both of these have the problems that (1) to do what
-you want, you sometimes have to jump through some enormous and untenable hoops,
-which follows from (2) these annotation features have their hands tied by the
-bondage-and-discipline (or as `Martin Fowler gently puts it: "Directing"
-<http://martinfowler.com/bliki/SoftwareDevelopmentAttitude.html>`_) nature of
-those languages.
-
-In a slightly different vein, many C++ programmers (myself included) have noted
-the generative abilities of C++ templates and have used that feature in a macro-
-like fashion.
-
-Many other languages have incorporated macros, but without knowing much about it
-I will go out on a limb and say that Python decorators are similar to Lisp
-macros in power and possibility.
-
-The Goal of Macros
-============================
-
-I think it's safe to say that the goal of macros in a language is to provide a
-way to modify elements of the language. That's what decorators do in Python --
-they modify functions, and in the case of *class decorators*, entire classes.
-This is why they usually provide a simpler alternative to metaclasses.
-
-The major failings of most language's self-modification approaches are that they
-are too restrictive and that they require a different language (I'm going to say
-that Java annotations with all the hoops you must jump through to produce an
-interesting annotation comprises a "different language").
-
-Python falls into Fowler's category of "enabling" languages, so if you want to
-do modifications, why create a different or restricted language? Why not just
-use Python itself? And that's what Python decorators do.
-
-What Can You Do With Decorators?
-===================================
-
-Decorators allow you to inject or modify code in functions or classes. Sounds a
-bit like *Aspect-Oriented Programming* (AOP) in Java, doesn't it? Except that
-it's both much simpler and (as a result) much more powerful. For example,
-suppose you'd like to do something at the entry and exit points of a function
-(such as perform some kind of security, tracing, locking, etc. -- all the
-standard arguments for AOP). With decorators, it looks like this::
-
-    @entryExit
-    def func1():
-        print("inside func1()")
-
-    @entryExit
-    def func2():
-        print("inside func2()")
-
-The ``@`` indicates the application of the decorator.
-
-Function Decorators
-==============================
-
-A function decorator is applied to a function definition by placing it on the
-line before that function definition begins. For example::
-
-    @myDecorator
-    def aFunction():
-        print("inside aFunction")
-
-When the compiler passes over this code, ``aFunction()`` is compiled and the
-resulting function object is passed to the ``myDecorator`` code, which does
-something to produce a function-like object that is then substituted for the
-original ``aFunction()``.
-
-What does the ``myDecorator`` code look like? Well, most introductory examples
-show this as a function, but I've found that it's easier to start understanding
-decorators by using classes as decoration mechanisms instead of functions. In
-addition, it's more powerful.
-
-The only constraint upon the object returned by the decorator is that it can be
-used as a function -- which basically means it must be callable. Thus, any
-classes we use as decorators must implement ``__call__``.
-
-What should the decorator do? Well, it can do anything but usually you expect
-the original function code to be used at some point. This is not required,
-however::
-
-    class myDecorator(object):
-
-        def __init__(self, f):
-            print("inside myDecorator.__init__()")
-            f() # Prove that function definition has completed
-
-        def __call__(self):
-            print("inside myDecorator.__call__()")
-
-    @myDecorator
-    def aFunction():
-        print("inside aFunction()")
-
-    print("Finished decorating aFunction()")
-
-    aFunction()
-
-
-When you run this code, you see::
-
-    inside myDecorator.__init__()
-    inside aFunction()
-    Finished decorating aFunction()
-    inside myDecorator.__call__()
-
-Notice that the constructor for ``myDecorator`` is executed at the point of
-decoration of the function. Since we can call ``f()`` inside ``__init__()``, it
-shows that the creation of ``f()`` is complete before the decorator is called.
-Note also that the decorator constructor receives the function object being
-decorated. Typically, you'll capture the function object in the constructor and
-later use it in the ``__call__()`` method (the fact that decoration and calling
-are two clear phases when using classes is why I argue that it's easier and more
-powerful this way).
-
-When ``aFunction()`` is called after it has been decorated, we get completely
-different behavior; the ``myDecorator.__call__()`` method is called instead of
-the original code. That's because the act of decoration *replaces* the original
-function object with the result of the decoration -- in our case, the
-``myDecorator`` object replaces ``aFunction``. Indeed, before decorators were
-added you had to do something much less elegant to achieve the same thing::
-
-    def foo(): pass
-    foo = staticmethod(foo)
-
-With the addition of the ``@`` decoration operator, you now get the same result
-by saying::
-
-    @staticmethod
-    def foo(): pass
-
-This is the reason why people argued against decorators, because the ``@`` is
-just a little syntax sugar meaning "pass a function object through another
-function and assign the result to the original function."
-
-The reason I think decorators will have such a big impact is because this little
-bit of syntax sugar changes the way you think about programming. Indeed, it
-brings the idea of "applying code to other code" (i.e.: macros) into mainstream
-thinking by formalizing it as a language construct.
-
-Slightly More Useful
-========================
-
-Now let's go back and implement the first example. Here, we'll do the more
-typical thing and actually use the code in the decorated functions::
-
-    class entryExit(object):
-
-        def __init__(self, f):
-            self.f = f
-
-        def __call__(self):
-            print("Entering", self.f.__name__)
-            self.f()
-            print("Exited", self.f.__name__)
-
-    @entryExit
-    def func1():
-        print("inside func1()")
-
-    @entryExit
-    def func2():
-        print("inside func2()")
-
-    func1()
-    func2()
-
-The output is::
-
-    Entering func1
-    inside func1()
-    Exited func1
-    Entering func2
-    inside func2()
-    Exited func2
-
-You can see that the decorated functions now have the "Entering" and "Exited"
-trace statements around the call.
-
-The constructor stores the argument, which is the function object. In the call,
-we use the ``__name__`` attribute of the function to display that function's
-name, then call the function itself.
-
-Using Functions as Decorators
-=====================================
-
-The only constraint on the result of a decorator is that it be callable, so it
-can properly replace the decorated function. In the above examples, I've
-replaced the original function with an object of a class that has a
-``__call__()`` method. But a function object is also callable, so we can rewrite
-the previous example using a function instead of a class, like this::
-
-    def entryExit(f):
-        def new_f():
-            print("Entering", f.__name__)
-            f()
-            print("Exited", f.__name__)
-        return new_f
-
-    @entryExit
-    def func1():
-        print("inside func1()")
-
-    @entryExit
-    def func2():
-        print("inside func2()")
-
-    func1()
-    func2()
-    print(func1.__name__)
-
-``new_f()`` is defined within the body of ``entryExit()``, so it is created and
-returned when ``entryExit()`` is called. Note that ``new_f()`` is a *closure*,
-because it captures the actual value of ``f``.
-
-Once ``new_f()`` has been defined, it is returned from ``entryExit()`` so that
-the decorator mechanism can assign the result as the decorated function.
-
-The output of the line ``print(func1.__name__)`` is ``new_f``, because the
-``new_f`` function has been substituted for the original function during
-decoration. If this is a problem you can change the name of the decorator
-function before you return it::
-
-    def entryExit(f):
-        def new_f():
-            print("Entering", f.__name__)
-            f()
-            print("Exited", f.__name__)
-        new_f.__name__ = f.__name__
-        return new_f
-
-The information you can dynamically get about functions, and the modifications
-you can make to those functions, are quite powerful in Python.
-
-Review: Decorators without Arguments
-=========================================
-
-If we create a decorator without arguments, the function to be decorated is
-passed to the constructor, and the ``__call__()`` method is called whenever the
-decorated function is invoked::
-
-    class decoratorWithoutArguments(object):
-
-        def __init__(self, f):
-            """
-            If there are no decorator arguments, the function
-            to be decorated is passed to the constructor.
-            """
-            print("Inside __init__()")
-            self.f = f
-
-        def __call__(self, *args):
-            """
-            The __call__ method is not called until the
-            decorated function is called.
-            """
-            print("Inside __call__()")
-            self.f(*args)
-            print("After self.f(*args)")
-
-    @decoratorWithoutArguments
-    def sayHello(a1, a2, a3, a4):
-        print('sayHello arguments:', a1, a2, a3, a4)
-
-    print("After decoration")
-
-    print("Preparing to call sayHello()")
-    sayHello("say", "hello", "argument", "list")
-    print("After first sayHello() call")
-    sayHello("a", "different", "set of", "arguments")
-    print("After second sayHello() call")
-
-Any arguments for the decorated function are just passed to ``__call__()``. The
-output is::
-
-    Inside __init__()
-    After decoration
-    Preparing to call sayHello()
-    Inside __call__()
-    sayHello arguments: say hello argument list
-    After self.f(*args)
-    After first sayHello() call
-    Inside __call__()
-    sayHello arguments: a different set of arguments
-    After self.f(*args)
-    After second sayHello() call
-
-Notice that ``__init__()`` is the only method called to perform decoration, and
-``__call__()`` is called every time you call the decorated ``sayHello()``.
-
-
-Decorators with Arguments
-====================================
-
-The decorator mechanism behaves quite differently when you pass arguments to the
-decorator.
-
-Let's modify the above example to see what happens when we add arguments to the
-decorator::
-
-    class decoratorWithArguments(object):
-
-        def __init__(self, arg1, arg2, arg3):
-            """
-            If there are decorator arguments, the function
-            to be decorated is not passed to the constructor!
-            """
-            print("Inside __init__()")
-            self.arg1 = arg1
-            self.arg2 = arg2
-            self.arg3 = arg3
-
-        def __call__(self, f):
-            """
-            If there are decorator arguments, __call__() is only called
-            once, as part of the decoration process! You can only give
-            it a single argument, which is the function object.
-            """
-            print("Inside __call__()")
-            def wrapped_f(*args):
-                print("Inside wrapped_f()")
-                print("Decorator arguments:", self.arg1, self.arg2, self.arg3)
-                f(*args)
-                print("After f(*args)")
-            return wrapped_f
-
-    @decoratorWithArguments("hello", "world", 42)
-    def sayHello(a1, a2, a3, a4):
-        print('sayHello arguments:', a1, a2, a3, a4)
-
-    print("After decoration")
-
-    print("Preparing to call sayHello()")
-    sayHello("say", "hello", "argument", "list")
-    print("after first sayHello() call")
-    sayHello("a", "different", "set of", "arguments")
-    print("after second sayHello() call")
-
-From the output, we can see that the behavior changes quite significantly::
-
-    Inside __init__()
-    Inside __call__()
-    After decoration
-    Preparing to call sayHello()
-    Inside wrapped_f()
-    Decorator arguments: hello world 42
-    sayHello arguments: say hello argument list
-    After f(*args)
-    after first sayHello() call
-    Inside wrapped_f()
-    Decorator arguments: hello world 42
-    sayHello arguments: a different set of arguments
-    After f(*args)
-    after second sayHello() call
-
-Now the process of decoration calls the constructor and then immediately invokes
-``__call__()``, which can only take a single argument (the function object) and
-must return the decorated function object that replaces the original. Notice
-that ``__call__()`` is now only invoked once, during decoration, and after that
-the decorated function that you return from ``__call__()`` is used for the
-actual calls.
-
-Although this behavior makes sense -- the constructor is now used to capture the
-decorator arguments, but the object ``__call__()`` can no longer be used as the
-decorated function call, so you must instead use ``__call__()`` to perform the
-decoration -- it is nonetheless surprising the first time you see it because
-it's acting so much differently than the no-argument case, and you must code the
-decorator very differently from the no-argument case.
-
-Decorator Functions with Decorator Arguments
-==================================================
-
-Finally, let's look at the more complex decorator function implementation, where
-you have to do everything all at once::
-
-    def decoratorFunctionWithArguments(arg1, arg2, arg3):
-        def wrap(f):
-            print("Inside wrap()")
-            def wrapped_f(*args):
-                print("Inside wrapped_f()")
-                print("Decorator arguments:", arg1, arg2, arg3)
-                f(*args)
-                print("After f(*args)")
-            return wrapped_f
-        return wrap
-
-    @decoratorFunctionWithArguments("hello", "world", 42)
-    def sayHello(a1, a2, a3, a4):
-        print('sayHello arguments:', a1, a2, a3, a4)
-
-    print("After decoration")
-
-    print("Preparing to call sayHello()")
-    sayHello("say", "hello", "argument", "list")
-    print("after first sayHello() call")
-    sayHello("a", "different", "set of", "arguments")
-    print("after second sayHello() call")
-
-Here's the output::
-
-    Inside wrap()
-    After decoration
-    Preparing to call sayHello()
-    Inside wrapped_f()
-    Decorator arguments: hello world 42
-    sayHello arguments: say hello argument list
-    After f(*args)
-    after first sayHello() call
-    Inside wrapped_f()
-    Decorator arguments: hello world 42
-    sayHello arguments: a different set of arguments
-    After f(*args)
-    after second sayHello() call
-
-The return value of the decorator function must be a function used to wrap the
-function to be decorated. That is, Python will take the returned function and
-call it at decoration time, passing the function to be decorated. That's why we
-have three levels of functions; the inner one is the actual replacement
-function.
-
-Because of closures, ``wrapped_f()`` has access to the decorator arguments
-``arg1``, ``arg2`` and ``arg3``, *without* having to explicitly store them as in
-the class version. However, this is a case where I find "explicit is better than
-implicit," so even though the function version is more succinct I find the class
-version easier to understand and thus to modify and maintain.
-
-.. seealso::
-
-    http://wiki.python.org/moin/PythonDecoratorLibrary
-        More examples of decorators. Note the number of these examples that
-        use classes rather than functions as decorators.
-
-    http://scratch.tplus1.com/decoratortalk
-        Matt Wilson's *Decorators Are Fun*.
-
-    http://loveandtheft.org/2008/09/22/python-decorators-explained
-        Another introduction to decorators
-
-    http://www.phyast.pitt.edu/~micheles/python/documentation.html
-        Michele Simionato's decorator module wraps functions for you. The page
-        includes an introduction and some examples.
-

File Rules.rst

-*******************************************************************************
-Book Development Rules
-*******************************************************************************
-
-Guidelines for the creation process.
-
-.. note:: This is just a start. This document will evolve as more issues appear.
-
-Contribute What You Can
-===============================================================================
-
-One of the things I've learned by holding open-spaces conferences is that
-everyone has something useful to contribute, although they often don't know it.
-
-Maybe you're don't feel expert enough at Python to contribute anything yet.
-But you're in this field, so you've got some useful abilities.
-
-- Maybe you're good at admin stuff, figuring out how things work and configuring
-  things.
-
-- If you have a flair for design and can figure out Sphinx templating,
-  that will be useful.
-
-- Perhaps you are good at Latex. We need to figure out how to format the
-  PDF version of the book from the Sphinx sources, so that we can produce
-  the print version of the book without going through hand work in a layout
-  program.
-
-- You probably have ideas about things you'd like to understand, that haven't
-  been covered elsewhere.
-
-- And sometimes people are particularly good at spotting typos.
-
-Don't Get Attached
-===============================================================================
-
-Writing is rewriting. Your stuff will get rewritten, probably multiple times.
-This makes it better for the reader. It doesn't mean it was bad. Everything can
-be made better.
-
-By the same measure, don't worry if your examples or prose aren't perfect. Don't
-let that keep you from contributing them early. They'll get rewritten anyway, so
-don't worry too much -- do the best you can, but don't get blocked.
-
-There's also an editor who will be rewriting for clarity and active voice. He
-doesn't necessarily understand the technology but he will still be able to
-improve the flow. If you discover he has introduced technical errors in the
-prose, then feel free to fix it but try to maintain any clarity that he has
-added.
-
-If something is moved to Volume 2 or the electronic-only appendices, it's just
-a decision about the material, not about you.
-
-Credit
-===============================================================================
-
-As much as possible, I want to give credit to contributions. Much of this will
-be taken care of automatically by the Launchpad.net "Karma" system. However, if
-you contribute something significant, for example the bulk of a new chapter,
-then you should put "contributed by" at the beginning of that chapter, and if
-you make significant improvements and changes to a chapter you should say
-"further contributions by" or "further changes by", accordingly.
-
-Mechanics
-===============================================================================
-
-- Automate everything. Everything should be in the build script; nothing should
-  be done by hand.
-
-- All documents will be in Sphinx restructured text format. Here's the
-  `link to the Sphinx documentation <http://sphinx.pocoo.org/contents.html>`_.
-
-- Everything goes through Launchpad.net and uses Launchpad's Bazzar distributed
-  version control system.
-
-- Follow PEP8 for style. That way we don't have to argue about it.
-
-- Camelcasing for naming. PEP8 suggests underscores as a preference rather than
-  a hard-and fast rule, and camelcasing *feels* more like OO to me, as if we are
-  emphasizing the design here (which I want to do) and putting less focus on the
-  C-ish nature that *can* be expressed in Python.
-
-::
-
-    The above point is still being debated.
-
-- Four space indents.
-
-- We're not using chapter numbers because we'll be moving chapters around.
-  If you need to cross-reference a chapter, use the chapter name and a
-  link.
-
-- Index as you go. Indexing will happen throughout the project. Although
-  finalizing the index is a task in itself, it will be very helpful if everyone
-  adds index entries anytime they occur to you. You can find example index
-  entries by going to the index, clicking on one of the entries, then selecting
-  "view source" in the left-side bar (Sphinx cleverly shows you the Sphinx
-  source so you can use it as an example).
-
-- Don't worry about chapter length. Some chapters may be very small, others may
-  be quite significant. It's just the nature of this book. Trying to make the
-  chapters the same length will end up fluffing some up which will not benefit
-  the reader. Make the chapters however long they need to be, but no longer.
-
-Diagrams
-===============================================================================
-
-Create diagrams using whatever tool is convenient for you, as long as it produces
-formats that Sphinx can use.
-
-It doesn't matter if your diagram is imperfect. Even if you just sketch something
-by hand and scan it in, it will help readers visualize what's going on.
-
-At some point, diagrams will be redone for consistency using a single tool,
-with print publication in mind. This tool may be a commercial product. However,
-if you need to change the diagram you can replace it with your new version using
-your tool of choice. The important thing is to get the diagram right; at some
-point it will be redone to look good.
-
-Note that all image tags should use a ``*`` at the end, not the file extension
-name. For example ``..image:: _images/foo.*``. This way the tag will work for
-both the HTML output and the Latex output. Also, all images should be placed
-in the ``_images`` directory.
-
-Here's an example which was done with the free online service Gliffy.com, then
-modified using the free Windows program Paint.NET (note, however, that we should
-not use color because it won't translate well to the print book):
-
-.. image:: _images/DistributedSystem.*
-

File SanityCheck.py

-# SanityCheck.py
-#! /usr/bin/env python
-import string, glob, os
-# Do not include the following in the automatic
-# tests:
-exclude = ("SanityCheck.py", "BoxObserver.py",)
-
-def visitor(arg, dirname, names):
-    dir = os.getcwd()
-    os.chdir(dirname)
-    try:
-        pyprogs = [p for p in glob.glob('*.py')
-                   if p not in exclude ]
-        if not pyprogs: return
-        print '[' + os.getcwd() + ']'
-        for program in pyprogs:
-            print '\t', program
-            os.system("python %s > tmp" % program)
-            file = open(program).read()
-            output = open('tmp').read()
-            # Append output if it's not already there:
-            if file.find("output = '''") == -1 and \
-              len(output) > 0:
-                divider = '#' * 50 + '\n'
-                file = file.replace('#' + ':~', '#<hr>\n')
-                file += "output = '''\n" + \
-                  open('tmp').read() + "'''\n"
-                open(program,'w').write(file)
-    finally:
-        os.chdir(dir)
-
-if __name__ == "__main__":
-    os.path.walk('.', visitor, None)

File TeachingSupport.rst

-.. _TeachingSupport:
-
-*******************************************************************************
-Teaching Support
-*******************************************************************************
-
-Teachers and lecturers often need support material to help them use a book for
-teaching. I have put some exercises in, and I hope we can add more.
-
-I'd also like to create teaching materials like slides and exercises as a group
-effort with a creative commons license, especially by allying with those people
-who are in the teaching professions. I'd like to make it something that everyone
-would like to teach from -- including myself.
-
-Here are some places to get ideas for exercises and projects:
-
-  - `For coding dojos <http://www.dtsato.com/blog/2008/10/21/source-of-problems-for-your-coding-dojo/>`_
-
-  - `Rosetta Code <http://www.rosettacode.org/wiki/Category:Python>`_

File Todo.txt

-Refine "Printed Book" and "Translations"
-Code extractor for rst files (maybe part of intro chapter?)
-Code updater to put code in/refresh code into book.
-
-Move frontmatter into its own directory
-
-<!> Seems to be a warning sign (but initial tests didn't work)
-
-Idea: decorator on a dictionary object, to turn it into an ordered dictionary.
-
-"Other resources" at the end of each chapter
-
-For print version, convert hyperlinks into footnotes.
-(build tool for this)

File _images/DistributedSystem.pdf

Binary file removed.

File _images/DistributedSystem.png

Removed
Old image

File _images/coffeeExplosion.gif

Removed
Old image

File _images/coffeeExplosion.pdf

Binary file removed.

File _images/compromiseDecoration.gif

Removed
Old image

File _images/compromiseDecoration.pdf

Binary file removed.

File _images/decoratedCoffee.gif

Removed
Old image

File _images/decoratedCoffee.pdf

Binary file removed.

File _images/decorator.gif

Removed
Old image

File _images/decorator.pdf

Binary file removed.

File _images/pushPath.pdf

Binary file removed.

File _images/pushPath.png

Removed
Old image

File _images/stateMachine.gif

Removed
Old image

File _images/stateMachine.pdf

Binary file removed.

File _images/surrogate.gif

Removed
Old image

File _images/surrogate.pdf

Binary file removed.

File _images/trashSorter1.gif

Removed
Old image

File _images/trashSorter1.pdf

Binary file removed.

File _images/trashSorter2.gif

Removed
Old image

File _images/trashSorter2.pdf

Binary file removed.

File _images/trashSorter3.gif

Removed
Old image

File _images/trashSorter3.pdf

Binary file removed.

File _images/trashVisitor.gif

Removed
Old image

File _images/trashVisitor.pdf

Binary file removed.

File _static/LaunchpadBrand.png

Removed
Old image

File _static/LaunchpadIcon.png

Removed
Old image

File _static/LaunchpadLogo.png

Removed
Old image

File _static/Logo.png

Removed
Old image

File _static/Thumbs.db

Binary file removed.

File _static/favicon.ico

Removed
Old image

File _templates/layout.html

-{% extends "!layout.html" %}
-{% block sidebarsearch %}
-    {{ super() }}
-    <h4><a href="http://www.mindviewinc.com/Books/Python3Patterns/Index.php">Project Homepage</a></h4>
-    <h4><a href="http://www.bitbucket.org/BruceEckel/python-3-patterns-idioms/issues/">Corrections/Suggestions</a></h4>
-    <h4><a href="http://www.mindviewinc.com/Consulting/Index.php">Consulting &amp; Training</a></h4><br><br>
-{% endblock %}

File appFrameworks.rst

-
-*******************************************************************************
-Building Application Frameworks
-*******************************************************************************
-
-An application framework allows you to inherit from a class or set of classes
-and create a new application, reusing most of the code in the existing classes
-and overriding one or more methods in order to customize the application to your
-needs. A fundamental concept in the application framework is the *Template
-Method* which is typically hidden beneath the covers and drives the application
-by calling the various methods in the base class (some of which you have
-overridden in order to create the application).
-
-For example, whenever you create an applet you're using an application
-framework: you inherit from **JApplet** and then override **init( )**. The
-applet mechanism (which is a *Template Method*) does the rest by drawing the
-screen, handling the event loop, resizing, etc.
-
-Template Method
-=======================================================================
-
-An important characteristic of the *Template Method* is that it is defined in
-the base class and cannot be changed. It's sometimes a **private** method but
-it's virtually always **final**. It calls other base-class methods (the ones you
-override) in order to do its job, but it is usually called only as part of an
-initialization process (and thus the client programmer isn't necessarily able to
-call it directly)::
-
-    # appFrameworks/TemplateMethod.py
-    # Simple demonstration of Template Method.
-
-    class ApplicationFramework:
-        def __init__(self):
-            self.__templateMethod()
-        def __templateMethod(self):
-            for i in range(5):
-                self.customize1()
-                self.customize2()
-
-    # Create an "application":
-    class MyApp(ApplicationFramework):
-        def customize1(self):
-            print("Nudge, nudge, wink, wink! ",)
-        def customize2(self):
-            print("Say no more, Say no more!")
-
-    MyApp()
-
-
-
-The base-class constructor is responsible for performing the necessary
-initialization and then starting the "engine" (the template method) that runs
-the application (in a GUI application, this "engine" would be the main event
-loop). The client programmer simply provides definitions for **customize1( )**
-and **customize2( )** and the "application" is ready to run.
-
-We'll see *Template Method* numerous other times throughout the book.
-
-Exercises
-=======================================================================
-
-#.  Create a framework that takes a list of file names on the command line. It
-    opens each file except the last for reading, and the last for writing. The
-    framework will process each input file using an undetermined policy and
-    write the output to the last file. Inherit to customize this framework to
-    create two separate applications:
-
-        #. Converts all the letters in each file to uppercase.
-        #. Searches the files for words given in the first file.
-
-
-

File build

-python build.py $*

File build.bat

-python build.py %1 %2 %3 %4 %5 %6 %7

File build.py

-from builder import rule
-import os, shutil
-# for a complete distribution build from scratch, say 'build clean package'
-
-@rule()
-def html():
-    "Create html files"
-    os.system("make html")
-
-@rule("_build/htmlhelp")
-def winhelp():
-    "Create Windows Help file"
-    os.system("make htmlhelp")
-    os.chdir("_build/htmlhelp")
-    os.system(r"hhc Python3PatternsIdiomsdoc.hhp")
-    os.chdir("../..")
-
-@rule()
-def clean():
-    "Remove files that have been built"
-    os.system("make clean")
-    if os.path.exists("_test"):
-        shutil.rmtree("_test")
-    if os.path.exists("_code"):
-        shutil.rmtree("_code")
-
-# Bug: This needs to work:
-#@rule(["_build/Python3PatternsAndIdioms-html.zip",
-#       "_build/Python3PatternsAndIdioms-htmlhelp.zip"], html, winhelp)
-
-@rule(None, html, winhelp)
-def package():
-    "Create Zip files for upload to Launchpad; for end-user downloads"
-    os.chdir("_build")
-    os.system("zip -r Python3PatternsAndIdioms-html.zip html")
-    os.system("zip -r Python3PatternsAndIdioms-htmlhelp.zip htmlhelp/Python3PatternsIdiomsdoc.*")
-    os.chdir("..")
-
-@rule(None, html, winhelp)
-def all():
-    "Build both html and windows help files"
-
-rule.default = all
-rule.main() # Does the build, handles command-line arguments

File builder.py

-# builder.py
-import sys, os, stat
-"""
-Adds build rules atop Python, to replace make, etc.
-by Bruce Eckel
-License: Creative Commons with Attribution.
-"""
-
-def reportError(msg):
-    print >> sys.stderr, "Error:", msg
-    sys.exit(1)
-
-class Dependency(object):
-    "Created by the decorator to represent a single dependency relation"
-
-    changed = True
-    unchanged = False
-
-    @staticmethod
-    def show(flag):
-        if flag: return "Updated"
-        return "Unchanged"
-
-    def __init__(self, target, dependency):
-        self.target = target
-        self.dependency = dependency
-
-    def __str__(self):
-        return "target: %s, dependency: %s" % (self.target, self.dependency)
-
-    @staticmethod
-    def create(target, dependency): # Simple Factory
-        if target == None:
-            return NoTarget(dependency)
-        if type(target) == str: # String means file name
-            if dependency == None:
-                return FileToNone(target, None)
-            if type(dependency) == str:
-                return FileToFile(target, dependency)
-            if type(dependency) == Dependency:
-                return FileToDependency(target, dependency)
-        reportError("No match found in create() for target: %s, dependency: %s"
-            % (target,  dependency))
-
-    def updated(self):
-        """
-        Call to determine whether this is up to date.
-        Returns 'changed' if it had to update itself.
-        """
-        assert False, "Must override Dependency.updated() in derived class"
-
-class NoTarget(Dependency): # Always call updated() on dependency
-    def __init__(self, dependency):
-        Dependency.__init__(self, None, dependency)
-    def updated(self):
-        if not self.dependency:
-            return Dependency.changed # (None, None) -> always run rule
-        return self.dependency.updated() # Must be a Dependency or subclass
-
-class FileToNone(Dependency): # Run rule if file doesn't exist
-    def updated(self):
-        if not os.path.exists(self.target):
-            return Dependency.changed
-        return Dependency.unchanged
-
-class FileToFile(Dependency): # Compare file datestamps
-    def updated(self):
-        if not os.path.exists(self.dependency):
-            reportError("%s does not exist" % self.dependency)
-        if not os.path.exists(self.target):
-            return Dependency.changed # If it doesn't exist it needs to be made
-        if os.path.getmtime(self.dependency) > os.path.getmtime(self.target):
-            return Dependency.changed
-        return Dependency.unchanged
-
-class FileToDependency(Dependency): # Update if dependency object has changed
-    def updated(self):
-        if self.dependency.updated():
-            return Dependency.changed
-        if not os.path.exists(self.target):
-            return Dependency.changed # If it doesn't exist it needs to be made
-        return Dependency.unchanged
-
-class rule(object):
-    """
-    Decorator that turns a function into a build rule. First file or object in
-    decorator arglist is the target, remainder are dependencies.
-    """
-    rules = []
-    default = None
-
-    class _Rule(object):
-        """
-        Command pattern. name, dependencies, ruleUpdater and description are
-        all injected by class rule.
-        """
-
-        def updated(self):
-            if Dependency.changed in [d.updated() for d in self.dependencies]:
-                self.ruleUpdater()
-                return Dependency.changed
-            return Dependency.unchanged
-
-        def __str__(self): return self.description
-
-    def __init__(self, *decoratorArgs):
-        """
-        This constructor is called first when the decorated function is
-        defined, and captures the arguments passed to the decorator itself.
-        (Note Builder pattern)
-        """
-        self._rule = rule._Rule()
-        decoratorArgs = list(decoratorArgs)
-        if decoratorArgs:
-            if len(decoratorArgs) == 1:
-                decoratorArgs.append(None)
-            target = decoratorArgs.pop(0)
-            if type(target) != list:
-                target = [target]
-            self._rule.dependencies = [Dependency.create(targ, dep)
-                for targ in target for dep in decoratorArgs]
-        else: # No arguments
-            self._rule.dependencies = [Dependency.create(None, None)]
-
-    def __call__(self, func):
-        """
-        This is called right after the constructor, and is passed the function
-        object being decorated. The returned _rule object replaces the original
-        function.
-        """
-        if func.__name__ in [r.name for r in rule.rules]:
-            reportError("@rule name %s must be unique" % func.__name__)
-        self._rule.name = func.__name__
-        self._rule.description = func.__doc__ or ""
-        self._rule.ruleUpdater = func
-        rule.rules.append(self._rule)
-        return self._rule # This is substituted as the decorated function
-
-    @staticmethod
-    def update(x):
-        if x == 0:
-            if rule.default:
-                return rule.default.updated()
-            else:
-                return rule.rules[0].updated()
-        # Look up by name
-        for r in rule.rules:
-            if x == r.name:
-                return r.updated()
-        raise KeyError
-
-    @staticmethod
-    def main():
-        """
-        Produce command-line behavior
-        """
-        if len(sys.argv) == 1:
-            print Dependency.show(rule.update(0))
-        try:
-            for arg in sys.argv[1:]:
-                print Dependency.show(rule.update(arg))
-        except KeyError:
-            print "Available rules are:\n"
-            for r in rule.rules:
-                if r == rule.default:
-                    newline = " (Default if no rule is specified)\n"
-                else:
-                    newline = "\n"
-                print "%s:%s\t%s\n" % (r.name, newline, r)
-            print "(Multiple targets will be updated in order)"
-        # Create "build" commands for Windows and Unix:
-        if not os.path.exists("build.bat"):
-            file("build.bat", 'w').write("python build.py %1 %2 %3 %4 %5 %6 %7")
-        if not os.path.exists("build"):
-            # Unless you can detect cygwin independently of Windows
-            file("build", 'w').write("python build.py $*")
-            os.chmod("build", stat.S_IEXEC)
-
-############### Test/Usage Examples ###############
-
-if __name__ == "__main__":
-    if not os.path.exists("build.py"):
-        file("build.py", 'w').write('''\
-# Use cases: both test code and usage examples
-from builder import rule
-import os
-
-@rule("file1.txt")
-def file1():
-    "File doesn't exist; run rule"
-    file("file1.txt", 'w')
-
-def touchOrCreate(f): # Ordinary function
-    "Bring file up to date; creates it if it doesn't exist"
-    if os.path.exists(f):
-        os.utime(f, None)
-    else:
-        file(f, 'w')
-
-dependencies = ["dependency1.txt", "dependency2.txt",
-                "dependency3.txt", "dependency4.txt"]
-
-targets = ["file1.txt", "target1.txt", "target2.txt"]
-
-allFiles = targets + dependencies
-
-@rule(allFiles)
-def multipleTargets():
-    "Multiple files don't exist; run rule"
-    [file(f, 'w') for f in allFiles if not os.path.exists(f)]
-
-@rule(["target1.txt", "target2.txt"], "dependency1.txt", "dependency2.txt")
-def multipleBoth():
-    "Multiple targets and dependencies"
-    [touchOrCreate(f) for f in ["target1.txt", "target2.txt"]]
-
-@rule("target1.txt","dependency1.txt","dependency2.txt","dependency3.txt")
-def target1():
-    "Brings target1.txt up to date with its dependencies"
-    touchOrCreate("target1.txt")
-
-@rule()
-def updateDependency():
-    "Updates the timestamp on all dependency.* files"
-    [touchOrCreate(f) for f in allFiles if f.startswith("dependency")]
-
-@rule()
-def clean():
-    "Remove all created files"
-    [os.remove(f) for f in allFiles if os.path.exists(f)]
-
-@rule()
-def cleanTargets():
-    "Remove all target files"
-    [os.remove(f) for f in targets if os.path.exists(f)]
-
-@rule("target2.txt", "dependency2.txt", "dependency4.txt")
-def target2():
-    "Brings target2.txt up to date with its dependencies, or creates it"
-    touchOrCreate("target2.txt")
-
-@rule(None, target1, target2)
-def target3():
-    "Always brings target1 and target2 up to date"
-    print target3
-
-@rule(None, clean, file1, multipleTargets, multipleBoth, target1,
-      updateDependency, target2, target3)
-def all():
-    "Brings everything up to date"
-    print all
-
-rule.default = all
-rule.main() # Does the build, handles command-line arguments
-''')

File builder.pyc

Binary file removed.

File changeInterface.rst

-
-********************************************************************************
-Changing the Interface
-********************************************************************************
-
-Sometimes the problem that you're solving is as simple as "I don't have the
-interface that I want." Two of the patterns in *Design Patterns* solve this
-problem: *Adapter* takes one type and produces an interface to some other type.
-*Façade* creates an interface to a set of classes, simply to provide a more
-comfortable way to deal with a library or bundle of resources.
-
-Adapter
-=======================================================================
-
-When you've got *this*, and you need *that*, *Adapter* solves the problem. The
-only requirement is to produce a *that*, and there are a number of ways you can
-accomplish this adaptation::
-
-    # changeInterface/Adapter.py
-    # Variations on the Adapter pattern.
-
-    class WhatIHave:
-        def g(self): pass
-        def h(self): pass
-
-    class WhatIWant:
-        def f(self): pass
-
-    class ProxyAdapter(WhatIWant):
-        def __init__(self, whatIHave):
-            self.whatIHave = whatIHave