By Developers, For Developers
| PDF Pg | Paper Pg | Type | Description | Fixed on | Comments |
|---|---|---|---|---|---|
| 77 | ERROR | Incorrect code sample shown for method ChatRoomCountedHandler. The code does not contain the loop to calculate the timedelta field as referenced in the following text. | 2010-04-04 | ||
| 83 | TYPO | 2nd para. Sentence starting “In the next chapter…” missing word “to” at end of 4th line (after “how”). Same sentence, line 6, word “sour” should be “our” | 2010-03-31 | ||
| 46 | ERROR | textarea tags in file chattwo.py don’t render in browser when using self closing tags ie. <textarea ….. /> | 2010-03-31 | Strange... Works for me in both Safari and Chrome. But I've modified the code so that it should work for you now. | |
| 53 | ERROR | codeblock for retrieving persistent objects. lines 5-9 should not be there (they are a variation of lines 1-4 but with a limit clause in) | 2010-03-31 | Thanks; accidentally reused a metadata label, so it added both code fragments. | |
| 57 | ERROR | codeblock for retrieving persistent objects. | 2010-03-31 | ||
| 59 | ERROR | line 12 of the code block the order clause should be “order by timestamp” and not "order by time | 2010-03-31 | ||
| 68 | TYPO | last paragraph: | 2010-03-31 | ||
| 65 | TYPO | in line 24 of code block
Enter new message from: " %s | 2010-03-31 | ||
| 71 | ERROR | line 8 the order clause should be “order by timestamp” and not “order by time” | 2010-03-31 | ||
| 69 | TYPO | lines 6-8 in the code block are rendering part of your internal markup showing {#} at the end of the lines where they are numbered for reference | 2010-04-03 | I think this is fixed; it's messy, because I get different results in my local build versus the online build, and the template is an overlap between two different languages with two different comment syntaxes. | |
| 71 | ERROR | error in downloadable code of codeblock at (media.pragprog.com/titles/mcappe/code/template-chat/tchat.py) missing http call at front of url as this wont allow me to post a url this downloadable code is missing the following import statements: import os | 2010-04-03 | ||
| 50 | ERROR | Link to Wikipedia article on HTTP is incorrect | 2010-03-31 | ||
| 56 | TYPO | 2nd para references to “time” property should be to “timestamp” property | 2010-03-31 | ||
| 57 | ERROR | last line of page “ORDER BY time” should be “ORDER BY timestamp” | 2010-03-31 | ||
| 59 | ERROR | I go the following error when running sample code: ‘GqlQuery’ object has no attribute ‘reverse’ I deleted the line messages.reverse() and changed the for loop to: for msg in reversed(list(messages)): | 2010-04-03 | Things in AppEngine change too fast! Thanks for catching that. | |
| 61 | TYPO | Missing comma at end of 2nd line of code, after (‘/talk’, ChatRoomPoster) | 2010-03-31 | ||
| 13 | TYPO | 2nd paragraph, line 6, “VAX 11/780, named nicknamed” should be “VAX 11/780 named” or “VAX 11/780 nicknamed”. | 2010-04-19 | Thanks! I have no idea how many times I've ready that section without noticing that. | |
| 24 | SUGGEST | In the gray aside box, the author states, “I’ll say more about this later, but I’m not a huge Python fan.” The Python sections of this book are why I bought it. So, my initial reaction to this comment was a feeling that I had wasted my money, and I nearly put the book down. I feel if the author doesn’t like Python, how can I possibly expect quality coverage of it? I would recommend removing such personal commentary from the final product since Python coverage may be the sole reason a reader, such as myself, bought your book. | 2010-04-27 | I've toned it down a bit. But I'd be lying if I said that I love Python, or that I think it's the best way of building programs in AppEngine. But that doesn't mean that I'm not going to cover it thoroughly or fairly. In fact, I think that it's really unreasonable to expect that only a person who is a huge fan of Python can possibly write a quality text using Python. \n \nHonestly, given my choice, I wouldn't be writing in Python *or* Java. But the point of the book isn't "Here's how to write cloud applications in my favorite programming language". It's "Here's how to write cloud applications". \n \nOne of the things that makes this book - and prag books in general - special is that the authors have very distinct voices and opinions, and those are reflected in the books. The book definitely reflects my opinions, and I think that taking them out would make the book much less valuable. But you'll still get your moneys worth even if your opinions don't match with mine. \n | |
| 21 | TYPO | “Create at Application” instead of “Create an Application”: When you have the tools you need to write Python programs, you can | 2010-04-27 | ||
| 24 | TYPO | “configures application” instead of “configures applications” or “configures your application”? appcfg.py uploads and configures application using AppEngine in | 2010-04-27 | ||
| 25 | TYPO | “nderstand” instead of “understand” When | 2010-04-27 | ||
| 74 | TYPO | “an consistent” instead of “a consistent” you provide the user with the feeling that they’re using an | 2010-04-27 | ||
| 71 | SUGGEST | Your templates contain “{#}” but you don’t explain it. I guess they’re django comment tags. I suggest adding some comment text, deleting the empty comment tags or explaining the comment tag. | 2010-04-27 | Those are typesetting artifacts which we're working on correcting. They're fragments left from the markup that generates the callout numbers. The typesetting code that we use doesn't yet support Django comments correctly, so those are left in the typeset results. I'm aware of them, and they'll eventually be fixed, when the prag hamsters have time. | |
| 106 | TYPO | “user as on actions” instead of “user actions” With JavaScript, you can embed programs in your application’s pages | 2010-04-27 | ||
| 106 | TYPO | “as a object” instead of “as an object” Second, your JavaScript program can manipulate the entire HTML page, | 2010-04-27 | ||
| 115 | TYPO | “sent a XML document” instead of “send an XML document” We’ll just sent a XML | 2010-04-27 | ||
| 139 | TYPO | “It’s as full-featured” instead of “It isn’t as full-featured” It’s as full-featured as our | 2010-04-27 | ||
| 160 | TYPO | “60emss” instead of “60ems” We set its width to 60emss, | 2010-04-27 | ||
| 179 | TYPO | “users first connects” instead of “users first connect” When users first connects to a chatroom, | 2010-04-27 | ||
| 187 | TYPO | “strangeness” instead of “strangenesses” (or is that too strange?) here are | 2010-04-27 | ||
| 78 | TYPO | The “ChatRoomCountedHandler” class in the code listing should be named “ChatRoomCountViewPage” to be consistent with the example in the previous chapter | 2010-06-02 | This isn't a typo - it's just a change in naming as the code gets more complex. That's deliberate: my experience is that people often start off very rough and fuzzy, and then as they progress, things become more robust -both in terms of functionality, and in terms of stylistic things like naming. \n | |
| 16 | TYPO | Second paragraph, last sentence: “You can build anything as a service in the cloud, but it might be a lot harder that developing it as a standalone application.” Suppose it should be: “…a lot harder than developing…” | 2010-08-16 | ||
| 30 | TYPO | Last sentence on page 30 reads: For this, we’re using two basic webapp building blocks: the webapp module itself, and a a webapp function called run_wsgi_app. “and a a webapp” should be “and a webapp” | 2010-08-16 | ||
| 47 | TYPO | 7th paragraph reads: To implement in AppEngine, we need to build a RequestHander Should be “RequestHandler” | 2010-08-16 | ||
| 48 | ERROR | Code on page 48 is correct, but the download file chattwo.py has an error in this line: Missing close tag “>” in: </textarea Should be : | 2010-08-16 | ||
| 29 | TYPO | Command sample (middle of page): “$ appcfg.py update chat” The running example is using a directory name of ‘chatone’ but the command uses ‘chat’. If this is correct, it is (at least) not clear how the author gets from one to another. | 2010-08-17 | ||
| 31 | TYPO | Item #7 - second sentence: The function called is listed as “run_wsgiapplication”. It should be “run_wsgi_app”. | 2010-08-16 | ||
| 31 | SUGGEST | Item #7 - First sentence: “…makes use of a common Google idiom.” One could argue that it is in fact a Python idiom. At least even I have seen it used in the regular Python documentation (and tutorials). | 2010-08-16 | ||
| 58 | TYPO | Second paragraph: This text and the following code snippets uses ‘time’ for the property called ‘timestamp’ in the ChatMessage class. Coding while following the text then returns no chat entries in the GQL queries because of the ‘ORDER BY time’ clause. | 2010-08-16 | ||
| 63 | TYPO | Download file ‘persist-chat/pchat.py’ contains no definition for class ChatRoomTimeViewPage, but instead a duplicate implementation of ChatRoomCountViewPage. | 2010-08-17 | ||
| 230 | ERROR | Graf says: I interpret the docs to mean “keep it at most this long,” which the next sentence implies as well. AppEngine docs say: | 2010-08-16 | ||
| 60 | TYPO | the query should be “… order by timestamp” the text shows just “time” | 2011-01-09 | ||
| 64 | TYPO | Missing a comma on second continuation line: | 2011-01-09 | ||
| 62 | TYPO | In the persist-chat/pchat.py example, the source code for the first change is truncated with the text “…TRUNC”. | 2011-01-09 | ||
| 45 | TYPO | The text in bullet #1 should read “…method for the request, followed BY the URL of the resource..”. The word “by” is missing. | 2011-01-09 | ||
| 63 | TYPO | Using a bound parameter in the LIMIT clause is producing the error “Non-number limit in LIMIT clause”. According to AppEngine issue #179, bound parameters are not supported in LIMIT and OFFSET clauses. Unfortunately I can’t include a link to the issue entry on the AppEngine Google code website. Standard Python string substitution appears to work OK. | 2011-01-09 | Grumble - this worked when I wrote the chapter. Unfortunately, things keep changing; this, however, is the first time I recall a change that reduced a useful and simple function. \n | |
| 18 | ERROR | “you can run your application in EC2 using Linux, Solaris, AIX, or Windows Server” - I don’t believe AIX is available. AIX runs on Power RISC processors, not on Intel. | 2011-01-09 | ||
| 32 | SUGGEST | Item 7 - “The rest of the file makes use of a common Google idiom” - wasn’t this a common Python idiom, long before Google existed? | 2011-01-09 | There are a few different idioms that are used for things like this in Python. This is the particular one that we follow at Google. I don't think it's incorrect to say it's the Google idiom - it's the one that we use. \n | |
| 47 | TYPO | “4. Four indicates a client error (for example, 401 means that the client requested a resource which doesn’t exist on the server).” - “401” should be “404”. | 2011-01-09 | ||
| 49 | SUGGEST | Where you have I suggest you should have | 2011-02-02 | ||
| 49 | SUGGEST | Your submit button is labelled “Send ChatMessage” - but ChatMessage is the name of an implementation class; I don’t think it’s intended to be part of the user’s conceptual model of the application. “Send Message”, or just “Send”, would be better. I know this is a small point, but things like this distract readers. | 2011-01-09 | The user is in a chat room, sending chat messages. I don't think that there's anything unclear about saying "send chat message" versus "send message". It's a matter of taste which you prefer. \n | |
| 58 | SUGGEST | Somewhere in this discussion of the datastore you need to show the import required, e.g. | 2011-01-30 | ||
| 68 | TYPO | Near the bottom of the page, the line of code containing “Enter new message from: %s” is missing closing b and p tags. | 2011-01-30 | ||
| 69 | SUGGEST | The reader also needs to know the additional import needed: | 2011-01-30 | ||
| 64 | SUGGEST | “We don’t yet have a nice way of moving between the views, and their implementations have a silly amount of duplication. We’ll look at how to clean that up in the next chapter—but for now, we’ve got something that works.” - In fact, the next chapter looks at authentication. I’d prefer it if you did clean things up before going on to a different topic. | 2011-02-02 | ||
| 49 | ERROR | In the listing on this page user-provided data is being sent to the browser without HTML escaping. This makes it easy for users to break the application and opens up the possibility of XSS attacks. Using
%s " % cgi.escape(str(msg))) | 2011-01-09 | This is deliberate; I use it as an example of a common error later on, in the security chapter, by pointing out that that the way we implemented the code here leaves it open to an XSS attack. \n | |
| 66 | SUGGEST | I think you should point out that applications hosted on Google App Engine can use whatever authentication and authorisation mechanisms they like - it isn’t necessary for users to have Google accounts to log in to GAE apps, if the app implements some other authentication mechanism. It’s just really convenient if the users do have Google accounts. | 2011-01-09 | ||
| 72 | SUGGEST | You can improve the formatting of the message timestamp and escape the user-provided message content using filters:
{{ m.user }} ( {{ m.timestamp|date:“F j Y H:i” }} ): {{ m.message|escape }} | 2011-01-09 | Yes, I could - but it just adds a bit more noise and complexity to the code. The point of the code here is to be as clear and focused as possible: to show what's essential. Adding extra template format controls just isn't necessary. I can't cover every feature of the template system - that would be an entire book of its own. So I'd prefer to keep it as simple as possible, and try to focus on GAE. The Django template docs are pretty good, and if people are writing apps using them, they'll need to read the Django manuals. \n | |
| 74 | SUGGEST | Imports again: | 2011-01-30 | ||
| 94 | TYPO | Half way down the page (in reason 2): “when we change the way that we write them in XML, we won’t need to change our CSS” - “XML” should be “HTML”. | 2011-01-09 | ||
| 118 | TYPO | Second line on page: “Now we’re going to implement to controller.” - “to controller” should be “the controller”. | 2011-01-09 | ||
| 68 | TYPO | The code downloaded from this page (login-chat/pchat.py) make reference to ChatRoomTimeViewPage and ChatRoomCountViewPage, but these classes are not in the file downloaded. Also the code still has “ORDER BY time” where the model defines it as timestamp | 2011-01-30 | ||
| 128 | TYPO | The file generated by Eclipse for HelloChat.gwt.xml doesn’t contain a doctype declaration | 2011-01-30 | That's peculiar. The file that's used to generate that piece of the book was generated by Eclipse, and when I try it even in a newer version of Eclipse, I still get the doctype declaration. \n | |
| 129 | TYPO | The HelloChat.html has the doctype <!doctype html> For standards mode and html5 compatibility | 2011-01-09 | ||
| 16 | TYPO | in “The computer may not have be sitting on” … “not have be” should be: not have to be | 2011-01-09 | Fixed; actually, though, it should read "not be". \n | |
| 18 | TYPO | “Before we start actually writing programs, we’ll take a quick look at a few examples, to give you a sense of what the options.” should be something more along the following: Before we start actually writing programs, we’ll take a quick look at a few examples to give you a sense of the options available. | 2011-01-09 | ||
| 23 | TYPO | “But for a cloup app” cloup should be cloud | 2011-01-09 | ||
| 63 | TYPO | When adding the time-limited view ChatMessage.gql(“WHERE timestamp > :fiveago ORDER BY time”, fiveago=datetime.now() - timedelta(minutes=5)). Should be “timestamp” after ORDER BY (Actually, learning how to correct this is a good way to dig into Python and appengine logs) | 2011-01-30 | ||
| 86 | TYPO | In the multichat app , the landing page is not described. The chat.html template is neither described nor provided in the source files. chatapp = webapp.WSGIApplication([(‘/’ , ChatRoomLandingPage), | 2011-01-30 | ||
| 127 | TYPO | On my setup (Eclipse Helios / appenfine 1.4.0) the GreetingServiceImpl.java file is part of the server package, not the client one. The third flie of the client package is GreetingServiceAsync.java “The client side has a three files. One of them, HelloChat.java is the main body of our application. The other two, GreetingService.java and GreetingServiceImpl. | 2011-01-30 | ||
| 78 | TYPO | In the code for the master.html template, there is a loop that prints elements for the primary navigation section. Within that loop, the line that prints the actual link has the following code: This line should have the chat name in curly brackets, like so: | |||
| 71 | SUGGEST | Authentication description is very limited in the book and adds little value to what is available in google’s own “getting started” tutorial Some insight about how to authenticate using an alternative provider (facebook, openid) and how to glue it all together would be very valuable. | |||
| 60 | TYPO | Section: Retrieving Persistent Objects | |||
| 64 | TYPO | Line 2 should be DATETIME.datetime.now() - DATETIME.timedelta(minutes=5) (dont forget to change the gql query on line 13 and 14) | |||
| 66 | TYPO | line 10: … to use USE GAE’s login service. (one use too much?) | |||
| 69 | TYPO | The indentation level of the first if statement in the post method is wrong. But it’s correct in the pchat.py source file. | |||
| 69 | TYPO | I’m sorry. The indentation of the first if statement in the post method in the pchat.py source file is wrong too. | |||
| 69 | TYPO | post method: | |||
| 82 | SUGGEST | I tried to run the source code from chapter 6 and got the following error: no matching index found. I’m new to GAE so this error message didn’t help me much, at first. It took me some time to figure it out. | |||
| 128 | TYPO | 4th paragraph: | |||
| 137 | TYPO | 2) The service interface declaration must extend >>T<<he GWT interface | |||
| 158 | TYPO | Is the bottomPanel a HorizontalPanel or a VerticalPanel. | |||
| 159 | TYPO | Does the title label get the style apptitle or title? | |||
| 159 | TYPO | “(There is a setStyle name, but …” <- setStyleName not setStyle name | |||
| 159 | TYPO | (3) | |||
| 170 | SUGGEST | 11.6 The GWT Widget Gallery. . . I think it’s best to provide a link to the newest WidgetGallery. …/webtoolkit/doc/1.6/RefWidgetGallery.html <- change 1.6 to latest | |||
| 171 | TYPO | We’ll examine WE else we need in our server | |||
| 32 | TYPO | ‘debugging’ -> ‘debugger’ | |||
| 94 | ERROR | The closing body tag |
is in the wrong place. In the document, it has been placed within the closing div tag for the content div.
Move the closing body tag to the line before the closing html tag.
/ Fired when the user types in the nameField. */
“nameField” should be “messageBox”
The author has chosen not to display the Import statements as he modifies the code going from oen chapter to the next and that means those lines are missing when I write the code myself and so my code errors out when run. I have to search online for the right imports (e.g., “from google.appengine.api import users” and “import sys” for this User login chapter) and then my code works. This is not ideal, IMO.
In the “post” code for the login-chat example, these two lines are shown in the wrong order so the program errors until these lines are swapped:
You can’t say “if user is None” unless you’ve tried to instantiate “user” first.
In the post method, the ChatMessage should be passed the variable “nick” instead of “user.nickname()” since the previous lines of code check for an undefined user.nickname().
In other words…
msg = ChatMessage(user=user.nickname(), message=msgtext)
should be:
msg = ChatMessage(user=nick, message=msgtext)
Note: Since the book requires Python 2.5, you could also shorten the code for the nickname to use the ternary in Python 2.5 and up:
so…
if user.nickname() is None or user.nickname() == “”:
nick = “No Nickname”
else:
nick = user.nickname()
becomes…
nick = “No Nickname” if (user.nickname() is None or user.nickname == “”) else user.nickname()
In the post method, the ChatMessage should be passed the variable “nick” instead of “user.nickname()” since the previous lines of code check for an undefined user.nickname().
In other words…
msg = ChatMessage(user=user.nickname(), message=msgtext)
should be:
msg = ChatMessage(user=nick, message=msgtext)
Note: Since the book requires Python 2.5, you could also shorten the code for the nickname to use the ternary in Python 2.5 and up:
so…
if user.nickname() is None or user.nickname() == “”:
nick = “No Nickname”
else:
nick = user.nickname()
becomes…
nick = “No Nickname” if (user.nickname() is None or user.nickname() == “”) else user.nickname()
Downloaded both the template-chat files, and the multi-chat files. Can’t seem to get either of them to work. Am getting a “raise BadValueError(’Property s is required’ self.name) BadValueError: Property chat is required” … Any ideas?
Downloaded both the template-chat files, and the multi-chat files. Can’t seem to get either of them to work. Am getting a “raise BadValueError(’Property s is required’ self.name) BadValueError: Property chat is required” … Any ideas?
SOLVED - Had been using chatone all the way through on dev_appserver.py and had just been updating the app.yaml page to point to a new python file with each new exercise.
Typing “dev_appserver.py —clear_datastore chatone” in terminal fixed my problems above.