### Spyce configuration file example Source: http://spyce.sourceforge.net/docs/doc-single.html Example Spyce configuration file (spyceconf.py) that sets SPYCE_HOME, builds the module search path, defines global tag libraries, and sets the default parent template. Use this as a starting point for custom configuration, but avoid importing it directly from application code. ```python # NOTE: do note write code that directly imports this module # (except when you are writing a custom configuration module.) # This is a recipe for trouble, since spyce allows the user # to specify the configuration module filename on the commandline. # Instead, use import spyce; spyce.getServer().config. import os, sys import spycePreload # Determine SPYCE_HOME dynamically. # (you can hardcode SPYCE_HOME if you really want to, but it shouldn't be necessary.) SPYCE_HOME = spycePreload.guessSpyceHome() # The spyce path determines which directories are searched for when # loading modules (with [[.import]]) and tag libraries (with [[.taglib]] # and the globaltags configuration later in this file. # # By default, the Spyce installation directory is always searched # first. Any directories in the SPYCE_PATH environment are also # searched. # # If you need to import from .py modules in nonstandard locations # (i.e., not in your python installation's library directory), # you will want to add their directories to sys.path as well, as # done here for the error module. (However, Spyce automagically # changes sys.path dynamically so you will always be able to import # modules in the same directory as your currently-processing .spy file.) # # path += ['/usr/spyce/inc/myapplication', '/var/myapp/lib'] path = [os.path.join(SPYCE_HOME, 'modules'), os.path.join(SPYCE_HOME, 'contrib', 'modules')] path.append(os.path.join(SPYCE_HOME, 'tags')) path.append(os.path.join(SPYCE_HOME, 'contrib', 'tags')) if os.environ.has_key('SPYCE_PATH'): path += os.environ['SPYCE_PATH'].split(os.pathsep) # provide originalsyspath so if someone wants to maintain a config file via # "from spyceconf import *" # he can remove the above modifications if desired. originalsyspath = list(sys.path) sys.path.extend(path) # The globaltags option specifies a group of tag libraries that will be autoloaded # as if [[.taglib name=libname from=file as=prefix]] were specified in every .spy # file. (There is no performance hit if the library is not used on a page; # the Spyce compiler optimizes it out.) # # The format is ('libname', 'file', 'prefix'). # For a 2.0-style tag library, the libname attribute is ignored. Passing None is fine. # # globaltags.append(('mytag', 'mytaglib.py', 'my')) # globaltags.append((None, 'taglib2.py', 'my2')) globaltags = [ ('core', 'core.py', 'spy'), ('form', 'form.py', 'f'), (None, 'render.spi', 'render'), ] # The default parent template is the one that is used by # if no src attribute is given, specified as an absolute url. defaultparent = "/parent.spi" ``` -------------------------------- ### Custom filters and transform.create example (examples/transform.spy) Source: http://spyce.sourceforge.net/docs/doc-single.html Full example from examples/transform.spy demonstrating the flexibility of the transform module. It defines custom filters (tag, bold, bolditalic, simpletable), creates a compound filter with transform.create, and shows both installing filters via transform.expr and calling them directly. Not typical usage, but highlights creative possibilities. ```spyce [[.import name=transform]] [[\ def tag(o, tags=[], **kwargs): import string pre = string.join(map(lambda x: '<'+x+'>',tags)) tags.reverse() post = string.join(map(lambda x: '',tags)) return pre+str(o)+post def bold(o, _tag=tag, **kwargs): kwargs['tags'] = ['b'] return apply(_tag, (o,), kwargs) def bolditalic(o, _tag=tag, **kwargs): kwargs['tags'] = ['b','i'] return apply(_tag, (o,), kwargs) myfilter = transform.create(['html_encode', bolditalic]) mystring = 'bold and italic unsafe string: < > &' def simpletable(o, **kwargs): s = '' for row in o: s=s+'' for cell in row: s=s+'' s=s+'' s = s+'
'+str(cell)+'
' return s ]] install an expression filter:
[[transform.expr(['html_encode', tag])]] 1.[[=mystring, tags=['b','i'] ]]
[[transform.expr(myfilter)]] 2.[[=mystring]] [[transform.expr()]]

or use a filter directly:
1.[[=transform.create(['html_encode',tag])(mystring,tags=['b','i'])]]
2.[[=myfilter(mystring)]]

Formatting data in a table...
[[=simpletable([ [1,2,3], [4,5,6] ])]]

Though the transform module is flexible,
most users will probably only install the
html_encode filter. ``` -------------------------------- ### Form tag intro example Source: http://spyce.sourceforge.net/docs/doc-single.html Simple form example using Spyce form tags. Demonstrates text inputs, a checkboxlist, and a submit button. Shows that Spyce automatically remembers user input unless a value parameter is given, and that arbitrary parameters are passed through to HTML. ```spyce

One or two? Or both?
``` -------------------------------- ### stdout module usage example (examples/stdout.spy) Source: http://spyce.sourceforge.net/docs/doc-single.html Example from examples/stdout.spy showing how to use the stdout module: print directly to the response, capture output with stdout.push(), and retrieve it with stdout.pop(). The captured string is later displayed with [[=cached]]. ```spyce ** [[ print '''Using the stdout module redirects stdout to the response object, so you can use print!''']]
redirecting stdout can be used to... [[stdout.push()]] [[print 'capture']] out[[='put']] [[cached = stdout.pop()]] ... for later:
[[=cached]] ** ``` -------------------------------- ### Start Spyce web server with spyceCmd.py -l Source: http://spyce.sourceforge.net/docs/doc-single.html Starts the Spyce web server on port 8000 by default. The port can be changed in the spyceconf module. ```bash spyceCmd.py -l ``` -------------------------------- ### Create symlink to Spyce executable Source: http://spyce.sourceforge.net/docs/doc-single.html Creates a symlink to the Spyce command-line executable for CGI/FastCGI installation. Adjust the path if Spyce is installed elsewhere. ```bash ln -sf /usr/share/spyce/run_spyceCmd.py /usr/bin/spyce ``` -------------------------------- ### Hello world Spyce template with version output Source: http://spyce.sourceforge.net/docs/doc-single.html Example Spyce source file from examples/hello.spy. Uses the tag to set the page title, imports the spyce module, and prints the Spyce version using an expression chunk. ```spyce ** [[ import spyce ]] Hello from Spyce version [[= spyce.__version__ ]]! ** ``` -------------------------------- ### Redirect example using redirect.internal, redirect.external, and redirect.externalRefresh Source: http://spyce.sourceforge.net/docs/doc-single.html Example from examples/redirect.spy showing possible redirects: internal, external, and externalRefresh (with 3-second delay). It reads request['type'] and request['url'] from POST data, displays an error if url is missing, and calls the corresponding redirect method. The form posts back to the current path via request.uri('path'). ```spy **[[.import name=redirect]] [[ type = request['type'] url = request['url'] if url and not type: { ]] please select a redirect type
[[ } if type and url: { if type=='internal': redirect.internal(url) if type=='external': redirect.external(url) if type=='externalRefresh': redirect.externalRefresh(url, 3) ]] Received POST info: [[=request.post1()]] [[ } ]]
Redirection url:
Redirection type:
internal
external
externalRefresh (3 seconds)
** ``` -------------------------------- ### spy:parent tag example Source: http://spyce.sourceforge.net/docs/doc-single.html Wraps the current page in the parent template found at parent.spi in the same directory. Uses the core tag library installed under the spy prefix. ```spyce ``` -------------------------------- ### Include module example with header template Source: http://spyce.sourceforge.net/docs/doc-single.html Demonstrates the include module. The first block includes a common header template (inc/head.spi) and passes a context dictionary with pagename and page values. The second block, from head.spi, uses the include.context field to set the title. ```spyce [[.import name=include]] [[include.spyce('inc/head.spi', {'pagename': 'Documentation', 'page': 'manual.html'}) ]] ``` ```spyce [[.import name=include]] [[=include.context['pagename'] ]] ``` -------------------------------- ### Generate GIF image with Spyce (examples/gif.spy) Source: http://spyce.sourceforge.net/docs/doc-single.html Spyce example that generates a GIF image by setting the content type to 'image/gif', reading the Spyce logo file from the server's SPYCE_HOME directory, and writing it to the response. Raises spyceDone to stop processing after writing the binary content. ```spyce **[[.import name=include ]] [[\ # Spyce can also generate other content types # The following code displays the Spyce logo response.setContentType('image/gif') import os.path, spyce path = os.path.join(spyce.getServer().config.SPYCE_HOME, 'www', 'spyce.gif') response.write(include.dump(path, 1)) raise spyceDone ]] ** ``` -------------------------------- ### Error handling with setFileHandler Source: http://spyce.sourceforge.net/docs/doc-single.html Example of using the error module to set a file handler for error handling. The page raises an error, and the handler is invoked. The second block appears to be a duplicate of the first in the source. ```spyce **[[error.setFileHandler('error.spi') ]] This is a page with an error... [[ raise 'an error' ]] ** ``` ```spyce ** [[error.setFileHandler('error.spi') ]] This is a page with an error... [[ raise 'an error' ]] ** ``` -------------------------------- ### Invoke Spyce code programmatically with spyceStringHandler Source: http://spyce.sourceforge.net/docs/doc-single.html Programmatic usage example from examples/programmaticUsage.py. Defines fake request and response classes, then invokes spyce.spyceStringHandler with a signature and arguments to pass parameters into the Spyce code. The output is printed to resp.err and resp.out. ```python import os import spyce #--------------------------------------------------[ a hardcoded fake request ] class TestRequest(spyce.spyceRequest): environment = {'QUERY_STRING': '', 'REQUEST_METHOD': 'get'} headers = {} def env(self, name=None): if not name: return self.environment return self.environment[name] def getHeader(self, type=None): return self.headers[type] def getServerID(self): os.getpid() #--------------------------------------------------[ a hardcoded fake response ] class TestResponse(spyce.spyceResponse): returncode = spyce.spyceResponse.RETURN_OK out = '' err = '' headers = {} def write(self, s): self.out = self.out+s def writeErr(self, s): self.err = self.err+s def close(self): pass def clear(self): self.out = '' def sendHeaders(self): pass def clearHeaders(self): self.headers = {} def setContentType(self, content_type): self.headers['content-type'] = content_type def setReturnCode(self, code): self.returncode = code def addHeader(self, type, data, replace=0): self.headers[type] = data def flush(self, *args): pass def unbuffer(self): pass #--------------------------------------------------[ invoking Spyce code ] import spyceConfig req = TestRequest() resp = TestResponse() spyceCode = 'Hello, the following names are defined: "[[print dir(),]]", and ' spyceCode += 'these were the parameters passed: [[print (a, b, c, d)]]\n', spyce.spyceStringHandler( req, resp, spyceCode, sig='a, b, c="asd", d=None', args=(1, 'two'), kwargs={'c': 'aa'}, config=spyceConfig) print resp.err print resp.out ``` -------------------------------- ### Compress module example with HTTP request Source: http://spyce.sourceforge.net/docs/doc-single.html Shows the compress module in use. The first block is a Spyce file that imports the compress module with gzip and spaces compression enabled. The second block is an HTTP request that includes the Accept-Encoding: gzip header, which is required for the compression to take effect. ```spyce **[[.import name=compress args="gzip=1, spaces=1"]] [[\ response.write('') response.write(' Space compression will remove these spaces.
') response.write(' gzip compression will highly compress this:
') for i in range(1000): response.write(' hello') response.write('') ]] ** ``` ```http GET /spyce/examples/compress.spy HTTP/1.1 Accept-Encoding: gzip ``` -------------------------------- ### File upload handling with request.file and response.setContentType Source: http://spyce.sourceforge.net/docs/doc-single.html Spyce file upload example (examples/fileupload.spy). Checks for a posted content-type, sets the response content type, and writes the uploaded file's value back to the client; raises spyceDone after handling the upload. ```spyce **[[\ if request.post('ct'): response.setContentType(request.post1('ct')) if request.file('upfile')!=None: response.write(request.file('upfile').value) else: print 'file not properly uploaded' raise spyceDone ]] Upload a file and it will be sent back to you.
[[-- input forms --]]
file:
content-type:
** ``` -------------------------------- ### Access spyceConfig.SPYCE_HOME in Spyce Source: http://spyce.sourceforge.net/docs/doc-single.html Example Spyce script that imports the spyceConfig module to access the SPYCE_HOME configuration value and outputs it. Use this to retrieve configuration settings from within a Spyce page. ```spyce [[\ import spyceConfig home = spyceConfig.SPYCE_HOME ]] [[= home ]] ``` -------------------------------- ### Read and insert data with Spyce db module (examples/db.spy) Source: http://spyce.sourceforge.net/docs/doc-single.html Example from examples/db.spy showing how to read and insert rows in a table named todo_lists using the implicit Spyce db module. It defines a handler that checks for an existing name, inserts a new row, and flushes; then it selects all lists ordered by name and renders a form to create a new list. ```spyce [[! def list_new(self, api, name): if api.db.todo_lists.selectfirst_by(name=name): raise HandlerError('New list', 'a list with that description already exists') api.db.todo_lists.insert(name=name) api.db.flush() ]] (This is an self-contained example using the same database as the to-do demo.)

To-do lists

[[ lists = db.todo_lists.select(order_by=db.todo_lists.c.name) ]]

New list

: ``` -------------------------------- ### Initialize Spyce request filters Source: http://spyce.sourceforge.net/docs/doc-single.html Initializes the Spyce request filter lists. Each callable in param_filters is called twice per request (once for GET, once for POST), while each callable in file_filters is called once. Each callable receives the request object and the dictionary being filtered. ```python param_filters = [] file_filters = [] ``` -------------------------------- ### Schedule daily task with Spyce scheduler Source: http://spyce.sourceforge.net/docs/doc-single.html Example from examples/scheduling.py that schedules a daily task to delete unsubmitted alerts older than one week. Uses scheduler.schedule_daily with hour and minute arguments (00, 10) and accesses a database pool from spyce.SPYCE_GLOBALS. ```python import spyce, scheduler def delete_unsubmitted(): db = spyce.SPYCE_GLOBALS['dbpool'].connection() sql = "DELETE FROM alerts WHERE status = 'unsubmitted' AND created < now() - '1 week'::interval" db.execute(sql) # delete alerts that were created over a week ago but but still not submitted scheduler.schedule_daily(00, 10, delete_unsubmitted) ``` -------------------------------- ### Login required and logout tags example Source: http://spyce.sourceforge.net/docs/doc-single.html Shows how to use the login_required and logout tags. If a valid login cookie is not present, login_required generates a login form and halts execution. The logout tag clears the cookie generated by login and login_required. ```spyce You are logged in. ``` -------------------------------- ### spy:for and spy:print tag example Source: http://spyce.sourceforge.net/docs/doc-single.html Prints the value of foo five times. The expression =range(5) is evaluated by Spyce before being sent to the tag; do not use [[= ]] for tag attributes because it sends output directly and prevents tag recognition. ```spyce ``` -------------------------------- ### Active handler example with calculate function Source: http://spyce.sourceforge.net/docs/doc-single.html Shows how to attach a Python function as an active handler to a form submission. The handler signature pulls parameters from the form; here x and y are typed as float and converted automatically. The result is stored on self and displayed after submission. ```spyce **[[! def calculate(self, api, x, y): self.result = x * y ]]

Result: [[= hasattr(self, 'result') and self.result or '(no result yet)' ]]

** ``` -------------------------------- ### Memoized Spyce lambda table template (examples/spylambda.spy) Source: http://spyce.sourceforge.net/docs/doc-single.html Example from examples/spylambda.spy showing a memoized Spyce lambda ([[spy! ... : ...]]) that builds an HTML table from title and data lists, then emits a web page. The lambda is defined with the spy! syntax to enable memoization, and the page calls table(title, data) inside the HTML body. ```spyce **[[\ # table template table = **[[spy! title, data: [[for cell in title: {]] [[}]] [[for row in data: {]] [[for cell in row: {]] [[}]] [[}]]
[[=cell]]
[[=cell]]
]]** # table information title = ['Country', 'Size', 'Population', 'GDP per capita'] data = [ [ 'USA', '9,158,960', '280,562,489', '$36,300' ], [ 'Canada', '9,220,970', '31,902,268', '$27,700' ], [ 'Mexico', '1,923,040', '103,400,165', '$9,000' ], ] ]] [[-- emit web page --]] [[ table(title, data) ]] ** ``` -------------------------------- ### Request object methods table with GET/POST forms Source: http://spyce.sourceforge.net/docs/doc-single.html Spyce page that displays a form for GET and POST requests and a table of request method return values. Uses request.uri('path') for form actions and evaluates each request method with eval('request.%s' % method). ```spyce ** Using the Spyce request object, we can obtain information sent along with the request. The table below shows some request methods and their return values. Use the form below to post form data via GET or POST.

[[-- input forms --]]
get:
post:

[[-- tabulate response information --]] [[ for method in ['uri()', 'uri("path")', 'uri("query")', 'method()','query()', 'get()','get1()', 'post()','post1()', 'getHeader()','env()', 'filename()']: { ]] [[ } ]]
Method Return value
request.[[=method]] [[=eval('request.%s' % method)]]
** ``` -------------------------------- ### Create a Spyce project with spyceProject.py Source: http://spyce.sourceforge.net/docs/doc-single.html Creates a new Spyce project directory structure. The command generates the shown tree, including config.py, lib, login_tokens, and www directories. After creation, run spyceCmd.py -l --conf /var/firstproject/config.py and browse to http://localhost:8000/index.spy to verify. ```bash python spyceProject.py /var/firstproject ``` ```text $ tree /var/firstproject/ /var/firstproject/ |-- config.py |-- lib |-- login_tokens `-- www |-- _util | |-- form_calendar.gif | `-- form_calendar.js |-- index.spy |-- parent.spi `-- style.css ``` -------------------------------- ### Request param filter example (examples/filter.py) Source: http://spyce.sourceforge.net/docs/doc-single.html Example filter function for the request module's param_filters hook. It cleans or escapes user-supplied values to prevent HTML injection, using the __htmlfields marker to decide which fields to clean. ```python def htmlFilter(request, d): # note that spoofing __htmlfields doesn't help attacker get unsafe html in; # we always call either clean() or escape(). try: # don't use request['__htmlfields'], or you will recurse infinitely toClean = request._post['__htmlfields'][0].split(',') except KeyError: toClean = [] for key in d: if key in toClean: d[key] = [Html.clean(s) for s in d[key]] else: d[key] = [Html.escape(s) for s in d[key]] ``` -------------------------------- ### request.method() Source: http://spyce.sourceforge.net/docs/doc-single.html Returns the HTTP method (e.g., GET, POST) of the current request. ```APIDOC ## request.method() ### Description Returns the HTTP method (e.g., GET, POST) of the current request. ### Method -- ### Endpoint -- ### Parameters No parameters. ### Request Example -- ### Response #### Success Response Returns a string representing the HTTP method used for the current request. #### Response Example -- ``` -------------------------------- ### request.get() Source: http://spyce.sourceforge.net/docs/doc-single.html Returns a dictionary or similar structure containing all GET parameters sent with the request. ```APIDOC ## request.get() ### Description Returns a dictionary or similar structure containing all GET parameters sent with the request. ### Method -- ### Endpoint -- ### Parameters No parameters. ### Request Example -- ### Response #### Success Response Returns a mapping of GET parameter names to values. #### Response Example -- ``` -------------------------------- ### Spyce command-line usage Source: http://spyce.sourceforge.net/docs/doc-single.html Shows the full command-line syntax for the Spyce 2.1 executable, including options for compiling, CGI mode, batch processing, and running as a proxy server. Use this to understand the available flags such as -c, -w, -O, -l, and --conf. ```text Spyce 2.1 Command-line usage: spyce -c [-o filename.html] spyce -w <-- CGI spyce -O filename(s).spy <-- batch process spyce -l [-d file ] <-- proxy server spyce -h | -v -h, -?, --help display this help information -v, --version display version -o, --output send output to given file -O send outputs of multiple files to *.html -c, --compile compile only; do not execute -w, --web cgi mode: emit headers (or use run_spyceCGI.py) -q, --query set QUERY_STRING environment variable -l, --listen run in HTTP server mode -d, --daemon run as a daemon process with given pidfile --conf [file] Spyce configuration file To configure Apache, please refer to: spyceApache.conf For more details, refer to the documentation. http://spyce.sourceforge.net Send comments, suggestions and bug reports to . ``` -------------------------------- ### Form tag example with primitive and compound controls Source: http://spyce.sourceforge.net/docs/doc-single.html Complete example of Spyce form tags: primitive controls (text, password, textarea, checkbox, radio) and compound controls (radiolist, checkboxlist, select, date). The data attribute for compound controls is an iterable of (description, value) pairs, here defined inline as L. The default attribute for checkboxlist is a list expression, e.g. ['0', '1']. ```spyce **

Primitive controls

Compound controls

[[-- a simple data source for the compound controls -- in practice this would probably come from the database --]] [[ L = [('option %d' %i, str(i)) for i in range(5)] ]]
Radiolist
Checkboxlist
Select
Date

Test it!

** ``` -------------------------------- ### request.get1() Source: http://spyce.sourceforge.net/docs/doc-single.html Returns the first value of a GET parameter. Typically used to retrieve a single value when multiple values may exist. ```APIDOC ## request.get1() ### Description Returns the first value of a GET parameter. Typically used to retrieve a single value when multiple values may exist. ### Method -- ### Endpoint -- ### Parameters No parameters. ### Request Example -- ### Response #### Success Response Returns a single value (string) of a GET parameter. #### Response Example -- ``` -------------------------------- ### CompoundHandlerError example with multiple errors Source: http://spyce.sourceforge.net/docs/doc-single.html Shows how to raise multiple validation errors at once using CompoundHandlerError. The handler adds two HandlerError instances and raises the compound error if it is non-empty. The form displays all errors together. ```spyce **[[! def errors(self, api): from spyceException import HandlerError, CompoundHandlerError cve = CompoundHandlerError() cve.add(HandlerError('One', 'First error')) cve.add(HandlerError('Two', 'Second error')) if cve: raise cve ]] ** ``` -------------------------------- ### Configure Apache to handle .spy files Source: http://spyce.sourceforge.net/docs/doc-single.html Add this line to httpd.conf or .htaccess to enable Spyce as a CGI script. Requires the ExecCGI option and cgi_allow_only_redirect set to False. ```apache AddHandler cgi-script spy ``` -------------------------------- ### Dynamic include with include.spyce() Source: http://spyce.sourceforge.net/docs/doc-single.html Shows dynamic includes: the main file uses include.spyce() to include 'include.spi' with a context, and the included file accesses that context and returns a value. The included file runs in a separate context, so changes to its variables do not affect the main file. ```spyce **[[.import name=include]] main file

[[ context = {'foo': 'old value'} result=include.spyce('include.spi', context) ]]
main file again
context: [[=context]]
return value: [[=result]]
** ``` ```spyce **begin include
context: [[=include.context ]]
from: [[=request.stack()[-2] ]]
foo was [[=include.vars.foo]]
setting foo to 'new value' [[include.vars.foo = 'new value']]
returing 'retval'
end include
[[ return 'retval' ]] ** ``` -------------------------------- ### Execute raw SQL via SqlSoup engine Source: http://spyce.sourceforge.net/docs/doc-single.html Shows how to access SqlSoup's engine attribute and use its execute method to run raw SQL, returning a ResultProxy with fetch methods. The output displays the fetched rows. ```python >>> rp = db.engine.execute('select name, email from users order by name') >>> for name, email in rp.fetchall(): print name, email Bhargan Basepair basepair+nospam@example.edu Joe Student student@example.edu ```