About
This distribution provides code reloading middleware for use with your WSGI applications. Two implementations are included. One is inspired by the RollBackImporter used by Steve Purcell in PyUnit. The other reloads a list of packages you supply (minus a list of exceptions).
Download
Download the latest release from memento's Cheese Shop Page.
Blessed are the cheesemakers!
Example
A complete script to run your app via wsgiref with code reloading might look like this:
from wsgiref.simple_server import make_server
import memento
# Mori doesn't always play well with others
# so we will use Assassin
#app = memento.Mori("mypackage.mymodule:my_app")
app = memento.Assassin("mypackage.mymodule:my_app", ["mypackage"])
try:
server = make_server('localhost', 9999, app)
server.serve_forever()
except KeyboardInterrupt, ki:
print "See ya!"
Use this in combination with setuptools' development mode and you will not have to restart your server between edits to see your changes take effect.
memento.Assassin
You may notice that instantiating the Assassin class
is a little different than many other WSGI middlewares.
Instead of passing it a WSGI app directly, we pass it a
resolver statement. (A description of resolver statements
can be found in the
resolver documentation.)
This tells your instance how to import your app.
When instantiating Assassin two arguments are required:
the resolver statement mentioned above, and a list of absolute package
or module names to be reloaded. An optional keyword arg called
exceptions lists the names within those packages to
not reload. A final optional keyword argument, turn_on
sets the reloading mode to on or off (defaults to turn_on=True).
Assassin was created as a simpler and safer
replacement for Mori. Assassin
only makes the interpreter forget previous imports based on a given
list of names while Mori is much more brutal.
memento.Mori
Mori does not play well with others and will be deprecated in the next version if I cannot correct this.
Mori's __init__ method
takes a resolver statement (as mentioned above)
optional boolean keyword argument called turn_on
which specifies whether to start watching imports right away.
Once it is on, the instance keeps track of everything that is
imported. Anything that was not imported before this point
is forgotten each time the _reload() method is
called, which happens each time a request is processed. These
forgotten imports will then be reloaded by the interpreter
as a matter of course. There are also turn_on() and
turn_off() methods to turn code reloading on and off.
Order of Operations
Since only modules that had not already been imported will
be reloaded, it is important to pay attention to when you turn
reloading on. If things are not being reloaded the way
you expect, try logging what is in
Mori.previous_modules,
Mori.new_modules
and
sys.modules.keys()
to see what is going on.
Why Resolver Statements?
Resolving a resolver statement triggers an import that results in the reloading of relevant packages or modules for which caching has been circumvented.
Questions, comments, suggestions, bugs... : luke.arno@gmail.com