summaryrefslogtreecommitdiff
path: root/CHANGES
blob: 1b6a2df0abace3f364b7bc602034423e35643a91 (plain)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
Please initial your changes (there's a key at bottom) and add a date for each
release
================================================================================

2.0rc7 (unreleased )
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]      
    - extended the #implements directive so an arguments list can be declared in
      the same fashion as #def and #block.

    - tweaked the parser so it's possible to place a comment on the same line as
      a directive without needing to explicitly close the directive first. This
      works regardless of whether or not you added a colon.
      
              self.verify("#if 1:\n$aStr\n#end if\n",
                          "blarg\n")
      
              self.verify("#if 1:   \n$aStr\n#end if\n",
                          "blarg\n")
      
              self.verify("#if 1: ##comment \n$aStr\n#end if\n",
                              "blarg\n")
      
              self.verify("#if 1 ##comment \n$aStr\n#end if\n",
                              "blarg\n")
      
      Previously, that last test would have required an extra # to close the #if 
      directive before the comment directive started:
              self.verify("#if 1 ###comment \n$aStr\n#end if\n",
                              "blarg\n")
      
      Code that makes use of explicit directive close tokens immediately followed by 
      another directive will still work as expected:
      #if test##for i in range(10)# foo $i#end for##end if

  Core changes by MO:
    - WebSafe and the other optional filters in Filters.py now use
      RawOrEncodedUnicode instead of Filter as a base class.  This allows them
      to work with Unicode values containing non-ASCII characters.
          User-written custom filters should inherit from 
      RawOrEncodedUnicode and call the superclass .filter() instead of str().
      str() as of Python 2.4.2 still converts Unicode to string using
      ASCII codec, which raises UnicodeEncodeError if it contains non-ASCII
      characters.
          

2.0rc6 (Feb 4, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]      
    - added a Cheetah version dependency check that raises an assertion if a
      template was compiled with a previous version of Cheetah whose templates
      must be recompiled.

    - made the Cheetah compilation metadata accessible via class attributes in
      addition to module globals

    - major improvement to exception reporting in cases where bad Python syntax
      slips past the Cheetah parser:
      """
         File "/usr/lib/python2.4/site-packages/Cheetah/Template.py", line 792, in compile
           raise parseError
       Cheetah.Parser.ParseError: 
       
       Error in the Python code which Cheetah generated for this template:
       ================================================================================
       
       invalid syntax (DynamicallyCompiledCheetahTemplate.py, line 86)
       
       Line|Python Code
       ----|-------------------------------------------------------------
       84  |        
       85  |        write('\n\n')
       86  |        for i an range(10): # generated from line 4, col 1
                           ^
       87  |            _v = i # '$i' on line 5, col 3
       88  |            if _v is not None: write(_filter(_v, rawExpr='$i')) # from line 5, col 3.
       89  |            write('\n')
       
       ================================================================================
       
       Here is the corresponding Cheetah code:
       
       Line 4, column 1
       
       Line|Cheetah Code
       ----|-------------------------------------------------------------
       2   |#compiler useNameMapper=False
       3   |
       4   |#for i an range(10)
            ^
       5   |  $i
       6   |#end for
       7   |
       """
       
2.0rc5 (Feb 3, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]      
    - fixed a memory leak in Template.compile(), reported by Andrea Arcangeli
    - simplified concurrency locking and compile caching in Template.compile()

  The command line tool (CheetahWrapper.py): 
    - added new option --settings for supplying compiler settings
    - added new option --templateAPIClass to replace the environment var
      CHEETAH_TEMPLATE_CLASS lookup I added in 2.0b1

2.0rc4 (Jan 31, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]      
    - fixed a typo-bug in the compile hashing code in Template.compile() 
    - improved the macros framework and made it possible to implement macros in
      Python code so they can be shared between templates
    - more work on the #i18n directive.  It's now a macro directive.
    - added new Cheetah.Macros package
    - more tests
 
2.0rc3 (Jan 29, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]      
    - added short-form single line versions of all directives that have an #end
      tag, except for #errorCatcher:
         #if, #else, #elif, #unless,
         #for, #while, #repeat,  
	 #try, #except, #finally, 
	 #cache, #raw
 	 #call, #capture

      The #def and #block directives already had single-line versions.
          #if cond: foo
	  #elif cond2: bar
	  #else: blarg
	  
	  #for i, val in enumerate(vals): $i-$val

      Note that if you accidentally leave a colon at the end of one of these
      directives but nothing else follows it, aside from whitespace, the parser
      will treat it as a normal multi-line directive.

      The first leading space after the colon is discarded. Any additional
      spaces will be included in the output.
      
      Also note, if you use the short form versions of #if/#else/#elif you must
      it for all three.  The following is not valid:
          #if cond: foo
	  #elif cond2
	     bar
	  #else: blarg

    - added support for $!silentModePlaceholders
      This is the same as quiet mode in Velocity: 
       http://jakarta.apache.org/velocity/docs/user-guide.html#Quiet%20Reference%20Notation

    - added support for function/method @decorators.  It also works with blocks.
      As in vanilla Python, the @decorator statement must be followed with a
      function/method definition (i.e. #def or #block).

        #from xxx import aDecorator
        ...  
        ...
        #@aDecorator
        #def func
          foo
        #end def

        #@aDecorator
        #def singleLineShortFormfunc: foo

        #@aDecorator
        #block func2
          bar
        #end block

    - added a new callback hook 'handlerForExtendsDirective' to the compiler settings. It
      can be used to customize the handling of #extends directives.  The
      callback can dynamically add import statements or rewrite the baseclass'
      name if needed:
         baseClassName = handler(compiler, baseClassName)
      See the discussion on the mailing list on Jan 25th for more details.

    - changed the default filter to the one that doesn't try to encode Unicode
      It was 'EncodeUnicode' and is now 'RawOrEncodedUnicode'.

    - added optional support for parsing whitespace between the directive start
      token (#) and directive names, per Christophe Eymard's request.  For the
      argument behind this see the mailing list archives for Jan 29th.  This is
      off by default.  You must turn it on using the compiler setting
      allowWhitespaceAfterDirectiveStartToken=True

        #for $something in $another
        #  for $somethin2 in $another2
              blahblah $something in $something2
        #  end for
        #end for
        
    - made the handling of Template.compile()'s preprocessors arg simpler and
      fixed a bug in it.

    - fixed attribute name bug in the .compile() method (it affected the feature
      that allows generated module files to be cached for better exception
      tracebacks)

    - refactored the #cache/CacheRegions code to support abitrary backend cache
      data stores.

    - added MemcachedCacheStore, which allows cache data to be stored in a
      memcached backend.  See http://www.linuxjournal.com/article/7451 and
      http://www.danga.com/memcached/.  This is only appropriate for systems
      running many Python server processes that need to share cached data to
      reduce memory requirements. Don't bother with this unless you actually
      need it. If you have a limited number of Python server processes it is
      much faster, simpler, and more secure to just cache in the memory of each
      process.

      KEEP MEMCACHED'S LIMITED SECURITY IN MIND!!  It has no authentication or
      encryption and will introduce a gaping hole in your defenses unless you
      are careful.  If you are caching sensitive data you should take measures
      to ensure that a) untrusted local system users cannot connect to memcached
      server, b) untrusted external servers cannot connect, and c) untrusted
      users on trusted external servers cannot connect.  Case (a) can be dealt
      with via iptable's owner match module for one way to do this: "iptables -A
      ... -m owner ..."  Cases (b) and (c) can be handled by tunnelling
      memcached network connections over stunnel and implementing stunnel
      authentication with mandatory peer/client certs.

    - some under-the-hood refactoring of the parser
    
    - made it possible to add custom directives, or customize the
      parsing/handling of existing ones, via the compiler settings
      'directiveNamesAndParsers' and 'endDirectiveNamesAndHandlers'
      
    - added a compile-time macro facility to Cheetah. These macros are very
      similar to macros in Lisp:
      http://www.apl.jhu.edu/~hall/Lisp-Notes/Macros.html.  

      As with Lisp macros, they take source code (Cheetah source) as input and
      return source code (again Cheetah source) as output. They are executed at
      compile-time, just like in Lisp and C. The resultant code
      gets executed at run-time.

      The new #defmacro directive allows users to create macros inside the
      source of their templates.  Macros can also be provided via the compiler
      setting 'macroDirectives'. The 'macroDirectives' setting allows you to
      share common macros between templates.  

      The syntax for the opening tag of #defmacro is the same as for #def and
      #block.  It expects a macro name followed by an optional argument list in
      brackets.  A `src` argument is automatically added to the beginning of
      every macro's argument list.  The value of the `src` is the block of
      input source code that is provided during a macro call (see below).  

        #defmacro <macroname>[(argspec)]
 	  <macrobody>
	#end defmacro

      All of Cheetah's syntax is available for use inside macros, but the
      placeholderStartToken is @ instead of $ and the
      directiveStartToken/EndToken is % instead of #.  Any syntax using the
      standard $/# tokens will be treated as plain text and included in the output
      of the macro.

      Here are some examples:
        #defmacro addHeaderFooter
	  header 
	  @src 
	  footer
	#end defmacro

        #defmacro addHeaderFooter(header='h', footer='f')
	  @header 
	  @src 
	  @footer
	#end defmacro

      There is a single-line short form like for other directives:
 		
        #defmacro addHeaderFooter: header @src footer
        #defmacro addHeaderFooter(header='h', footer='f'): @header @src @footer
     
      The syntax for calling a macro is similar to the simplest usage of the
      #call directive:

        #addHeaderFooter
	  Source $code to wrap
	#end addHeaderFooter

        #addHeaderFooter: Source $code to wrap

        #addHeaderFooter header='header', footer='footer: Source $code to wrap


      In Elisp you write
        (defmacro inc (var)
           (list 'setq var (list '1+ var)))
      to define the macro `inc` and write
        (inc x)  
      which expands to 
        (setq x (1+ x))

      In Cheetah you'd write
        #defmacro inc: #set @src +=1
	#inc: $i
      which expands to 
        #set $i += 1
      
        print Template("""\
	#defmacro inc: #set @src +=1
        #set i = 1
        #inc: $i
        $i""").strip()==2
  
    - fixed some bugs related to advanced usage of Template.compile(). These
      were found via new unit tests. No one had actually run into them yet.

    - added the initial bits of an #i18n directive.  It has the same semantics
      as 
        #call self.handleI18n
	  Some $var cheetah source
	#end call
      but has a simpler syntax:
      	#i18n
	  Some $var cheetah source
	#end i18n  

	## single-line short form:
      	#i18n: Some $var cheetah source

      The method it calls, self.handleI18n, is just a stub at the moment, but it
      will soon be a wrapper around gettext.  It currently has one required
      positional argument `message`. I anticipate supporting the following
      optional arguments:

      	   id = msgid in the translation catalog
	   domain = translation domain
	   source = source lang
	   target = a specific target lang
	   comment = a comment to the translation team

	   plural = the plural form of the message
	   n = a sized argument to distinguish between single and plural forms
	   
      #i18n is executed at runtime, but it can also be used in conjunction with
      a Cheetah preprocessor or macro (see above) to support compile time
      translation of strings that don't have to deal with plural forms.
	   
    - added Cheetah.Utils.htmlEncode and Cheetah.Utils.htmlDecode    

    - more docstring text

  Unit tests: [TR]
    - extended the caching tests
    - added tests for the various calling styles of Template.compile()
    - added copies of all the SyntaxAndOutput tests that use a template
      baseclass other than `Template`. This ensures that all syntax & core
      features work with 2.0's support for arbitrary baseclasses.
    - added tests for all the new directives and the new single-line short forms
  
2.0rc2 (Jan 13th, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]      
    - fixed some python 2.4isms that slipped in.  All the tests pass with Python
      2.2 now
    - added lots more docstring content in the Template class
    - made multiline comments gobble whitespace like other directives, per JJ's
      request.  The rather longwinded compiler setting
      gobbleWhitespaceAroundMultiLineComments can be used to go back to the old
      non-gobbling behaviour if needed.
    - added #capture directive to complement the #call directive.  
      #call executes a region of Cheetah code and passes its output into a function call
      #capture executes a region of Cheetah code and assigns its output to a variable
    - extended the compile caching code in Template.compile so it works with the
     'file' arg.
    - added cacheModuleFilesForTracebacks and cacheDirForModuleFiles args to
      Template.compile(). See the docstring for details.
    - misc internal refactoring in the parser
    - improved handling of keyword args in the __init__ method and fixed a
      potential clash between the namespaces and searchList args

  WWW: [TR]
    - added the source for the new Cheetah website layout/content

2.0rc1 (Jan 10, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]    
    - made it possible nest #filter directives
    - added lots more docstring content in the Template class
    - added Template.subclass() classmethod for quickly creating subclasses of
      existing Cheetah template classes. It takes the same args as the
      .compile() classmethod and returns a template that is a subclass of the
      template .subclass() is called from:
          T1 = Template.compile(' foo - $meth1 - bar\n#def meth1: this is T1.meth1')
          T2 = T1.subclass('#implements meth1\n this is T2.meth1')

    - added baseclass arg to Template.compile(). It simplifies the reuse of
      dynamically compiled templates:
      # example 1, quickly subclassing a normal Python class and using its
      #  __init__ call signature:
        dictTemplate = Template.compile('hello $name from $caller', baseclass=dict)
        print dictTemplate(name='world', caller='me')

      # example 2, mixing a Cheetah method into a class definition:
        class Foo(dict):
            def meth1(self): 
                return 'foo'
            def meth2(self): 
                return 'bar'        
        Foo = Template.compile('#implements meth3\nhello $name from $caller', 
                               baseclass=Foo)
	print Foo(name='world', caller='me')  

      A side-benefit is the possibility to use the same Cheetah source with
      several baseclass, as the baseclass is orthogonal to the source code,
      unlike the #extends directive.
    
    - added 'namespaces' as an alias for 'searchList' in Template.__init__
    - made it possible to pass in a single namespace to 'searchList', which will
      automatically be converted into a list.
    - fixed issue with buffering and use of #call when template is used as a
       webkit servlet
    - added Cheetah.Utils.htmlEncode and htmlDecode
   
  The command line tool (CheetahWrapper.py): 
    - changed insertion order for the --env and --pickle options so they match the
      commandline UI of the compiled template modules themselves [TR]

2.0b5 (Jan 7, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]    
    - made Cheetah.Template a new-style class by inserting 'object' into its'
      inheritance tree.  Templates can now use super(), properties and all the
      other goodies that come with new-style classes.
    - removed the WebInputMixin by placing its one method directly in the
      Template class.
    - removed the SettingsManager Mixin. It wasn't being used by anything
      anymore.
    - added a framework for caching the results of compilations in
      Template.compile().  This is on by default and protects against bad
      performance issues that are due to programmers misguidedly compiling
      templates inside tight loops.  It also saves on memory usage.
    - misc attr name changes to avoid namespace pollution
    - more + improved docstrings
    - replaced the oldstyle dynamic compile hacks with a wrapper around
      Template.compile().  The old usage pattern Template(src) now benefits from
      most of the recent changes.  
         Template(src).__class__ == Template.compile(src)
    - removed all the extra imports required by oldstyle dynamic compile hacks
    - converted the cheetah #include mechanism to newstyle compilation and made it
      more flexible
    - made the #include mechanism work with file objects in addition to file names
    - made the handling of args to Template.compile() more flexible.  You can now
      provide defaults via class attributes.
    - made preprocessors for Template.compile() work with file arguments
    - added support for specifying a __metaclass__ on cheetah template classes
    - refactored both the class and instance initialization processes
    - improved the handling of __str__ in _assignRequiredMethodsToClass

  The command line tool (CheetahWrapper.py):  [TR]
    - improved error output in CheetahWrapper
    - switched fill command over to new style compile usage

  Unit tests: [TR]
    - fixed format string bug in unittest_local_copy.py 

2.0b4 (Jan 6, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]
    - fixed up parsing of target lists in for loops. This was previously limited 
      to fairly simple target lists.
      #for ($i, $j) in [('aa','bb'),('cc','dd')]
        $i.upper,$j.upper
      #end for"
      #for (i, j) in [('aa','bb'),('cc','dd')]
        $i.upper,$j.upper
      #end for"
      #for i,(j, k) in enumerate([('aa','bb'),('cc','dd')])
        $j.upper,$k.upper
      #end for"
- refactored the class initialization process
    - improved handling of target lists in #set directive. This was previously 
      limited to fairly simple target lists.
      #set i,j = [1,2] ... #set $i,$j = [1,2]
      #set (i,j) = [1,2] ... #set ($i,$j) = [1,2]
      #set i, (j,k) = [1,(2,3)] ... #set $i, ($j,$k) = [1,(2,3)]

    - made it possible for the expressionFilter hooks to modify the code chunks
      they are fed. Also documented the hooks in a docstring.  Thus the hooks
      can be used as preprocessors for expressions, 'restricted execution', or
      even enforcement of style guidelines.

    - removed cheetah junk from docstrings and placed it all in comments or
      __moduleVars__. Per JJ's suggestion.
  
    - made it possible to nest #cache directives to any level
    - made it possible to nest #call directives to any level

  Unit Tests [TR]
    - extended tests for #for directive
    - expanded tests for #set directive
    - expanded tests for #call directive
    - expanded tests for #cache directive
    - added basic tests for the new $placeholder string expressions:
      c'text $placeholder text'

2.0b3 (Jan 5, 2006)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!
  Core Changes: [TR]
    - added #yield statement
    - added ability to create nested scopes/functions via nested #def statements
    - added new #call directive and related #arg directive, per Ian Bicking's
      suggestion.        
    - added new expression syntax c"text $placeholder text"
        
        for those basic function calling cases where you just need to pass in a
        small bit of cheetah output as an argument:
        
        c'a string with $placeholders', 
        c'''a string with $placeholders''', 
        c"a string with $placeholders", 
        c"""a string with $placeholders"""
        
        - They can't contain #directives, but accept any valid $placeholder syntax 
        except caching placeholders. Caching placeholders don't make any sense in 
        this context.
        - They can be used *any* place where a python expression is expected.
        - They can be nested to any depth.
        
        $func(c'<li>$var1-$var2</li>')
        $func(c'<li>$var1-$var2</li>', doSomething=True)
        $func(content=c'<li>$var1-$var2</li>', doSomething=True)
        $func(lambda x,y: c'<li>$x-$y</li>')
        $func(callback=lambda x,y: c'<li>$x-$y</li>')
        $func(lambda x,y: c'<li>$x-$y-$varInSearchList</li>')
        $func(c'<li>$var1-$var2-$(var3*10)-$(94.3*58)</li>')
        $func(c'<li>$var1-$var2-$func2(c"a nested expr $var99")</li>')
        #if $cond then c'<li>$var1-$var2</li>' else c'<p>$var1-$var2</p>'
        #def foo(arg1=c'$var1<span class="foo">$var2</span>'):  blah $arg1 blah
        $foo(c'$var1<i>$var2</i>')

    - added preprocessor hooks to Template.compile()
      can be used for partial completion or 'compile-time-caching'
      ... more details and examples coming.  It's very useful, but takes a bit
      of explaining.
    - added '#set module varName = expr' for adding module globals. JJ's suggestion
    - improved generated docstring notes about cached vars
    - fixed silly bug related to """ in docstring comments and statements like
      this '#def foo: $str("""foo""")'.  Reported by JJ.
    - changed the handling of single-line defs so that 
      '#def xxx:<just whitespace>\n' will be treated as a multi-line #def.  
      The same applies to #block.  There's a compiler setting to turn this off
      if you really need empty single-line #def:'s.
      JJ reported that this was causing great confusion with beginners.
    - improved error message for unclosed directives, per Mike Orr's suggestion.  
    - added optional support for passing the trans arg to methods via **KWS rather
      than trans=None.  See the discussion on the mailing list Jan 4th (JJ's post) for
      details.  The purpose is to avoid a positional argument clash that
      apparently is very confusing for beginners.

        Note that any existing client code that passing the trans arg in
        positionally rather than as a keyword will break as a result.  WebKit
        does this with the .respond method so I've kept the old style there.
        You can also turn this new behaviour off by either manually including
        the trans arg in your method signature (see the example below) or by
        using the compiler setting 'useKWsDictArgForPassingTrans'=False.
        
        #def manualOverride(arg1, trans=None)
          foo $arg1
        #end def

  ImportHooks: 
    - made the ImportHook more robust against compilation errors during import [TR]

  Install scripts: [TR]
    - added optional support for pje's setuptools 
    - added cheeseshop classifiers 
    - removed out of date install instructions in __init__.py

  Servlet Base Class For Webkit: [TR]
    - disabled assignment of self.application (was a webware hack)   

  Unit Tests: [TR]
    - unit tests for most of the new syntax elements
    - tidied up some old tests
    - misc refactoring

2.0b2 (Dec 30, 2005)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!

  Core Changes: 
    - In previous versions of Cheetah tracebacks from exceptions that were raised
      inside dynamically compiled Cheetah templates were opaque because
      Python didn't have access to a python source file to use in the traceback:

        File "xxxx.py", line 192, in getTextiledContent
          content = str(template(searchList=searchList))
        File "cheetah_yyyy.py", line 202, in __str__
        File "cheetah_yyyy.py", line 187, in respond
        File "cheetah_yyyy.py", line 139, in writeBody
       ZeroDivisionError: integer division or modulo by zero

      It is now possible to keep the generated source code from the python
      classes returned by Template.compile() in a cache dir.  Having these files
      around allows Python to include the actual source lines in tracebacks and
      makes them much easier to understand:

       File "/usr/local/unsnarl/lib/python/us/ui/views/WikiPageRenderer.py", line 192, in getTextiledContent
         content = str(template(searchList=searchList))
       File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 202, in __str__
         def __str__(self): return self.respond()
       File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 187, in respond
         self.writeBody(trans=trans)
       File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 139, in writeBody
         __v = 0/0 # $(0/0)
      ZeroDivisionError: integer division or modulo by zero

      This is turned off by default. To turn it on, do this:

        class NiceTracebackTemplate(Template):
            _CHEETAH_cacheModuleFilesForTracebacks = True
            _CHEETAH_cacheDirForModuleFiles = '/tmp/CheetahCacheDir' # change to a dirname
        
        templateClass = NiceTracebackTemplate.compile(src)

	# or
        templateClass = Template.compile(src,
           cacheModuleFilesForTracebacks=True, cacheDirForModuleFiles='/tmp/CheetahCacheDir')
	

      This only works with the new Template.compile(src) usage style!

      Note, Cheetah generated modules that are compiled on the command line have
      never been affected by this issue. [TR]

    - added an extra comment per $placeholder to generated python code so it is
      easier to grok. [TR]

2.0b1 (Dec 29, 2005)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!

  Core Changes: 
    - enabled use of any expression in ${placeholders}. See the examples I posted to
      the email list on Dec 12th.  All use cases of the #echo directive can now
      be handled with ${placeholders}.  This came from a suggestion by Mike
      Orr. [TR]
         
    - made it possible for templates to #extend (aka subclass) any arbitrary
      baseclass, including Python's new style classes.  You must either compile
      your classes on the command line or use the new classmethod
      Template.compile() as described below.  The old Template(src) interface
      still works, provided you don't try to use this new arbitrary baseclass
      stuff.  See my messages to the email list for more details. [TR]

    - made it possible to create template classes dynamically, rather than just
      instances.  See the new classmethod Template.compile().  See my messages
      to the email list for more details. [TR]
      
          klass = Template.compile(src)

    - made it easier to work with custom compiler settings, particularly from
      the command line tool.  You can now define a subclass of Template which
      will compile your templates using custom compilerSettings, or even a
      custom compiler class, without requiring you to manually pass in your
      compilerSettings each time or define them in the template src itself via
      the #compiler directive.  You can make the command line tool use your
      subclass by defining the environment variable CHEETAH_TEMPLATE_CLASS.  It
      should be in the form 'package.module:class'.  See my messages
      to the email list for more details. [TR]

    - made it possible to pass the searchList in as an argument to #def'ined
      methods.  This makes all lookup that occur within the scope of that method
      use the provided searchList rather than self._searchList.  This does not
      carry over to other methods called within the top method, unless they
      explicitly accept the searchList in their signature AND you pass it to
      them when calling them.  This behaviour can be turned off with the
      corresponding compilerSetting 'allowSearchListAsMethArg' [TR]

    - added hooks for filtering / restricting dangerous stuff in cheetah source
      code at compile time.  These hooks can be used to enable Cheetah template
      authoring by untrusted users. See my messages to the email list for more
      details. Note, it filters expressions at parse/compile time, unlike Python's
      old rexec module which restricted the Python environment at runtime. [TR] 
          
          # Here are the relevant compiler settings:
          # use lower case keys here!!
          'disabledDirectives':[], # list of directive keys, without the start token
          'enabledDirectives':[], # list of directive keys, without the start token
      
          'disabledDirectiveHooks':[], # callable(parser, directiveKey), 
              # called when a disabled directive is found, prior to raising an exception
      
          'preparseDirectiveHooks':[], # callable(parser, directiveKey)
          'postparseDirectiveHooks':[], # callable(parser, directiveKey)
      
          'preparsePlaceholderHooks':[], # callable(parser)
          'postparsePlaceholderHooks':[], # callable(parser)
      
          'expressionFilterHooks':[], 
          # callable(parser, expr, exprType, rawExpr=None, startPos=None)
          # exprType is the name of the directive, 'psp', or 'placeholder'. 
          #all lowercase

    - added support for a short EOLSlurpToken to supplement the #slurp
      directive.  It's currently re.compile('#\s*\n') (i.e # followed by
      arbitrary whitespace and a new line), but this is not set in stone.  One
      other suggestion was the backslash char, but I believe Python's own
      interpretation of backslashes will lead to confusion.  The compiler
      setting 'EOLSlurpToken' controls this.  You can turn it off completely by
      setting 'EOLSlurpToken' to None. See the email list for more details. [TR]

    - added '_CHEETAH_' prefix to all instance attribute names in compiled
      templates. This is related to the arbitrary baseclass change. [TR] 

    - shifted instance attribute setup to _initCheetahAttributes() method.  This
      is related to the arbitrary baseclass change. [TR]

    - made it possible to use full expressions in the #extends directive, rather
      than just dotted names. This allows you to do things like this: 

      #from xx.TemplateRepository import getTemplateClass
      #extends getTemplateClass('someName')

      I don't expect this to be used much. I needed it for a wiki system in
      which the baseclasses for the templates are dynamically compiled at run
      time and are not available via simple imports. [TR]

    - added compiler setting autoImportForExtendDirective=True, so this existing
      default behaviour can be turned off when needed. [TR]

    - fixed a bug in the parsing of single-line #def's and #block's when they
      are enclosed within #if ... #end if. Reported by Marcin Gajda [TR]

    - tweak to remove needless write('') calls in generated code [TR]

  The command line tool (CheetahWrapper.py): 
    - added code to cleanup trailing slashes on path arguments (code originally
      from Mike Orr) [TR]
    - turned on the ImportHooks by default for the 'cheetah fill' command. See the
      discussion on the email list [TR]

  ImportHooks: 
    - fixed a name error bug in the ImportHooks [TR]

1.0 (Dec 4, 2005)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!

  Version bump from 1.0rc3

1.0rc3 (Nov 30, 2005)
  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!

  - added useSearchList compiler setting [TR]
    This defaults to True, but if false, the compiler assumes the first
    portion of a $variable (before the first dot) is a global, builtin, or local
    var that doesn't need looking up in the searchlist.  NameMapper's unified
    dotted notation will still be used on the rest of the lookup (provide the
    setting useNameMapper==True):
      $aLocalDictVar.aKey.somethingElse

1.0rc2 (Nov 19, 2005)

  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!

  See my email to the cheetahtemplate-discuss list on Sat. Nov. 12th for more
  details on these changes:

  - faster list-based buffering in DummyTrans, rather than StringIO (my 
    benchmarks showed it to be significantly faster.  collections.deque wasn't 
    any faster than a simple list.) [TR]
  - new CompilerSettings to tweak generated code: [TR]
    * alwaysFilterNone: filter out None immediately, before the filter is called
    * useFilters: allows you to turn them off completely and default to str()
    * includeRawExprInFilterArgs: allows you to disable this behaviour
    * autoAssignDummyTransactionToSelf: off by default 
  - and automatic $trans finding without having to pass it as an arg to methods 
    based Jonathan Mark's suggestion.  If the template's self.transaction
    attribute has been set, each method of the template will use it when
    called. [TR]
  - applied Chris Murphy's patch to fix a bug in the #shBang directive. [TR]

1.0rc1 (Nov 2, 2005)

  !!!THIS RELEASE REQUIRES RECOMPILATION OF ALL COMPILED CHEETAH TEMPLATES!!!

  - added the compiler option "useStackFrames" for optionally turning off the
    default lookup method which doesn't work with psyco because it uses stack
    frame introspection.  When useStackFrames=False, an alternative psyco
    friendly lookup method is used. [TR]

  - fixed treatment of None in several filters, bug reported by Daniele Varrazzo
    [TR]

0.9.18 (Aug 22, 2005)
  - version bump from 0.9.18rc1 [TR]

0.9.18rc1 (Aug 15, 2005)
  - applied Philippe Normand's patch for extended cache support [TR]
  - added filter RawOrEncodedUnicode to fix a unicode issue that was discussed
    on the email list on Aug. 9th 2005 [TR]

0.9.17 (May 30, 2005)
  - this is just 0.9.17rc1 repackaged [TR]

0.9.17-rc1 (May 12, 2005)
  This simple bug fix release resolves some issues introduced by
  under-the-hood changes in release 0.9.16a1.

  - removed the use of temp files for handling imports with dynamic
    compilation. This removes a whole slew of issues, including a temp file
    security issue reported on the email list by Brian Bird. [TR]
  - fixed bug with handling of the searchList with dynamic inheritance, as
    reported by  Brian Bird. [TR]

0.9.16 (Mar 27, 2005)
  - this is just 0.9.16b1 repackaged [TR]

0.9.16b1 (Feb 28, 2005)
  - fixed attr error in Parser.eatEncoding [TR]
  - some tweaks to Compiler.py to prevent errors with dynamically compiled
    templates [TR]
  - added tests for the #encoding directive [TR]

0.9.16a1 (Jan 6, 2005)
  - fixed a unicode bug in Compiler.py [TR]
  - added new EncodeUnicode filter that Rene Pijlman contributed (I optimized it
    slightly) and made it the default filter for all templates. [TR]
  - added test cases for handling unicode with the default filter [TR]
  - fixed a caching bug related to the #include directive. Thanks to Michael
    Engelhart for reporting it.[TR]
  - added the new #encoding directive to handle PEP 263
    http://www.python.org/doc/2.3/whatsnew/section-encodings.html [TR]
  - Tools.CGITemplate: fix bug in comment.[MO]
  - Abort with a helpful error message if user runs 'cheetah test' in a
    directory without write permission.  (Kludge in CheetahWrapper.py; we
    should probably move the temp files under the system tmp directory.) [MO]
  - added better string type checking for args in Template.py, as suggested by
    Terrel Shumway [TR]
  - minor tweak to the class attribute lookup style in the Compiler.py
    __getattr__ methods [TR]
  - Fix printf format bug in "cheetah c --debug", found by Terry MacDonald. [MO]
  - Disabled NameMapperDict test (in SyntaxAndOutput.py) because the
    namemappers still have the dict-method bug.  (Reminder: don't use 
    placehold names like $update that match dict method names.) [MO]
  - #repeat now uses a local variable of the form __i$num which permits 
    nesting [JJ]
  - implemented a modified version of Bob and JJ's patch for better parser
    warnings about mismatched directives and #end directives [TR]
  - lots of little cleanups and refactoring [TR]
  - refactored the class tree for the Parser and Compiler.  They are now
    completely separate trees and the communication between them is one-way:
    explicit commands from the parser to the compiler.  The parser now handles
    all parsing tasks by itself and delegates *all* code generation to the
    compiler.  This last bit was my original intention, but things got a bit
    mixed up over time.  Also, all SettingsManager stuff for handling
    compiler/parser settings is now handled by ModuleCompiler.  This should make
    it easier to grok, maintain, and extend both. [TR]
  - improved the parsing of singe-line #if directives. [TR]
  - removed the old webware example of the cheetah site, as it was way out of
    date and was more confusing than helpful. [TR]
  - added two new lookup functions to NameMapper (valueFromFrame and
    valueFromFrameOrSearchList) and synchronized the behaviour of the C and
    Python versions of all functions. [TR]
  - improved the exception handling of both versions of NameMapper. NotFound
    exceptions now include more detail about what wasn't found. [TR]
  - made NameMapper's searchList lookup functions work with any iterable
    type/class rather than just with lists. [TR]
  - added and updated a variety of test cases. [TR]
  - checked in a patch to CheetahWrapper that improves handling of the odir
    option when the path is absolute.  I can't remember where the patch came
    from. [TR]
  - checked in a patch to Template.py for better include/import support under
    Jython.  Again, I've forgotten who contributed it. [TR]
  - updated various bits of the user guide. [TR]
  - made the Cheetah NameMapper calls in the generated code use the new function
    valueFromFrameOrSearchList rather than passing locals, searchList, globals,
    and __builtins__ into valueFromSearchList.  This is faster, less bug prone
    and simpler to read/grok. I also removed all tracking of local
    variable names by the compiler. [TR]
  - other misc. refactorings [TR]
 
0.9.15 (Mar 25, 2003)
  - a minor tweak to the cleanup actions of one of the test cases [TR]

0.9.15rc2 (Mar 23, 2003)
  - Fixed a python version dependency bug related to Compiler.py's use of 
    isinstance() [TR]

0.9.15rc1 (Mar 21, 2003)
  This is just 0.9.15b1 renamed.

0.9.15b1 (Mar 17, 2003)
  - The Cheetah version of unittest now prints a blank line after each 
    traceback to separate them.  (MO)
  - .webInput() now saves the cgi.FieldStorage() instance in a global
    variable rather than recreating it each call.  That should allow the
    method to be called multiple times with POST variables outside Webware.
    (MO)
  - CheetahWrapper: no verbose output on stdout with --stdout/-p. (MO)
  - "#indent" is now undocumented.  The existing code remains intact for now.
    See the TODO file for our future plans. (MO)
  - Apply 2 unicode-support patches from Rodrigo B. de Oliveira (rodrigobamboo)
    that affected the Template and ModuleCompiler classes. (TR)
  - Template: compiling a template from a string now works if the current
    directory doesn't have write permission.  (MO)
  - remove temporary .pyo files in addition to .py and .pyc files (TR)

0.9.15a3 (Nov 10, 2002)
  - corrected a dictionary bug in the Python version of NameMapper (TR)
  - Rewrote the "cheetah" command (CheetahWrapper.py) again and added test
    cases.  New options --flat and --nobackup; --stdout is now a synonym for
    -p.  See the "cheetah compile" section in the Users' Guide for details.
    Deleted Utils.dualglob: merged into CheetahWrapper.  (MO)
  - .addToSearchList() and .prependToSearchList() are gone.  Instead of 
    adding containers to the searchList after instantiation, pass all the
    containers you need to the constuctor, keep another reference somewhere
    to the containers, and modify the containers directly.  Generic libraries
    that want to add a new kind of information to the searchList (e.g.,
    web variables) should do "self.searchList().insert(0, myContainer)". (MO)

0.9.15a2 (Nov 4th, 2002)
  - Filters now have access to the name of the placeholder they're filtering.
    In the .filter() method, kw['rawExpr'] gives the entire placeholder name
    including subscripts and arguments, exactly as it appears in the template
    definition. (TR)
  - Fix three bugs in "cheetah compile -R": (1) the generated class name 
    contained the subdirectory, (2) the destination path did not contain the
    subdirectory, (3) Cheetah failed to create the destination subdirectory
    if missing.  All subdirectories created have an "__init__.py" file. 
    "cheetah fill -R" does the same thing but does not create 
    "__init__.py". (MO)  NOTE: this is still buggy!
  - New directory "attic" in source contains code that has been abandoned
    for now but may come in handy someday. (MO)
  - Tests.CheetahWrapper: test suite for "cheetah compile" and
    "cheetah fill".  If the module is run from the command line, the
    option "--list PATH/CheetahWrapper.py", lists all scenarios that would be
    tested; the argument is the path to the test module itself. (MO)
  - made Cheetah.NameMapper.NotFound subclass the builtin LookupError (TR)
  - added an initial implementation of single line #if directives
    #if <condition> then <true> else <false>
    The parsing is fairly rudimentary for now and assumes that the keywords
    'then' and 'else' won't appear any inside a string in this directive (TR)

0.9.15a1 (Oct 6th, 2002)
  - fixed a package-relative import bug in ImportHooks.py (TR)
  - set 'monitorSrcFile' to false as it was causing problems with the
    ImportHooks ... This might be temporary as the problem needs more thought
    (TR)
  - fixed meta tag http_equiv to be http-equiv in SkeletonPage (TR)
  - $webInput (Utils.WebInputMixin) 'source' arg can be either case. (MO)
  - fixed code-gen bug in MethodCompiler.commitStrConst that was leading to
    triple single quotes followed immediately by another single quote if the
    template def contained a '$placeholder' surrounded in single quotes and
    multiple \n newlines ... plus added new test case.(TR)
  - undocumented the '#settings' directive.  The directive itself will be
    removed soon.  (MO)
  - Utils.optik: Optik 1.3 package by Gregory P Ward, for parsing
    command-line options in 'cheetah' comamnd.  Copied unchanged into
    Cheetah except added "Cheetah.Utils.optik." prefix to intra-package
    imports.  Optik's copyright and license is in an appendix in the
    Cheetah Users' Guide.  (MO)
  - rewrite of the "cheetah" and "cheetah-compile" commands. 
    The command-line options have changed!  Removed CheetahCompile module
    removed and its test suite too; CheetahWrapper now takes its place. (MO)
  - Utils.dualglob: new module to recursively generate source+destination
    filenames from command-line filespecs. (MO)
  - The command-line options of .py template modules have also changed
    to conform with the "cheetah" command.  Also a --pickle bug was
    fixed.  (MO)
  - Utils.WebMixin: made a string type comparision backward compatible.
    This was why the Cheetah test suite was failing on Python < 2.2! (MO)
  - SettingsManager._createConfigFile(): bugfix in default argument. (MO)
  - $hasVar('varName') is an alias for $varExists('varName').  (MO)
  - $_fileDirName and $_filePath are now None rather than missing if
    the template definition did not come from a named file.  (MO)
  - applied patch on SourceForge for "%" in default arguments of a block (TR)
  - removed the _underscored attribute lookup step from NameMapper NOTE THIS
    MIGHT BREAK EXISTING TEMPLATES (TR)
  - Install Cheetah into site-packages/Cheetah/ rather than
    site-packages/Webware/Cheetah/. Added code to automatically remove the old
    dir.(TR)
  - fixed the variable name resolution order bug in $placeholders.  The new
    implementation uses 
     valueFromSearchList([locals()] + searchList + [globals(), __builtin__],
     rest of the args) for all lookups. (TR)
  - removed the #settings directive (TR)
  - added the #del directive, for using Python's del statement (TR)
  - I think I've fixed the problem with the searchList arg being discarded when a
    template is generated from a .tmpl file that #extends another template. This
    bug was reported by Edmund on Aug 30th 
    (subject: "Bug? Was: Really basic searchList question") (TR)

0.9.14 (July 14, 2002)
  - Precompiled template Templates/SkeletonPage.py added to CVS.  This file is
    needed for Cheetah's regression tests. (MO)
  - removed automatic recompilation of .py template in memory if the
    .tmpl file has changed.  (TR)

0.9.14b1 (June 30, 2002)
  - moved the Users' Guide and the Developers' Guide into a separate CVS module,
    'CheetahDocs', so they can be distributed separately from the source distro
    (TR,MO)
  - added TypeType to the types that NameMapper won't do autocalling on (TR)
  - in Template.py moved the global LegalKWs to Template._legalKWs (TR)
  - made #set work with RVALUES that are missing the recommended $ (TR)
  - added some new test cases for the #set directive (TR)
  - fixed bug in the output of the #unless directive that Mike found (TR)
  - added some module constants to clear up a missing name bug that Mike found
    in cases where you use **KW in a Cheetah method definition (TR)
  - fixed a bug in Parser.py:_LowLevelSemanticsParser.getExpression() that was
    related to the default enclosures=[] argument.  This arg was unintentionally
    being shared between calls and thus leading to parsing errors as reported by
    Greg Czajkowski (TR)
  - Filter: fixed an '== None' expression (should be 'is None'). (MO)
  - TemplateMisc: new base class for Template.  This is for optional
    convenience methods that don't require Webware. (MO)
  - User's Guide: new sections "Non-Webware HTML Output" and "Non-HTML
    Output". (MO)
  - Expanded $webInput() -- renamed from $cgiImport() -- to work both with
    Webware input and CGI scripts.  Handles GET/POST/cookie/session vars under
    Webware, and GET/POST under CGI.  Defined in Cheetah.Utils.WebInputMixin,
    now inherited by Template directly. (MO)
  - Tools.CGITemplate has methods to output CGI headers: .isCgi, .cgiHeaders
    and .cgiHeadersHook in TemplateMisc. (MO)
  - New #indent directive allows you to indent block constructs in the
    template definition without having that indentation in the output, and
    allows you to set the output indentation per line independent of the
    indentation in the template definition.  This version uses Robert
    Kuzelj's #indent syntax exactly.  In the next few days, 
    Cheetah.Utils.Indenter will be refactored and
    *** THE #INDENT SYNTAX WILL CHANGE! *** (MO)
  - added the #return directive as requested by Robert Kulezj (TR)
  - added some test cases for the #return directive (TR)
  - removed buggy import statement that had been left in Servlet.py after the
    CGIInputMixin changes (TR)


0.9.13 (May 8, 2002)
  - changed Cheetah.Servlet.isRunningFromWebKit to isWebwareInstalled (TR)

  - fixed parsing bug that would exit an expression if the directiveEndToken was a
    valid Python token and was found inside the directive.  (TR)

    E.g.:
    #compiler-settings
    directiveStartToken = .
    directiveEndToken = :
    commentStartToken = #
    #end compiler-settings
    
    .for a in [1,2,3,4][2:3]:
    blag
    .end for

  - fixed #include bug that was resulting in non-unique includeIDs (TR)

0.9.13b2 (May 3, 2002)
  - fixed the bug in Cheetah.Servlet.Servlet.serverSidePath that Jeff Johnson
    found. (TR)
  - changed the attribute Cheetah.Servlet.ServletisRunningFromWebKit to
    isControlledByWebKit and set the default to False unless the .awake method
    is called.  This makes a clear distinction between templates that are being
    used with WebKit via the inheritance approach and the containment approach
    (TR)

 
0.9.13b1 (May 1, 2002)
  - Was going to import cStringIO instead of StringIO, but it made the 
    DummyTransaction.py unittest fail so I undid it.  Cheetah aims to provide
    Unicode support, which cStringIO does not provide. (TR/MO)
  - Utils.Misc.CheckKeywords(): prevent misspelled keyword arguments,
    used by Template constructor. (MO)
  - removed support for multiple inheritance (TR)
  - added some bounds-checking code to _namemapper.c's getNameChunks function
    (TR)
  - changed the exceptions in _namemapper.c from the old string exceptions
    to proper exception objects (TR)
  - first portion of Developers' Guide written (MO)
  - implemented the extended #extends directive, which does automatic importing
    (MO,TR)
  - added some new testcases for the extended #extends directive (TR)
  - lots of work on the Users' Guide (MO)
  - implemented and tested an import hook for .tmpl files (TR):
      import MyTemplate  # will compile and import MyTemplate.tmpl
  - made my True/False declarations friendly with Python 2.2.1, which already
    includes True/False as builtins (TR)
  - implemented the #compiler directive that Edmund Lian suggested (TR)
      e.g.:
        #compiler commentStartToken = '//'
        // a comment
        #compiler reset
	// no longer a comment
  - fixed the bug that Edmund Lian found in .addSet() when useNameMapper = 0
  (TR)
  - fixed bug in comment creation using lineCol that Mike found (TR)

0.9.12 (April 3, 2002)
   - no code changes from beta 2
   - more work on the docs (MO)

0.9.12b2 (Mar 28, 2002)
   - fixed Win32 path bug in Template._makeDummyPackageForDir() (TR)
   - prettied up the format of the debug comments in the Cheetah generated
     Python code (TR)
   - fixed the non-unique key error in Template._includeCheetahSource (TR)
   - fixed the module import bug in 'cheetah compile -w' (TR)

0.9.12b1 (Mar 24, 2002)
   - $request().field(args) now works, identical to $request.field(args)
     to implement this, the request object is now self.request() instead of
     self.request.  This provides compatibility with Webware's servlet API.
     (self.session already was an accessor method).  New read-only attribute
     self.isRunningFromWebKit is boolean.  All changes are in Servlet.py. (MO)
   - fixed nested-NotFound bug in _namemapper.c's valueFromSearchList (TR)
   - 'cheetah' wrapper script has abbreviation -c for the 'compile' command,
     -t for 'test', and an ASCII-art cheetah face in the help message. (MO)
   - CheetahCompile.py: fixed to recognize --help option and to show --help/-h
     in help message. (MO)
   - CheetahCompile.py: 
     changed the order of the VERBOSE mode printouts, as per Mike's request (TR)
   - Template.py:
     fixed the #include'd template searchList sharing problem, as reported by
     Johannes (TR)
   - corrected namemapper translation bug in
     Compiler.GenUtils.genNameMapperVar() (TR)
   - Utils.Misc.UseOrRaise(): convenience function to return a 
     value, or raise it if it's a subclass of Exception. (MO)
   - Utils.CGIImportMixin replaces Tools.WebwareMixin.  Servlet now
     subclasses it.  This adds the .cgiImport() method to all servlets, allowing
     sophisticated retrieval of form fields, cookies or session variables from
     one line of Cheetah or Python code.  See module docstring. (MO)
   - lots of updates to the docs (MO)

0.9.11 (Mar 07, 2002)
   - fixed a careless bug in cheetah-compile (TR)
   - implemented the new 'cheetah' wrapper script (TR)
   - refactored the local copy of unittest a bit (TR)

0.9.10 (Mar 06, 2002): Primarily a bug fix release
   - fixed bug in srcfile-mtime monitoring / update code (TR)
   - fixed the parsing of single-line #defs and #blocks so they can have
     arguments (TR)
   - added test cases for single-line #defs and #blocks with args (TR)
   - fixed a silly typo bug in Parser.py where a comma was left at the end of
     regex definition, make it a tuple rather than a regex
   - fixed the directive matching bug that Jeff Johnson reported.  It was
     causing #else# to not match, while #else # was matching. + added a test
     for it.(TR)
   - fixed bug in a regex that was preventing bare $'s followed by whitespace
     and then valid varname chars from parsing as just $ instead of as a
     placeholder (TR)
   - added some code to break reference cycles after the compilation is
     complete. This helps prevent memory leaks when a process in creating then
     discarding lots of Templates.  You also need to manually call
     "template.shutdown()" to clear the remaining reference cycles.
     (TR)
   - fixed string formating bug in the autogenerated docstring code (TR)
   - added better error message for the #attr directive (TR)
   - removed some residual code that was causing a bug with cheetahvars that
     started with the name of one of the imported modules, such as 'time'. (TR)

0.9.9 (Dec 14, 2001)
   - implemented one-line #def's and #block's (TR)
        #def aTest: This is a $adj test   ---- READ THE MANUAL FOR MORE INFO.
     NOTE: leading and trailing whitespace is stripped.  These should only be
     used on lines by themselves as it reads to the end of the line.
   - made cheetah-compile accept input on standard input (TR)
   - made sure that #def and #block work with $'s on the method names (TR)

0.9.9b1 (Dec 6, 2001)
   - template constructor arg 'outputFilter' now 'filter', for consistency
     with #filter (MO)
   - template constructor raises TypeError if bad arguments (MO)
   - Cheetah.Utils.VerifyType new module containing functions for verifying the
     type of an argument (MO)
   - Cheetah.Utils: new package for non-Cheetah-specific modules needed by
     Cheetah (MO)
   - Cheetah.Filters: new filter WebSafe, several bugfixes (MO)
   - more work on the Users' Guide (MO)
   - fixed bug with adding Python's __builtins__ to the local vars list (TR)
   - fixed bug with #echo (TR)
   - fixed bug that was preventing ${a, $b=1234} from working like ${a, b=1234} (TR)
   - fixed some bugs in Template.varExists and Template.getVar() 
     (TR - thanks to MH for spotting them)
   - made it possible to use filenames like 'spam-eggs.txt' that have invalid
     characters for module names with Template(): Template(file='spam-eggs.txt')
     (TR/MH)
   - refactored 'cheetah-compile' a little (TR)
   - Cheetah.Filters.Strip: new filter to strip leading/trailing whitespace
     but preserve newlines.  Suitable for #filter directive or (possible)
     future #sed directive. (MO)
   - Cheetah.Filters.StripSqueeze: new filter to canonicalize all whitespace
     chunks to ' '.  Also removes all newlines (joining multi-line input into
     one long line), and leading/trailing whitespace from the final result. (MO)
   - Filters can now be used standalone for debugging or for use outside
     Cheetah.  This works transparently; details are in Filters.py docstring.
     (MO)
   - Cheetah.Tools.MondoReport: new module for dividing a long list into
     "pages", and for calculating statistics useful in reports. (MO)
   - refactored Cheetah.Servlet.Servlet.Awake a little (TR)
   - fixed an output bug in the #block generated code that turned up when you
     tried to override a block method from Python rather than Cheetah. (TR)
   - started preparing to shift some of the 'shared' utility classes, such as
     SettingsManager, to the Webware core.  Cheetah 1.0 will probably require
     Webware to be installed so it can access those shared classes. (TR)
   - extended the template module command line interface(TR/MO)

0.9.9a6 (Nov 6, 2001) 
   - fixed bug with quotations in longer constant string chunks (TR)
   - fixed another bug in the cheetah-compile script (TR)
   - fixed a bug in the file-update monitoring code that was resulting in
     infinite loops when used with Template sub-classes (TR)
   - extended the #filter framework according to Mike's suggestions (TR)  
   - added test modules for cheetah-compile and the file-update monitoring code (TR)
   - extended the capabilities of cheetah-compile ... (IB)
   - updated the docs (MO)

0.9.9a5 (October 31, 2001) 
   - fixed a bug I created yesterday (TR)

0.9.9a4 (October 30, 2001) 
   - added #repeat (TR implementing Chuck's suggestion)
   - added #unless (TR implementing Mike's suggestion)
   - updates to the Users' Guide (MO)
   - fixed a small bug in the cheetah-compile script, as reported by Ian on the
     list (TR)

0.9.9a3 (October 12, 2001) 
   - more in the Users Guide (TR)
   - renamed #attribute as #attr  (TR)
   - renamed #call as #silent (TR)
   - added #echo directive (TR)
 
0.9.9a2 (October 11, 2001) 
   - updated the example site and the SkeletonPage framework (TR)
   - fixed some small bugs (TR)
   - corrected some typos in the docs (TR + MO)
   - added Ian's sitehiearchy class to Cheetah.Tools (TR + IB)

0.9.9a1 (October 9, 2001)  [many changes and bug-fixes]
   - a complete reimplementation of Cheetah's core (the parser and compiler
     classes) (TR + IB)

   - implemented the #def, #implements, #import, and #from directives
     + removed #redefine and #macros
     + renamed #extend as #extends (TR + IB)

   - replaced #data with #settings, see the docs (TR)

   - restructured and updated the docs (TR + MO + IB)

   - reimplemented the cheetah-compile script, without the -g option that Ian
     had added (TR)

   - changed the signature of Template.__init__.  See the docs. (TR)

   - made #set distinguish between local and global vars.  See the docs. (TR)

   - added hundreds of new test cases (TR)

   - added the #breakpoint and #compiler-settings directives (TR)

   - started restructuring the SkeletonPage framework [not complete yet] (TR)
   - started restructuring the example sites [not complete yet] (TR)


0.9.8 (October 9, 2001)
   - added a few new language constructs (aka 'directives') to Cheetah (TR)
     #while ... #end while
     #try ... #except ... #else ... #finally ... #end try

   - fixed a bug in the handling of local vars in #for loops that was preventing
     callable local vars from being handled properly. See Chuck's post of Sept
     10. (TR)

   - fixed a pointer bug in the C version of NameMapper.valueFromSearchList()
     that was yielding undefined values for the NotFound exception when it was
     raised (TR)

   - prefaced all internal args to Template() with underscores (TR)
   - fixed the problem with parsing triple quoted strings in arg lists (TR)
   - updated the docs (TR)

0.9.8a4 (September 7, 2001)

  - Added -g (appendGen function argument), which compiles x.tmpl to xGen.py,
    with x.py being for non-generated Python code. Also changed option handling
    a little and added a comment to the top of compiled files. (IB + MO)

  - finalized the #include syntax after a lengthy discussion on the list 
    This is different from in 0.9.8a3 (TR)
        #include <ARGS> <EXPR> 
        ... uses the value of EXPR as the path of the file to include.
        
        #include <ARGS> source = <EXPR> 
        ... includes the value of the EXPR 

        where <ARGS> is 'raw' or ''

  - re-implemented the output mechanism to use streaming via Webware's
    Transaction and Response objects when available and fake it with the
    DummyTransaction DummyResponse classes when the Webware Transaction is not
    avialable. This behaviour is roughly the same as in Webware's PSP.  Will
    implement output buffering PHP-style later if there is any demand. (TR)

  - made #include a run-time directive rather than compile-time.  This is
    slower, but the semantics are better. (TR)

  - various small optimizations to the generated code (TR)

  - updated the docs (TR)


0.9.8a3 (August 22, 2001) [includes changes for 0.9.8a1 and 0.9.8a2]

  - Added package ./src/Tools/ for contributed classes/functions/packages not
    necessary to run Cheetah.  The first such class is RecursiveNull.py by Ian
    Bicking.  Added package Cheetah.Tools to list in ./setup.py . (MO)
  - Template.__init__ keyword arg 'searchList': no longer has to be a tuple.  It
    may be a list or any type that that Python's 'tuple' function accepts. (MO)
  - Template.__init__ new keyword arg 'file': this may be a filename or file
    object to read the Template Definition from.  If you use this, you must not
    pass a Template Definition string also.  New instance variables 
    ._fileName and ._fileMtime are set if a filename was passed; otherwise they
    are None. (MO)
  - CodeGenerator new function 'varNotFound_KeyError': raises KeyError if a
    placeholder name is missing when filling the template.  Disabled by default.
    (MO)  NB - this change has been superceeded by 'errorCheckers'
  - Template.getUnknowns (new method): returns a list of Placeholder Names
    missing in the Search List. (MO) - this change has been superceeded by 
    'errorCheckers'
  - made changes to Template.py, CodeGenerator.py, PlaceholderProcessor.py,
    and TagProcessor.py to enable customization of the placeholderStartToken so 
    it can be set to any character sequence, rather than just the default '$'.
    This is configurable by the Template setting 'placeholderStartToken' (TR)
  - fixed a small bug in PlaceholderProcessor.processTag() that prevented
    static caching (i.e. $*) of a value containing ''' style quotes
  - added #break and #continue (TR)
  - fixed the relative path problem with #include when using Cheetah with WebKit
    (TR)
  - implemented the #stop directive (TR)
  - fixed a bug in the macro processing that prevented macros defined inside
    #includes from being visible at the top level (TR)
  - fixed a bug in the handling of the setting 'useAutocalling' (TR)
  - fixed some bugs in the handling of macros (TR)
  - completed the transition to nested template #includes (TR)
  - added direct #includes (TR)
  - completed the transition to run-time evaluation (TR)
  - renamed the .startServer() method of Template to .compile() (TR)
  - renamed the 'delayedStart' setting as 'delayedCompile' (TR)
  - added .redefineTemplateBlock as an alias to Template.defineTemplateBlock
    (TR)
  - got relative path includes working with Webware and Cheetah.Servlet (TR)
  - lots of changes in the docs (TR & MO)
  - implemented a C version of NameMapper (TR + CE)
  - added the 'errorCheckers' framwork (TR)
  - added the 'formatters' framework and the #formatter directive
  - a major restructuring of the modules and internal API (TR)
  - made sure that all the #directives with start and end tags are
    implemented in such a way that they won't cause 'maximum recursion' limit
    errors if their content block is long.  Simple regexes didn't cut it in these 
    cases. (TR)
    - #macro
    - multiline comments
    - #data
    - #block
    - #raw
    - the parsing of the core tags (the state-dependent ones) after they have been
      translated to the internal delimiters
  - made a Template.shutdown() method for cleaning up reference cycles before a 
    template object is deleted. (TR)
  - made the parsing and processing of #macros() more robust (TR)
  - implemented the file update checking mechanism (TR)
    NOTE, the syntax for the #include is now:
        #include <ARGS> file = <EXPR> 
        ... uses the value of EXPR as the path of the file to include.

        #include <ARGS> <EXPR> 
        ... includes the value of the EXPR 

        where <ARGS> is 'raw' or 'direct'

 
0.9.7 (July 13, 2001)

  - reimplemented the parsing of $placeholders using the Python tokenize module (TR)
    - now translates into Python code instead of going through NameMapper for
      each request
    - supports arg lists and nested placeholders
    - maintained support for autocalling of functions and methods,
      will do this serially for $func.otherFunc, etc.
  - reimplemented the #include and #raw directives using nested templates for
    parsed includes and  string attributes of 'Template' to store raw text
    The support for file update monitoring of includes is still not implemented (TR)
  - moved some stuff from __init__.py into CHANGES and TODO  (TR)
  - added a new command 'sdist_docs' to setup.py which rebuilds the docs
    when making a source distribution (TR)
  - changed the name of the ./Cheetah dir to ./src (TR)
  - fixed a bug in one of the code filters that was preventing commas from 
    being used between $placeholders (TR)
  - generalized the line ending regex for single-line comments (TR)
  - corrected the spelling of 'Delimiters' throughout Cheetah (TR)
  - made insertLines in Utilities.py more robust (Chuck)
  - added key argument to raising some NotFound exceptions in NameMapper (Chuck)
  - fixed strange bug involving missing templateObj parameter 
    in PlaceholderProcessor.py(Chuck)
  - expanded on the docs (Mike)

0.9.6 (June 12, 2001)
  - fixed a bug in NameMapper that was preventing 'obj.__class__.__name__' from mapping (TR)

0.9.5 (June 10, 2001)
  - implemented the #cache directive - see the mailing list (TR)
  - reworked the handling of cached $placeholders and set $var to mean NO_CACHE,
    $*var to mean STATIC_CACHE, and $*15*var to mean TIMED_REFRESH_CACHE (TR)
  - renamed Template._getValueForName as Template.mapName (TR)

0.9.4 (June 9, 2001)
  - created a SettingsManager base class to handle settings for the Template class (TR)
  - moved the HTML docs icons into the same dir as the HTML (TR)

0.9.3
  - updated the User's Guide Makefile. Builds HTML, PDF, and PS in the ./docs dir now. (TR)
  - changed the refs to 'Tavis Rudd' in the docs to 'The Cheetah Development Team' (TR)
  - added a few bits to the docs (TR)
  - did some internal renaming so 'nameMapperTags' are referred as 'placeholderTags' (TR)
  - added the #slurp directive (TR)
  
0.9.2
  - got the PSP plugin working again.  It still need test cases. (TR)

0.9.1
  - Changed the name of the package to 'Cheetah' from TemplateServer (TR)
  - Changed the name of the Server module and its TemplateServer class to 'Template' (TR)
  - Changed the name of the 'TScompile' script to 'cheetah-compile' (TR)
  - updated the docs (TR)

0.9.0
  - changed the names and behaviour of the #parse and #include directives (TR)
    see the docs for more. (TR)
  - changed #verbatim to #raw (TR)
  - fixed a bug in Tests.py that caused an error on the first run. (TR)
  - more docs (TR + MO)
  ! all tests pass with Python 2.1 and 2.0 (TR)
  
0.8.4
  - changed the #directive end tags to #end if instead of #/if and #end (TR)
    macro instead of #/macro (TR)
  - more work on the User's Guide (TR)
  - fixed a bug in TScompile (TR)
  
0.8.3
  - fixed a problem with the regexs that caused $vars and #directives at the (TR)
    very beginning of the template string not to match in Python 2.0 (TR)
  - removed some Test cases that made invalid assumptions about the order (TR)
    of items in dictionaries. (TR)

0.8.2
  - finished half of the User's Guide (TR)
  - fixed several small bugs (TR)
  - added the #comment directive and removed the old <# multiline comment tag #> (TR)
  - changed the explicit directive closure to /# from ;# (TR)

  
0.7.6
  - several small bug fixes (TR)
  - reimplemented the #block directive to avoid maximum recursion depth errors (TR)
    with large blocks. (TR)
  - created many new test cases in the regression testing suite (TR)
  - added an example site to the examples/ directory (TR)
  - started the User's Guide (TR)

0.7.5
  - implemented the command-line compiler (TR)

0.7.3-4
  - implemented the regression testing suite (TR)
  - fixed a number of small bugs (TR)

0.7.2
  - implemented the #longMacro directive (TR)


================================================================================
KEY TO INITIALS USED ABOVE:
TR - Tavis Rudd
MO - Mike Orr
JJ - Shannon 'jj' Behrens
IB - Ian Bicking
CE - Chuck Esterbrook
MH - Mike Halle