= amplee on !IronPython and .NET = [[PageOutline]] == Overview == amplee has been designed very early in a way that would allow it to be run on different Python implementation. Although the main target is CPython it has long been a goal to make amplee working on !IronPython as well, the .NET implementation of the Python language. The present document aims at explaining how to deploy amplee via !IronPython. == Requirements == This document will make some assumptions in regards to your environment. === !IronPython === Because amplee relies heavily on the [http://docs.python.org/modindex.html Python standard library] the [http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython IronPython package distributed by Microsoft] cannot be used as-is as it misses most of the standard modules. Instead you must use the [http://fepy.sourceforge.net/ IronPython Community Edition] created and maintained by Seo Sanghyeon and more specifically IPCEr5. If you use [http://www.mono-project.com/Main_Page Mono] this package is shipped from Mono 1.2.3.1 so you don't need to install it separatly. === amplee === You must use [http://trac.defuze.org/wiki/amplee amplee 0.4.2] at the very least. === bridge === You must use [http://trac.defuze.org/wiki/bridge bridge 0.2.6] at the least. Note that we will be using the .NET parser provided by bridge. === Additional packages === In order to run the examples within this documents you should also have: * The [http://zesty.ca/python/uuid.py uuid] module * The [http://www.python.org/pypi/selector selector] [http://wsgi.org/wsgi WSGI] middleware * The [http://www.python.org/pypi/resolver resolver] module Note that the last two items are only compulsory because our example uses the selector middleware to perform the dispatching of the URI to the correct WSGI application. Once you are fine with this example you could use a different middleware. === Deployment of the Python modules === The required Python modules and packages should be added to the {{{Lib}}} directory of !IronPython. Note that !IronPython does not yet support [http://peak.telecommunity.com/DevCenter/setuptools setuptools] and therefore eggs are not welcome. ---- == Mono == === Requirement === In addition to the above requirements you will need Mono 1.2.3.1 at the minimum. === The example code === You can find the code of the example [http://www.defuze.org/oss/amplee/amplee_on_mono_0.1.tgz here]. === Deployment of the example === Decompress the tarball of the example above into a directory then move into the newly created directory. You should see the following structure: {{{ appsite.py appstore.conf bin/ core/ repository/ Web.config }}} Let's review each file: * {{{appsite.py}}} is the entry point of the application as it will be called by the server to handle requests. Basically it creates a WSGI application using the {{{selector}}} middleware to dispatch per the request URI. It assigns to the URI based on the HTTP method a WSGI application that handles the request. The {{{app}}} object will be created on the first request which is handled by the WSGI handler. Therefore do not be surprised if the first request is rather slow to respond. * {{{appstore.conf}}} contains the description of the APP store following the amplee config format. In a nutshell it creates a store, one workspace with two collections. Each collection only supportes {{{application/atom+xml}}} media-type for the purpose of this example. Moreover to keep things simple we only use the filesystem storage which should work as-is anywhere. * {{{Web.config}}} contains the settings that the server will load to serve an application from this folder. * {{{repository}}} is the top level directory where resources will be stored. * {{{bin}}} contains the .NET assemblies to be loaded by mono at runtime. The tarball contains the {{{WSGI.dll}}} assembly compiled by the {{{gmcs}}} compiler from Mono 1.2.3.1. You can find the source code of that handler in the [https://fepy.svn.sourceforge.net/svnroot/fepy/trunk/src/ IPCE repository]. In addition it's likely that will need to copy the !IronPython dlls there too (!IronPython.dll and !IronMath.dll). Finally you should either copy the {{{Lib}}} directory completely into {{{bin}}} or alternatively create a symbolic link to it via the {{{ln -s}}} command. * {{{core}}} contains some additionnal code expected by amplee. === Running the example === To run the example on mono we will be using the {{{xsp2}}} command line that launches an HTTP server. To do use the following command: {{{ xsp2 --appconfigfile Web.config --verbose --port 8080 --applications localhost:8080:/:. }}} Which should return the following output: {{{ xsp2 Adding applications 'localhost:8080:/:.'... Registering application: Host: localhost Port: 8080 Virtual path: / Physical path: XXXXXXXXXX Adding applications from config file 'Web.config' Listening on port: 8080 (non-secure) Listening on address: 0.0.0.0 Root directory: XXXXXXXXXXX Hit Return to stop the server. }}} Then on the first request that the WSGI handlers manages: {{{ Creating the APP store Creating the service WSGI application Creating the music collection WSGI application Creating the photo collection WSGI application All good... }}} Next you can test the application using Python interpreter using the [http://bitworking.org/projects/httplib2/ httplib2] package. {{{ #!python Python 2.5 [GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import httplib2 >>> h = httplib2.Http() # Retrieve the service document >>> r, c = h.request('http://localhost:8080/service') # Assuming you have an Atom entry in the current directory. >>> content = file('entry.atom', 'rb').read() # Retrieve the feed music collection >>> r, c = h.request('http://localhost:8080/music/manage/') # POST the Atom entry to that collection >>> r, c = h.request('http://localhost:8080/music/manage/', method='POST', body=content, headers={'content-type': 'application/atom+xml'}) # Retrieve the created member resource # Note that the last part of the URI depends on the atom:title value of the Atom entry. In my case it was 'Test'. >>> r, c = h.request('http://localhost:8080/music/manage/Test.atom', headers={'accept': 'application/atom+xml'}) # PUT a new version of the Atom entry at that URI >>> r, c = h.request('http://localhost:8080/music/manage/Test.atom', method='PUT', body=otherentrycontent, headers={'content-type': 'application/atom+xml'}) # DELETE the resource >>> r, c = h.request('http://localhost:8080/music/manage/Test.atom', method='DELETE') }}} These are just a few examples of what can be done. ---- == Microsoft .NET and IIS == Soon :) ---- == !CherryPy 3 == An alternative to using either IIS or XSP2 as an HTTP server for amplee is [http://www.cherrypy.org/ CherryPy]. !CherryPy provides the HTTP server layer but also a engine layer with a developer friendly API to write web applications. It's entirely written in Python. In our context we are only interested in the HTTP server itself to serve our WSGI applications. The interesting aspect of this method is that the !CherryPy HTTP server resides in a single Python module while still being HTTP/1.1 conditionally compliant, well tested and efficient. Therefore it is lighter to deploy than IIS for instance. === Requirement === For this example you will need to install !CherryPy or at least its [http://www.cherrypy.org/browser/trunk/cherrypy/wsgiserver/__init__.py WSGI server module]. In any case you must have a directory {{{cherrypy/wsgiserver}}} under the {{{Lib}}} directory of !IronPython. The !CherryPy web server requires [http://fepy.sourceforge.net/ IPCE] and not the vanilla !IronPython distribution. If you run Mono 1.2.3.1 you do not need to install IPCE itself as it is bundled with the mono distribution. === The example code === You can find the code of the example [http://www.defuze.org/oss/amplee/amplee_on_IP_cherrypy_0.1.tgz here]. === Deployment of the example === Decompress the tarball of the example above into a directory then move into the newly created directory. You should see the following structure: {{{ appsite.py appstore.conf core/ repository/ }}} Let's review each file: * {{{appsite.py}}} is the entry point of the application as it will be called by the server to handle requests. Basically it creates a WSGI application using the {{{selector}}} middleware to dispatch per the request URI. It assigns to the URI based on the HTTP method a WSGI application that handles the request. It also starts the CherryPy WSGI server hosting the WSGI application. * {{{appstore.conf}}} contains the description of the APP store following the amplee config format. In a nutshell it creates a store, one workspace with two collections. Each collection only supportes {{{application/atom+xml}}} media-type for the purpose of this example. Moreover to keep things simple we only use the filesystem storage which should work as-is anywhere. * {{{repository}}} is the top level directory where resources will be stored. * {{{core}}} contains some additionnal code expected by amplee. === Running the example === You must ensure IPCE is setup correctly. Simply set the following environment variable: {{{ export FEPY_OPTIONS=network,encoding }}} Next you can issue the following command: {{{ ipy appsite.py }}} This will start the server and create the application: {{{ Creating the APP store Creating the service WSGI application Creating the music collection WSGI application Creating the photo collection WSGI application All good... Serving HTTP on http://localhost:8080 }}} You can now issue the same commands as shown in the Mono example above.