This document is deprecated. For the latest version, please see http://packages.python.org/wille/

Tutorial

Using Wille Client

Wille Client is the part of Wille2 framework that can be used to create visualisation and data processing pipelines with Wille. With Wille Client you can specifically:

  • Find and execute Wille services
  • Manage visualisation data
  • Launch visualisations (in stand-alone mode)
Wille Client can be used either in stand-alone mode (Python scripts) or as part of other Wille Services and Apps.

Using Wille Client in a Python Script

Let us consider that we want to use Wille Client in an arbitrary Python script for executing a PDF2TXT converter service.

First, import Wille Client module and create an instance:

import wille.client
client = wille.client.Client(debug=False)

Load services to the client and for verification, display a list of them:

client.load_dir('../../services')
print "Services loaded: ", client.services()

Execute a PDF2TXT converter service with an example PDF file:

data = open('data/example.pdf').read()
result = client.execute_service(type='pdf2txt', params={'filename.pdf': data})

Examine if the execution was successful and display results / error:
if result.metadata['success']: 
   print (result.data)
else:
   print ("ERROR:\n", result.data)

Working with user data

Wille client supports use of an external user data folder for persistent storage of user session and visualisation data.

By using user data folder, the previous result could be saved under userdata folder as follows:

import os
filename = os.path.join(client.userdata_dir, 'result.txt')
file = open(filename, 'w')
file.write(result.data)
file.close()
print ("Wrote %s" % filename)

By default, userdata folder is located at [HOME_DIR]/willedata. During instantiation of Wille client, you may choose to use another userdata folder instead, with userdata_dir argument.

Using keyring

Wille client carries a keyring that can be used to manage user various tokens for authenticating user to various resources and services. Two types of tokens are currently supported: username and API key tokens, but new token types may be introduces as necessary.

Tokens can be added to the keyring as follows:

  • Adding a password token:
    • client.keyring.add_credentials('email', 'password', domain='facebook.com')
  • Adding an API key token:
    • client.keyring.add_apikey('apikey', 'secret', domain='api.flickr.com')
Optional domain argument allows you to specify a domain (or domains) for which the token is valid.

Keys from keyring can be obtained as follows:

  • Return all keys from keyring:
    • client.keyring.keys()
  • Return all API keys valid for domain api.flickr.com
    • client.keyring.keys(type='APIKeyToken', domain='api.flickr.com')

Using Wille Server

Running Wille Server

Wille is bundled with a command-line server, which can be started from command-line by invoking (in Wille's root):

python wille-server.py

Wille Server can be customised by adding command-line options. In order to see a full list of available options, run:

python wille-server.py -h

  • Enable debug mode with more verbose console output, add -d
  • To change user data directory (for default, directory willedata in your home directory is used), define the -u parameter (See also: working with user data)
  • To start Wille with only specified profiles enabled, add option -f profile1,profile2 (see also: packaging with profiles)
  • Change server port with -p
  • Enable per-request Python source code reloader with -r (good for development!)

Creating a Service

  • Create new folder under services, the name of the folder defines the name of the service at wille, i.e. c:\wille2\services\myservice
  • Write willeservice.properties file
  • add files that service uses under your service folder

Willeservice.properties file

The key to adapting components as new services to Wille is willeservice.properties file. Properties file contains all necessary information to wrap a component as a service to Wille.

For instance, if we want to specify a service using HTML tidy, a command-line tool for parsing and cleaning HTML documents, we could create the following properties file:

# Lines beginning with a hash (#) are treated as comments
# These files are treated as Java .properties
# For pointers, see http://en.wikipedia.org/wiki/.properties
# Properties "parameters" and "adapter" are required
parameters=html_data
parameters.html_data.type=file
adapter=IsolatedCommandLine
adapter.command=tidy -asxhtml < @{html_data} > result.html
adapter.errors=ignore
adapter.output=result.html

Important notes:
  • List names of parameters separated by commas (,)
  • Values from (short) string parameters are extracted in adapter.command in format ${name}.
  • If parameter contains a file (or binary data), it can be saved to a file and a filename can be passed instead by invoking @{name} instead
For a more detailed specification of willeservice.properties, see README.txt

Creating an App

Wille Apps are special web applications that run on Wille Server, and can access services via a Wille Client. In this section, we will briefly go through what is needed in order to create a new Wille App. In this tutorial, we will walk through creating requestsniffer application, available in Wille bundle.

Start by creating a folder for the app, under apps (in our example: apps/requestsniffer).

Next, create a new Python file for the app, following the name of the folder (apps/requestsniffer/requestsniffer.py). The following lines are minimally needed to create a functioning app:

class IndexPage:
    def GET(self, request):
        # (Insert your code here) return "OK"

urls = ( ("/", IndexPage), )

  • In lines 1-3 we create a class for handling requests to our App's indexpage
  • In line 5, we assign this class to the root URL of our application
In order to try out the application, we also need to create a willeapp.properties file that provides metadata about the application (minimally an empty file is sufficient):

description=With Request Sniffer you can inspect what data gets passed to Wille Apps
profile=

Once we start Wille server, the application should now become available at http://localhost://apps/requestsniffer/. At this point, responses from the application only include simple "OK" text.

Let us next build the actual application itself. The idea in our sample application, request sniffer, is that we find out and display what data gets passed to Wille Apps. To achieve this, we replace the GET method returning simple OK message, with several lines of code as follows:

  • Input parameters (both GET and POST) can be accessed via request.input('varname'). In order to return all parameter, we call params = request.input()
  • An instance of Wille Client can be retrieved by invoking wille = request.wille_client()
  • Wille services available via the client can be accessed via wille.services()
  • Tokens in keyring can be accessed via wille.keyring.keys()

When we put extraction of these properties together and create a simple HTML document as an output, the body GET function becomes as follows:

params = request.input()
wille = request.wille_client()
data = '<h1>App Request Sniffer</h1>'
      
# Data
data += '<h2>Input parameters:</h2>'
data += '<ul>'
for key in params:
   data += "<li>%s=%s</li>" % (key, params[key])
if len(params) == 0:
   data += '<li>No input parameters. Try adding some!</li>'
data += '</ul>'
      
data += '<h2>Services</h2>'
data += '<ul>'
if wille.services():
   for service in wille.services():
      data += "<li>%s</li>" % service.name
data += '</ul>'

data += '<h2>Keyring</h2>'
data += '<ul>'
if wille.keyring:
   print wille.keyring.keys()
   for key in wille.keyring.keys():
      data += ("<li><code>%s</code></li>" % cgi.escape(str(key)))
   else:
      data += "<li><i>(empty)</i></li>"
   data += '</ul>'
      
return data

Once you add this code as the GET method in your Wille App, after a server restart a snapshot of request data should be displayed in your browser.

In case one wishes to develop an application further, note the following:
  • Once application grows, multiple URLs maybe added to urls variable. Regular expressions (re) can be used to match multiple URLs. In order to capture these expressions as request variables, provide them with parenthesis ().
  • If you wish to process input data sent via POST, make sure you encode them as multipart/form-data. In HTML form this requires you to add enctype header to form element (<form ... enctype="multipart/form-data" .../>).
Note that optionally, you may also explictly specify response metadata. For example, if we wish to specify Content-type as XML UTF-8 encoding, we can return as follows:

return (data, {'Content-type': 'application/xml; charset=utf-8'})

Willeapp.properties file

Contains profile and description for application.

To interact with the user trough wille api the application requires definition of GET and POST functions and urls variable.

import os
import wille

class MyClass:
    def GET(self, context):
        str += '<form enctype="multipart/form-data" method="post">' #Creates a simple input field for a file
        str += '<input type="file" name="content"/> '
        str += '<input type="submit" value="Upload"/> '
        str += '</form>'
        return str

    def POST(self, context):
        xhtml = context.wille_client().execute_service(name='tidy', params={'hmtl_data': context.input('content')}) #Calls tidy service
        str1 = '<body>' #with given parameters
        str1 += xhtml.data
        str1 += '</body>'

        return (str1, {'Content-type': 'text/plain'} )

urls = ( ( "/", MyClass), )

When you are developing new Wille Apps, it is generally good idea to enable reloader (-r option). When enabled, Wille Server will automatically detect and reload changed Python source code files, requiring fewer server restarts during application development. Reloader works best when combined with debug mode:

wille-server -dr

Publishing and Packaging Components

Packaging with Profiles

Profiles are keywords that can be used to organise Wille Apps and Services into arbitrary groups. With profiles, you can manage different configurations of Wille. Profiles can be used for instance to group together different components into a single toolkit or package. Wille Server maybe then used to selective start components based on profiles.

For instance, if we wish to add our component to profile examples, we add the following line to willeapp.properties or to willeservice.properties:

profile=examples

Several profiles maybe specified by separating them with a comma. For example if we want assign a component to xml profile as well, we may type:

profile=examples,xml
Print version |  PDF  | History: r61 < r60 < r59 < r58 | 
Topic revision: r61 - 12 Mar 2013 - 14:43:23 - JaakkoSalonen
 

TUTWiki

Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TUTWiki? Send feedback