CSC/ECE 517 Fall 2014/ch1a 3 cp: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
 
(38 intermediate revisions by 2 users not shown)
Line 1: Line 1:
='''CherryPy'''=
='''CherryPy'''=
 
{| border="1" class="wikitable" style="float:{{{align|right}}}"
|colspan="2" align="center" |[[File:Cherrypy.png|center|CherryPy Logo<ref>http://www.cherrypy.org/images/cherrypy.png</ref>]]
|-
|'''Name'''||[http://www.cherrypy.org/ CherryPy]
|-
|'''Category'''||[http://en.wikipedia.org/wiki/Open-source_software Open Source Software]
|-
|'''Type'''||[http://en.wikipedia.org/wiki/Web_application_framework Web Application Framework]
|-
|'''Developer(s)'''||[https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPyTeam CherryPyTeam]
|-
|'''License'''||[https://en.wikipedia.org/wiki/BSD_licenses BSD]
|-
|'''Latest Stable Version'''||[https://cherrypy.readthedocs.org/en/3.3.0/intro/install.html#download-stable-versions 3.3.0 / April 16, 2014]
|-
|'''Written in'''||[http://en.wikipedia.org/wiki/Python_%28programming_language%29 Python]
|}
__TOC__
__TOC__


Line 7: Line 23:
It is important to note that it is not a complete stack such as [http://en.wikipedia.org/wiki/Ruby_on_Rails Ruby on Rails], [http://en.wikipedia.org/wiki/Laravel Laravel], or [http://en.wikipedia.org/wiki/Django Django]. Complete stack web frameworks offer frontend utilities and storage communications along with other abilities. These aspects that make the frameworks so powerful, however, also contribute to the framework being bulky making development of small web applications such as blogs a bit cumbersome. CherryPy instead prefers to defer decisions such as storage management and interface utilities to the developer <ref>http://docs.cherrypy.org/en/latest/intro.html</ref>
It is important to note that it is not a complete stack such as [http://en.wikipedia.org/wiki/Ruby_on_Rails Ruby on Rails], [http://en.wikipedia.org/wiki/Laravel Laravel], or [http://en.wikipedia.org/wiki/Django Django]. Complete stack web frameworks offer frontend utilities and storage communications along with other abilities. These aspects that make the frameworks so powerful, however, also contribute to the framework being bulky making development of small web applications such as blogs a bit cumbersome. CherryPy instead prefers to defer decisions such as storage management and interface utilities to the developer <ref>http://docs.cherrypy.org/en/latest/intro.html</ref>


===History===
The CherryPy project v0.1 was founded and release by Remi Delon in Jul 2002<ref>http://freecode.com/projects/cherrypy/</ref> on [http://freecode.com/ FreeCode]. Version v2.0 released in May 2005 and was moved to [https://bitbucket.org/ BitBucket] from v2.1 onwards. Remi Delon is now works full time on [http://www.webfaction.com WebFaction] (which he also founded in 2003) although he is still recognized as project leader for CherryPy. Finally in Dec 2006 v3.0 came out with much of the original code rewritten under Robert Brewer as the lead developer.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPyTeam</ref><ref>https://docs.google.com/presentation/d/1NOGM5w1yu6dnXyEyYC4r6ZDuRgii4YaqlkrrlxfbnzM/edit?pli=1#slide=id.g178c5c5e9_032</ref>
{| border="1" class="wikitable" style="{{{align|right}}}"
|+Major Changes
|-
|'''v2.0'''|| Unpythonic features removed. There is no longer a compilation step; it is pure Python source code (no more "CherryClass"). <ref>http://freecode.com/projects/cherrypy/releases</ref>
|-
|'''v2.1'''||New HTTP servers, and [http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface WSGI] support. New Profiler module. New config system added<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn21</ref>
|-
|'''v2.2'''||Custom WSGI server support<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn22</ref>
|-
|'''v3.0'''||[[#Per-Request Functions (Tools)| Tools]] support. New Logger. Multiple HTTP server support. Considerable speedup.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn30</ref>
|-
|'''v3.1'''||[[#Server Wide Functions (Plugins)| Plugins]] support. [[#Deployment| cherryd]] script.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn31</ref>
|-
|'''v3.2'''|| Python 3 support.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn32</ref>
|}


==Installation==
==Installation==
Line 24: Line 58:


===Installing===
===Installing===
CherryPy can be installed through common Python package managers with the following commands: [http://docs.cherrypy.org/en/latest/install.html]<br/>
CherryPy can be installed through common Python package managers with the following commands:<ref>http://docs.cherrypy.org/en/latest/install.html</ref><br/>


Install (choose on of the following commands appropriately):
Install (choose on of the following commands appropriately):
Line 32: Line 66:
     $ apt-get install python python-dev
     $ apt-get install python python-dev


Refer [[#Additional Installation Instructions| Additional Instructions]] for more details.
===Install via yum===
CherryPy is provided by the fedora base repository. In [http://en.wikipedia.org/wiki/Fedora_%28operating_system%29 Fedora] (and other [http://en.wikipedia.org/wiki/RPM_Package_Manager RPM] based Linux distributions, such as [http://en.wikipedia.org/wiki/CentOS CentOS] and [http://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux Red Hat Enterprise Linux]):<br/>
    $ yum install python-cherrypy
 
===Install via apt-get===
CherryPy is also provided in the [http://en.wikipedia.org/wiki/Ubuntu_(operating_system) Ubuntu] base repository. In Ubuntu (and other [http://en.wikipedia.org/wiki/Debian Debian]-based Linux distributions such as Debian and [http://en.wikipedia.org/wiki/Linux_Mint Linux Mint]):
    $ apt-get install python python-dev
 
===Installation from source===
The source code is hosted on [http://en.wikipedia.org/wiki/Bitbucket BitBucket] and requires [http://en.wikipedia.org/wiki/Mercurial Mercurial] to pull and install from the site itself.
    $ hg clone https://bitbucket.org/cherrypy/cherrypy
    $ cd cherrypy
    $ python setup.py install
 
Alternatively, the source can be manually downloaded from [https://bitbucket.org/cherrypy/cherrypy/downloads here] in a tarball.
    $ tar -xvf CherryPy-#.#.#.tar.gz
    $ cd CherryPy-#.#.#
    $ python setup.py install


===Install for Windows===
*If you are using Windows, install Linux and follow any of the a forementioned methods.
*If you absolutely must use windows, you can download the .exe file to install CherryPy from [https://bitbucket.org/cherrypy/cherrypy/downloads here].


==Interface==
==Interface==


CherryPy is meant to be pythonic, meaning that development time  is meant to be minimized and code is meant to be sparse and clean [http://docs.cherrypy.org/en/latest/intro.html]
CherryPy is meant to be pythonic, meaning that development time  is meant to be minimized and code is meant to be sparse and clean <ref>http://docs.cherrypy.org/en/latest/intro.html</ref>


===Basic Example===
===Basic Example===
Lets look at a hello world example<ref>https://cherrypy.readthedocs.org/en/3.2.6/concepts/basics.html</ref><ref>http://stackoverflow.com/questions/419163/what-does-if-name-main-do</ref>
<pre>
<pre>
#Use the cherrypy python library
#Use the cherrypy python library
import cherrypy
import cherrypy
#Hello World project
#Hello World project
class HelloWorld(object):
class HelloWorld(object):
    #index page
 
#   index page
     def index(self):
     def index(self):
        #Return the page contents
#       Return the page contents
         return “Hello World!”
         return “Hello World!”
    #Allow the page to be visible
 
#   Allow the page to be visible
     index.exposed = True
     index.exposed = True
#designates this module as main
#designates this module as main
if __name__ == ‘__main__’:
if __name__ == ‘__main__’:
    #instantiates app and starts server
 
#   instantiates app and starts server
     cherrypy.quickstart(HelloWorld())
     cherrypy.quickstart(HelloWorld())
</pre>
</pre>
 
The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a [http://en.wikipedia.org/wiki/Representational_state_transfer RESTful] request. Otherwise, the method is internal only. This is similar to making a method public in Java. <ref>http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html</ref>
[http://stackoverflow.com/questions/419163/what-does-if-name-main-do]
[https://cherrypy.readthedocs.org/en/3.2.6/concepts/basics.html]
 
 
The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a RESTful request. Otherwise, the method is internal only. This is similar to making a method public in Java. <ref>http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html</ref>


===Routing, Parameters, and Exposure===
===Routing, Parameters, and Exposure===
 
Routing is the act of finding the appropriate code to handle a request. CherryPy uses a dispatcher to perform most of these, but premade dispatchers exist to handle more sophisticated handling of request. The most common is a page handler (the name of the object). Parameters can be passed into the handler via http query strings. These strings are appended to the URL of a site after a "?". Exposure is just the way CherryPy prevents access to objects from the users. Without the exposed attribute set to true, an object won't be accessible to the user.
<pre>
<pre>
#import python library
#import python library
Line 89: Line 145:
     def route2(self):
     def route2(self):
         return “Still another one”
         return “Still another one”
if __name__ == '__main__':
if __name__ == '__main__':
     cherrypy.quickstart(MoreRoutes())
     cherrypy.quickstart(MoreRoutes())
</pre>
</pre>


The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error).
The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error).


===Multiple Applications===
===Multiple Applications===  
 


<pre>
<pre>
Line 111: Line 170:
#designates the forum to be under /forum route
#designates the forum to be under /forum route
     cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”)
     cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”)
</pre>
</pre> <ref>http://docs.cherrypy.org/en/latest/basics.html#multiple-applications</ref>
 
In the above example, the blog would be found under /blog in the URL, wheras the forum will be mounted at /forum in the application tree. The XXX.conf files are configuration files, which are dictionaries containing string keys and polymorphic values and can be used to set attributes on the engine, server, request, response, and log objects. <ref>https://cherrypy.readthedocs.org/en/3.2.6/concepts/config.html</ref>
<ref>http://docs.cherrypy.org/en/latest/basics.html#multiple-applications</ref>


===Database Support===
===Database Support===
CherryPy offers multiple database integration possibilities including
CherryPy offers multiple database integration possibilities including
*relational: PostgreSQL, SQLite, MariaDB, Firebird
*[http://en.wikipedia.org/wiki/Relational_database Relational]: [http://en.wikipedia.org/wiki/PostgreSQL PostgreSQL], [http://en.wikipedia.org/wiki/SQLite SQLite], [http://en.wikipedia.org/wiki/MariaDB MariaDB], [http://en.wikipedia.org/wiki/Firebird_%28database_server%29 Firebird]
*column-oriented: HBase, Cassandra
*[http://en.wikipedia.org/wiki/Column-oriented_DBMS Column-Oriented]: [http://en.wikipedia.org/wiki/Apache_HBase HBase], [http://en.wikipedia.org/wiki/Apache_Cassandra Cassandra]
*key-store: redis, memcached
*[http://en.wikipedia.org/wiki/NoSQL#Key.E2.80.93value_stores Key-Store]: [http://en.wikipedia.org/wiki/Redis Redis], [http://en.wikipedia.org/wiki/Memcached Memcached]
*document oriented: Couchdb, MongoDB
*[http://en.wikipedia.org/wiki/Document-oriented_database Document-Oriented]: [http://en.wikipedia.org/wiki/CouchDB Couchdb], [http://en.wikipedia.org/wiki/MongoDB MongoDB]
*graph-oriented: neo4j<br/>
*[http://en.wikipedia.org/wiki/Graph_database Graph-Oriented]: [http://en.wikipedia.org/wiki/Neo4j Neo4j]<br/>
Unfortunately, unlike [[CSC/ECE_517_Fall_2011/ch2_2f_mm|Ruby on Rails]], CherryPy does not have a sophisticated [[CSC/ECE_517_Fall_2007/wiki2_2_aa#ActiveRecord_in_Ruby|ActiveRecord]]-like class for database abstraction, and the database connection has to be established manually. The queries are constructed as static SQL strings with values concatenated during function calls.<br/>
Unfortunately, unlike [https://en.wikipedia.org/wiki/Ruby_on_Rails Ruby on Rails], CherryPy does not have a sophisticated [https://en.wikipedia.org/wiki/Active_record_pattern#Ruby Active Record Pattern] based class for database abstraction, and the database connection has to be established manually. The queries are constructed as static [https://en.wikipedia.org/wiki/SQL SQL] strings with values concatenated during function calls.<br/>


Here is an example of how it would look like
Here is an example of how it would look like<ref>http://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorial-9-data-is-all-my-life</ref>
<pre>
<pre>
# import the Handles
# import the Handles
import MySQLdb
import MySQLdb
import cherrypy
import cherrypy
# defining the connection function
# defining the connection function
def connect(thread_index):
def connect(thread_index):
    # Create a connection and store it in the current thread
#   Create a connection and store it in the current thread
     cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname')
     cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname')
# tell cherrypy to  call connect function for each thread
# tell cherrypy to  call connect function for each thread
cherrypy.engine.subscribe('start_thread', connect)
cherrypy.engine.subscribe('start_thread', connect)
# example query function
# example query function
@cherrypy.expose
def count(val)
def count(val)
c = cherrypy.thread_data.db.cursor()
#  fetching instance of db connection
c.execute( 'select count(‘ + val + ’) from table' )
    c = cherrypy.thread_data.db.cursor()
res = c.fetchone()
#  executing query
c.close()
    c.execute( 'select count(‘ + val + ’) from table' )
return res
#  fetching results from db
    res = c.fetchone()
#  releasing instance of the connection
    c.close()
#  returning the count value
    return res
 
</pre>
</pre>
<ref>http://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorial-9-data-is-all-my-life</ref>


==RESTful CherryPy==
==RESTful CherryPy==
REST (Representational State Transfer) is an abstraction of the architectural elements within a distributed hypermedia system. It ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. [http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm]<br/>
[http://en.wikipedia.org/wiki/Representational_state_transfer REST] (Representational State Transfer) is an abstraction of the architectural elements within a distributed hypermedia system. It ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. <ref>http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm</ref><br/>
In othe words, REST is defined by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the engine of application state. [https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html]
In othe words, REST is defined by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the engine of application state.<ref>https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html</ref>


===Identification of Resources===
===Identification of Resources===
[https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html]
Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment.<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#implementing-rest-in-cherrypy</ref><br/>
Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment.<br/>
*Scheme: in [http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol http], the scheme is always http or [http://en.wikipedia.org/wiki/HTTP_Secure https].
*Scheme: in HTTP, the scheme is always http or https.  
*Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism.
*Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism.  


===Manipulation of Resources Through Representations===
===Manipulation of Resources Through Representations===
[https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html]
The standard [http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html HTTP methods] are as follows<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#manipulation-of-resources-through-representations</ref>
The standard HTTP methods are as follows:
*<code>GET</code> retrieves the state of a specific resource
*<code>GET</code> retrieves the state of a specific resource
*<code>PUT</code> creates or replaces the state of a specific resource
*<code>PUT</code> creates or replaces the state of a specific resource
Line 165: Line 230:


===Self-Descriptive Messages===
===Self-Descriptive Messages===
[https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html]
REST requires messages to be self-descriptive, meaning everything about a message is within the message itself. Such information can be found in the method headers or the definitions of the message’s media type. cherrypy.request.headers and cherrypy.response.headers are used to get this information. Custom-Types are allowed as well.<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#self-descriptive-messages</ref>
REST requires messages to be self-descriptive, meaning everything about a message is within the message itself. Such information can be found in the method headers or the definitions of the message’s media type. cherrypy.request.headers and cherrypy.response.headers are used to get this information. Custom-Types are allowed as well.  


===Hypermedia as the Engine of the Application State===
===Hypermedia as the Engine of the Application State===
Since REST is stateless and the state is maintained by the application in question, sessions are not maintained by REST, so, by association, CherryPy does not enable sessions by default. However, the REST server helps clients maintain a meaningful state through meaningful URIs
Since REST is stateless and the state is maintained by the application in question, sessions are not maintained by REST, so, by association, CherryPy does not enable sessions by default. However, the REST server helps clients maintain a meaningful state through meaningful URIs<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#hypermedia-as-the-engine-of-application-state</ref>


==Crash Course==
==Crash Course==
Line 199: Line 263:
     $cherryd -c <config file> -d -p <PID file>
     $cherryd -c <config file> -d -p <PID file>


==Testing==
CherryPy provides a helper class for testing. The feature of the framework is that test are run against a running cherrypy server and testing small cmponents without actually starting the server is not natively suported.
Lets look at an example<ref>http://cherrypy.readthedocs.org/en/latest/advanced.html#testing-your-application</ref>
<pre>
#importing cherrypy library
import cherrypy
#importing the helper class
from cherrypy.test import helper
#creating a simple test class
class SimpleCPTest(helper.CPWebCase):
#  function to start the cherrypy server
    def setup_server():
#      root class of application  to be tested
        class Root(object):
#          the expose method which we are trying to test
#          this method will respond to localhost/echo and actually echo the argument sent to it
            @cherrypy.expose
            def echo(self, message):
                return message
#      settingup the root class to be created on server start
        cherrypy.tree.mount(Root())
#  grabbing the decorator for starting the server
    setup_server = staticmethod(setup_server)
#  This is the actual test code
    def test_message_should_be_returned_as_is(self):
#      sending arguments to the echo method via html request
        self.getPage("/echo?message=Hello%20world")
#      chechink if server accepted our request
        self.assertStatus('200 OK')
#      cheching response from server
        self.assertHeader('Content-Type', 'text/html;charset=utf-8')
#      checking if the was an "Hello World" in the response from server
        self.assertBody('Hello world')
</pre>


==Extensions==
==Extensions==


CherryPy provides a flexible open framework. Similar to gems in [[CSC/ECE_517_Fall_2011/ch2_2f_mm|Ruby on Rails]] which add a range of functionality to the framework CherryPy also supports plugins in the the following forms
CherryPy provides a flexible open framework. Similar to [http://en.wikipedia.org/wiki/RubyGems RubyGems] in [http://en.wikipedia.org/wiki/Ruby_on_Rails Ruby on Rails] which add a range of functionality to the framework CherryPy also supports plugins in the the following forms


===Server Wide Functions (Plugins)===
===Server Wide Functions (Plugins)===
<ref>http://docs.cherrypy.org/en/latest/extend.html#id13</ref>
This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place.<ref>http://docs.cherrypy.org/en/latest/extend.html#id13</ref><br/>
This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place.<br/>
Typical use case involve
Typical use case involve
*Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests)
*Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests)
*External Connections (For establishing and maintaining threaded connections to external database or other servers)
*External Connections (For establishing and maintaining threaded connections to external database or other servers)
*Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.)<br/>
*Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.)<br/>
These function utilize the Publish-Subscribe Framework<ref>http://en.wikipedia.org/wiki/Publish–subscribe_pattern</ref> implementation of CherryPy. Each function subscribes to one or more events on the bus which are published by the CherryPy engine.<br/> The database connection is a good example of such a function<br/>
These function utilize the [http://en.wikipedia.org/wiki/Publish–subscribe_pattern Publish-Subscribe Framework] implementation of CherryPy. Each function subscribes to one or more events on the bus which are published by the CherryPy engine.<br/> The database connection is a good example of such a function<br/>


<pre>
<pre>
Line 230: Line 342:


===Per-Request Functions (Tools)===
===Per-Request Functions (Tools)===
<ref>http://docs.cherrypy.org/en/latest/extend.html#per-request-functions</ref>
This type of extension is typically used to insert functionality between stages of request processing. Also known as [http://docs.cherrypy.org/en/latest/extend.html#tools Tools] these are simple call-back functions registered with a [http://docs.cherrypy.org/en/latest/extend.html#hookpoint Hook Point]. Hook Points are predefined stages of request processing. CherryPy provides a [http://tools.cherrypy.org/ Default ToolBox] containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one.<ref>http://docs.cherrypy.org/en/latest/extend.html#per-request-functions</ref><br/>
This type of extension is typically used to insert functionality between stages of request processing. Also known as Tools<ref>http://docs.cherrypy.org/en/latest/extend.html#tools</ref> these are simple call-back functions registered with a Hook Point<ref>http://docs.cherrypy.org/en/latest/extend.html#hookpoint</ref>. Hook Points are predefined stages of request processing. CherryPy provides a Default ToolBox<ref>http://tools.cherrypy.org/</ref> containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one.<br/>
An example for creating a tool
An example for creating a tool


Line 252: Line 363:
     return “Hello World”
     return “Hello World”
</pre>
</pre>


==Watch It In Action==
==Watch It In Action==
Line 258: Line 368:
CherryPy is used as a building block for [http://www.hulu.com/ Hulu]<ref>http://tech.hulu.com/blog/2013/03/13/python-and-hulu</ref> and [https://www.netflix.com/ Netflix]<ref>http://techblog.netflix.com/2013/03/python-at-netflix.html</ref>
CherryPy is used as a building block for [http://www.hulu.com/ Hulu]<ref>http://tech.hulu.com/blog/2013/03/13/python-and-hulu</ref> and [https://www.netflix.com/ Netflix]<ref>http://techblog.netflix.com/2013/03/python-at-netflix.html</ref>


==Additional Instructions==
==Further Reading==
 
[https://docs.google.com/presentation/d/1NOGM5w1yu6dnXyEyYC4r6ZDuRgii4YaqlkrrlxfbnzM/edit?pli=1#slide=id.p PowerPoint Presentation]
===Install via yum===
CherryPy is provided by the fedora base repository. In Fedora<ref>http://en.wikipedia.org/wiki/Fedora_%28operating_system%29</ref> (and other RPM<ref>http://en.wikipedia.org/wiki/RPM_Package_Manager</ref> based Linux distributions, such as CentOS<ref>http://en.wikipedia.org/wiki/CentOS</ref> and Red Hat Enterprise Linux<ref>http://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux</ref>):<br/>
    $ yum install python-cherrypy
 
===Install via apt-get===  
[https://cherrypy.readthedocs.org/en/3.2.6/intro/install.html]
CherryPy is also provided in the ubuntu base repository. In Ubuntu[en.wikipedia.org/wiki/Ubuntu_(operating_system)] (and other Debian[http://en.wikipedia.org/wiki/Debian]-based Linux distributions such as Debian and Mint Linux<ref>http://en.wikipedia.org/wiki/Linux_Mint</ref>):
    $ apt-get install python python-dev
 
===Installation from source===
The source code is hosted on BitBucket and requires Mercurial<ref>http://en.wikipedia.org/wiki/Mercurial</ref> to pull and install from the site itself.
    $ hg clone https://bitbucket.org/cherrypy/cherrypy
    $ cd cherrypy
    $ python setup.py install
 
Alternatively, the source can be manually downloaded from [https://bitbucket.org/cherrypy/cherrypy/downloads here] in a tarball.
    $ tar -xvf CherryPy-#.#.#.tar.gz
    $ cd CherryPy-#.#.#
    $ python setup.py install
 
===Install for Windows===
*If you are using Windows, install Linux and follow any of the a forementioned methods.
*If you absolutely must use windows, you can download the .exe file to install CherryPy from [https://bitbucket.org/cherrypy/cherrypy/downloads here].




==References==
==References==
<references/>
<references/>

Latest revision as of 01:40, 26 September 2014

CherryPy

CherryPy Logo<ref>http://www.cherrypy.org/images/cherrypy.png</ref>
CherryPy Logo<ref>http://www.cherrypy.org/images/cherrypy.png</ref>
Name CherryPy
Category Open Source Software
Type Web Application Framework
Developer(s) CherryPyTeam
License BSD
Latest Stable Version 3.3.0 / April 16, 2014
Written in Python

Overview

CherryPy is an Object-Oriented Web Application Framework meant to be Python-like (sparse and clean code).
It is important to note that it is not a complete stack such as Ruby on Rails, Laravel, or Django. Complete stack web frameworks offer frontend utilities and storage communications along with other abilities. These aspects that make the frameworks so powerful, however, also contribute to the framework being bulky making development of small web applications such as blogs a bit cumbersome. CherryPy instead prefers to defer decisions such as storage management and interface utilities to the developer <ref>http://docs.cherrypy.org/en/latest/intro.html</ref>

History

The CherryPy project v0.1 was founded and release by Remi Delon in Jul 2002<ref>http://freecode.com/projects/cherrypy/</ref> on FreeCode. Version v2.0 released in May 2005 and was moved to BitBucket from v2.1 onwards. Remi Delon is now works full time on WebFaction (which he also founded in 2003) although he is still recognized as project leader for CherryPy. Finally in Dec 2006 v3.0 came out with much of the original code rewritten under Robert Brewer as the lead developer.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPyTeam</ref><ref>https://docs.google.com/presentation/d/1NOGM5w1yu6dnXyEyYC4r6ZDuRgii4YaqlkrrlxfbnzM/edit?pli=1#slide=id.g178c5c5e9_032</ref>

Major Changes
v2.0 Unpythonic features removed. There is no longer a compilation step; it is pure Python source code (no more "CherryClass"). <ref>http://freecode.com/projects/cherrypy/releases</ref>
v2.1 New HTTP servers, and WSGI support. New Profiler module. New config system added<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn21</ref>
v2.2 Custom WSGI server support<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn22</ref>
v3.0 Tools support. New Logger. Multiple HTTP server support. Considerable speedup.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn30</ref>
v3.1 Plugins support. cherryd script.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn31</ref>
v3.2 Python 3 support.<ref>https://bitbucket.org/cherrypy/cherrypy/wiki/WhatsNewIn32</ref>

Installation

Overview

Because CherryPy is nothing more than a Python library, it needs a Python environment (Python 2.3 through to 3.4) and can also run on various implementations of Python including IronPython for .NET and Jython for Java.<ref>http://docs.cherrypy.org/en/latest/install.html</ref>

Requirements

CherryPy requires a Python version between 2.3 and 3.4 inclusively. Certain features require packages but none are mandatory for installation.<ref>http://docs.cherrypy.org/en/latest/install.html</ref>


Installing

CherryPy can be installed through common Python package managers with the following commands:<ref>http://docs.cherrypy.org/en/latest/install.html</ref>

Install (choose on of the following commands appropriately):

   $ easy_install cherrypy
   $ pip install cherrypy
   $ yum install python-cherrypy
   $ apt-get install python python-dev

Install via yum

CherryPy is provided by the fedora base repository. In Fedora (and other RPM based Linux distributions, such as CentOS and Red Hat Enterprise Linux):

   $ yum install python-cherrypy

Install via apt-get

CherryPy is also provided in the Ubuntu base repository. In Ubuntu (and other Debian-based Linux distributions such as Debian and Linux Mint):

   $ apt-get install python python-dev

Installation from source

The source code is hosted on BitBucket and requires Mercurial to pull and install from the site itself.

   $ hg clone https://bitbucket.org/cherrypy/cherrypy
   $ cd cherrypy
   $ python setup.py install

Alternatively, the source can be manually downloaded from here in a tarball.

   $ tar -xvf CherryPy-#.#.#.tar.gz
   $ cd CherryPy-#.#.#
   $ python setup.py install

Install for Windows

  • If you are using Windows, install Linux and follow any of the a forementioned methods.
  • If you absolutely must use windows, you can download the .exe file to install CherryPy from here.

Interface

CherryPy is meant to be pythonic, meaning that development time is meant to be minimized and code is meant to be sparse and clean <ref>http://docs.cherrypy.org/en/latest/intro.html</ref>

Basic Example

Lets look at a hello world example<ref>https://cherrypy.readthedocs.org/en/3.2.6/concepts/basics.html</ref><ref>http://stackoverflow.com/questions/419163/what-does-if-name-main-do</ref>

#Use the cherrypy python library
import cherrypy

#Hello World project
class HelloWorld(object):

#   index page
    def index(self):
#       Return the page contents
        return “Hello World!”

#   Allow the page to be visible
    index.exposed = True

#designates this module as main
if __name__ == ‘__main__’:

#   instantiates app and starts server
    cherrypy.quickstart(HelloWorld())

The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a RESTful request. Otherwise, the method is internal only. This is similar to making a method public in Java. <ref>http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html</ref>

Routing, Parameters, and Exposure

Routing is the act of finding the appropriate code to handle a request. CherryPy uses a dispatcher to perform most of these, but premade dispatchers exist to handle more sophisticated handling of request. The most common is a page handler (the name of the object). Parameters can be passed into the handler via http query strings. These strings are appended to the URL of a site after a "?". Exposure is just the way CherryPy prevents access to objects from the users. Without the exposed attribute set to true, an object won't be accessible to the user.

#import python library
import cherrypy

#More Routes application
class MoreRoutes(object):

#   Method decorator for index and equates to index.exposed = True
    @cherrypy.expose
    def index(self):
        return "Hello world!"

#   http://localhost:8080/route1
    def route1(self, id=”charles”):
#       http://localhost:8080/route1?id=somestring
        return “Your name is ” + id

#   Params passed as a GET request.
#   Default string is “charles”
    route1.exposed = True

#   No explicit indication of exposure so calling this route will generate a 404 error
    def route2(self):
        return “Still another one”

if __name__ == '__main__':
    cherrypy.quickstart(MoreRoutes())

The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error).

Multiple Applications

import cherrypy
#blog module
class Blog(object):
    ...<blog code>...
#forum module
class Forum(object):
    ...<forum code>...
#”main” method
if __name__ == '__main__':
#designates the blog to be under /blog route
    cherrypy.tree.mount(Blog(), ‘/blog’, “blog.conf”)
#designates the forum to be under /forum route
    cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”)

<ref>http://docs.cherrypy.org/en/latest/basics.html#multiple-applications</ref>

In the above example, the blog would be found under /blog in the URL, wheras the forum will be mounted at /forum in the application tree. The XXX.conf files are configuration files, which are dictionaries containing string keys and polymorphic values and can be used to set attributes on the engine, server, request, response, and log objects. <ref>https://cherrypy.readthedocs.org/en/3.2.6/concepts/config.html</ref>

Database Support

CherryPy offers multiple database integration possibilities including

Unfortunately, unlike Ruby on Rails, CherryPy does not have a sophisticated Active Record Pattern based class for database abstraction, and the database connection has to be established manually. The queries are constructed as static SQL strings with values concatenated during function calls.

Here is an example of how it would look like<ref>http://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorial-9-data-is-all-my-life</ref>


# import the Handles
import MySQLdb
import cherrypy

# defining the connection function
def connect(thread_index):
#   Create a connection and store it in the current thread
    cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname')

# tell cherrypy to  call connect function for each thread
cherrypy.engine.subscribe('start_thread', connect)

# example query function
@cherrypy.expose
def count(val)
#   fetching instance of db connection
    c = cherrypy.thread_data.db.cursor()
#   executing query
    c.execute( 'select count(‘ + val + ’) from table' )
#   fetching results from db
    res = c.fetchone()
#   releasing instance of the connection
    c.close()
#   returning the count value
    return res

RESTful CherryPy

REST (Representational State Transfer) is an abstraction of the architectural elements within a distributed hypermedia system. It ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. <ref>http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm</ref>
In othe words, REST is defined by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the engine of application state.<ref>https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html</ref>

Identification of Resources

Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment.<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#implementing-rest-in-cherrypy</ref>

  • Scheme: in http, the scheme is always http or https.
  • Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism.

Manipulation of Resources Through Representations

The standard HTTP methods are as follows<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#manipulation-of-resources-through-representations</ref>

  • GET retrieves the state of a specific resource
  • PUT creates or replaces the state of a specific resource
  • POST passes information to a resource to use as it sees fit
  • DELETE removes resources

Self-Descriptive Messages

REST requires messages to be self-descriptive, meaning everything about a message is within the message itself. Such information can be found in the method headers or the definitions of the message’s media type. cherrypy.request.headers and cherrypy.response.headers are used to get this information. Custom-Types are allowed as well.<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#self-descriptive-messages</ref>

Hypermedia as the Engine of the Application State

Since REST is stateless and the state is maintained by the application in question, sessions are not maintained by REST, so, by association, CherryPy does not enable sessions by default. However, the REST server helps clients maintain a meaningful state through meaningful URIs<ref>https://cherrypy.readthedocs.org/en/3.3.0/progguide/REST.html#hypermedia-as-the-engine-of-application-state</ref>

Crash Course

Development

Create an application. Application requirements:

  • The module needs to define a __main__
  • cherrypy.quickstart(<Application Name>()) for hosting a single application. For example: cherrypy.quickstart(Blog())
  • cherrypy.tree.mount(<Application Name>(), ‘/<hosting path segment>’, <configuration>) for hosting multiple applications. For example: cherrypy.tree.mount(Blog(), ‘/blog’, blog_conf)
  • All parts the users will see must be exposed with either the decorator @cherrypy.expose or attribues exposed = True or route.exposed = True.
import cherrypy
class HelloWorld(object):
    def index(self):
        return “Hello World!”
    index.exposed = True
if __name__ == ‘__main__’:
    cherrypy.quickstart(HelloWorld())

Deployment

The application can be run as a python script in the Python interpreter.

   $ python <app file>.py

It will hosted at http://127.0.0.1:8080/ It can also be run as a daemon process with

   $cherryd -c <config file> -d -p <PID file>

Testing

CherryPy provides a helper class for testing. The feature of the framework is that test are run against a running cherrypy server and testing small cmponents without actually starting the server is not natively suported.

Lets look at an example<ref>http://cherrypy.readthedocs.org/en/latest/advanced.html#testing-your-application</ref>

#importing cherrypy library
import cherrypy

#importing the helper class
from cherrypy.test import helper

#creating a simple test class
class SimpleCPTest(helper.CPWebCase):

#   function to start the cherrypy server
    def setup_server():

#       root class of application  to be tested
        class Root(object):

#           the expose method which we are trying to test
#           this method will respond to localhost/echo and actually echo the argument sent to it
            @cherrypy.expose
            def echo(self, message):
                return message

#       settingup the root class to be created on server start
        cherrypy.tree.mount(Root())

#   grabbing the decorator for starting the server
    setup_server = staticmethod(setup_server)

#   This is the actual test code
    def test_message_should_be_returned_as_is(self):

#       sending arguments to the echo method via html request
        self.getPage("/echo?message=Hello%20world")

#       chechink if server accepted our request
        self.assertStatus('200 OK')

#       cheching response from server
        self.assertHeader('Content-Type', 'text/html;charset=utf-8')

#       checking if the was an "Hello World" in the response from server
        self.assertBody('Hello world')

Extensions

CherryPy provides a flexible open framework. Similar to RubyGems in Ruby on Rails which add a range of functionality to the framework CherryPy also supports plugins in the the following forms

Server Wide Functions (Plugins)

This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place.<ref>http://docs.cherrypy.org/en/latest/extend.html#id13</ref>
Typical use case involve

  • Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests)
  • External Connections (For establishing and maintaining threaded connections to external database or other servers)
  • Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.)

These function utilize the Publish-Subscribe Framework implementation of CherryPy. Each function subscribes to one or more events on the bus which are published by the CherryPy engine.
The database connection is a good example of such a function

# import the Handles
import MySQLdb
import cherrypy
# defining the connection function
def connect(thread_index): 
    # Create a connection and store it in the current thread 
    cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname')

# tell cherrypy to  call connect function for each thread
cherrypy.engine.subscribe('start_thread', connect)

Here the function connect subscribes to the start_thread channel. An event is published on the start_thread channel whenever a server thread is started. Here engine is the central bus of the CherryPy server.
Similarly it is also possible to create new channels and even buses themselves.

Per-Request Functions (Tools)

This type of extension is typically used to insert functionality between stages of request processing. Also known as Tools these are simple call-back functions registered with a Hook Point. Hook Points are predefined stages of request processing. CherryPy provides a Default ToolBox containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one.<ref>http://docs.cherrypy.org/en/latest/extend.html#per-request-functions</ref>
An example for creating a tool

# defining the function to be called
def my_tool():
    # put tool functunality here
    print (“Super Amazing Tool”);

# creating the decorator for the tool
# specifying the hook point and function to be called
cherrypy.tools.mytool = cherrypy.Tool(‘on_end_request’, my_tool())

#Sample Usage

class Root(object):
@cherrypy.expose()
@cherrypy.tools.mytool()
def index()
    return “Hello World”

Watch It In Action

CherryPy is used as a building block for Hulu<ref>http://tech.hulu.com/blog/2013/03/13/python-and-hulu</ref> and Netflix<ref>http://techblog.netflix.com/2013/03/python-at-netflix.html</ref>

Further Reading

PowerPoint Presentation


References

<references/>