Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/cherrypy/tutorial
diff options
context:
space:
mode:
Diffstat (limited to 'cherrypy/tutorial')
-rw-r--r--cherrypy/tutorial/README.txt16
-rwxr-xr-xcherrypy/tutorial/__init__.py3
-rwxr-xr-xcherrypy/tutorial/bonus-sqlobject.py168
-rw-r--r--cherrypy/tutorial/custom_error.html14
-rw-r--r--cherrypy/tutorial/pdf_file.pdfbin85698 -> 0 bytes
-rwxr-xr-xcherrypy/tutorial/tut01_helloworld.py35
-rwxr-xr-xcherrypy/tutorial/tut02_expose_methods.py32
-rwxr-xr-xcherrypy/tutorial/tut03_get_and_post.py53
-rwxr-xr-xcherrypy/tutorial/tut04_complex_site.py98
-rwxr-xr-xcherrypy/tutorial/tut05_derived_objects.py83
-rwxr-xr-xcherrypy/tutorial/tut06_default_method.py64
-rwxr-xr-xcherrypy/tutorial/tut07_sessions.py44
-rwxr-xr-xcherrypy/tutorial/tut08_generators_and_yield.py47
-rwxr-xr-xcherrypy/tutorial/tut09_files.py107
-rwxr-xr-xcherrypy/tutorial/tut10_http_errors.py81
-rw-r--r--cherrypy/tutorial/tutorial.conf4
16 files changed, 0 insertions, 849 deletions
diff --git a/cherrypy/tutorial/README.txt b/cherrypy/tutorial/README.txt
deleted file mode 100644
index 2b877e1..0000000
--- a/cherrypy/tutorial/README.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-CherryPy Tutorials
-------------------------------------------------------------------------
-
-This is a series of tutorials explaining how to develop dynamic web
-applications using CherryPy. A couple of notes:
-
- - Each of these tutorials builds on the ones before it. If you're
- new to CherryPy, we recommend you start with 01_helloworld.py and
- work your way upwards. :)
-
- - In most of these tutorials, you will notice that all output is done
- by returning normal Python strings, often using simple Python
- variable substitution. In most real-world applications, you will
- probably want to use a separate template package (like Cheetah,
- CherryTemplate or XML/XSL).
-
diff --git a/cherrypy/tutorial/__init__.py b/cherrypy/tutorial/__init__.py
deleted file mode 100755
index c4e2c55..0000000
--- a/cherrypy/tutorial/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-
-# This is used in test_config to test unrepr of "from A import B"
-thing2 = object() \ No newline at end of file
diff --git a/cherrypy/tutorial/bonus-sqlobject.py b/cherrypy/tutorial/bonus-sqlobject.py
deleted file mode 100755
index c43feb4..0000000
--- a/cherrypy/tutorial/bonus-sqlobject.py
+++ /dev/null
@@ -1,168 +0,0 @@
-'''
-Bonus Tutorial: Using SQLObject
-
-This is a silly little contacts manager application intended to
-demonstrate how to use SQLObject from within a CherryPy2 project. It
-also shows how to use inline Cheetah templates.
-
-SQLObject is an Object/Relational Mapper that allows you to access
-data stored in an RDBMS in a pythonic fashion. You create data objects
-as Python classes and let SQLObject take care of all the nasty details.
-
-This code depends on the latest development version (0.6+) of SQLObject.
-You can get it from the SQLObject Subversion server. You can find all
-necessary information at <http://www.sqlobject.org>. This code will NOT
-work with the 0.5.x version advertised on their website!
-
-This code also depends on a recent version of Cheetah. You can find
-Cheetah at <http://www.cheetahtemplate.org>.
-
-After starting this application for the first time, you will need to
-access the /reset URI in order to create the database table and some
-sample data. Accessing /reset again will drop and re-create the table,
-so you may want to be careful. :-)
-
-This application isn't supposed to be fool-proof, it's not even supposed
-to be very GOOD. Play around with it some, browse the source code, smile.
-
-:)
-
--- Hendrik Mans <hendrik@mans.de>
-'''
-
-import cherrypy
-from Cheetah.Template import Template
-from sqlobject import *
-
-# configure your database connection here
-__connection__ = 'mysql://root:@localhost/test'
-
-# this is our (only) data class.
-class Contact(SQLObject):
- lastName = StringCol(length = 50, notNone = True)
- firstName = StringCol(length = 50, notNone = True)
- phone = StringCol(length = 30, notNone = True, default = '')
- email = StringCol(length = 30, notNone = True, default = '')
- url = StringCol(length = 100, notNone = True, default = '')
-
-
-class ContactManager:
- def index(self):
- # Let's display a list of all stored contacts.
- contacts = Contact.select()
-
- template = Template('''
- <h2>All Contacts</h2>
-
- #for $contact in $contacts
- <a href="mailto:$contact.email">$contact.lastName, $contact.firstName</a>
- [<a href="./edit?id=$contact.id">Edit</a>]
- [<a href="./delete?id=$contact.id">Delete</a>]
- <br/>
- #end for
-
- <p>[<a href="./edit">Add new contact</a>]</p>
- ''', [locals(), globals()])
-
- return template.respond()
-
- index.exposed = True
-
-
- def edit(self, id = 0):
- # we really want id as an integer. Since GET/POST parameters
- # are always passed as strings, let's convert it.
- id = int(id)
-
- if id > 0:
- # if an id is specified, we're editing an existing contact.
- contact = Contact.get(id)
- title = "Edit Contact"
- else:
- # if no id is specified, we're entering a new contact.
- contact = None
- title = "New Contact"
-
-
- # In the following template code, please note that we use
- # Cheetah's $getVar() construct for the form values. We have
- # to do this because contact may be set to None (see above).
- template = Template('''
- <h2>$title</h2>
-
- <form action="./store" method="POST">
- <input type="hidden" name="id" value="$id" />
- Last Name: <input name="lastName" value="$getVar('contact.lastName', '')" /><br/>
- First Name: <input name="firstName" value="$getVar('contact.firstName', '')" /><br/>
- Phone: <input name="phone" value="$getVar('contact.phone', '')" /><br/>
- Email: <input name="email" value="$getVar('contact.email', '')" /><br/>
- URL: <input name="url" value="$getVar('contact.url', '')" /><br/>
- <input type="submit" value="Store" />
- </form>
- ''', [locals(), globals()])
-
- return template.respond()
-
- edit.exposed = True
-
-
- def delete(self, id):
- # Delete the specified contact
- contact = Contact.get(int(id))
- contact.destroySelf()
- return 'Deleted. <a href="./">Return to Index</a>'
-
- delete.exposed = True
-
-
- def store(self, lastName, firstName, phone, email, url, id = None):
- if id and int(id) > 0:
- # If an id was specified, update an existing contact.
- contact = Contact.get(int(id))
-
- # We could set one field after another, but that would
- # cause multiple UPDATE clauses. So we'll just do it all
- # in a single pass through the set() method.
- contact.set(
- lastName = lastName,
- firstName = firstName,
- phone = phone,
- email = email,
- url = url)
- else:
- # Otherwise, add a new contact.
- contact = Contact(
- lastName = lastName,
- firstName = firstName,
- phone = phone,
- email = email,
- url = url)
-
- return 'Stored. <a href="./">Return to Index</a>'
-
- store.exposed = True
-
-
- def reset(self):
- # Drop existing table
- Contact.dropTable(True)
-
- # Create new table
- Contact.createTable()
-
- # Create some sample data
- Contact(
- firstName = 'Hendrik',
- lastName = 'Mans',
- email = 'hendrik@mans.de',
- phone = '++49 89 12345678',
- url = 'http://www.mornography.de')
-
- return "reset completed!"
-
- reset.exposed = True
-
-
-print("If you're running this application for the first time, please go to http://localhost:8080/reset once in order to create the database!")
-
-cherrypy.quickstart(ContactManager())
diff --git a/cherrypy/tutorial/custom_error.html b/cherrypy/tutorial/custom_error.html
deleted file mode 100644
index d0f30c8..0000000
--- a/cherrypy/tutorial/custom_error.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html>
-<head>
- <title>403 Unauthorized</title>
-</head>
- <body>
- <h2>You can't do that!</h2>
- <p>%(message)s</p>
- <p>This is a custom error page that is read from a file.<p>
- <pre>%(traceback)s</pre>
- </body>
-</html>
diff --git a/cherrypy/tutorial/pdf_file.pdf b/cherrypy/tutorial/pdf_file.pdf
deleted file mode 100644
index 38b4f15..0000000
--- a/cherrypy/tutorial/pdf_file.pdf
+++ /dev/null
Binary files differ
diff --git a/cherrypy/tutorial/tut01_helloworld.py b/cherrypy/tutorial/tut01_helloworld.py
deleted file mode 100755
index ef94760..0000000
--- a/cherrypy/tutorial/tut01_helloworld.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""
-Tutorial - Hello World
-
-The most basic (working) CherryPy application possible.
-"""
-
-# Import CherryPy global namespace
-import cherrypy
-
-class HelloWorld:
- """ Sample request handler class. """
-
- def index(self):
- # CherryPy will call this method for the root URI ("/") and send
- # its return value to the client. Because this is tutorial
- # lesson number 01, we'll just send something really simple.
- # How about...
- return "Hello world!"
-
- # Expose the index method through the web. CherryPy will never
- # publish methods that don't have the exposed attribute set to True.
- index.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(HelloWorld(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(HelloWorld(), config=tutconf)
diff --git a/cherrypy/tutorial/tut02_expose_methods.py b/cherrypy/tutorial/tut02_expose_methods.py
deleted file mode 100755
index 600fca3..0000000
--- a/cherrypy/tutorial/tut02_expose_methods.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""
-Tutorial - Multiple methods
-
-This tutorial shows you how to link to other methods of your request
-handler.
-"""
-
-import cherrypy
-
-class HelloWorld:
-
- def index(self):
- # Let's link to another method here.
- return 'We have an <a href="showMessage">important message</a> for you!'
- index.exposed = True
-
- def showMessage(self):
- # Here's the important message!
- return "Hello world!"
- showMessage.exposed = True
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(HelloWorld(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(HelloWorld(), config=tutconf)
diff --git a/cherrypy/tutorial/tut03_get_and_post.py b/cherrypy/tutorial/tut03_get_and_post.py
deleted file mode 100755
index 283477d..0000000
--- a/cherrypy/tutorial/tut03_get_and_post.py
+++ /dev/null
@@ -1,53 +0,0 @@
-"""
-Tutorial - Passing variables
-
-This tutorial shows you how to pass GET/POST variables to methods.
-"""
-
-import cherrypy
-
-
-class WelcomePage:
-
- def index(self):
- # Ask for the user's name.
- return '''
- <form action="greetUser" method="GET">
- What is your name?
- <input type="text" name="name" />
- <input type="submit" />
- </form>'''
- index.exposed = True
-
- def greetUser(self, name = None):
- # CherryPy passes all GET and POST variables as method parameters.
- # It doesn't make a difference where the variables come from, how
- # large their contents are, and so on.
- #
- # You can define default parameter values as usual. In this
- # example, the "name" parameter defaults to None so we can check
- # if a name was actually specified.
-
- if name:
- # Greet the user!
- return "Hey %s, what's up?" % name
- else:
- if name is None:
- # No name was specified
- return 'Please enter your name <a href="./">here</a>.'
- else:
- return 'No, really, enter your name <a href="./">here</a>.'
- greetUser.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(WelcomePage(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(WelcomePage(), config=tutconf)
diff --git a/cherrypy/tutorial/tut04_complex_site.py b/cherrypy/tutorial/tut04_complex_site.py
deleted file mode 100755
index b4d820e..0000000
--- a/cherrypy/tutorial/tut04_complex_site.py
+++ /dev/null
@@ -1,98 +0,0 @@
-"""
-Tutorial - Multiple objects
-
-This tutorial shows you how to create a site structure through multiple
-possibly nested request handler objects.
-"""
-
-import cherrypy
-
-
-class HomePage:
- def index(self):
- return '''
- <p>Hi, this is the home page! Check out the other
- fun stuff on this site:</p>
-
- <ul>
- <li><a href="/joke/">A silly joke</a></li>
- <li><a href="/links/">Useful links</a></li>
- </ul>'''
- index.exposed = True
-
-
-class JokePage:
- def index(self):
- return '''
- <p>"In Python, how do you create a string of random
- characters?" -- "Read a Perl file!"</p>
- <p>[<a href="../">Return</a>]</p>'''
- index.exposed = True
-
-
-class LinksPage:
- def __init__(self):
- # Request handler objects can create their own nested request
- # handler objects. Simply create them inside their __init__
- # methods!
- self.extra = ExtraLinksPage()
-
- def index(self):
- # Note the way we link to the extra links page (and back).
- # As you can see, this object doesn't really care about its
- # absolute position in the site tree, since we use relative
- # links exclusively.
- return '''
- <p>Here are some useful links:</p>
-
- <ul>
- <li><a href="http://www.cherrypy.org">The CherryPy Homepage</a></li>
- <li><a href="http://www.python.org">The Python Homepage</a></li>
- </ul>
-
- <p>You can check out some extra useful
- links <a href="./extra/">here</a>.</p>
-
- <p>[<a href="../">Return</a>]</p>
- '''
- index.exposed = True
-
-
-class ExtraLinksPage:
- def index(self):
- # Note the relative link back to the Links page!
- return '''
- <p>Here are some extra useful links:</p>
-
- <ul>
- <li><a href="http://del.icio.us">del.icio.us</a></li>
- <li><a href="http://www.mornography.de">Hendrik's weblog</a></li>
- </ul>
-
- <p>[<a href="../">Return to links page</a>]</p>'''
- index.exposed = True
-
-
-# Of course we can also mount request handler objects right here!
-root = HomePage()
-root.joke = JokePage()
-root.links = LinksPage()
-
-# Remember, we don't need to mount ExtraLinksPage here, because
-# LinksPage does that itself on initialization. In fact, there is
-# no reason why you shouldn't let your root object take care of
-# creating all contained request handler objects.
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(root, config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(root, config=tutconf)
-
diff --git a/cherrypy/tutorial/tut05_derived_objects.py b/cherrypy/tutorial/tut05_derived_objects.py
deleted file mode 100755
index 3d4ec9b..0000000
--- a/cherrypy/tutorial/tut05_derived_objects.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""
-Tutorial - Object inheritance
-
-You are free to derive your request handler classes from any base
-class you wish. In most real-world applications, you will probably
-want to create a central base class used for all your pages, which takes
-care of things like printing a common page header and footer.
-"""
-
-import cherrypy
-
-
-class Page:
- # Store the page title in a class attribute
- title = 'Untitled Page'
-
- def header(self):
- return '''
- <html>
- <head>
- <title>%s</title>
- <head>
- <body>
- <h2>%s</h2>
- ''' % (self.title, self.title)
-
- def footer(self):
- return '''
- </body>
- </html>
- '''
-
- # Note that header and footer don't get their exposed attributes
- # set to True. This isn't necessary since the user isn't supposed
- # to call header or footer directly; instead, we'll call them from
- # within the actually exposed handler methods defined in this
- # class' subclasses.
-
-
-class HomePage(Page):
- # Different title for this page
- title = 'Tutorial 5'
-
- def __init__(self):
- # create a subpage
- self.another = AnotherPage()
-
- def index(self):
- # Note that we call the header and footer methods inherited
- # from the Page class!
- return self.header() + '''
- <p>
- Isn't this exciting? There's
- <a href="./another/">another page</a>, too!
- </p>
- ''' + self.footer()
- index.exposed = True
-
-
-class AnotherPage(Page):
- title = 'Another Page'
-
- def index(self):
- return self.header() + '''
- <p>
- And this is the amazing second page!
- </p>
- ''' + self.footer()
- index.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(HomePage(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(HomePage(), config=tutconf)
-
diff --git a/cherrypy/tutorial/tut06_default_method.py b/cherrypy/tutorial/tut06_default_method.py
deleted file mode 100755
index fe24f38..0000000
--- a/cherrypy/tutorial/tut06_default_method.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""
-Tutorial - The default method
-
-Request handler objects can implement a method called "default" that
-is called when no other suitable method/object could be found.
-Essentially, if CherryPy2 can't find a matching request handler object
-for the given request URI, it will use the default method of the object
-located deepest on the URI path.
-
-Using this mechanism you can easily simulate virtual URI structures
-by parsing the extra URI string, which you can access through
-cherrypy.request.virtualPath.
-
-The application in this tutorial simulates an URI structure looking
-like /users/<username>. Since the <username> bit will not be found (as
-there are no matching methods), it is handled by the default method.
-"""
-
-import cherrypy
-
-
-class UsersPage:
-
- def index(self):
- # Since this is just a stupid little example, we'll simply
- # display a list of links to random, made-up users. In a real
- # application, this could be generated from a database result set.
- return '''
- <a href="./remi">Remi Delon</a><br/>
- <a href="./hendrik">Hendrik Mans</a><br/>
- <a href="./lorenzo">Lorenzo Lamas</a><br/>
- '''
- index.exposed = True
-
- def default(self, user):
- # Here we react depending on the virtualPath -- the part of the
- # path that could not be mapped to an object method. In a real
- # application, we would probably do some database lookups here
- # instead of the silly if/elif/else construct.
- if user == 'remi':
- out = "Remi Delon, CherryPy lead developer"
- elif user == 'hendrik':
- out = "Hendrik Mans, CherryPy co-developer & crazy German"
- elif user == 'lorenzo':
- out = "Lorenzo Lamas, famous actor and singer!"
- else:
- out = "Unknown user. :-("
-
- return '%s (<a href="./">back</a>)' % out
- default.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(UsersPage(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(UsersPage(), config=tutconf)
-
diff --git a/cherrypy/tutorial/tut07_sessions.py b/cherrypy/tutorial/tut07_sessions.py
deleted file mode 100755
index 4b1386b..0000000
--- a/cherrypy/tutorial/tut07_sessions.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-Tutorial - Sessions
-
-Storing session data in CherryPy applications is very easy: cherrypy
-provides a dictionary called "session" that represents the session
-data for the current user. If you use RAM based sessions, you can store
-any kind of object into that dictionary; otherwise, you are limited to
-objects that can be pickled.
-"""
-
-import cherrypy
-
-
-class HitCounter:
-
- _cp_config = {'tools.sessions.on': True}
-
- def index(self):
- # Increase the silly hit counter
- count = cherrypy.session.get('count', 0) + 1
-
- # Store the new value in the session dictionary
- cherrypy.session['count'] = count
-
- # And display a silly hit count message!
- return '''
- During your current session, you've viewed this
- page %s times! Your life is a patio of fun!
- ''' % count
- index.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(HitCounter(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(HitCounter(), config=tutconf)
-
diff --git a/cherrypy/tutorial/tut08_generators_and_yield.py b/cherrypy/tutorial/tut08_generators_and_yield.py
deleted file mode 100755
index a6fbdc2..0000000
--- a/cherrypy/tutorial/tut08_generators_and_yield.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""
-Bonus Tutorial: Using generators to return result bodies
-
-Instead of returning a complete result string, you can use the yield
-statement to return one result part after another. This may be convenient
-in situations where using a template package like CherryPy or Cheetah
-would be overkill, and messy string concatenation too uncool. ;-)
-"""
-
-import cherrypy
-
-
-class GeneratorDemo:
-
- def header(self):
- return "<html><body><h2>Generators rule!</h2>"
-
- def footer(self):
- return "</body></html>"
-
- def index(self):
- # Let's make up a list of users for presentation purposes
- users = ['Remi', 'Carlos', 'Hendrik', 'Lorenzo Lamas']
-
- # Every yield line adds one part to the total result body.
- yield self.header()
- yield "<h3>List of users:</h3>"
-
- for user in users:
- yield "%s<br/>" % user
-
- yield self.footer()
- index.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(GeneratorDemo(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(GeneratorDemo(), config=tutconf)
-
diff --git a/cherrypy/tutorial/tut09_files.py b/cherrypy/tutorial/tut09_files.py
deleted file mode 100755
index 4c8e581..0000000
--- a/cherrypy/tutorial/tut09_files.py
+++ /dev/null
@@ -1,107 +0,0 @@
-"""
-
-Tutorial: File upload and download
-
-Uploads
--------
-
-When a client uploads a file to a CherryPy application, it's placed
-on disk immediately. CherryPy will pass it to your exposed method
-as an argument (see "myFile" below); that arg will have a "file"
-attribute, which is a handle to the temporary uploaded file.
-If you wish to permanently save the file, you need to read()
-from myFile.file and write() somewhere else.
-
-Note the use of 'enctype="multipart/form-data"' and 'input type="file"'
-in the HTML which the client uses to upload the file.
-
-
-Downloads
----------
-
-If you wish to send a file to the client, you have two options:
-First, you can simply return a file-like object from your page handler.
-CherryPy will read the file and serve it as the content (HTTP body)
-of the response. However, that doesn't tell the client that
-the response is a file to be saved, rather than displayed.
-Use cherrypy.lib.static.serve_file for that; it takes four
-arguments:
-
-serve_file(path, content_type=None, disposition=None, name=None)
-
-Set "name" to the filename that you expect clients to use when they save
-your file. Note that the "name" argument is ignored if you don't also
-provide a "disposition" (usually "attachement"). You can manually set
-"content_type", but be aware that if you also use the encoding tool, it
-may choke if the file extension is not recognized as belonging to a known
-Content-Type. Setting the content_type to "application/x-download" works
-in most cases, and should prompt the user with an Open/Save dialog in
-popular browsers.
-
-"""
-
-import os
-localDir = os.path.dirname(__file__)
-absDir = os.path.join(os.getcwd(), localDir)
-
-import cherrypy
-from cherrypy.lib import static
-
-
-class FileDemo(object):
-
- def index(self):
- return """
- <html><body>
- <h2>Upload a file</h2>
- <form action="upload" method="post" enctype="multipart/form-data">
- filename: <input type="file" name="myFile" /><br />
- <input type="submit" />
- </form>
- <h2>Download a file</h2>
- <a href='download'>This one</a>
- </body></html>
- """
- index.exposed = True
-
- def upload(self, myFile):
- out = """<html>
- <body>
- myFile length: %s<br />
- myFile filename: %s<br />
- myFile mime-type: %s
- </body>
- </html>"""
-
- # Although this just counts the file length, it demonstrates
- # how to read large files in chunks instead of all at once.
- # CherryPy reads the uploaded file into a temporary file;
- # myFile.file.read reads from that.
- size = 0
- while True:
- data = myFile.file.read(8192)
- if not data:
- break
- size += len(data)
-
- return out % (size, myFile.filename, myFile.content_type)
- upload.exposed = True
-
- def download(self):
- path = os.path.join(absDir, "pdf_file.pdf")
- return static.serve_file(path, "application/x-download",
- "attachment", os.path.basename(path))
- download.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(FileDemo(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(FileDemo(), config=tutconf)
diff --git a/cherrypy/tutorial/tut10_http_errors.py b/cherrypy/tutorial/tut10_http_errors.py
deleted file mode 100755
index dfa5733..0000000
--- a/cherrypy/tutorial/tut10_http_errors.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""
-
-Tutorial: HTTP errors
-
-HTTPError is used to return an error response to the client.
-CherryPy has lots of options regarding how such errors are
-logged, displayed, and formatted.
-
-"""
-
-import os
-localDir = os.path.dirname(__file__)
-curpath = os.path.normpath(os.path.join(os.getcwd(), localDir))
-
-import cherrypy
-
-
-class HTTPErrorDemo(object):
-
- # Set a custom response for 403 errors.
- _cp_config = {'error_page.403' : os.path.join(curpath, "custom_error.html")}
-
- def index(self):
- # display some links that will result in errors
- tracebacks = cherrypy.request.show_tracebacks
- if tracebacks:
- trace = 'off'
- else:
- trace = 'on'
-
- return """
- <html><body>
- <p>Toggle tracebacks <a href="toggleTracebacks">%s</a></p>
- <p><a href="/doesNotExist">Click me; I'm a broken link!</a></p>
- <p><a href="/error?code=403">Use a custom error page from a file.</a></p>
- <p>These errors are explicitly raised by the application:</p>
- <ul>
- <li><a href="/error?code=400">400</a></li>
- <li><a href="/error?code=401">401</a></li>
- <li><a href="/error?code=402">402</a></li>
- <li><a href="/error?code=500">500</a></li>
- </ul>
- <p><a href="/messageArg">You can also set the response body
- when you raise an error.</a></p>
- </body></html>
- """ % trace
- index.exposed = True
-
- def toggleTracebacks(self):
- # simple function to toggle tracebacks on and off
- tracebacks = cherrypy.request.show_tracebacks
- cherrypy.config.update({'request.show_tracebacks': not tracebacks})
-
- # redirect back to the index
- raise cherrypy.HTTPRedirect('/')
- toggleTracebacks.exposed = True
-
- def error(self, code):
- # raise an error based on the get query
- raise cherrypy.HTTPError(status = code)
- error.exposed = True
-
- def messageArg(self):
- message = ("If you construct an HTTPError with a 'message' "
- "argument, it wil be placed on the error page "
- "(underneath the status line by default).")
- raise cherrypy.HTTPError(500, message=message)
- messageArg.exposed = True
-
-
-import os.path
-tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
-
-if __name__ == '__main__':
- # CherryPy always starts with app.root when trying to map request URIs
- # to objects, so we need to mount a request handler root. A request
- # to '/' will be mapped to HelloWorld().index().
- cherrypy.quickstart(HTTPErrorDemo(), config=tutconf)
-else:
- # This branch is for the test suite; you can ignore it.
- cherrypy.tree.mount(HTTPErrorDemo(), config=tutconf)
diff --git a/cherrypy/tutorial/tutorial.conf b/cherrypy/tutorial/tutorial.conf
deleted file mode 100644
index 6537fd3..0000000
--- a/cherrypy/tutorial/tutorial.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-[global]
-server.socket_host = "127.0.0.1"
-server.socket_port = 8080
-server.thread_pool = 10