294 lines
18 KiB
HTML
294 lines
18 KiB
HTML
<?xml version="1.0" encoding="us-ascii" ?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
|
|
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
|
|
<title>Upgrading code from older versions of Quixote</title>
|
|
<link rel="stylesheet" href="default.css" type="text/css" />
|
|
</head>
|
|
<body>
|
|
<div class="document" id="upgrading-code-from-older-versions-of-quixote">
|
|
<h1 class="title">Upgrading code from older versions of Quixote</h1>
|
|
<p>This document lists backward-incompatible changes in Quixote, and
|
|
explains how to update application code to work with the newer
|
|
version.</p>
|
|
<div class="section" id="changes-from-1-0-to-2-0">
|
|
<h1><a name="changes-from-1-0-to-2-0">Changes from 1.0 to 2.0</a></h1>
|
|
<p>Change any imports you have from quixote.form to be from quixote.form1.</p>
|
|
<p>Change any imports you have from quixote.form2 to be from quixote.form.</p>
|
|
<p>Replace calls to HTTPRequest.get_form_var() with calls to get_field().</p>
|
|
<p>Define a create_publisher() function to get the publisher you need
|
|
and figure out how you want to connect it to web server.
|
|
See files in demo and server for examples. Note that publish1.py
|
|
contains a publisher that works more like the Quixote1 Publisher,
|
|
and does not require the changes listed below.</p>
|
|
<p>Make every namespace be an instance of quixote.directory.Directory.
|
|
Update namespaces that are modules (or in the init.py of a package) by
|
|
defining a new class in the module that inherits from Directory and
|
|
moving your _q_exports and _q_* functions onto the class. Replace
|
|
"request" parameters with "self" parameters on the new methods. If
|
|
you have a _q_resolve method, include Resolving in the bases of your
|
|
new class.</p>
|
|
<p>Remove request from calls to _q_ functions. If request, session,
|
|
user, path, or redirect is used in these new methods, replace as
|
|
needed with calls to get_request(), get_session(), get_user(),
|
|
get_path(), and/or redirect(), imported from quixote.</p>
|
|
<p>In every namespace that formerly traversed into a module, import the
|
|
new Directory class from the module and create an instance of the
|
|
Directory in a variable whose name is the name of the module.</p>
|
|
<p>In every namespace with a _q_exports and a _q_index, either add "" to
|
|
_q_exports or make sure that _q_lookup handles "" by returning the result
|
|
of a call to _q_index.</p>
|
|
<p>If your code depends on the Publisher's namespace_stack attribute,
|
|
try using quixote.util.get_directory_path() instead. If you need the
|
|
namespace stack after the traversal, override Directory._q_traverse()
|
|
to call get_directory_path() when the end of the path is reached, and
|
|
record the result somewhere for later reference.</p>
|
|
<p>If your code depends on _q_exception_handler, override the _q_traverse
|
|
on your root namespace or on your own Directory class to catch exceptions
|
|
and handle them the way you want. If you just want a general customization
|
|
for exception responses, you can change or override
|
|
Publisher.format_publish_error().</p>
|
|
<p>If your code depended on _q_access, include the AccessControlled with
|
|
the bases of your Directory classes as needed.</p>
|
|
<p>Provide imports as needed to htmltext, TemplateIO, get_field,
|
|
get_request, get_session, get_user, get_path, redirect, ?. You may
|
|
find dulcinea/bin/unknown.py useful for identifying missing imports.</p>
|
|
<p>Quixote 1's secure_errors configuration variable is not present in Quixote 2.</p>
|
|
<p>Form.__init__ no longer has name or attrs keywords. If your existing
|
|
code calls Form.__init__ with 'attrs=foo', you'll need to change it to
|
|
'<a href="#id1" name="id2"><span class="problematic" id="id2">**</span></a>foo'. Form instances no longer have a name attribute. If your code
|
|
looks for form.name, you can find it with form.attrs.get('name').
|
|
The Form.__init__ keyword parameter (and attribute) 'action_url' is now
|
|
named 'action'.</p>
|
|
<div class="system-message" id="id1">
|
|
<p class="system-message-title">System Message: <a name="id1">WARNING/2</a> (<tt>upgrading.txt</tt>, line 65); <em><a href="#id2">backlink</a></em></p>
|
|
Inline strong start-string without end-string.</div>
|
|
<p>The SessionPublisher class is gone. Use the Publisher class instead.
|
|
Also, the 'session_mgr' keyword has been renamed to 'session_manager'.</p>
|
|
</div>
|
|
<div class="section" id="changes-from-0-6-1-to-1-0">
|
|
<h1><a name="changes-from-0-6-1-to-1-0">Changes from 0.6.1 to 1.0</a></h1>
|
|
<div class="section" id="sessions">
|
|
<h2><a name="sessions">Sessions</a></h2>
|
|
<p>A leading underscore was removed from the <tt class="literal"><span class="pre">Session</span></tt> attributes
|
|
<tt class="literal"><span class="pre">__remote_address</span></tt>, <tt class="literal"><span class="pre">__creation_time</span></tt>, and <tt class="literal"><span class="pre">__access_time</span></tt>. If
|
|
you have pickled <tt class="literal"><span class="pre">Session</span></tt> objects you will need to upgrade them
|
|
somehow. Our preferred method is to write a script that unpickles each
|
|
object, renames the attributes and then re-pickles it.</p>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="changes-from-0-6-to-0-6-1">
|
|
<h1><a name="changes-from-0-6-to-0-6-1">Changes from 0.6 to 0.6.1</a></h1>
|
|
<div class="section" id="q-exception-handler-now-called-if-exception-while-traversing">
|
|
<h2><a name="q-exception-handler-now-called-if-exception-while-traversing"><tt class="literal"><span class="pre">_q_exception_handler</span></tt> now called if exception while traversing</a></h2>
|
|
<p><tt class="literal"><span class="pre">_q_exception_handler</span></tt> hooks will now be called if an exception is
|
|
raised during the traversal process. Quixote 0.6 had a bug that caused
|
|
<tt class="literal"><span class="pre">_q_exception_handler</span></tt> hooks to only be called if an exception was
|
|
raised after the traversal completed.</p>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="changes-from-0-5-to-0-6">
|
|
<h1><a name="changes-from-0-5-to-0-6">Changes from 0.5 to 0.6</a></h1>
|
|
<div class="section" id="q-getname-renamed-to-q-lookup">
|
|
<h2><a name="q-getname-renamed-to-q-lookup"><tt class="literal"><span class="pre">_q_getname</span></tt> renamed to <tt class="literal"><span class="pre">_q_lookup</span></tt></a></h2>
|
|
<p>The <tt class="literal"><span class="pre">_q_getname</span></tt> special function was renamed to <tt class="literal"><span class="pre">_q_lookup</span></tt>,
|
|
because that name gives a clearer impression of the function's
|
|
purpose. In 0.6, <tt class="literal"><span class="pre">_q_getname</span></tt> still works but will trigger a
|
|
warning.</p>
|
|
</div>
|
|
<div class="section" id="form-framework-changes">
|
|
<h2><a name="form-framework-changes">Form Framework Changes</a></h2>
|
|
<p>The <tt class="literal"><span class="pre">quixote.form.form</span></tt> module was changed from a .ptl file to a .py
|
|
file. You should delete or move the existing <tt class="literal"><span class="pre">quixote/</span></tt> directory
|
|
in <tt class="literal"><span class="pre">site-packages</span></tt> before running <tt class="literal"><span class="pre">setup.py</span></tt>, or at least delete
|
|
the old <tt class="literal"><span class="pre">form.ptl</span></tt> and <tt class="literal"><span class="pre">form.ptlc</span></tt> files.</p>
|
|
<p>The widget and form classes in the <tt class="literal"><span class="pre">quixote.form</span></tt> package now return
|
|
<tt class="literal"><span class="pre">htmltext</span></tt> instances. Applications that use forms and widgets will
|
|
likely have to be changed to use the <tt class="literal"><span class="pre">[html]</span></tt> template type to avoid
|
|
over-escaping of HTML special characters.</p>
|
|
<p>Also, the constructor arguments to <tt class="literal"><span class="pre">SelectWidget</span></tt> and its subclasses have
|
|
changed. This only affects applications that use the form framework
|
|
located in the <tt class="literal"><span class="pre">quixote.form</span></tt> package.</p>
|
|
<p>In Quixote 0.5, the <tt class="literal"><span class="pre">SelectWidget</span></tt> constructor had this signature:</p>
|
|
<pre class="literal-block">
|
|
def __init__ (self, name, value=None,
|
|
allowed_values=None,
|
|
descriptions=None,
|
|
size=None,
|
|
sort=0):
|
|
</pre>
|
|
<p><tt class="literal"><span class="pre">allowed_values</span></tt> was the list of objects that the user could choose,
|
|
and <tt class="literal"><span class="pre">descriptions</span></tt> was a list of strings that would actually be
|
|
shown to the user in the generated HTML.</p>
|
|
<p>In Quixote 0.6, the signature has changed slightly:</p>
|
|
<pre class="literal-block">
|
|
def __init__ (self, name, value=None,
|
|
allowed_values=None,
|
|
descriptions=None,
|
|
options=None,
|
|
size=None,
|
|
sort=0):
|
|
</pre>
|
|
<p>The <tt class="literal"><span class="pre">quote</span></tt> argument is gone, and the <tt class="literal"><span class="pre">options</span></tt> argument has been
|
|
added. If an <tt class="literal"><span class="pre">options</span></tt> argument is provided, <tt class="literal"><span class="pre">allowed_values</span></tt>
|
|
and <tt class="literal"><span class="pre">descriptions</span></tt> must not be supplied.</p>
|
|
<p>The <tt class="literal"><span class="pre">options</span></tt> argument, if present, must be a list of tuples with
|
|
1,2, or 3 elements, of the form <tt class="literal"><span class="pre">(value:any,</span> <span class="pre">description:any,</span>
|
|
<span class="pre">key:string)</span></tt>.</p>
|
|
<blockquote>
|
|
<ul class="simple">
|
|
<li><tt class="literal"><span class="pre">value</span></tt> is the object that will be returned if the user chooses
|
|
this item, and must always be supplied.</li>
|
|
<li><tt class="literal"><span class="pre">description</span></tt> is a string or htmltext instance which will be
|
|
shown to the user in the generated HTML. It will be passed
|
|
through the htmlescape() functions, so for an ordinary string
|
|
special characters such as '&' will be converted to '&amp;'.
|
|
htmltext instances will be left as they are.</li>
|
|
<li>If supplied, <tt class="literal"><span class="pre">key</span></tt> will be used in the value attribute
|
|
of the option element (<tt class="literal"><span class="pre"><option</span> <span class="pre">value="..."></span></tt>).
|
|
If not supplied, keys will be generated; <tt class="literal"><span class="pre">value</span></tt> is checked for a
|
|
<tt class="literal"><span class="pre">_p_oid</span></tt> attribute and if present, that string is used;
|
|
otherwise the description is used.</li>
|
|
</ul>
|
|
</blockquote>
|
|
<p>In the common case, most applications won't have to change anything,
|
|
though the ordering of selection items may change due to the
|
|
difference in how keys are generated.</p>
|
|
</div>
|
|
<div class="section" id="file-upload-changes">
|
|
<h2><a name="file-upload-changes">File Upload Changes</a></h2>
|
|
<p>Quixote 0.6 introduces new support for HTTP upload requests. Any HTTP
|
|
request with a Content-Type of "multipart/form-data" -- which is
|
|
generally only used for uploads -- is now represented by
|
|
HTTPUploadRequest, a subclass of HTTPRequest, and the uploaded files
|
|
themselves are represented by Upload objects.</p>
|
|
<p>Whenever an HTTP request has a Content-Type of "multipart/form-data",
|
|
an instance of HTTPUploadRequest is created instead of HTTPRequest.
|
|
Some of the fields in the request are presumably uploaded files and
|
|
might be quite large, so HTTPUploadRequest will read all of the fields
|
|
supplied in the request body and write them out to temporary files;
|
|
the temporary files are written in the directory specified by the
|
|
UPLOAD_DIR configuration variable.</p>
|
|
<p>Once the temporary files have been written, the HTTPUploadRequest
|
|
object is passed to a function or PTL template, just like an ordinary
|
|
request. The difference between HTTPRequest and HTTPUploadRequest
|
|
is that all of the form variables are represented as Upload objects.
|
|
Upload objects have three attributes:</p>
|
|
<dl>
|
|
<dt><tt class="literal"><span class="pre">orig_filename</span></tt></dt>
|
|
<dd>the filename supplied by the browser.</dd>
|
|
<dt><tt class="literal"><span class="pre">base_filename</span></tt></dt>
|
|
<dd>a stripped-down version of orig_filename with unsafe characters removed.
|
|
This could be used when writing uploaded data to a permanent location.</dd>
|
|
<dt><tt class="literal"><span class="pre">tmp_filename</span></tt></dt>
|
|
<dd>the path of the temporary file containing the uploaded data for this field.</dd>
|
|
</dl>
|
|
<p>Consult upload.txt for more information about handling file uploads.</p>
|
|
</div>
|
|
<div class="section" id="refactored-publisher-class">
|
|
<h2><a name="refactored-publisher-class">Refactored <cite>Publisher</cite> Class</a></h2>
|
|
<p>Various methods in the <cite>Publisher</cite> class were rearranged. If your
|
|
application subclasses Publisher, you may need to change your code
|
|
accordingly.</p>
|
|
<blockquote>
|
|
<ul>
|
|
<li><p class="first"><tt class="literal"><span class="pre">parse_request()</span></tt> no longer creates the HTTPRequest object;
|
|
instead a new method, <tt class="literal"><span class="pre">create_request()</span></tt>, handles this,
|
|
and can be overridden as required.</p>
|
|
<p>As a result, the method signature has changed from
|
|
<tt class="literal"><span class="pre">parse_request(stdin,</span> <span class="pre">env)</span></tt> to <tt class="literal"><span class="pre">parse_request(request)</span></tt>.</p>
|
|
</li>
|
|
<li><p class="first">The <tt class="literal"><span class="pre">Publisher.publish()</span></tt> method now catches exceptions raised
|
|
by <tt class="literal"><span class="pre">parse_request()</span></tt>.</p>
|
|
</li>
|
|
</ul>
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="changes-from-0-4-to-0-5">
|
|
<h1><a name="changes-from-0-4-to-0-5">Changes from 0.4 to 0.5</a></h1>
|
|
<div class="section" id="session-management-changes">
|
|
<h2><a name="session-management-changes">Session Management Changes</a></h2>
|
|
<p>The Quixote session management interface underwent lots of change and
|
|
cleanup with Quixote 0.5. It was previously undocumented (apart from
|
|
docstrings in the code), so we thought that this was a good opportunity
|
|
to clean up the interface. Nevertheless, those brave souls who got
|
|
session management working just by reading the code are in for a bit of
|
|
suffering; this brief note should help clarify things. The definitive
|
|
documentation for session management is session-mgmt.txt -- you should
|
|
start there.</p>
|
|
<div class="section" id="attribute-renamings-and-pickled-objects">
|
|
<h3><a name="attribute-renamings-and-pickled-objects">Attribute renamings and pickled objects</a></h3>
|
|
<p>Most attributes of the standard Session class were made private in order
|
|
to reduce collisions with subclasses. The downside is that pickled
|
|
Session objects will break. You might want to (temporarily) modify
|
|
session.py and add this method to Session:</p>
|
|
<pre class="literal-block">
|
|
def __setstate__ (self, dict):
|
|
# Update for attribute renamings made in rev. 1.51.2.3
|
|
# (between Quixote 0.4.7 and 0.5).
|
|
self.__dict__.update(dict)
|
|
if hasattr(self, 'remote_address'):
|
|
self.__remote_address = self.remote_address
|
|
del self.remote_address
|
|
if hasattr(self, 'creation_time'):
|
|
self.__creation_time = self.creation_time
|
|
del self.creation_time
|
|
if hasattr(self, 'access_time'):
|
|
self.__access_time = self.access_time
|
|
del self.access_time
|
|
if hasattr(self, 'form_tokens'):
|
|
self._form_tokens = self.form_tokens
|
|
del self.form_tokens
|
|
</pre>
|
|
<p>However, if your sessions were pickled via ZODB, this may not work. (It
|
|
didn't work for us.) In that case, you'll have to add something like
|
|
this to your class that inherits from both ZODB's Persistent and
|
|
Quixote's Session:</p>
|
|
<pre class="literal-block">
|
|
def __setstate__ (self, dict):
|
|
# Blechhh! This doesn't work if I put it in Quixote's
|
|
# session.py, so I have to second-guess how Python
|
|
# treats "__" attribute names.
|
|
self.__dict__.update(dict)
|
|
if hasattr(self, 'remote_address'):
|
|
self._Session__remote_address = self.remote_address
|
|
del self.remote_address
|
|
if hasattr(self, 'creation_time'):
|
|
self._Session__creation_time = self.creation_time
|
|
del self.creation_time
|
|
if hasattr(self, 'access_time'):
|
|
self._Session__access_time = self.access_time
|
|
del self.access_time
|
|
if hasattr(self, 'form_tokens'):
|
|
self._form_tokens = self.form_tokens
|
|
del self.form_tokens
|
|
</pre>
|
|
<p>It's not pretty, but it worked for us.</p>
|
|
</div>
|
|
<div class="section" id="cookie-domains-and-paths">
|
|
<h3><a name="cookie-domains-and-paths">Cookie domains and paths</a></h3>
|
|
<p>The session cookie config variables -- <tt class="literal"><span class="pre">COOKIE_NAME</span></tt>,
|
|
<tt class="literal"><span class="pre">COOKIE_DOMAIN</span></tt>, and <tt class="literal"><span class="pre">COOKIE_PATH</span></tt> -- have been renamed to
|
|
<tt class="literal"><span class="pre">SESSION_COOKIE_*</span></tt> for clarity.</p>
|
|
<p>If you previously set the config variable <tt class="literal"><span class="pre">COOKIE_DOMAIN</span></tt> to the name
|
|
of your server, this is most likely no longer necessary -- it's now fine
|
|
to leave <tt class="literal"><span class="pre">SESSION_COOKIE_DOMAIN</span></tt> unset (ie. <tt class="literal"><span class="pre">None</span></tt>), which
|
|
ultimately means browsers will only include the session cookie in
|
|
requests to the same server that sent it to them in the first place.</p>
|
|
<p>If you previously set <tt class="literal"><span class="pre">COOKIE_PATH</span></tt>, then you should probably preserve
|
|
your setting as <tt class="literal"><span class="pre">SESSION_COOKIE_PATH</span></tt>. The default of <tt class="literal"><span class="pre">None</span></tt> means
|
|
that browsers will only send session cookies with requests for URIs
|
|
under the URI that originally resulted in the session cookie being sent.
|
|
See session-mgmt.txt and RFCs 2109 and 2965.</p>
|
|
<p>If you previously set <tt class="literal"><span class="pre">COOKIE_NAME</span></tt>, change it to
|
|
<tt class="literal"><span class="pre">SESSION_COOKIE_NAME</span></tt>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|