Skip to content
doc-single.html 270 KiB
Newer Older
Thorsten Eggeling's avatar
Thorsten Eggeling committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <style type="text/css"><!--
  body {
    font-family: arial,helvetica;
  }

  #sidebar table {
  }
  #sidebar td {
    background-color: #eeeeff;
  }

  #sidebar p {
    margin: 0;
    padding: 0;
  }

  #sidebar div {
    margin: 0px;
    margin-bottom: 5px;
    padding-left: 0.5em;
    padding-right: 0.5em;
    width: 100%;
  }
  #sidebar h2 {
    font-family: sans-serif;
    margin: 0px;
    width: 100%;
    font-size: 150%;
    background-color: #6622cc;
    color: white;
    text-align: center;
  }
  #sidebar h3 {
    margin: 0px;
    font-size: 130%;
  }
  #sidebar ul a {
    font-style: bold;
  }

  #sidebar ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
  }

	.code {
	  border: 2px dotted;

	  font-family: Courier,monospace;
	  font-size: 90%;

	  background-color: #E0E0E0;
	  margin-left: 10;
	  margin-right: 10;
	  padding-left: 10;
	  padding-right: 10;
	  padding-top: 0;
	  padding-bottom: 10;
	}
    a { text-decoration: none; color: #0000cc }
    a:hover { text-decoration: underline; color: #0000cc; }
  --></style>
<title>Spyce - Python Server Pages (PSP)</title>
  <meta NAME="LANGUAGE" CONTENT="en-US">
  <meta NAME="RATING" CONTENT="GENERAL">
  <meta NAME="ROBOTS" CONTENT="ALL">
  <meta name="abstract" content="Spyce is a server-side language that supports simple and efficient Python-based dynamic HTML generation. Those who like Python and are familiar with JSP, or PHP, or ASP, should have a look at Spyce.">
  <meta name="description" content="Spyce - Python Server Pages: a server-side language that supports simple and efficient Python-based dynamic HTML generation.">
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta HTTP-EQUIV="Refresh" CONTENT="1800">
  <meta HTTP-EQUIV="Revisit-After" CONTENT="15 days">
  <link rel="icon" href="spycefav.ico" type="image/x-icon">
  <link rel="shortcut icon" href="spycefav.ico" type="image/x-icon">
</head>

<body bgcolor="#ffffff">

<table border=0 cellspacing=0 cellpadding=0 width="100%"><tr><td valign=top>

<!-- index -->
<div style="text-align:center">
<a href="http://spyce.sourceforge.net"><img src="/spyce.gif" border=0 alt="spyce" width=58 height=70></a>
</div>

<table id=sidebar width=250px>
<tr><td>

<h2>Download</h2>
<div>
  <h3>Spyce 2.1</h3>
  <center style="font-size: small">
  <a href=/docs/whats-new-2-1.html>what's new</a>
  &nbsp;&nbsp;&nbsp;
  <a href=http://svn.sourceforge.net/svnroot/spyce/branches/spyce-2.1/CHANGES>changelog</a>
  &nbsp;&nbsp;&nbsp;
  <a href=/docs/license.html>license</a>
  </center>
  <center><a href=/docs/get.html><b>DOWNLOAD</b></a></center>
</div>

<h2>Community</h2>
<div>
  <b>Discussion list signup</b>:
  <FORM name=list1 Method=POST ACTION="https://lists.sourceforge.net/lists/subscribe/spyce-users">
  <INPUT type="Text" name="email" size="30" value=""> <a href="javascript:document.list1.submit()">Go</a>
  </FORM>

  <b>Announcement list signup</b>:
  <FORM name=list2 Method=POST ACTION="https://lists.sourceforge.net/lists/subscribe/spyce-announce">
  <INPUT type="Text" name="email" size="30" value=""> <a href="javascript:document.list2.submit()">Go</a>
  </FORM>
</div>

<h2>Documentation</h2>
<div>
<ul>
  <li><a href=/docs/doc-intro.html>introduction</a>
  <li><a href=/docs/doc-lang.html>language</a>
  <li><a href=/docs/doc-runtime.html>runtime</a>
  <li><a href=/docs/doc-mod.html>modules</a>
  <li><a href=/docs/doc-tag.html>tags</a>
  <li><a href=/docs/doc-conf.html>install</a>
  <li><a href=/docs/eg.html>examples list</a>
</div>

<h2>Other</h2>
<div>
<ul>
  <li><a href=http://sourceforge.net/projects/spyce>Sourceforge project</a>
  <li><a href=/docs/mail.html>"Spyce Powered"</a>
  <li><a href=/docs/links.html>Resources</a>
  <li><a href=http://spyced.blogspot.com/>Spyced blog</a>
</ul>
</div>

</td></tr>
</table>

</td> 
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td width="100%" valign=top>

<!-- page title -->
<table border=0 width="100%"><tr>
  <td align=right nowrap valign=bottom>
    <a href=/index.html>home</a>
    &nbsp;&nbsp;&nbsp;
    <a href=/docs/doc.html>documentation</a>
    &nbsp;&nbsp;&nbsp;
    <a href=/docs/get.html>download</a>
    &nbsp;&nbsp;&nbsp;
  </td>
  <td align=right nowrap valign=bottom width=1>
    <img alt="Spyce logo" src="/spyce2.png">
  </td>
</tr></table>

<br><br>
<b><font face="arial, helvetica" size="+1"><big>Documentation</big></font></b><br clear=all>
<hr>

<!-- body -->






<center>
<big><b>Spyce - Python Server Pages (PSP) <br>
<big>User Documentation</big></b></big><p>
Release 2.1<p>
</center>
<center><b>
 [ <a href="doc.html">Multi-Page Format</a> ]
</b></center>
<p>
<font color="#ee0000"><b>TABLE OF CONTENTS</b><br></font>
<ul>

<li>1. <a href="#intro">Introduction</a></li>

<ul>

<li>1.1. <a href="#intro_rationale">Rationale / competitive analysis</a></li>

<li>1.2. <a href="#intro_design">Design Goals</a></li>

</ul>

<li>2. <a href="#lang">Language</a></li>

<ul>

<li>2.1. <a href="#lang_string">Plain HTML and Active Tags</a></li>

<li>2.2. <a href="#lang_comment">Spyce Comments</a></li>

<li>2.3. <a href="#lang_directive">Spyce Directives</a></li>

<li>2.4. <a href="#lang_stmt">Python Statements</a></li>

<li>2.5. <a href="#lang_chunk">Python Chunks</a></li>

<li>2.6. <a href="#lang_chunkc">Python Class Chunks</a></li>

<li>2.7. <a href="#lang_expr">Python Expressions</a></li>

<li>2.8. <a href="#lang_lambda">Spyce Lambdas</a></li>

<li>2.9. <a href="#lang_asp">ASP/JSP syntax</a></li>

</ul>

<li>3. <a href="#runtime">Runtime</a></li>

<ul>

<li>3.1. <a href="#runtime_except">Exceptions</a></li>

<li>3.2. <a href="#runtime_transform">Code Transformation</a></li>

<li>3.3. <a href="#runtime_web">Dynamic Content</a></li>

<li>3.4. <a href="#runtime_static">Static Content</a></li>

<li>3.5. <a href="#runtime_cmdline">Command line</a></li>

<li>3.6. <a href="#runtime_common">Configuration</a></li>

<li>3.7. <a href="#runtime_util">Server utilities</a></li>

<ul>

<li>3.7.1. <a href="#runtime_util_scheduler">The Spyce scheduler</a></li>

<li>3.7.2. <a href="#runtime_util_su">spyceUtil</a></li>

</ul>

<li>3.8. <a href="#mod">Modules</a></li>

<ul>

<li>3.8.1. <a href="#mod_db">DB (implicit)</a></li>

<li>3.8.2. <a href="#mod_request">Request (implicit)</a></li>

<li>3.8.3. <a href="#mod_response">Response (implicit)</a></li>

<li>3.8.4. <a href="#mod_redirect">Redirect</a></li>

<li>3.8.5. <a href="#mod_cookie">Cookie</a></li>

<li>3.8.6. <a href="#mod_session">Session</a></li>

<li>3.8.7. <a href="#mod_pool">Pool</a></li>

<li>3.8.8. <a href="#mod_transform">Transform</a></li>

<li>3.8.9. <a href="#mod_compress">Compress</a></li>

<li>3.8.10. <a href="#mod_include">Include</a></li>

<li>3.8.11. <a href="#mod_internal">Internal modules</a></li>

<ul>

</ul>

<li>3.8.12. <a href="#mod_new">Writing Modules</a></li>

</ul>

<li>3.9. <a href="#tag">Tags</a></li>

<ul>

<li>3.9.1. <a href="#tag_core">Core</a></li>

<li>3.9.2. <a href="#tag_form">Form</a></li>

<li>3.9.3. <a href="#tag_handlers">Active Handlers</a></li>

<li>3.9.4. <a href="#tag_new2">Writing Tag Libraries</a></li>

<li>3.9.5. <a href="#tag_new">Writing Tag Libraries the hard way</a></li>

</ul>

<li>3.10. <a href="#conf">Installation</a></li>

<ul>

<li>3.10.1. <a href="#conf_overview">Overview</a></li>

<li>3.10.2. <a href="#conf_proxy">Web Server</a></li>

<li>3.10.3. <a href="#conf_source">CGI/FastCGI installation</a></li>

<li>3.10.4. <a href="#conf_modpython">Mod_Python</a></li>

<li>3.10.5. <a href="#conf_windows">Notes for Windows</a></li>

<li>3.10.6. <a href="#conf_rpm">Notes on RPM installation</a></li>

<li>3.10.7. <a href="#conf_apache">Notes on Apache integration</a></li>

<li>3.10.8. <a href="#conf_next">Starting your first project</a></li>

</ul>

<li>3.11. <a href="#runtime_prog">Programmatic Interface</a></li>

<ul>

<li>3.11.1. <a href="#runtime_prog_basicUsage">Basic usage</a></li>

<li>3.11.1. <a href="#runtime_prog_passingParameters">Passing parameters</a></li>

<li>3.11.1. <a href="#runtime_prog_requestAndResponse">Customized Request/Response classes</a></li>

<li>3.11.1. <a href="#runtime_prog_example">Example</a></li>

</ul>

</ul>

<li>4. <a href="#add">Addenda</a></li>

<ul>

<li>4.1. <a href="#add_perf">Performance</a></li>

<li>4.2. <a href="#add_history">History</a></li>

</ul>

</ul>

<hr>

<p><big><a name="intro"></a><b>1. <font color=#ee0000>INTRODUCTION</font></b></big><p>


This document aims to be the authoritative source of
information about Spyce, usable as a comprehensive refence, a user guide and a
tutorial. It should be at least skimmed from beginning to end,
so you have at least an idea of the functionality available and can refer
back for more details as needed. <p>

Spyce is a server-side language that supports elegant and
efficient Python-based dynamic HTML generation.
Spyce allows embedding Python in pages similar to how JSP embeds Java,
but Spyce is far more than a JSP clone.  Out of the box, Spyce provides
development as rapid as other modern frameworks like Rails, but with an
cohesive design rather than a morass of special cases.

<p>
Spyce's modular design makes it very flexible
and extensible. It can also be used as a command-line utility for static text
pre-processing or as a web-server proxy.
<p>
Spyce's <a
href="#add_perf">performance</a> is comparable to the
other solutions in its class. <p>
<b>Note:</b> This manual assumes a knowledge of Python and focusses
exclusively on Spyce. If you do not already know Python, it is easy to
learn via this short <a
href="http://www.python.org/doc/current/tut/tut.html">tutorial</a>, and has
extensive <a href="http://www.python.org/doc/current/">documentation</a>.<p>
<big><a name="intro_rationale"></a><b>1.1. <font color=#ee0000>Rationale / competitive analysis</font></b></big><p>


<i>This section is somewhat dated. We plan to update it soon.</i>
<p>
A natural question to ask is why one would choose Spyce over JSP, ASP, PHP,
or any of the other HTML scripting languages that
perform a similar function. We compare Spyce with an array of exising tools:
<ul>
<li><i><b>Java Server Pages, JSP,</b></i> is a widely popular, effective and
well-supported solution based on Java Servlet technology. Spyce differs from
JSP in that it embeds Python code among the HTML, thus providing a number of
advantages over Java.
<ul>
<li>Python is a high-level scripting language,
where rapid prototyping is syntactically easier to perform.
<li>There is no need for a separate "expression langauge" in Spyce;
Python is well-suited for both larger modules and active tag scripting.
<li>Python
is interpreted and latently typed, which can be advantageous for
prototyping, especially in avoiding unnecessary binary incompatibility of
classes for minor changes.
<li>Spyce code is of first-order in the Spyce
language, unlike JSP, which allows you to create useful Spyce lambda
functions.
<li>Creating new active tags and modules is simpler in
Spyce than in JSP.
<li>Spyce is better-integrated than JSP; to get similar functionality
in JSP, you have to add JSF (Java Server Faces) and Tiles, or
equivalents.
</ul>
<p>
</li>
<li><i><b>PHP</b></i> is another popular webserver module for dynamic
content generation. The PHP interpreter engine and the language itself were
explicitly designed for the task of dynamic HTML generation, while Python is
a general-purpose scripting language.
<ul>
<li>Spyce leverages from the extensive
development effort in Python: since any Python library can be imported and
reused, Spyce does not need to rebuild many of the core function libraries
that have been implemented by the PHP project.
<li>Use of Python
often simplifies integration of Spyce with existing system environments.
<li>Spyce code is also first-order in the Spyce language and Spyce supports
active tags.
<li>Spyce is modular in its design, allowing
users to easily extend its base functinality with add-on modules.
<li>The Spyce engine can be run from the command-line, which allows
Spyce to be used as an HTML preprocessor.
</ul>
Spyce,
like PHP, can run entirely within the process space of a webserver or via
CGI (as well as other web server adapters), and has been benchmarked to be
competitive in <a href="#add_perf">performance</a>. </li> <p>
<li><i><b>ASP.NET</b></i> is a Microsoft technology
popular with Microsoft Internet Information Server (IIS) users. Visual
Basic .NET and C# are both popular implementation languages.
<ul>
<li>Spyce provides the power of the ASP.NET "component" development style
without trying to pretend that web applications live in a stateful,
event-driven environment. This is a leaky abstraction that causes
ASP.NET to have a steep learning curve while the user learns
where the rough edges are.
<li>ASP.NET is not well-supported outside the IIS environment. Spyce can
currently run as a standalone or proxy server, under mod_python (Apache),
or under CGI and <a
href="http://www.fastcgi.com">FastCGI</a>, which are
supported in the majority of web server environments. Adapters have also
been written for Xitami, Coil, Cheetah -- other web servers and frameworks.
<li>Spyce is open-source, and free.
</ul>
</li>
<p>
<li><i><b>WebWare with Python Server Pages, PSP,</b></i> is another
Python-based open-source development. PSP is similar in design to the Spyce
language, and shares many of the same benefits. Some important differences
include
<ul>
<li>Spyce supports both
Python chunks (indented Python) as well as PSP-style statements (braced
Python).
<li>Spyce supports active tags and component-based development
<li>Spyce code is first-order in the Spyce language
</ul>
PSP is also an integral part of
WebWare, an application-server framework similar to Tomcat Java-based
application server of the Apache Jakarta project. Spyce is to WebWare as JSP
is to Tomcat. Spyce is far simpler to install and run than WebWare (in the
author's humble opinion), and does not involve notions such as application
contexts. It aims to do only one thing well: provide a preprocessor and
runtime engine for the dynamic generation of HTML using embedded Python.
</li> <p>
<li><i><b>Zope</b></i> is an object-oriented open-source application server,
specializing in "content management, portals, and custom applications." Zope
is the most mature Python web application development environment, but
to a large degree suffers from
<a href=http://en.wikipedia.org/wiki/Second-system_effect>second-system syndrome</a>.
In the author's opinion, Zope is to a large degree responsible for the
<a href=http://www.python.org/moin/WebProgramming>large number of python
web environments</a>: a few years ago, it was de rigeur for talented programmers
to try Zope, realize it was a mess, and go off to write their own framework.
<p>
Zope provides a scripting language called DHTML and can call
extensions written in Perl or Python. Spyce embeds Python directly in the
HTML, and only Python. It is an HTML-embedded language, not an application
server. </li> <p>
</ul>
Spyce strikes a unique balance between power and simplicity.
Many users have said that this
is "exactly what they have been waiting for". Hopefully, this is the correct
point in the design space for your project as well.
<p>
<big><a name="intro_design"></a><b>1.2. <font color=#ee0000>Design Goals</font></b></big><p>


As a Spyce user, it helps to understand the broad design goals of this tool.
Spyce is designed to be:
<ul>
<li><b>Minimalist:</b> The philosophy behind the design of Spyce is only
to include features that particularly enhance its functionality over the
wealth that is already available from within Python. One can readily import
and use Python modules for many functions, and there is no need to recode
large bodies of functionality. </li> <p>
<li><b>Powerful:</b> Spyce aims to free the programmer from as much
"plumbing"-style drudgery as possible through features such as
<a href="#tag_handlers">Active Handlers</a>
and reusable <a href="#tag">Active Tags</a>.</li><p>
<li><b>Modular:</b> Spyce is built to be extended with
<a href="#mod">Spyce modules</a> and
<a href="#tag">Active Tags</a>
that provide additional functionality over the core engine
capabilities and standard Python modules. New features in the core engine
and language are rationalised against the option of creating a new module or
a new tag library. Standard Spyce modules and tag libraries are those that
are considered useful in a general setting and are included in the default
Spyce distribution. Users and third-parties are encouraged to develop their
own Spyce modules. </li> <p>
<li><b>Intuitive:</b> Obey user expectations. Part of this is avoiding
special cases.</li> <p>
<li><b>Convenient:</b> Using Spyce should be made as efficient as possible.
This, for example, is the reason behind the choice of <font
face=courier>[[</font> as delimeters over alternatives such as <font
face=courier>&lt;?</font> (php) and <font face=courier>&lt;%</font> (jsp).
(However, ASP/JSP-style delimeters are also supported, so if you're
used to that style and like it, feel free to continue using it with Spyce.)
Functions and
modules are also designed with as many defaults as possible.
There are no XML configuration files in Spyce.
</li> <p>
<li><b>Single-purpose:</b> To be the best, most versatile, wildly-popular
Python-based dynamic HTML engine. Nothing more; nothing less. </li> <p>
<li><b>Fast:</b> <a href="#add_perf">Performance</a> is
important. It is expected that Spyce will perform comparably with any other
dynamic, scripting solutions available.
</li> <p>
</ul> <p>
Now, let's start using Spyce... <p>

<p><big><a name="lang"></a><b>2. <font color=#ee0000>LANGUAGE</font></b></big><p>


The basic structure of a Spyce script is an HTML file with embeddings. There
are six types of possible embeddings among the plain HTML text:
<ul>
<li><font face=courier><b>&lt;</b><a href="#lang_string">taglib:name</a> attr1=val1&nbsp;...<b>&gt;</b></font>
<br><i>Active tags may include presentation and action code.</i>
<li><font face=courier><b>[[--</b>&nbsp;<a href="#lang_comment">Spyce comment</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>--]]</b></font>
<br><i>Enclosed code is elided from the compiled Spyce class.</i>
<li><font face=courier><b>[[\</b>&nbsp;&nbsp;<a href="#lang_chunk">Python chunk</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>]]</b></font>
<br><i>Embed python in your code.</i>
<li><font face=courier><b>[[!</b>&nbsp;&nbsp;<a href="#lang_chunkc">Python class chunk</a>&nbsp;&nbsp;<b>]]</b></font>
<br><i>Like chunks, but at the class level rather than the spyceProcess method.</i>
<li><font face=courier><b>[[</b>&nbsp;&nbsp;&nbsp;<a href="#lang_stmt">Python statement(s)</a>&nbsp;&nbsp;<b>]]</b></font>
<br><i>Like chunks, but may include braces to indicate that the block should continue after the ]].</i>
<li><font face=courier><b>[[=</b>&nbsp;&nbsp;<a href="#lang_expr">Python expression</a>&nbsp;&nbsp;&nbsp;&nbsp;<b>]]</b></font>
<br><i>Output the result of evaluating the given expression.</i>
<li><font face=courier><b>[[.</b>&nbsp;&nbsp;<a href="#lang_directive">Spyce directive</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>]]</b></font>
<br><i>Pass options to the Spyce compiler.</i>
<li><font face=courier><b>[[spy</b>&nbsp;&nbsp;<a href="#lang_lambda">lambda</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>]]</b></font>
<br><i>Allows dynamic compilation of Spyce code to a python function.</i>
</ul>
Each Spyce tag type has a
unique beginning delimeter, namely <font face=courier><b>[[</b></font>, <font
face=courier><b>[[\</b></font>, <font face=courier><b>[[=</b></font>, <font
face=courier><b>[[.</b></font> or <font face=courier><b>[[--</b></font>. All
tags end with <font face=courier><b>]]</b></font>, except comment tags, which
end with <font face=courier><b>--]]</b></font>.
<p>
Since
<font face=courier><b>[[</b></font> and
<font face=courier><b>]]</b></font>
are special Spyce delimeters, one would escape them as
<font face=courier><b>\[[</b></font> and
<font face=courier><b>\]]</b></font>
for use in HTML text. They can not be escaped within Python code, but the
string expressions
<font face=courier><b>("["*2)</b></font> and
<font face=courier><b>("]"*2)</b></font>, or equivalent expressions,
can be used instead, or the brackets can be conveniently separated with a
space in the case of list or slicing expressions. <p>
<big><a name="lang_string"></a><b>2.1. <font color=#ee0000>Plain HTML and Active Tags</font></b></big><p>


Static plain HTML strings are printed as they are encountered. Depending on
the <a href="#lang_directive">compacting</a> mode of the
Spyce compiler, some whitespace may be eliminated. The Spyce <a
href="#mod_transform">transform</a> module, for example, may
further pre-processes this string, by inserting transformations into the
output pipe. This is useful, for example, for dynamic compression of the
script result. <p>
The Spyce language supports <a href="">tag libraries</a>.
Once a tag library is imported under some name, <i>mytags</i>, then all static
HTML tags of the form <font
face=courier>&lt;<i>mytags</i>:foo&nbsp;...&nbsp;&gt;</font> become "active".
That is, code from the tag library is executed at that point in the document.
Tags can control their output, conditionally skip or loop the execution of
their bodies, and can interact with other active tags in the document. They
are similar, in spirit and functionality, to JSP tags. Tag libraries and <a
href="">modules</a> (discussed later) can both
considerably reduce the amount of code on a Spyce page, and increase code
reuse and modularity. <p>
<big><a name="lang_comment"></a><b>2.2. <font color=#ee0000>Spyce Comments</font></b></big><p>


<b>Syntax: <font face=courier>[[-- comment --]]</font></b> <p>
Spyce comments are ignored, and do not produce any output, meaning that they
will not appear at the browser even in the HTML source. The first line of a
Spyce file, if it begins with the characters <b>#!</b>, is also considered a
comment, by Unix scripting convention. Spyce comments do <i>not</i> nest. <p>
<big><a name="lang_directive"></a><b>2.3. <font color=#ee0000>Spyce Directives</font></b></big><p>


<b>Syntax: <font face=courier>[[. directive ]]</font></b>
<p>
Spyce directives directly affect the operation of the Spyce compiler. There
is a limited set of directives, listed and explained below:
<ul>
<li><b><font face=courier>
[[.<b>compact</b>&nbsp;mode=<i>mode</i>]] </font>:</b><br>
Spyce can output the static HTML strings in various modes of compaction,
which can both save bandwidth and improve download times without visibly
affecting the output. Compaction of static HTML strings is performed once
when the input Spyce file is compiled, and there is no additional run-time
overhead beyond that. Dynamically generated content from Python code tags
and expressions is not compacted nor altered in any way. Spyce can operate
in one of the compaction modes listed below. One can use the <b>compact</b>
tag to change the compaction mode from that point in the file forwards. <p>
<ul>
<li><b>off</b>: No compaction is performed. Every space and newline in the
static HTML strings is preserved. </li> <p>
<li><b>space</b>: Space compaction involves reducing any consecutive runs
of spaces or tabs down to a single space. Any spaces or tabs at the
beginning of a line are eliminated. These transformations will not affect
HTML output, barring the &lt;pre&gt; tag, but can considerably reduce the
size of the emitted text. </li> <p>
<li><b>line</b>: Line compaction eliminates any (invisible) trailing
whitespace at the end of lines. More significantly it improves the indented
presentation of HTML, by ignoring any lines that do not contain any static
text or expression tags. Namely, it removes all the whitespace, including
the line break, surrounding the code or directives on that line. This
compaction method usually "does the right thing", and produces nice HTML
without requiring tricky indentation tricks by the developer. It is,
therefore, the <b>initial</b> compaction mode. </li><p>
<li><b>full</b>: Full compaction applies both space and line compaction. If
the optional mode attribute is omitted, full compaction mode is the
<b>default</b> value assumed. </li><p>
</ul>
</li><p>
<li><b><font face=courier>
[[.<b>import</b>&nbsp;name=<i>name</i>&nbsp;from=<i>file</i>&nbsp;as=<i>name</i>&nbsp;args=<i>arguments</i>]] </font>:</b><br>
The import directive loads and defines a Spyce module into the global
context. (The <font face=courier>[[.module&nbsp;...&nbsp;]]</font>directive
is synonymous.) A Spyce <a href="#mod">module</a> is a
Python file, written specifically to interact with Spyce. The <b>name</b>
parameter is required, specifying the name of the Python class to load. The
<b>file</b> parameter is optional, specifying the file where the named class
is to be found. If omitted, file will equal <font
face=courier><i>name</i>.py</font>. The file path can be absolute or
relative. Relative paths are scanned in the Spyce home, user-configurable <a
href="#runtime_common">server path</a> directories and current
script directory, in that order. Users are encouraged to name or prefix their
modules uniquely so as not to be masked by system modules or tag libraries.
The <b>as</b> parameter is optional, and specifies the name under which the
module will be installed in the global context. If omitted, this parameter
defaults to the name parameter. Lastly, the optional <b>args</b> parameter
provides arguments to be passed to the module initialization function. All
Spyce modules are <b>start()</b>ed before Spyce processing begins,
<b>init()</b>ed at the point where the directive is placed in the code, and
<b>finish()</b>ed after Spyce processing terminates. It is convention to
place modules at, or near, the very top of the file unless the location of
initialization is relevant for the functioning of the specific module. <p>
<b><font face=courier>
[[.<b>import</b>&nbsp;names="<i>name1,name2,...</i>"]] </font>:</b><br>
An alternative syntax allows convenient loading of multiple Spyce modules.
One can not specify non-standard module file locations, nor rename the
modules using this syntax. </li><p>
<li><b><font face=courier>
[[.<b>taglib</b>&nbsp;name=<i>name</i>&nbsp;from=<i>file</i>&nbsp;as=<i>name</i>]] </font>:</b><br>
The taglib directive loads a Spyce tag library. A Spyce <a
href="#tag">tag library</a> is a Python file, written
specifically to interact with Spyce. The <b>name</b> parameter specifies
the name of the Python class to load if using a 1.x-style taglib;
otherwise it is ignored. The <b>file</b> parameter is
optional, specifying the file where the named class is to be found. If
omitted, file will equal <font face=courier><i>name</i>.py</font>. The file
path can be absolute or relative. Relative paths are scanned in the Spyce
home, user-configurable <a href="#runtime_common">server
path</a> directories and current script directory, in that order. Users are
encouraged to name or prefix their tag libraries uniquely so as not to be
masked by system tag libraries and modules. The <b>as</b> parameter is
optional, and specifies the unique tag prefix that will be used to identify
the tags from this library. If omitted, this parameter defaults to the name
parameter. It is convention to place tag library directives at, or near, the
very top of the file. The tags only become active after the point of the tag
library directive. <p>
Also note that the configuration parameter <i>globaltags</i> allows you
to set up tag libraries globally, freeing you from having to specify the
taglib directive on each page that uses a tag. By default, globaltags
installs core under the spy: prefix, and form under the f: prefix.
(Tag libraries specified in globaltags are only loaded if the Spyce compiler
determines they are actually used on the page, so there is no performance
difference between globaltags and manually setting up taglib for each page.)
<p>There are some additional directives that are only legal when
<a href="#tag_new2">defining an active tag library</a>.
</ul> <p>
It is important to note that Spyce directives are processed at <i>compile</i>
time, not during the execution of the script, much like directives in C, and
other languages. In other words, they are processed as the Python code for the
Spyce script is being produced, not as it is being executed. Consequently, it
is not possible to include runtime values as parameters to the various
directives.<p>
<big><a name="lang_stmt"></a><b>2.4. <font color=#ee0000>Python Statements</font></b></big><p>


<b>Syntax: <font face=courier>[[ statement(s) ]]</font></b> <p>
The contents of a code tag is one or more Python statements. The statements
are executed when the page is emitted. There will be no output unless the
statements themselves generate output. <p>
The statements are separated with semi-colons or new lines, as in regular
Python scripts. However, unlike regular Python code, Python statements <i>do
<b>not</b> nest based on their level of indentation</i>. This is because
indenting code properly in the middle of HTML is difficult on the developer.
To alleviate this problem, Spyce supports a slightly modifed Python syntax:
proper nesting of Spyce statements is achieved using begin- and end-braces:
<font face=courier><b>{</b></font> and <font face=courier><b>}</b></font>,
respectively. These <b>MUST</b> be used, because the compiler regenerates the
correct indentation based on these markers alone. Even single-statement blocks
of code must be wrapped with begin and end braces. (If you prefer to use
Python-like indentation, read about <a
href="#lang_chunk">chunks</a>). <p>
The following Spyce code, from the <font face=courier>Hello World!</font>
example above: <p>

<table align=center border=0><tr><td>
<font face=courier>
<b><pre>
  [[ for i in range(10): <font color=red>{</font> ]]
    [[=i]]
  [[ <font color=red>}</font> ]]
</pre></b>
</font>
</td></tr></table>
<p>
produces the following indented Python code:<p>

<table align=center border=0><tr><td>
<font face=courier>
<b><pre>
  for i in range(10):
    response.writeStatic('  ')
    response.writeExpr(i)
    response.writeStatic('\n')
</pre></b>
</font>
</td></tr></table>
<p>
Without the braces, the code produced would be unindented and, in this case,
also invalid: <p>

<table align=center border=0><tr><td>
<font face=courier>
<b><pre>
  for i in range(10):
  response.writeStatic('  ')
  response.writeExpr(i)
  response.writeStatic('\n')
</pre></b>
</font>
</td></tr></table>
<p>
Note how the indentation of the expression does not affect the indentation of
the Python code that is produced; it merely changes the number of spaces in
the <font face=courier>writeStatic</font> string. Also note that unbalanced
open and close braces within a single tag are allowed, as in the example
above, and they modify the indentation level outside the code tag. However,
the braces must be balanced across an entire file. Remember: inside the <font
face=courier>[[&nbsp;...&nbsp;]]</font> delimiters, <b>braces are always
required</b> to change the indentation level. <p>
<big><a name="lang_chunk"></a><b>2.5. <font color=#ee0000>Python Chunks</font></b></big><p>


<b>Syntax: <font face=courier>[[\ Python chunk ]]</font></b>
<p>
There are many Python users that experience anguish, disgust or dismay upon
reading the previous section: "Braces!? Give me real, indented Python!". These
intendation zealots will be more comfortable using Python chunks, which is why
Spyce supports them. Feel free to use Spyce statements or chunks
inter-changeably, as the need arises.<p>
A Python chunk is straight Python code, and the <i>internal</i> indentation is
preserved. The entire block is merely outdented (or indented) as a whole, such
that the first non-empty line of the block matches the indentation level of
the context into which the chunk was placed. Thus, a Python chunk can not
affect the indentation level outside its scope, but internal indentation is
fully respected, relative to the first line of code, and braces (<font
face=courier>{</font>, <font face=courier>}</font>) are not required, nor
expected for anything but Python dictionaries. Since the first line of code is
used as an indentation reference, it is recommended that the start delimeter
of the tag (i.e. the <font face=courier>[[\</font>) be placed on its own
line, above the code chunk, as shown in the following example: <p>

<table align=center border=0><tr><td>
<font face=courier>
<b><pre>[[\
    def printHello(num):
      for i in range(num):
        response.write('hello&lt;br&gt;')

    printHello(5)
]]</pre></b>
</font>
</td></tr></table>
<p>
Naturally, one should <i>not</i> use braces here for purposes of indentation,
only for Python dictionaries. Additional braces will merely generate Python
syntax errors in the context of chunks. To recap: a Python statement tag
should contain braced Python; A Python chunk tag should contain regular
indented Python. <p>
<big><a name="lang_chunkc"></a><b>2.6. <font color=#ee0000>Python Class Chunks</font></b></big><p>


<b>Syntax: <font face=courier>[[! Python class chunk ]]</font></b>
<p>
Behind the scenes, your Spyce files are compiled into a class called <font
face=courier>spyceImpl</font>. Your Spyce script runs in a method of this class
called <font face=courier>spyceProcess</font>. Class chunks allow you to
specify code to be placed inside the class, but outside the main method,
analogously to the "&lt;%!" token in JSP code. (If you would like to
see your Spyce file in compiled Python form, use the following command-line:
<font face=courier><b>spyce.py -c myfile.spy</b></font>.) <p>
<p>
This is primarily useful when defining active
handlers without using a separate .py file: <a href="#tag_handlers">active handlers</a> are the first
thing that the spyceProcess calls, even before any "python chunks."
For a handler callback to be visible at this stage, it needs to be defined
at the class level. Class chunks to the rescue:
<p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/handlerintro.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">[[!
def calculate(self, api, x, y):
    self.result = x * y
]]</font>

<font color="#229922">&lt;spy:parent title=&quot;Active Handler example&quot; /&gt;</font>
<font color="#229922">&lt;f:form&gt;</font>
    <font color="#229922">&lt;f:text name=&quot;x:float&quot; default=&quot;2&quot; label=&quot;first value&quot; /&gt;</font>
    <font color="#229922">&lt;f:text name=&quot;y:float&quot; default=&quot;3&quot; label=&quot;second value&quot; /&gt;</font>

    <font color="#229922">&lt;f:submit handler=&quot;self.calculate&quot; value=&quot;Multiply&quot; /&gt;</font>
<font color="#229922">&lt;/f:form&gt;</font>

&lt;p&gt;
Result: <font color="#CC0000">[[= hasattr(self, 'result') and self.result or '(no result yet)' ]]</font>
&lt;/p&gt;
</b></font></pre>
  </font>
  </td></tr><tr><td align=right bgcolor="#cccccc">
    <font face="arial, helvetica" size="-1">
      <b><a href="/docs/examples/handlerintro.spy">Run this code</a></b>
    </font>
</td></tr></table>
 <p>
<big><a name="lang_expr"></a><b>2.7. <font color=#ee0000>Python Expressions</font></b></big><p>


<b>Syntax: <font face=courier>[[= expression ]]</font></b>
<p>
The contents of an expression tag is a Python expression. The result of that
expression evaluation is printed using the its string representation.
The Python object None is special cased to output as the empty string
just as it is in the Python interactive shell. This is almost always
more convenient when working with HTML. (If you really want a literal
string 'None' emitted instead, use response.write in a statement or chunk.)
<p>
The Spyce <a href="#mod_transform">transform</a> module, can
pre-processes this result, to assist with mundane tasks such as ensuring that
the string is properly HTML-encoded, or formatted. <p>
<big><a name="lang_lambda"></a><b>2.8. <font color=#ee0000>Spyce Lambdas</font></b></big><p>


<b>Syntax: <font face=courier>[[spy <i>[params]</i> : <i>spyce lambda code</i> ]]</font></b>
<br>
<b>or: <font face=courier>[[spy! <i>[params]</i> : <i>spyce lambda code</i> ]]</font></b>
<p>
A nice feature of Spyce is that Spyce scripts are first-class members of the
language. In other words, you can create a Spyce lambda (or function) in any
of the Spyce Python elements (statements, chunks and expressions). These can
then be invoked like regular Python functions, stored in variables for later
use, or be passed around as paramaters. This feature is often very useful for
templating (example shown below), and can also be used to implement more
esoteric processing functionality, such as internationalization, multi-modal
component frameworks and other kinds of polymorphic renderers. <p>
It is instructive to understand how these functions are generated. The <font
face="courier">[[spy&nbsp;...&nbsp;:&nbsp;...&nbsp;]]</font> syntax is first
translated during compilation into a call to the define() function of the <a
href="#mod_lambda">spylambda</a> module. At runtime, this
call compiles the Spyce code at the point of its definition, and returns a
function. While the invocation of a Spyce lambda is reasonably efficient, it
is certainly not as fast as a regular Python function invocation. The
spycelambda can be memoized (explained in the <a
href="#mod_lambda">spylambda</a> module section) by using
the <font face=courier>[[spy!&nbsp;...&nbsp;:&nbsp;...&nbsp;]]</font>
syntax. However, even with this optimization one should take care to use
Python lambdas and functions when the overhead of Spyce parsing and invocation
is not needed. <p>
Note that Spyce lambdas do not currently support nested variable scoping, nor
default parameters. The global execution context (specifically, Spyce modules)
of the Spyce lambda is defined at the point of its execution. <p>
<table border=1 align=center>
<tr><td align=left bgcolor="#cccccc">
  <font face="arial, helvetica" size="-1"><b>examples/spylambda.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">[[\
  # table template
  table = <font color="#000000"><b>[[spy! title, data: 
    &lt;table&gt;
      &lt;tr&gt;
        <font color="#0000CC">[[for cell in title: {]]</font>
          &lt;td&gt;&lt;b&gt;<font color="#CC0000">[[=cell]]</font>&lt;/b&gt;&lt;/td&gt;
        <font color="#0000CC">[[}]]</font>
      &lt;/tr&gt;
      <font color="#0000CC">[[for row in data: {]]</font>
        &lt;tr&gt;
          <font color="#0000CC">[[for cell in row: {]]</font>
            &lt;td&gt;<font color="#CC0000">[[=cell]]</font>&lt;/td&gt;
          <font color="#0000CC">[[}]]</font>
        &lt;/tr&gt;
      <font color="#0000CC">[[}]]</font>
    &lt;/table&gt; 
  ]]</b></font>

  # 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' ],
  ]
]]</font>

<font color="#ff7448">[[-- emit web page --]]</font>
&lt;html&gt;&lt;body&gt;
  <font color="#0000CC">[[ table(title, data) ]]</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/spylambda.spy">Run this code</a></b>
    </font>
</td></tr></table>
 <p>
<big><a name="lang_asp"></a><b>2.9. <font color=#ee0000>ASP/JSP syntax</font></b></big><p>


Finally, due to popular demand, because of current editor support and people
who actually enjoy pains in their wrists, the Spyce engine will respect
ASP/JSP-like delimeters. In other words, it will also recognize the following
syntax:
<ul>
<li><font face=courier><b>&lt;%--</b>&nbsp;<a href="#lang_comment">Spyce comment</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>--%&gt;</b></font></li>
<li><font face=courier><b>&lt;%@</b>&nbsp;&nbsp;<a href="#lang_directive">Spyce directive</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>%&gt;</b></font></li>
<li><font face=courier><b>&lt;%</b>&nbsp;&nbsp;&nbsp;<a href="#lang_stmt">Python statement(s)</a>&nbsp;&nbsp;<b>%&gt;</b></font></li>
<li><font face=courier><b>&lt;%\</b>&nbsp;&nbsp;<a href="#lang_chunk">Python chunk</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>%&gt;</b></font></li>
<li><font face=courier><b>&lt;%!</b>&nbsp;&nbsp;<a href="#lang_chunkc">Python class chunk</a>&nbsp;&nbsp;<b>%&gt;</b></font></li>
<li><font face=courier><b>&lt;%=</b>&nbsp;&nbsp;<a href="#lang_expr">Python expression</a>&nbsp;&nbsp;&nbsp;&nbsp;<b>%&gt;</b></font></li>
<li><font face=courier><b>&lt;%spy</b>&nbsp;[parameters]&nbsp;<b>:</b>&nbsp;<a href="#lang_lambda">spyce&nbsp;lambda&nbsp;code</a>&nbsp;<b>%&gt;</b></font></li>
</ul>
The two sets of delimeters may be used interchangeably within the same file,
though for the sake of consistency this is not recommended.

<p><big><a name="runtime"></a><b>3. <font color=#ee0000>RUNTIME</font></b></big><p>


Having covered the Spyce language syntax, we now move to describing the
runtime processing. Each time a request comes in, the cache of compiled Spyce
files is checked for the compiled version of the requisite Spyce file. If one
is not found, the Spyce file is quickly read, transformed, compiled and cached
for future use. <p>
The compiled Spyce is initialized, then processed, then finalized. The
initialization consists of initializing all the Spyce modules. The Spyce file
is executed top-down, until the end is reached or an exception is thrown,
whichever comes first. The finalization step then finalizes each module in
reverse order of initialization, and any buffered output is automatically
flushed. <p>
<big><a name="runtime_except"></a><b>3.1. <font color=#ee0000>Exceptions</font></b></big><p>


The Spyce file is executed top-down, until the end of the file is reached, a
valued is <font face="courier">return</font>ed, or an exception is thrown,
whichever comes first. If the code terminates via an unhandled exception, then
it is caught by the Spyce engine. Depending on the exception type, different
actions are taken:
<ul>
<li><b>spyceDone</b> can be raised at any time to stop the Spyce processing
(without error) at that point. It is often used to stop further output, as
in the example below that emits a binary image file. The spyceDone
exception, however, is more useful for modules writers. In regular Spyce
code one could simply issue a <font face="courier">return</font> statement,