Skip to content
doc-single.html 270 KiB
Newer Older
Thorsten Eggeling's avatar
Thorsten Eggeling committed
3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000
Below we contrast the difference between static and dynamic includes. A
dynamic include is included on each request; a static include is inserted at
compile time. A static include runs in the same context, while a dynamic
include has a separate context.<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/include.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b><font color="#CC00CC">[[.import name=include]]</font>
&lt;html&gt;&lt;body&gt;
  main file&lt;br&gt;
  &lt;hr&gt;
  <font color="#0000CC">[[
    context = {'foo': 'old value'}
    result=include.spyce('include.spi', context)
  ]]</font>
  &lt;hr&gt;
  main file again&lt;br&gt;
  context: <font color="#CC0000">[[=context]]</font>&lt;br&gt;
  return value: <font color="#CC0000">[[=result]]</font>&lt;br&gt;
&lt;/body&gt;&lt;/html&gt;
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/include.spy">Run this code</a></b>
    </font>
</td></tr></table>
<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/include.spi</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b>begin include&lt;br&gt;
context: <font color="#CC0000">[[=include.context ]]</font>&lt;br&gt;
from: <font color="#CC0000">[[=request.stack()[-2] ]]</font>&lt;br&gt;
foo was <font color="#CC0000">[[=include.vars.foo]]</font>&lt;br&gt;
setting foo to 'new value' <font color="#0000CC">[[include.vars.foo = 'new value']]</font>&lt;br&gt;
returing 'retval'&lt;br&gt;
end include&lt;br&gt;
<font color="#0000CC">[[ return 'retval' ]]</font>
</b></font></pre>
  </font>
</td></tr></table>
<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/includestatic.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b>&lt;html&gt;&lt;body&gt;
  <font color="#0000CC">[[x=1]]</font>
  main file&lt;br&gt;
  x=<font color="#CC0000">[[=x]]</font>&lt;br&gt;
  &lt;hr&gt;
  <font color="#CC00CC">[[.include file=&quot;includestatic.spi&quot;]]</font>
  &lt;hr&gt;
  main file again&lt;br&gt;
  x=<font color="#CC0000">[[=x]]</font>
&lt;/body&gt;&lt;/html&gt;
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/includestatic.spy">Run this code</a></b>
    </font>
</td></tr></table>
<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/includestatic.spi</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b>begin included file&lt;br&gt;
changing value of x&lt;br&gt;
<font color="#0000CC">[[x=2]]</font>
end included file&lt;br&gt;
</b></font></pre>
  </font>
</td></tr></table>
<p>
<big><a name="mod_internal"></a><b>3.8.11. <font color=#ee0000><i>Internal modules</i></font></b></big><p>


These modules are used internally by Spce. Documentation is included for
those curious about Spyce internals; ordinarily you will never use these
modules directly.

The error module is implicitly loaded and provides error-handling
functionality. An error is any <a
href="#runtime_except">unhandled runtime exception</a> that
occurs <b>during Spyce processing</b>. This mechanism does not include
exceptions that are not related to Spyce processing (i.e. server-related
exceptions), that can be caused before or after Spyce processing by invalid
syntax, missing files and file access restrictions. To install a server-level
error handler use a <a href="#runtime_common">configuration
file</a>. The default page-level error handler can also be modified in the <a
href="#runtime_common">configuration file</a>. This module
allows the user to install page-level error handling code, overriding the
default page-level handler, by using one of the following functions: <p>
<ul>
<li><b>setStringHandler</b>( string ): <br> Installs a function that will
processes the given <b>string</b>, as Spyce code, for error handling.
</li><p>
<li><b>setFileHandler</b>( uri ): <br> Installs a function that will
processes the given <b>uri</b> for error handling. </li><p>
<li><b>setHandler</b>( fn ): <br> Installs the <b>fn</b> function for error
handling. The function is passed one parameter, a reference to the error
module. From this, all the error information as well as references to other
modules and Spyce objects can be accessed.</li><p>
</ul>
The error module provides the following information about an error: <p>
<ul>
<li><b>isError</b>(): <br> Returns whether an error is being handled.
</li><p>
<li><b>getMessage</b>(): <br> Return the error message; the string of the
object that was raised, or None if there is no current error. </li><p>
<li><b>getType</b>(): <br> Return the error type; the type of the object
that was raised, or None if there is no current error. </li><p>
<li><b>getFile</b>(): <br> Return the file where the error was raised, or
None if there is no current error. </li><p>
<li><b>getTraceback</b>(): <br> Return the stack trace as an array of
tuples, or None if there is no current error. Each tuple entry is of the
form: (file, line numbers, function name, code context).</li><p>
<li><b>getString</b>(): <br> Return the string of the entire error (the
string representation of the message, type, location and stack trace), or
None if there is no current error. </li><p>
</ul>
The default error handling function uses the following string handler:
<table border=0 align=center><tr><td>
<pre><font color="#000000"><b>
<font color="#CC00CC">[[.module name=transform]]</font>
<font color="#0000CC">[[transform.expr('html_encode')]]</font>
&lt;html&gt;
&lt;title&gt;Spyce exception: <font color="#CC0000">[[=error.getMessage()]]</font>&lt;/title&gt;
&lt;body&gt;
&lt;table cellspacing=10 border=0&gt;
  &lt;tr&gt;&lt;td colspan=2&gt;&lt;h1&gt;Spyce exception&lt;/h1&gt;&lt;/td&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td valign=top align=right&gt;&lt;b&gt;File:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;<font color="#CC0000">[[=error.getFile()]]</font>&lt;/tr&gt;
  &lt;tr&gt;&lt;td valign=top align=right&gt;&lt;b&gt;Message:&lt;/b&gt;&lt;/td&gt;
    &lt;td&gt;&lt;pre&gt;<font color="#CC0000">[[=error.getMessage()]]</font>&lt;/pre&gt;&lt;/tr&gt;
  &lt;tr&gt;&lt;td valign=top align=right&gt;&lt;b&gt;Stack:&lt;/b&gt;&lt;/td&gt;&lt;td&gt;
    <font color="#0000CC">[[\
      L = list(error.getTraceback())
      L.reverse()
    ]]</font>
    <font color="#0000CC">[[ for frame in L: { ]]</font>
      <font color="#CC0000">[[=frame[0] ]]</font>:<font color="#CC0000">[[=frame[1] ]]</font>, in <font color="#CC0000">[[=frame[2] ]]</font>:&lt;br&gt;
      &lt;table border=0&gt;&lt;tr&gt;&lt;td width=10&gt;&lt;/td&gt;&lt;td&gt;
        &lt;pre&gt;<font color="#CC0000">[[=frame[3] ]]</font>&lt;/pre&gt;
      &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
    <font color="#0000CC">[[ } ]]</font>
    &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/body&gt;&lt;/html&gt;
</b></font></pre>
</td></tr></table>
<p>
The example below shows the error module in use. Error handling can often be
used to send emails notifying webmasters of problems, as this example shows.
<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/error.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b><font color="#0000CC">[[error.setFileHandler('error.spi') ]]</font>
This is a page with an error...
<font color="#0000CC">[[ raise 'an error' ]]</font>
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/error.spy">Run this code</a></b>
    </font>
</td></tr></table>
<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/error.spi</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b>&lt;h1&gt;Oops&lt;/h1&gt;
An error occurred while processing your request. 
We have logged this for our webmasters, and they 
will fix it shortly. We apologize for the inconvenience.
In the meantime, please use the parts of our site that 
actually do work... &lt;a href=&quot;somewhere&quot;&gt;somewhere&lt;/a&gt;.
<font color="#0000CC">[[\
  # could redirect the user immediately
  #response.getModule('redirect').external('somewhere.spy')

  # could send an email
  import time
  msg = '''
time: %s
error: %s
env: %s
other info...
''' % (
    time.asctime(time.localtime(time.time())), 
    error.getString(),
    request.env()
  )
  #function_to_send_email('webmaster@foo.com', msg)

  #or perform other generic error handling...
]]</font>
</b></font></pre>
  </font>
</td></tr></table>
<p>
This mechanism is not a subsititute for proper exception handling within the
code itself, and should not be abused. It does, however, serve as a useful
catch-all for bugs that slip through the cracks. <p>

The stdout module is loaded implicitly and redirects Python's <font
face=courier>sys.stdout</font> (in a thread-safe manner) to the appropriate
response object for the duration of Spyce processing. This allows one to use
<font face=courier>print</font>, without having to write <font
face=courier>print&nbsp;&gt;&gt;&nbsp;response,&nbsp;...</font>. The stdout
module provides a variable <font face=courier>stdout.stdout</font>, which
refers to the original stream, but is unlikely to be needed. It may also be
useful to know that <font face=courier>sys.stderr</font> is, under many
configurations, connected to the webserver error log. <p>
In addition, the stdout module provides the following functions for capturing
or redirecting output:
<ul>
<li><b>push</b>( [filename] ): <br> Begin capturing output. Namely, the current
output stream is pushed onto the stack and replaced with a memory buffer. An
optional <b>filename</b> may be associated with this operation (see pop()
method below). </li> <p>
<li><b>pop</b>(): <br> Close current output buffer, and return the captured
output as a string. If a filename was associated with the push(), then the
string will also be written to that file. </li> <p>
<li><b>capture</b>(f, [*args], [**kwargs] ): <br> Push the current stream,
call the given function <b>f</b> with any supplied arguments <b>*args</b>
and keyword arguments <b>**kwargs</b>, and then pop it back. Capture returns
a tuple (r,s), where r is the result returned by f and s is a string of its
output. </li> <p>
</ul> <p>
The example below show how the module is used:
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/stdout.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b>&lt;html&gt;&lt;body&gt;
  <font color="#0000CC">[[ print '''Using the stdout module redirects 
    stdout to the response object, so you can use
    &lt;b&gt;print&lt;/b&gt;!''']]</font>&lt;br&gt;
  redirecting stdout can be used to...
  <font color="#0000CC">[[stdout.push()]]</font>
  <font color="#0000CC">[[print 'capture']]</font> out<font color="#CC0000">[[='put']]</font>
  <font color="#0000CC">[[cached = stdout.pop()]]</font>
  ... for later: &lt;br&gt;
  <font color="#CC0000">[[=cached]]</font>
&lt;/body&gt;&lt;/html&gt;
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/stdout.spy">Run this code</a></b>
    </font>
</td></tr></table>


This module is used internally by Spyce, not usually by users. Documentation is
included for those curious about Spyce internals. The spylambda module is
loaded implicitly and allows the definition of functions based on Spyce
scripts; see <a href="#lang_lambda">Spyce Lambdas</a>. The
spylambda module provides the following methods:
<ul>
<li><b>define</b>( args, code, [memoize] ): <br> Returns a function that
accepts the given <b>args</b> and executes the Spyce script defined by the
<b>code</b> parameter. Note that the code is compiled immediately and that
<font face=courier>spyce.spyceSyntaxError</font> or <font
face=courier>spyce.spycePythonError</font> exceptions can be thrown for
invalid code arguments. The optional <b>memoize</b> parameter sets whether
the spyce can or can not be memoized, with the default being false.
Memoizing a function means capturing the result and output and caching them,
keyed on the function parameters. Later, if a function is called again with
the same parameters, the cached information is returned, if it exists, and
the function may not actually be called. Thus, you should only memoize
functions that are truly functional, i.e. they do not have side-effects:
they only return a value and output data to the response object, and their
behaviour depends exclusively on their parameters. If you memoize code that
does have side-effects, those side-effects may not occur on every
invocation. </li> <p>
<li><b>__call__</b>( args, code, _spyceCache ): <br> This is an alias to the
define function. Because of the special method name, the spylambda module
object can be <a
href="http://www.python.org/doc/current/ref/callable-types.html">called as
if it were a function</a>. </li> <p>
</ul>

The taglib module is loaded implicitly and supports
<a href="#tag">Active Tags</a>
functionality. The taglib module provides the following
methods:
<ul>
<li><b>load</b>( libname, [libfrom], [libas] ): <br> Loads a tag library
class named <b>libname</b> from a file called <b>libfrom</b> in the search
path, and installed it under the tag prefix <b>libas</b>. The default for
libfrom is <font face=courier><i>libname</i>.py</font>. The default for
libas is <font face=courier><i>libname</i></font>. Once installed, a library
name is its unique tag prefix. </li> <p>
<li><b>unload</b>( libname ): <br> Unload a tag library that is installed
under the <b>libname</b> prefix. This is usually performed only at the end
of a request. </li> <p>
<li><b>tagPush</b>( libname, tagname, pair ): <br> Push a new tag object for
a <b>libname</b>:<b>tagname</b> tag onto the tag stack. The <b>pair</b>
parameter is a flag indicating whether this is a singleton or a paired tag.
</li> <p>
<li><b>tagPop</b>(): <br> Pop the current tag from the tag stack. </li> <p>
<li><b>getTag</b>(): <br> Return the current tag object. </li> <p>
<li><b>outPush</b>(): <br> Begin capturing the current output stream. This
is usually called by the tagBegin method. </li> <p>
<li><b>outPopCond</b>(): <br> End capturing the current output stream, and
return the captured contents. It will only "pop" once, even if called
multiple times for the same tag. This method is usually called by either the
tagEnd(), tagCatch, or tagPop() methods. </li> <p>
<li><b>tagBegin</b>( attrs ): <br> This method sets the tag output and
variable environment, and then calls the tag's <b>begin()</b> method with
the given <b>attrs</b> tag attribute dictionary. This method returns a flag,
and the tag body must be processed if and only if this flag is true. </li>
<p>
<li><b>tagBody</b>(): <br> This method sets the tag output and variable
environment, and then calls the tag's <b>body()</b> method with the captured
output of the body processing. If this method returns true, then the
processing of the body must be repeated. </li> <p>
<li><b>tagEnd</b>(): <br> This method sets the tag output and variable
environment, and then calls the tag's <b>end()</b> method. This method must
be called if the tagBegin() method completes successfully in order to
preserve tag semantics. </li> <p>
<li><b>tagCatch</b>(): <br> This method should be called if any of the
tagBegin, tagBody or tagEnd methods raise an exception. It calls the tag's
<b>catch()</b> method with the current exception. </li> <p>
</ul>

<big><a name="mod_new"></a><b>3.8.12. <font color=#ee0000><i>Writing Modules</i></font></b></big><p>


Writing your own Spyce modules is simple.
<p>
A Spyce modules is simply a Python class that exposes specific methods
to the Spyce server. The most important are <b>start</b>, <b>finish</b>,
and <b>init</b>. With these,
a Spyce module may access the
internal request and response structures or alter the behaviour of the
runtime engine in some way.
<p>Let us begin with a basic example
called myModule. It is a module that implements one function named foo().
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/myModule.py</b></font>
</td></tr><tr><td>
  <font face=courier>
    
<style>    
.STRING {
  color: #a0522d;
}
.COMMENT {
  color: #ff7448;
  font-family: serif;
}
.KEYWORD {
  color: #9e79af;
}
.FUNCTION {
  color: #0074ef;
}
</style>
<pre>
<span class="KEYWORD">from</span> <span class="NAME">spyceModule</span> <span class="KEYWORD">import</span> <span class="NAME">spyceModule</span><span class="NEWLINE">
</span><span class="NL">
</span><span class="KEYWORD">class</span> <span class="FUNCTION">myModule</span><span class="OP">(</span><span class="NAME">spyceModule</span><span class="OP">)</span><span class="OP">:</span><span class="NEWLINE">
</span><span class="INDENT">  </span><span class="KEYWORD">def</span> <span class="FUNCTION">foo</span><span class="OP">(</span><span class="NAME">self</span><span class="OP">)</span><span class="OP">:</span><span class="NEWLINE">
</span><span class="INDENT">    </span><span class="KEYWORD">print</span> <span class="STRING">'foo called'</span><span class="NEWLINE">
</span><span class="NL">
</span><span class="DEDENT"></span><span class="DEDENT"></span><span class="ENDMARKER"></span>
</pre>
    
  </font>
</td></tr></table>
<p>
Saving this code in <font face=courier>myModule.py</font> in the same
directory as the Spyce script, or somewhere on the module path, we could use
it as expected: <p>
<table align=center border=0><tr><td><font face=courier>

<b><pre>[[.import name=myModule]]
[[ myModule.foo() ]]
</pre></b>
</font></td></tr></table>
<p>
A Spyce module can be any Python class that derives from
<b>spyceModule.spyceModule</b>. When it is loaded, Spyce assigns it a
__file__ attribute indicating its source location.
Do not override the <b> __init__(...)</b>
method because it is inherited from spyceModule and has an fixed signature
that is expected by the Spyce engine's module loader. The inherited method
accepts a Spyce API object, a <a
href="http://www.python.org/doc/current/lib/module-Bastion.html">Bastion</a>
of <b>spyce.spyceWrapper</b>, an internal engine object, and stores it in
<b>self._api</b>. This is the building block for all the functionality that
any module provides. The available API methods of the wrapper are (listed in
spyceModule.spyceModuleAPI):
<ul>

<li> <b>getFilename</b>: Return filename of current Spyce</li>

<li> <b>getCode</b>: Return processed Spyce (i.e. Python) code</li>

<li> <b>getCodeRefs</b>: Return python-to-Spyce code line references</li>

<li> <b>getModRefs</b>: Return list of import references in Spyce code</li>

<li> <b>getServerObject</b>: Return unique (per engine instance) server object</li>

<li> <b>getServerGlobals</b>: Return server configuration globals</li>

<li> <b>getServerID</b>: Return unique server identifier</li>

<li> <b>getModules</b>: Return references to currently loaded modules</li>

<li> <b>getModule</b>: Get module reference. The module is dynamically loaded and initialised
    if it does not exist (ie. if it was not explicitly imported, but requested
    by another module during processing)</li>

<li> <b>setModule</b>: Add existing module (by reference) to Spyce namespace (used for includes)</li>

<li> <b>getGlobals</b>: Return the Spyce global namespace dictionary</li>

<li> <b>registerModuleCallback</b>: Register a callback for modules change</li>

<li> <b>unregisterModuleCallback</b>: Unregister a callback for modules change</li>

<li> <b>getRequest</b>: Return internal request object</li>

<li> <b>getResponse</b>: Return internal response object</li>

<li> <b>setResponse</b>: Set internal response object</li>

<li> <b>registerResponseCallback</b>: Register a callback for when internal response changes</li>

<li> <b>unregisterResponseCallback</b>: Unregister a callback for when internal response changes</li>

<li> <b>spyceString</b>: Return a spyceCode object of a string</li>

<li> <b>spyceFile</b>: Return a spyceCode object of a file</li>

<li> <b>spyceModule</b>: Return Spyce module class</li>

<li> <b>spyceTaglib</b>: Return Spyce taglib class</li>

<li> <b>setStdout</b>: Set the stdout stream (thread-safe)</li>

<li> <b>getStdout</b>: Get the stdout stream (thread-safe)</li>

</ul> <p>
For convenience, one can sub-class the <b>spyceModulePlus</b> class instead of
the regular <b>spyceModule</b>. The spyceModulePlus defines a
<b>self.modules</b> field, which can be used to acquire references to other
modules loaded into the Spyce environment. The <i>response</i> module, for
instance, would be referenced as <i>self.modules.response</i>. Modules are
loaded on demand, if necessary. The spyceModulePlus also contains a
<b>self.globals</b> field, which is a reference to the Spyce global namespace
dictionary, though this should rarely be needed. <p>
<b>Note:</b> It is not expected that many module writers will need the entire
API functionality. In fact, the vast majority of modules will use a small
portion of the API, if at all. Many of these functions are included for just
one of the standard Spyce modules that needs to perform some esoteric
function. <p>
Three Spyce module methods, <b>start()</b>, <b>init([args])</b> and
<b>finish(error)</b> are special in that they are automatically called by the
runtime during Spyce request startup, processing and cleanup, respectively.
The modules are started in the order in which module directives appear in the
file, before processing begins. The implicitly loaded modules are always
loaded first. The init method is called during Spyce processing at the
location of the module directive in the file, with the optional args attribute
is passed as the arguments of this call. Finally, after Spyce processing is
complete, the modules are finalized in reverse order. If there is an unhandled
exception, it will be wrapped in a spyce.spyceException object and passed as
the first parameter to finish(). During successful completion of Spyce
processing (i.e. without exception), the error parameter is None. The default
inherited start, init and finish methods from spyceModule are noops. <p>
<b>Note 2:</b> When writing a Spyce module, consider carefully why you are
selecting a Spyce module over a regular Python module. If it is just code,
that does not interact with the Spyce engine, then a regular Python <font
face=courier>import</font> instead of an Spyce <font
face=courier>[[.import]]</font> can just as easily bring in the necessary
code, and is preferred. In other words, choose a Spyce module only when there
is a need for per-request initialization or for one of the engine APIs. <p>
Module writers are encouraged to look at the existing standard modules as
examples and the definitions of the core Spyce objects in <font
face=courier>spyce.py</font> as well. If you write or use a novel Spyce
module that you think is of general use, please email your
<a href="https://svn.sourceforge.net/svnroot/spyce/trunk/spyce/contrib/">contribution</a>,
or a link to it. Also, please keep in mind that the standard modules are designed
with the goal of being minimalist. Much functionality is readily available
using the Python language libraries. If you think that they should be
expanded, also please send a note. <p>

<big><a name="tag"></a><b>3.9. <font color=#ee0000>Tags</font></b></big><p>


The previous chapter discussed the Spyce module facility, the standard Spyce
modules and how users can create their own modules to extend Spyce. Spyce
functionality can also be extended via active tags, which are defined in tag
libraries. This chapter describes what Spyce active tags are, and how they are
used. We then describe each of the standard active tag libraries and, finally,
how to define <a href="#tag_new2">new tags libraries</a>. <p>
It is important, from the outset, to define what an active tag actually does.
A few illustrative examples may help. The examples below all use tags that are
defined in the <a href="#tag_core">core tag library</a>,
that has been installed under the <b>spy</b> prefix, as is the default. <p>
<ul>
<li><font face=courier>&lt;spy:parent&nbsp;src="parent.spi"/&gt;</font> <br>
Wraps the current page in the parent template found at parent.spi in the
same directory.
<li><font face=courier> &lt;spy:for items="=range(5)"&gt; <br>
&nbsp;&nbsp;&lt;spy:print value="=foo"/&gt; <br> &lt;/spy:for&gt; </font>
<br> As expected, these tags will print the value of <b>foo</b>, set to
<font face=courier>bar</font> above, 5&nbsp;times. </li> <p>
</ul>
<b>Common mistake:</b> Don't use [[= ]] to send values to active tag attributes:
[[= ]] sends its result directly to the output stream. And since those tokens
are parsed with higher precedence than the tag markup, Spyce won't recognize
your tag at all and will print it verbatim to the client.
Instead, prefix an expression with =, as in "=range(5)" above, and Spyce will
<i>eval</i> it before sending it to the tag.
<p>
Note that the same output could have been achieved in many different ways, and
entirely without active tags. The manner in which you choose to organize your
script or application, and when you choose active tags over other
alternatives, is a matter of personal preference. Notice also that active tags
entirely control their output and what they do with their attributes and the
result of processing their bodies (in fact, whether the body of the tag is
even processed). Tags can even supply additional syntax constraints on their
attributes that will be enforced at compile-time. Most commonly a tag could
require that certain attributes exist, and possibly that it be used only as a
single or only as a paired (open and close) tag. Unlike early versions of
HTML, active tags must be strictly balanced, and this will be enforced by the
Spyce compiler. <p>
Below, each individual standard Spyce tag library is documented, followed by a
description of how one would write a <a href="#tag_new">new
active tag library</a>. The following general information will be useful for
reading that material.
<ul>
<li>Active tags are installed using the <font
face=courier>[[.taglib]]</font>
<a href="#lang_directive">directive</a>, under some prefix.
Tag libraries may also be be loaded globally in the config module; by default
the core and form libraries are preloaded.
Active tags are of the format <font
face=courier>&lt;pre:name&nbsp;...&nbsp;&gt;</font>, where <b>pre</b> is the
prefix under which the tag library was installed, and <b>name</b> is defined
by the tag library. In the following tag library documentation, the prefix
is omitted from the syntax. </li>
<li>The following notation is used in the documentation of the tag libraries
below:
<ul>
<li> &lt;name .../&gt; : The tag should be used as a singleton. </li>
<li> &lt;name ... &gt; ... &lt;/name&gt; : The tag should be used as an
open-close pair. </li>
<li> [ x (default)] : The attribute is optional. Attributes not enclosed in
brackets are required. </li>
<li> foo|<u>bar</u> : indicates that an attribute may be one of two
constant strings. The underlined value is the default. </li>
<li> <i>string</i> : an arbitrary string constant, never evaluated as Python </li>
<li> <i>exprstring</i> : may be a string constant, and may be of the form
<font face=courier>'=expr'</font>, where <font face=courier>expr</font> is
a Python expression that will be evaluated in the tag context. </li>
<li> <i>expr</i>: a Python expression. (Currently only the "data" parameters
of some form and core tags use this rather than exprstring.)
</li>
<li> <i>exports foo, *bar</i> Exports to the parent context
the variable foo and the variable
with the name given by the expression bar. Normally, implementation
details of tags will not affect the parent context, so you do not have
to worry about your variables being clobbered. Tags may, however,
export specific parts of their own context to the parent.
See, for example,
the let and for tags in the core taglib.
<b>Note:</b> exporting of variables whose name
cannot be determined at compile time is deprecated, and will be removed in Spyce 2.2.
</li>
</ul>
</ul> <p>
<big><a name="tag_core"></a><b>3.9.1. <font color=#ee0000><i>Core</i></font></b></big><p>


The core tag library is aliased as "spy" by default.
<p>
This library contains various frequently-used tags: the parent tag, login tags, 
and some tags for generating lists and tables from Python iterators.

<p>
<big><b>Parent Tag</b></big>
<ul>
  <li><font face=courier>&lt;<b><a name=parent>parent</a></b> [src=<i>url</i>] [other parameters] /&gt;</font>
  <br>
  Specifies a parent template to apply to the current page, which
  is passed to the parent as child._body.  Any extra parameters are also
  passed in the child dictionary.  If src is not given, 'parent.spi' used if it exists
  in the current directory; otherwise, the default parent
  is used as specified in the config module.
  <p>
  <table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/hello-templated.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b><font color="#229922">&lt;spy:parent title=&quot;Hello, world!&quot; /&gt;</font>

<font color="#ff7448">[[-- Spyce can embed chunks of Python code, like this. --]]</font>
<font color="#0000CC">[[\
  import time
  t = time.ctime()
]]</font>

<font color="#ff7448">[[-- 
  pull the count from the GET variable.
  the int cast is necessary since request stores everything as a string 
--]]</font>
<font color="#0000CC">[[ for i in range(int(request.get1('count', 2))):{ ]]</font>
&lt;div&gt;Hello, world!&lt;/div&gt;
<font color="#0000CC">[[ } ]]</font>

The time is now <font color="#CC0000">[[= t ]]</font>.
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/hello-templated.spy">Run this code</a></b>
    </font>
</td></tr></table>

</ul>

<big><b>Login Tags</b></big>
<ul>
  <li><font face=courier>&lt;<b><a name=login>login</a></b> [validator=<i>function name</i>] /&gt;</font>
  <br>
  Generates a login form according to the template specified in your config file.
  If <b>validator</b> is not specified, the default validator from your config file is used.
  (<b>validator</b> may be the name of a function in a different Python module;
  just prefix it with the module name and Spyce will automaticall import it when
  necessary.)
  <p>
  <table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/login-optional.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b>&lt;html&gt;&lt;body&gt;

<font color="#229922">&lt;f:form&gt;</font>
  <font color="#0000CC">[[ if request.login_id():{ ]]</font>
    You are logged in with user id <font color="#CC0000">[[= request.login_id() ]]</font>
    <font color="#229922">&lt;spy:logout /&gt;</font>
  <font color="#0000CC">[[ } else: { ]]</font>
    <font color="#229922">&lt;spy:login /&gt;</font>
    You are not logged in.  (You may login with username/password: spyce/spyce.)
  <font color="#0000CC">[[ } ]]</font>
  
  &lt;p&gt;
  (Here is some content that is the same before and after login.)
<font color="#229922">&lt;/f:form&gt;</font>

&lt;/body&gt;&lt;/html&gt;</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/login-optional.spy">Run this code</a></b>
    </font>
</td></tr></table>


  <li><font face=courier>&lt;<b><a name=logout>logout</a></b> /&gt;</font>
  <br>
  Generates a logout button that will clear the cookie generated by <b>login</b>
  and <b>login_required</b>.
  <p>

  <li><font face=courier>&lt;<b><a name=login_required>login_required</a></b> [validator=<i>function name</i>] /&gt;</font>
  <br>
  If a valid login cookie is not present, generates a login form according to the 
	template specified in your config file, then halts execution of the current page.
  <p>
  (You may log in to this example as user <b>spyce</b>, password <b>spyce</b>.)
  <table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/login-required.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b><font color="#229922">&lt;spy:parent title=&quot;Login example&quot; /&gt;</font>

<font color="#229922">&lt;f:form&gt;</font>
  <font color="#229922">&lt;spy:login_required /&gt;</font>

  You are logged in.
  <font color="#229922">&lt;spy:logout /&gt;</font>
<font color="#229922">&lt;/f:form&gt;</font>
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/login-required.spy">Run this code</a></b>
    </font>
</td></tr></table>

</ul>

<big><b>Convenience Tags</b></big>
<p>
These tags are shortcuts for creatings lists and tables.  As with 
the <a href="#tag_form">form tag library</a>, any python
iterator may be given as the data parameter.  Also as with the form tags,
any unrecognized parameters will be passed through to the generated HTML.

<ul>
  <li><font face=courier>&lt;<b><a name=ul>ul</a></b> data=<i>expr</i>] /&gt;</font>
  <br>
  Convenience tag for the common use of ul; equivalent to
  <blockquote>
  <tt><pre>
    &lt;ul>
    [[ for item in data:{ ]]
      &lt;li>[[= item ]]&lt;/li>
    [[ } ]]
    &lt;/ul>
  </pre></tt>
  </blockquote>

  <li><font face=courier>&lt;<b><a name=ol>ol</a></b> data=<i>expr</i>] /&gt;</font>
  <br>
  Like ul, but for ordered lists.<br><br>

  <li><font face=courier>&lt;<b><a name=dl>dl</a></b> data=<i>expr</i>] /&gt;</font>
  <br>
  Convenience tag for the common use of dl; equivalent to
  <blockquote>
  <tt><pre>
  &lt;dl>
  [[ for term, desc in data:{ ]]
    &lt;dt>[[= term ]]&lt;/dt>
    &lt;dd>[[= desc ]]&lt;/dd>
  [[ } ]]
  &lt;/dl>
  </pre></tt>
  </blockquote>

  <li><font face=courier>&lt;<b><a name=table>table</a></b> data=<i>expr</i>] /&gt;</font>
  <br>
  Convenience tag for the common use of table; equivalent to
  <blockquote>
  <tt><pre>
  &lt;table>
  [[ for row in data:{ ]]
    &lt;tr>
    [[ for cell in row:{ ]]
      &lt;td>[[= cell ]]&lt;/td>
    [[ } ]]
    &lt;/tr>
  [[ } ]]
  &lt;/table>
  </pre></tt>
  </blockquote>

</ul>

<big><a name="tag_form"></a><b>3.9.2. <font color=#ee0000><i>Form</i></font></b></big><p>


The form tag library is aliased as "spy" by default.
<p>
This library simplifies the generation and handling of forms by
automating away repetitive tasks. Let's take a look at a simple example:
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/formintro.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b><font color="#229922">&lt;spy:parent title=&quot;Form tag intro&quot; /&gt;</font>

<font color="#229922">&lt;f:form&gt;</font>

&lt;div class=&quot;simpleform&quot;&gt;
  <font color="#229922">&lt;f:text name=&quot;text1&quot; label=&quot;Text input&quot; default=&quot;change me&quot; size=10 maxlength=30 /&gt;</font>
  <font color="#229922">&lt;f:text name=&quot;text2&quot; label=&quot;Text input 2&quot; value=&quot;change me&quot; size=10 maxlength=30 /&gt;</font>
&lt;/div&gt;

&lt;fieldset style=&quot;clear: both&quot;&gt;
  &lt;legend&gt;One or two?  Or both?&lt;/legend&gt;
  <font color="#229922">&lt;f:checkboxlist class=&quot;radio&quot; name=&quot;checkboxlist&quot; data=&quot;[(1, 'one'), (2, 'two')]&quot; /&gt;</font>
&lt;/fieldset&gt;

&lt;div style=&quot;clear: both&quot;&gt;<font color="#229922">&lt;f:submit /&gt;</font>&lt;/div&gt;

<font color="#229922">&lt;/f:form&gt;</font></b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/formintro.spy">Run this code</a></b>
    </font>
</td></tr></table>

<p>This demonstrates several properties of Spyce form tags:
<ul>
<li>Most tags take an optional label parameter; this is turned into an HTML label tag
associated with the form element itself.
<li>If you View Source in your browser while running this sample, you can
see that Spyce generates an id with the same value as the name parameter.
(You can override this by explicitly specifying a different id parameter,
if you need.)
<li>You can pass arbitrary parameters (such as the class parameter for &lt;f:form&gt;)
to a Spyce form tag; parameters that do not have special meaning to Spyce
will be passed through to the HTML output.
<li>Try changing the form values and submitting. By default, Spyce automatically
remembers the user input for you, unless you give a tag a <i>value</i>
parameter (or <i>selected</i> for collection elements), which has highest precedence.
Note the different behavior of text1 and text2 in this example.
<li>Spyce provides some higher-level tags such as checkboxlist that result in multiple
elements at the HTML level. For these tags, a "data" parameter is expected,
which is always interpreted as a Python expression.
Any iterable may be used as data, including generators and generator expressions
for those with recent Python versions. Typically data would come from the
database; here we're just using a literal list.
</ul>
<big><b>Handlers</b></big>
<p>
Active Handlers allow you to "attach" python functions to form submissions.
They are described in the
<a href="#tag_handlers">Active Handlers</a> manual page.
<p>
<big><b>Reference</b></big>
<p>
First, some general rules:
<p>The text displayed by a text-centric tag can come from one of three
places. In order of decreasing priority, these are
<ul>
<li>the <b>value</b> parameter
<li>the value submitted by the user is used
<li>the <b>default</b> parameter
</ul>
If none of these are found, the input will be empty.
<p>For determining whether option, radio, and checkbox tags are checked or selected,
a similar process is followed, with
<b>selected</b> and <b>checked</b> parameters as the highest-priority source.
The same parameters are used for select, radiolist, and checkboxlist tags;
the only difference is for the collection tags, you can also specify
multiple values in a Python list (or other iterable) in either the
<b>selected/checked</b> or <b>default</b> parameters.
<p>All tags except form and submit can be given names that tell Spyce how to
treat their submitted values when passing to an Active Handler function.
Adding ":int", ":float", ":bool", or ":list" is allowed. The first three
tell Spyce what kind of Python value to convert the submission to; ":list"
may be combined with these, or used separately, and tells Spyce to pass a
list of all values submitted instead of a single one.
(An example is given in the <a href="#tag_handlers">Active Handlers</a> page.)
Finally, here is the list of tags:
<ul>
<li><font face=courier>&lt;<b>form</b>
[method=<i>exprstring</i>]&nbsp;[action=<i>exprstring</i>]&nbsp;...&gt;&nbsp;&lt;/<b>form</b>&gt;</font>
<br> Begin a new form. The <b>method</b> parameter defaults
to 'POST'. The <b>action</b> parameter defaults to the current page.
</li> <p>
<li>
<font face=courier>&lt;<b><a name=submit>submit</a></b>
[handler=<i>exprstring</i>]&nbsp;[value=<i>exprstring</i>]&nbsp;...&nbsp;/&gt;
</font>
<br>Create a submit button. The <b>value</b> parameter is
emitted as the button text. If <b>handler</b> is given, Spyce will call the function(s)
it represents at the beginning of the page load after this button is clicked.
(Multiple function names may be separated with commas.)
<p>
If the handler is in a different [python] module, Spyce will automatically import it
before use.
<p>
A handler may take zero or more arguments.
For the first non-self argument (if present), Spyce always passes a
moduleFinder corresponding to the current
spyceWrapper object; it is customary to call this argument "api."
moduleFinder provides __getitem__ access to loaded modules; thus,
"api.request" would be the current request module. If a requested module
is not found, it is loaded.
<p>
(You can also directly access the wrapper with api._wrapper, providing
access to <a href="#mod_new">anything module authors have</a>,
but you will rarely if ever need to do this.)
<p>
For other handler function parameters, Spyce will pass the values for the
corresponding form input, or None if nothing was found in the GET or POST
variables.
<p>
See also the <a href="#tag_handlers">Active Handlers</a>
language section for a higher-level overview.
<p>
Limitation: currently, Active Handlers require resubmitting to the same spyce page;
of course, the handler method may perform an internal or external
<a href="#mod_redirect">redirect</a>.
</li> <p>
<li><font face=courier>&lt;<b>hidden</b>
name=<i>exprstring</i>&nbsp;[value=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;.../&gt;</font>
<br> Create a hidden form field. The <b>name</b> parameter is evaluated and
emitted.
</li> <p>
<li><font face=courier>&lt;<b>text</b>
name=<i>exprstring</i>&nbsp;[value=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;&nbsp;.../&gt;</font>
<br> Create a form text field. The <b>name</b> parameter is evaluated and
emitted.
</li> <p>
<li><font face=courier>&lt;<b>date</b>
name=<i>exprstring</i>&nbsp;[value=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;[size=<i>exprstring</i>]&nbsp;[format=<i>exprstring</i>]&nbsp;.../&gt;</font>
<br> Create a form text field with a javascript date picker. Format defaults to MM/DD/YYYY. Maxlength is always len(format);
this is also the default size, but size may be overridden for aesthetics.
<li><font face=courier>&lt;<b>password</b>
name=<i>exprstring</i>&nbsp;[value=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;[size=<i>exprstring</i>]&nbsp;[maxlength=<i>exprstring</i>]&nbsp;.../&gt;</font>
<br> Create a form password field. Parameters are the same as for <b>text</b>
fields, explained above. </li> <p>
<li><font face=courier>&lt;<b>textarea</b>
name=<i>exprstring</i>&nbsp;[value=<i>exprstring</i>]&nbsp;[rows=<i>exprstring</i>]&nbsp;[cols=<i>exprstring</i>]&nbsp;...&gt;default&lt;/<b>textarea</b>&gt;</font>
<br> Create a form textarea field. The <b>name</b> parameter is evaluated and
emitted. The <b>value</b> optional parameter is evaluated. A <b>default</b>
may be provided in the body of the tag. The value emitted is, in order of
decreasing priority: local tag value, value in submitted
request dictionary, local tag default. We search this list
for the first non-None value. The <b>rows</b> and <b>cols</b> optional
parameters are evaluated and emitted. </li> <p>
<li><font face=courier>&lt;<b>radio</b>
name=<i>exprstring</i>&nbsp;value=<i>exprstring</i>&nbsp;[checked]&nbsp;[default]&nbsp;.../&gt;</font>
<br> Create a form radio-box. The <b>name</b> and <b>value</b> parameters are
evaluated and emitted. A <b>checked</b> and <b>default</b> flags affect
whether this box is checked. The box is checked based on the following
values, in decreasing order of priority: tag value,
value in submitted request dictionary, tag default.
We search this list for the first non-None value. </li> <p>
<li><font face=courier>&lt;<b>checkbox</b>
name=<i>exprstring</i>&nbsp;value=<i>exprstring</i>&nbsp;[checked]&nbsp;[default]&nbsp;.../&gt;</font>
<br> Create a form check-box. Parameters are the same as for <b>radio</b>
fields, explained above. </li> <p>
<li><font face=courier>&lt;<b>select</b>
name=<i>exprstring</i>&nbsp;[selected=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;[data=<i>expr</i>]&nbsp;...&gt;...&lt;/<b>select</b>&gt;</font>
<br> Create a form select block. The <b>name</b> parameter is
evaluated and emitted. The optional <b>data</b> should be an iterable of
(description, value) pairs.
</li><p>
<li><font face=courier>&lt;<b>option</b>
[text=<i>exprstring</i>]&nbsp;[value=<i>exprstring</i>]&nbsp;[selected]&nbsp;[default]&nbsp;.../&gt;</font>
<br> <font face=courier>&lt;<b>option</b>
[value=<i>exprstring</i>]&nbsp;[selected]&nbsp;[default]&nbsp;...&gt;text&lt;/<b>option</b>&gt;</font>
<br> Create a form selection option. This tag must be nested within a
<b>select</b> tag. The <b>text</b> optional parameter is evaluated and
emitted in the body of the tag. It can also be provided in the body of the
tag, as you might be used to seeing in HTML.
</li> <p>
<li><font face=courier>&lt;<b>radiolist</b>
name=<i>exprstring</i>&nbsp;data=<i>expr</i>&nbsp;[checked=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;...&gt;...&lt;/<b>select</b>&gt;</font>
<br> Create multiple radio buttons from <b>data</b>, which should be an iterable of
(description, value) pairs.
</li><p>
<li><font face=courier>&lt;<b>checkboxlist</b>
name=<i>exprstring</i>&nbsp;data=<i>expr</i>&nbsp;[checked=<i>exprstring</i>]&nbsp;[default=<i>exprstring</i>]&nbsp;...&gt;...&lt;/<b>select</b>&gt;</font>
<br> Create multiple checkboxes from <b>data</b>, which should be an iterable of
(description, value) pairs.
</li><p>
</ul> <p>
Here is an example of all of these tags in use:
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/formtag.spy</b></font>
</td></tr><tr><td>
  <font face=courier>
    <pre style='font-family: courier,monospace; font-size: small'><font color="#000000"><b><font color="#229922">&lt;spy:parent title=&quot;Form tag example&quot; /&gt;</font>

<font color="#229922">&lt;f:form&gt;</font>

&lt;h2&gt;Primitive controls&lt;/h2&gt;

&lt;div class=&quot;simpleform&quot;&gt;
  <font color="#229922">&lt;f:text name=&quot;mytext&quot; label=&quot;Text&quot; default=&quot;some text&quot; size=10 maxlength=30 /&gt;</font>

  <font color="#229922">&lt;f:password name=&quot;mypass&quot; label=&quot;Password&quot; default=&quot;secret&quot; /&gt;</font>

  <font color="#229922">&lt;f:textarea name=&quot;mytextarea&quot; label=&quot;Textarea&quot; default=&quot;rimon&quot; rows=2 cols=50&gt;</font><font color="#229922">&lt;/f:textarea&gt;</font>

  &lt;label for=&quot;mycheck&quot;&gt;Checkbox&lt;/label&gt;<font color="#229922">&lt;f:checkbox name=mycheck value=check1 /&gt;</font>

  &lt;label for=&quot;myradio1&quot;&gt;Radio option 1&lt;/label&gt;<font color="#229922">&lt;f:radio name=myradio value=option1 /&gt;</font>
  &lt;label for=&quot;myradio2&quot;&gt;Radio option 2&lt;/label&gt;<font color="#229922">&lt;f:radio name=myradio value=option2 /&gt;</font>
&lt;/div&gt;

&lt;div style=&quot;clear: both&quot;&gt;
  &lt;h2 style=&quot;padding-top: 1em;&quot;&gt;Compound controls&lt;/h2&gt;
  <font color="#ff7448">[[-- a simple data source for the compound controls -- in practice