| <?xml version="1.0"?> |
| <!-- |
| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * 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. |
| */ |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Python Howto</title> |
| </properties> |
| |
| <body> |
| <section name="Turbine Python Support"> |
| <p> |
| Turbine has support for creating assemblers (see the <a href="fsd.html"> |
| specifications</a>) with Python, by making use of |
| <a href="http://www.jpython.org">JPython technology</a>. |
| </p> |
| <p> |
| The first question that comes to mind is why one would want do to something |
| like this. Here are some of the reasons you might want to do this: |
| </p> |
| <ul> |
| <li> |
| Python is an interpreted language which means that you do not have |
| to recompile and copy a new jar each time you make changes. |
| </li> |
| |
| <li> |
| Although Python is interpreted it is compiled to java bytecode. |
| Performance is on par with native java code. |
| </li> |
| |
| <li> |
| Python is very easy to learn. This, together with the fact that |
| you don't need to use a compiler, makes it possible for people with |
| little java experience to create screens. |
| </li> |
| |
| <li> |
| You can rapidly build a prototype using python, and later on find |
| that it is not necessary to systematically move to java :-) |
| </li> |
| </ul> |
| </section> |
| |
| <section name="Setting Up Python for Turbine"> |
| <p> |
| The first thing is to download JPython from www.jpython.org and copy |
| the jpython.jar file into your turibe/lib directory. Now you need to |
| prepare and compile the jpython files like this: |
| <source> |
| build prepare-python |
| build jar |
| </source> |
| This will create a new turbine library that contains the Python code. |
| You need to copy this new .jar file to your application's lib |
| directory. |
| </p> |
| <p> |
| Now we need to edit the TurbineResources.properties. Add the following |
| keys to your application's properties: |
| </p> |
| <source><![CDATA[ |
| services.AssemblerBrokerService.assembler.screen= |
| org.apache.turbine.util.assemblerbroker.python.PythonScreenFactory |
| services.AssemblerBrokerService.assembler.action= |
| org.apache.turbine.util.assemblerbroker.python.PythonActionFactory |
| |
| services.AssemblerBrokerService.python.path=/path/to/python |
| ]]></source> |
| <p> |
| The first two registers the Python Assembler Factories with the |
| AssemblerBrokerService. The last line tells the Python interpreter |
| where to find all the .py files for your application. |
| </p> |
| <p> |
| In the root of your services.AssemblerBrokerService.python.path |
| you need to add a file named config.py that looks like this: |
| </p> |
| |
| <source><![CDATA[ |
| import java |
| |
| from java.io import * |
| from java.util import * |
| |
| sys.add_package("org.apache.turbine.modules.screens") |
| sys.add_package("org.apache.turbine.modules") |
| sys.add_package("org.apache.turbine.util.db") |
| sys.add_package("org.apache.turbine.util") |
| sys.add_package("org.apache.turbine.services.security.TurbineSecurity") |
| sys.add_package("org.webmacro.servlet") |
| |
| |
| from org.apache.turbine.modules.screens import WebMacroSiteScreen |
| from org.apache.turbine.modules import Action |
| from org.apache.turbine.util.db import Criteria |
| from org.apache.turbine.util import RunData |
| from org.webmacro.servlet import WebContext |
| from org.apache.turbine.services.security import TurbineSecurity |
| ]]></source> |
| |
| <p> |
| JPython sometimes gets a bit confused with the Servlet Engine |
| classloader, which forces us to call sys.add_package for each java |
| package that we wish to use in our Python code. You also need to |
| import all the classes that you wish to use explicitly. You needn't |
| add the classes here, but it avoid some duplicate declarations at the |
| top of each screen/action. |
| </p> |
| </section> |
| |
| <section name="Using Python with Turbine"> |
| <p> |
| To create python screens we use exactly the same methodology than for |
| normal java screens. First you need a /screens subdirectory in your |
| services.AssemblerBrokerService.python.path. This is where your |
| screen code will live. Layouts goes in /layouts, actions in /actions |
| and so forth (just remember to register the appropriate assembler |
| factories). |
| </p> |
| <p> |
| I'm going to create a sample WebMacro screen. First we need a .py file |
| where this screen can live. The .py file should have the same name as |
| your .wm file and it must be all lower case. Inside this file we |
| create a new class with the same name as the file, but in this the |
| first letter is uppercase (the rest is always lower case). To override |
| a method is fairly simple (just create a new method with the same |
| name). |
| </p> |
| <p> |
| There is one problem however - Python does not support method |
| overloading based on type signatures, so usually the simplest for is |
| used, which is doBuildTemplate( RunData data ) for WebMacroSiteScreen |
| in stead of doBuildTemplate( RunData data, WebContext context ). You |
| have two options to overcome this problem. (1) Create a new superclass |
| that exposes a method under a different name or (2) just call |
| getContext in your python code. I usually just go for the second |
| option because it is fairly straight forward anyway. |
| </p> |
| <p> |
| Now for the code. Let's create a screen called Test. First create a |
| test.wm file (I assumer everybody knows how to do this). Now create a |
| test.py and place it in the python-path/screens directory. It should |
| look something like this: |
| </p> |
| |
| <source><![CDATA[ |
| class Subjectslist(WebMacroSiteScreen): |
| def doBuildTemplate (self,data): |
| context = self.getContext(data) |
| context.put ("me","Leon") |
| context.put ("text","Python is cool"); |
| ]]></source> |
| |
| <p> |
| For more information about the self parameter see the Python docs. You |
| can call any java code that you would normally be able to use (just |
| remember to add it to conf.py) including database, services, etc. You |
| can also freely use any of the Python built-in types and any Python |
| module that was built on 100% pure Python. |
| </p> |
| </section> |
| |
| </body> |
| </document> |