The errata list is a list of errors and their corrections that were found after the product was released.
The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.
| Version |
Location |
Description |
Submitted By |
| Printed |
Page 16
Example 2-4 |
When running the example an exception occured when it
is not possible to connect to the port:
> python connectiontest.py www.oreilly.com 80
/usr/lib/python2.6/site-packages/twisted/internet/_sslverify.py:4: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import itertools, md5
Connected to port 80
> python connectiontest.py www.oreilly.com 808
/usr/lib/python2.6/site-packages/twisted/internet/_sslverify.py:4: DeprecationWarning: the md5 module is deprecated; use hashlib instead
import itertools, md5
Error connecting to port 808: Connection was refused by other side: 111: Connection refused.
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/twisted/internet/defer.py", line 185, in addCallbacks
self._runCallbacks()
File "/usr/lib/python2.6/site-packages/twisted/internet/defer.py", line 323, in _runCallbacks
self.result = callback(self.result, *args, **kw)
File "/usr/lib/python2.6/site-packages/twisted/internet/base.py", line 388, in _continueFiring
callable(*args, **kwargs)
File "/usr/lib/python2.6/site-packages/twisted/internet/base.py", line 525, in disconnectAll
failure.Failure(main.CONNECTION_LOST))
--- <exception caught here> ---
File "/usr/lib/python2.6/site-packages/twisted/python/log.py", line 51, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/lib/python2.6/site-packages/twisted/python/log.py", line 36, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/lib/python2.6/site-packages/twisted/python/context.py", line 59, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/lib/python2.6/site-packages/twisted/python/context.py", line 37, in callWithContext
return func(*args,**kw)
File "/usr/lib/python2.6/site-packages/twisted/internet/tcp.py", line 574, in connectionLost
self.failIfNotConnected(error.ConnectError(string=reason))
File "/usr/lib/python2.6/site-packages/twisted/internet/tcp.py", line 479, in failIfNotConnected
self.connector.connectionFailed(failure.Failure(err))
File "/usr/lib/python2.6/site-packages/twisted/internet/base.py", line 929, in connectionFailed
self.factory.clientConnectionFailed(self, reason)
File "connectiontest.py", line 17, in clientConnectionFailed
self.deferred.errback(reason)
File "/usr/lib/python2.6/site-packages/twisted/internet/defer.py", line 264, in errback
self._startRunCallbacks(fail)
File "/usr/lib/python2.6/site-packages/twisted/internet/defer.py", line 293, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError:
|
Anonymous |
| Printed |
Page 19
Example 2-6 dataforward.py |
Inside Example 2-6 dataforward.py, the second line is::
from twisted.protocols import basic
However, basic is not used anywhere in the example.
|
Anonymous |
| Printed |
Page 19
Example 2-6 dataforward.py |
The dataforward.py program does not work under Windows XP, Python 2.4.3, Twisted
2.4.0.
I copied the example inside t.py. Once started, no echo is done when typing from the
console. The program does not read stdin and does not forward it in the connection.
I had to hit Ctrl-C to close it and you can see that what was typed at the console
was not taken by the program.
If twisted.internet.stdio.StandardIO is not working on Win32 systems, the book should say so.
...
D: mp>HEAD / HTTP/1.0
==> / <==
HEAD: error reading `/': Is a directory
HEAD: cannot open `HTTP/1.0' for reading: No such file or directory
|
Anonymous |
| Printed |
Page 19
Bottom of page |
Example 2-6. dataforward.py does not work on Windows. The Windows implementation of stdio.StandardIO loses the connection to stdin. It throws and catches an exception that indicates that the handle is invalid.
|
Anonymous |
| Printed |
Page 30
Code listing, primarily the encodeForm() function |
Figure 3-1 actually indicates an error, not a successful validation as the main text suggests. In fact, an error _is_ returned if the sample code is executed, for reasons discussed below.
The format of multipart/form-data data blocks is given by section 7.2.1 of RFC 1521.
The validate.py code does not define a (required) "boundary" parameter value in the enclosing Content-Type header field. For the purposes of further discussion, however, this value will be assumed to be the 20 character string derived from the the randomChars list generated in encodeForm.
The encodeForm function does not create a properly-formatted multipart/form-data data block.
Within a multipart/form-data data block, each body part must begin with an encapsulation boundary, defined as two hyphens, followed by the "boundary" parameter value from the enclosing Content-Type header field, followed by a CRLF pair. The final part must be trailed by a special encapsulation boundary. This special encapsulation boundary has an additional two hyphens inserted before the final CRLF pair. All encapsulation boundaries, except the first, must be preceeded by CRLF pairs.
The validate.py code's encapsulation boundaries, with the exception of the first and last, are comprised of a 2 CRLF pairs, followed by 3 hyphens, the boundary string, another 3 hyphens, and a CRLF pair.
The validate.py code's first encapsulation boundary is like its others, except it lacks the 2 preceeding CRLF pairs.
The validate.py code's last encapsulation boundary is like its others, except it lacks a trailing CRLF.
None of these encapsulation boundaries is correct.
Additionally, the validate.py code does not insert blank lines between the header and body content of body parts.
Finally, the W3C validator service won't properly validate XHTML files, unless the relevant body part includes a Content-Type header specifing application/xhtml+xml. Such a header is not inserted by the validate.py code.
|
Anonymous |
| Printed |
Page 45
3rd line from bottom |
The sentence ending in "send the form data to the page formhandler using an HTTP POST request" should read "send the form data to the page posthandler using an HTTP POST request".
This is also evident from the URL shown in the browser output of Figure 4-5 and from the code listing.
|
Anonymous |
| Printed |
Page 46
Second paragraph |
In paragraph 2, lines 2 and 3, both references to /formhandler
should be /posthandler.
This change is also needed to be consistent with the code in Example 4-3 and with the URL portrayed in Figure 4-5.
|
Anonymous |
| Printed |
Page 48
ColorRoot.render |
The return value references the URI /colors/, while the rest of the code uses
/color/.
|
Anonymous |
| Other Digital Version |
48
In errata sheet for Example 4-4 pages 48-49 of printed book |
The replacement code for Example 4-4 cut-and-pasted from
http://oreilly.com/catalog/9780596100322/errata/9780596100322.confirmed
doesn't work unless DEFANGED_link is changed to link and DEFANGED_style
is changed to style. With these substitutions, the code is consistent with the downloadable example code.
|
Anonymous |
| Printed |
Page 50
midpage table |
The table describes styles.css as being available under /css/styles.css, when in
fact it is at /styles.css.
|
Anonymous |
| Printed |
Page 56
in SavePage.render method |
Hi,
I am not sure whether this is really an error but I find that Example 4-6 modified for PostgreSQL and the psycopg2 database adapter crashes the python 2.5 interpreter unless I replace runQuery with runOperation.
Using the later, I get a working example with the following diff output from the original:
$diff databaseblog.py databaseblog.py.orig
2c2
< from twisted.enterprise import adbapi
---
> from twisted.enterprise import adbapi, util as dbutil
4,18c4,9
< #import psycopg2
<
< # This code depends on a pre-existing PostgreSQL table
< # created with the following SQL schema:
< #
< #CREATE TABLE posts(
< # post_id serial unique,
< # title varchar(255) NOT NULL,
< # body text,
< # primary key (post_id)
< # );
<
<
< DB_DRIVER = "psycopg2"
< DB_ARGS = "dbname=postgres host=localhost user=postgres password=mytestdb2"
---
> DB_DRIVER = "MySQLdb"
> DB_ARGS = {
> 'db': 'test',
> 'user': 'abe',
> 'passwd': 'gear42',
> }
82,84c73,77
< query = "insert into posts (title, body) values ('%s', '%s')" \
< % (title, body)
< self.db.runOperation(query).addCallback(
---
> query = """
> Insert into posts (title, body) values (%s, %s)
> """ % (dbutil.quote(title, "char"),
> dbutil.quote(body, "text"))
> self.db.runQuery(query).addCallback(
88c81
<
---
>
108c101
< dbConnection = adbapi.ConnectionPool(DB_DRIVER, DB_ARGS)
---
> dbConnection = adbapi.ConnectionPool(DB_DRIVER, **DB_ARGS)
|
Anonymous |
| Printed |
Page 56
class SavePage; def render |
Two issues:
util.quote is deprecated, so it will not work. Plus, it's not a great way to insert the data.
More seriously, runQuery will return an error saying that there are no results to fetch. runOperation is the correct function.
Corrected code:
def render(self, request):
title = request.args['title'][0]
body = request.args['body'][0]
query = "Insert into posts (title, body) values (%s, %s)"
self.db.runOperation(query, (title, body)).addCallback(self._saved, request).addErrback(self._saveFailed, request)
return server.NOT_DONE_YET
|
Xitij Patel |
| Printed |
Page 62
3rd line from bottom |
The sentence "The third class, WordCountProxy client, contains..."
should read "The third class, WordCountProxyClient, contains..."
|
Anonymous |
| Printed |
Page 75
in method __init__ of WIkiXmlRpc |
as a first line of this method should be inserted:
xmlrpc.XMLRPC.__init__(self)
If you don't, asking for a dotted function name via XMLRPC
(such as system.listMethods) will result in a Internal Server
error, instead of the expected:
xmlrpclib.Fault: <Fault 8001: 'function get_data not found'>
in addition the server itself outputs an AttributeError, after which
it recovers.
|
Anonymous |
| Printed |
Page 89
At the end of the 'requestAvatar' function of the 'TestRealm' class |
It seems a bit pedantic but there is slight typo in example 6.1 simplecred.py. The line:
"raise KeyError("None of the requested interfaces is supported")"
should probably read:
"raise KeyError("None of the requested interfaces are supported")"
In addition on that page there seems to be a mix of old and new-style classes in the example:
"class PasswordDictChecker(object):" but also "class TestRealm:" and "class NamedUserAvatar:"
I notice only because I have been staring at the page for hours on end.
|
Anonymous |
| Printed |
Page 127
2nd full paragraph |
The phrase "the server name by which the client addressed the server" suggests that
this string will be the hostname of the server. In fact, it is ordinarily the
hostname of the SMTP *client*.
|
Anonymous |
| Printed |
Page 135
top of page, 8th line of code from the top |
return defer.succeed(requestedInterface, avatar, logout)
should be
return defer.succeed((requestedInterface, avatar, logout))
it has been corrected in the downloadable example code, but the book is wrong.
|
Anonymous |
| Printed |
Page 135
6th line |
FIXME comment still included
|
Anonymous |
| Printed |
Page 155
3rd line |
The news server code connects to Abe's news server (news-server.maine.rr.com) rather
than using sys.argv[1]!
|
Anonymous |
| Printed |
Page 174
class SSHDemoAvatar |
When trying to connect to this example, I got an exception:
SSHDemoAvatar instance has no attribute 'eofReceived'
According to the source at http://twistedmatrix.com/trac/browser/tags/releases/twisted-8.2.0/twisted/conch/interfaces.py the ISession interface also needs eofReceived and windowChanged, in addition to the ones already in the example.
|
Anonymous |
| Printed |
Page 178
second paragraph |
"With key-based authentication, the server is given a copy of a user's private key."
Hmmm, that would make the private key "un-private" wouldn't it? This is the exact opposite of what the server gets. In reality the server needs a copy of the user's public key.
|
Anonymous |