Permalink
Browse files

Move Tornado project to Github

  • Loading branch information...
1 parent 07e5e8c commit 2afa97349330d1a224a7e4fdce0dcdf760222a8b @finiteloop finiteloop committed Sep 10, 2009
Showing with 15,274 additions and 8 deletions.
  1. +2 −0 MANIFEST.in
  2. +2 −8 README
  3. +48 −0 demos/appengine/README
  4. +11 −0 demos/appengine/app.yaml
  5. +169 −0 demos/appengine/blog.py
  6. +1,877 −0 demos/appengine/markdown.py
  7. +153 −0 demos/appengine/static/blog.css
  8. +31 −0 demos/appengine/templates/archive.html
  9. +29 −0 demos/appengine/templates/base.html
  10. +42 −0 demos/appengine/templates/compose.html
  11. +5 −0 demos/appengine/templates/entry.html
  12. +26 −0 demos/appengine/templates/feed.xml
  13. +8 −0 demos/appengine/templates/home.html
  14. +8 −0 demos/appengine/templates/modules/entry.html
  15. +81 −0 demos/auth/authdemo.py
  16. +57 −0 demos/blog/README
  17. +195 −0 demos/blog/blog.py
  18. +1,877 −0 demos/blog/markdown.py
  19. +44 −0 demos/blog/schema.sql
  20. +153 −0 demos/blog/static/blog.css
  21. +31 −0 demos/blog/templates/archive.html
  22. +27 −0 demos/blog/templates/base.html
  23. +42 −0 demos/blog/templates/compose.html
  24. +5 −0 demos/blog/templates/entry.html
  25. +26 −0 demos/blog/templates/feed.xml
  26. +8 −0 demos/blog/templates/home.html
  27. +8 −0 demos/blog/templates/modules/entry.html
  28. +156 −0 demos/chat/chatdemo.py
  29. +51 −0 demos/chat/static/chat.css
  30. +135 −0 demos/chat/static/chat.js
  31. +37 −0 demos/chat/templates/index.html
  32. +1 −0 demos/chat/templates/message.html
  33. +8 −0 demos/facebook/README
  34. +127 −0 demos/facebook/facebook.py
  35. +97 −0 demos/facebook/static/facebook.css
  36. 0 demos/facebook/static/facebook.js
  37. +29 −0 demos/facebook/templates/modules/post.html
  38. +22 −0 demos/facebook/templates/stream.html
  39. +22 −0 demos/facebook/uimodules.py
  40. +44 −0 demos/helloworld/helloworld.py
  41. +38 −0 setup.py
  42. +17 −0 tornado/__init__.py
  43. +878 −0 tornado/auth.py
  44. +155 −0 tornado/database.py
  45. +112 −0 tornado/epoll.c
  46. +112 −0 tornado/escape.py
  47. +437 −0 tornado/httpclient.py
  48. +330 −0 tornado/httpserver.py
  49. +339 −0 tornado/ioloop.py
  50. +228 −0 tornado/iostream.py
  51. +395 −0 tornado/locale.py
  52. +350 −0 tornado/options.py
  53. +255 −0 tornado/s3server.py
  54. +561 −0 tornado/template.py
  55. +1,185 −0 tornado/web.py
  56. +190 −0 tornado/wsgi.py
  57. +19 −0 website/app.yaml
  58. 0 website/index.yaml
  59. +603 −0 website/markdown/__init__.py
  60. +95 −0 website/markdown/blockparser.py
  61. +460 −0 website/markdown/blockprocessors.py
  62. +96 −0 website/markdown/commandline.py
  63. +33 −0 website/markdown/etree_loader.py
  64. 0 website/markdown/extensions/__init__.py
  65. +140 −0 website/markdown/extensions/toc.py
  66. +274 −0 website/markdown/html4.py
  67. +371 −0 website/markdown/inlinepatterns.py
  68. +162 −0 website/markdown/odict.py
  69. +77 −0 website/markdown/postprocessors.py
  70. +214 −0 website/markdown/preprocessors.py
  71. +329 −0 website/markdown/treeprocessors.py
  72. +120 −0 website/static/base.css
  73. +2 −0 website/static/robots.txt
  74. BIN website/static/tornado-0.1.tar.gz
  75. BIN website/static/tornado.png
  76. +27 −0 website/templates/base.html
  77. +9 −0 website/templates/documentation.html
  78. +856 −0 website/templates/documentation.txt
  79. +48 −0 website/templates/index.html
  80. +63 −0 website/website.py
View
@@ -0,0 +1,2 @@
+recursive-include demos *.py *.yaml *.html *.css *.png *.js *.xml *.sql README
+include tornado/epoll.c
View
10 README
@@ -1,17 +1,12 @@
Tornado
=======
Tornado is an open source version of the scalable, non-blocking web server
-and and tools that power FriendFeed. The FriendFeed application is written
-using a web framework that looks a bit like web.py or Google's webapp, but
-with additional tools and optimizations to take advantage of the underlying
-non-blocking infrastructure.
-
-Documentation and downloads are available at http://www.tornadoweb.org/
+and and tools that power FriendFeed. Documentation and downloads are
+available at http://www.tornadoweb.org/
Tornado is licensed under the Apache Licence, Version 2.0
(http://www.apache.org/licenses/LICENSE-2.0.html).
-
Installation
============
To install:
@@ -30,4 +25,3 @@ On Mac OS X, you can install the packages with:
On Ubuntu Linux, you can install the packages with:
sudo apt-get install python-pycurl python-simplejson
-
View
@@ -0,0 +1,48 @@
+Running the Tornado AppEngine example
+=====================================
+This example is designed to run in Google AppEngine, so there are a couple
+of steps to get it running. You can download the Google AppEngine Python
+development environment at http://code.google.com/appengine/downloads.html.
+
+1. Link or copy the tornado code directory into this directory:
+
+ ln -s ../../tornado tornado
+
+ AppEngine doesn't use the Python modules installed on this machine.
+ You need to have the 'tornado' module copied or linked for AppEngine
+ to find it.
+
+3. Install and run dev_appserver
+
+ If you don't already have the App Engine SDK, download it from
+ http://code.google.com/appengine/downloads.html
+
+ To start the tornado demo, run the dev server on this directory:
+
+ dev_appserver.py .
+
+4. Visit http://localhost:8080/ in your browser
+
+ If you sign in as an administrator, you will be able to create and
+ edit blog posts. If you sign in as anybody else, you will only see
+ the existing blog posts.
+
+
+If you want to deploy the blog in production:
+
+1. Register a new appengine application and put its id in app.yaml
+
+ First register a new application at http://appengine.google.com/.
+ Then edit app.yaml in this directory and change the "application"
+ setting from "tornado-appenginge" to your new application id.
+
+2. Deploy to App Engine
+
+ If you registered an application id, you can now upload your new
+ Tornado blog by running this command:
+
+ appcfg update .
+
+ After that, visit application_id.appspot.com, where application_id
+ is the application you registered.
+
View
@@ -0,0 +1,11 @@
+application: tornado-appengine
+version: 1
+runtime: python
+api_version: 1
+
+handlers:
+- url: /static/
+ static_dir: static
+
+- url: /.*
+ script: blog.py
View
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 Facebook
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import functools
+import markdown
+import os.path
+import re
+import tornado.web
+import tornado.wsgi
+import unicodedata
+import wsgiref.handlers
+
+from google.appengine.api import users
+from google.appengine.ext import db
+
+
+class Entry(db.Model):
+ """A single blog entry."""
+ author = db.UserProperty()
+ title = db.StringProperty(required=True)
+ slug = db.StringProperty(required=True)
+ markdown = db.TextProperty(required=True)
+ html = db.TextProperty(required=True)
+ published = db.DateTimeProperty(auto_now_add=True)
+ updated = db.DateTimeProperty(auto_now=True)
+
+
+def administrator(method):
+ """Decorate with this method to restrict to site admins."""
+ @functools.wraps(method)
+ def wrapper(self, *args, **kwargs):
+ if not self.current_user:
+ if self.request.method == "GET":
+ self.redirect(self.get_login_url())
+ return
+ raise web.HTTPError(403)
+ elif not self.current_user.administrator:
+ if self.request.method == "GET":
+ self.redirect("/")
+ return
+ raise web.HTTPError(403)
+ else:
+ return method(self, *args, **kwargs)
+ return wrapper
+
+
+class BaseHandler(tornado.web.RequestHandler):
+ """Implements Google Accounts authentication methods."""
+ def get_current_user(self):
+ user = users.get_current_user()
+ if user: user.administrator = users.is_current_user_admin()
+ return user
+
+ def get_login_url(self):
+ return users.create_login_url(self.request.uri)
+
+ def render_string(self, template_name, **kwargs):
+ # Let the templates access the users module to generate login URLs
+ return tornado.web.RequestHandler.render_string(
+ self, template_name, users=users, **kwargs)
+
+
+class HomeHandler(BaseHandler):
+ def get(self):
+ entries = db.Query(Entry).order('-published').fetch(limit=5)
+ if not entries:
+ if not self.current_user or self.current_user.administrator:
+ self.redirect("/compose")
+ return
+ self.render("home.html", entries=entries)
+
+
+class EntryHandler(BaseHandler):
+ def get(self, slug):
+ entry = db.Query(Entry).filter("slug =", slug).get()
+ if not entry: raise tornado.web.HTTPError(404)
+ self.render("entry.html", entry=entry)
+
+
+class ArchiveHandler(BaseHandler):
+ def get(self):
+ entries = db.Query(Entry).order('-published')
+ self.render("archive.html", entries=entries)
+
+
+class FeedHandler(BaseHandler):
+ def get(self):
+ entries = db.Query(Entry).order('-published').fetch(limit=10)
+ self.set_header("Content-Type", "application/atom+xml")
+ self.render("feed.xml", entries=entries)
+
+
+class ComposeHandler(BaseHandler):
+ @administrator
+ def get(self):
+ key = self.get_argument("key", None)
+ entry = Entry.get(key) if key else None
+ self.render("compose.html", entry=entry)
+
+ @administrator
+ def post(self):
+ key = self.get_argument("key", None)
+ if key:
+ entry = Entry.get(key)
+ entry.title = self.get_argument("title")
+ entry.markdown = self.get_argument("markdown")
+ entry.html = markdown.markdown(self.get_argument("markdown"))
+ else:
+ title = self.get_argument("title")
+ slug = unicodedata.normalize("NFKD", title).encode(
+ "ascii", "ignore")
+ slug = re.sub(r"[^\w]+", " ", slug)
+ slug = "-".join(slug.lower().strip().split())
+ if not slug: slug = "entry"
+ while True:
+ existing = db.Query(Entry).filter("slug =", slug).get()
+ if not existing or str(existing.key()) == key:
+ break
+ slug += "-2"
+ entry = Entry(
+ author=self.current_user,
+ title=title,
+ slug=slug,
+ markdown=self.get_argument("markdown"),
+ html=markdown.markdown(self.get_argument("markdown")),
+ )
+ entry.put()
+ self.redirect("/entry/" + entry.slug)
+
+
+class EntryModule(tornado.web.UIModule):
+ def render(self, entry):
+ return self.render_string("modules/entry.html", entry=entry)
+
+
+settings = {
+ "blog_title": u"Tornado Blog",
+ "template_path": os.path.join(os.path.dirname(__file__), "templates"),
+ "ui_modules": {"Entry": EntryModule},
+ "xsrf_cookies": True,
+}
+application = tornado.wsgi.WSGIApplication([
+ (r"/", HomeHandler),
+ (r"/archive", ArchiveHandler),
+ (r"/feed", FeedHandler),
+ (r"/entry/([^/]+)", EntryHandler),
+ (r"/compose", ComposeHandler),
+], **settings)
+
+
+def main():
+ wsgiref.handlers.CGIHandler().run(application)
+
+
+if __name__ == "__main__":
+ main()
Oops, something went wrong.

0 comments on commit 2afa973

Please sign in to comment.