~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/util/configobj/docs/validate.txt

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-10-31 03:15:38 UTC
  • mfrom: (3806.1.1 contrib)
  • Revision ID: pqm@pqm.ubuntu.com-20081031031538-0ih0zi2owevf6fwu
Add contrib/bzr_ssh_path_limiter. (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
===================================
 
2
 Validation Schema with validate.py
 
3
===================================
 
4
 
 
5
--------------------------
 
6
 Using the Validator class
 
7
--------------------------
 
8
 
 
9
 
 
10
:Authors: `Michael Foord`_, `Nicola Larosa`_, `Mark Andrews`_
 
11
:Version: Validate 0.3.2
 
12
:Date: 2008/02/24
 
13
:Homepage: `Validate Homepage`_
 
14
:License: `BSD License`_
 
15
:Support: `Mailing List`_
 
16
 
 
17
.. _Mailing List: http://lists.sourceforge.net/lists/listinfo/configobj-develop
 
18
.. _Michael Foord: fuzzyman@voidspace.org.uk
 
19
.. _Nicola Larosa: nico@teknico.net
 
20
.. _This Document:
 
21
.. _Validate Homepage: http://www.voidspace.org.uk/python/validate.html
 
22
.. _BSD License: http://www.voidspace.org.uk/python/license.shtml
 
23
 
 
24
 
 
25
.. contents:: Validate Manual
 
26
.. sectnum::
 
27
 
 
28
 
 
29
Introduction
 
30
============
 
31
 
 
32
Validation is used to check that supplied values conform to a specification.
 
33
 
 
34
The value can be supplied as a string, e.g. from a config file. In this case
 
35
the check will also *convert* the value to the required type. This allows you
 
36
to add validation as a transparent layer to access data stored as strings. The
 
37
validation checks that the data is correct *and* converts it to the expected
 
38
type.
 
39
 
 
40
Checks are also strings, and are easy to write. One generic system can be used
 
41
to validate information from different sources via a single consistent
 
42
mechanism.
 
43
 
 
44
Checks look like function calls, and map to function calls. They can include
 
45
parameters and keyword arguments. These arguments are passed to the relevant
 
46
function by the ``Validator`` instance, along with the value being checked.
 
47
 
 
48
The syntax for checks also allows for specifying a default value. This default
 
49
value can be ``None``, no matter what the type of the check. This can be used
 
50
to indicate that a value was missing, and so holds no useful value.
 
51
 
 
52
Functions either return a new value, or raise an exception. See `Validator
 
53
Exceptions`_ for the low down on the exception classes that ``validate.py``
 
54
defines.
 
55
 
 
56
Some standard functions are provided, for basic data types; these come built
 
57
into every validator. Additional checks are easy to write: they can be provided
 
58
when the ``Validator`` is instantiated, or added afterwards.
 
59
 
 
60
Validate was primarily written to support ConfigObj_, but is designed to be 
 
61
applicable to many other situations.
 
62
 
 
63
For support and bug reports please use the ConfigObj `Mailing List`_.
 
64
 
 
65
.. _ConfigObj: http://www.voidspace.org.uk/python/configobj.html
 
66
 
 
67
 
 
68
Downloading
 
69
===========
 
70
 
 
71
The current version is **0.3.2**, dated 24th February 2008. 
 
72
 
 
73
You can get obtain validate in the following ways :
 
74
 
 
75
 
 
76
Files
 
77
-----
 
78
 
 
79
* validate.py_ from Voidspace
 
80
 
 
81
* configobj.zip from Voidspace - See the homepage of ConfigObj_ for the latest 
 
82
  version and download links.
 
83
 
 
84
    This contains validate.py and `this document`_. (As well as ConfigObj_ and 
 
85
    the ConfigObj documentation).
 
86
    
 
87
* The latest development version can be obtained from the `Subversion Repository`_.
 
88
 
 
89
 
 
90
Documentation
 
91
-------------
 
92
 
 
93
*configobj.zip* contains `this document`_.
 
94
 
 
95
* You can view `this document`_ online as the `Validate Homepage`_.
 
96
 
 
97
 
 
98
Pythonutils
 
99
-----------
 
100
 
 
101
Validate_ is also part of the Pythonutils_ set of modules. This contains 
 
102
various other useful helper modules, and is required by many of the `Voidspace 
 
103
Python Projects`_.
 
104
 
 
105
.. _configobj.py: http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=configobj.py
 
106
.. _configobj.zip: http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=configobj-4.5.2.zip
 
107
.. _validate.py: http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=validate.py
 
108
.. _Subversion Repository: http://svn.pythonutils.python-hosting.com/trunk/pythonutils/
 
109
.. _Sourceforge: http://sourceforge.net/projects/configobj
 
110
.. _pythonutils: http://www.voidspace.org.uk/python/pythonutils.html
 
111
.. _Voidspace Python Projects: http://www.voidspace.org.uk/python
 
112
.. _validate: http://www.voidspace.org.uk/python/validate.html
 
113
 
 
114
 
 
115
The standard functions
 
116
======================
 
117
 
 
118
The standard functions come built-in to every ``Validator`` instance. They work
 
119
with the following basic data types :
 
120
 
 
121
* integer
 
122
* float
 
123
* boolean
 
124
* string
 
125
* ip_addr
 
126
 
 
127
plus lists of these datatypes.
 
128
 
 
129
Adding additional checks is done through coding simple functions.
 
130
 
 
131
The full set of standard checks are :
 
132
 
 
133
:'integer': matches integer values (including negative). Takes optional 'min'
 
134
            and 'max' arguments : ::
 
135
 
 
136
                integer()
 
137
                integer(3, 9)    # any value from 3 to 9
 
138
                integer(min=0) # any positive value
 
139
                integer(max=9)
 
140
 
 
141
:'float': matches float values
 
142
          Has the same parameters as the integer check.
 
143
 
 
144
:'boolean': matches boolean values: ``True`` or ``False``.
 
145
            Acceptable string values for True are : ::
 
146
 
 
147
             true, on, yes, 1
 
148
 
 
149
         Acceptable string values for False are : ::
 
150
 
 
151
             false, off, no, 0
 
152
 
 
153
         Any other value raises an error.
 
154
 
 
155
:'string': matches any string. Takes optional keyword args 'min' and 'max' to
 
156
           specify min and max length of string.
 
157
 
 
158
:'ip_addr': matches an Internet Protocol address, v.4, represented by a
 
159
            dotted-quad string, i.e. '1.2.3.4'.
 
160
 
 
161
:'list': matches any list. Takes optional keyword args 'min', and 'max' to
 
162
         specify min and max sizes of the list. The list checks always 
 
163
         return a list.
 
164
         
 
165
:'tuple': matches any list. This check returns a tuple rather than a list.
 
166
 
 
167
:'int_list': Matches a list of integers. Takes the same arguments as list.
 
168
 
 
169
:'float_list': Matches a list of floats. Takes the same arguments as list.
 
170
 
 
171
:'bool_list': Matches a list of boolean values. Takes the same arguments as
 
172
              list.
 
173
 
 
174
:'string_list': Matches a list of strings. Takes the same arguments as list.
 
175
 
 
176
:'ip_addr_list': Matches a list of IP addresses. Takes the same arguments as
 
177
                 list.
 
178
 
 
179
:'mixed_list': Matches a list with different types in specific positions.
 
180
               List size must match the number of arguments.
 
181
 
 
182
               Each position can be one of : ::
 
183
 
 
184
                   int, str, boolean, float, ip_addr
 
185
 
 
186
               So to specify a list with two strings followed by two integers,
 
187
               you write the check as : ::
 
188
 
 
189
                   mixed_list(str, str, int, int)
 
190
 
 
191
:'pass': matches everything: it never fails and the value is unchanged. It is
 
192
         also the default if no check is specified.
 
193
 
 
194
:'option': matches any from a list of options.
 
195
           You specify this test with : ::
 
196
 
 
197
               option('option 1', 'option 2', 'option 3')
 
198
 
 
199
The following code will work without you having to specifically add the
 
200
functions yourself.
 
201
 
 
202
.. raw:: html
 
203
 
 
204
    {+coloring}
 
205
 
 
206
    from validate import Validator
 
207
    #
 
208
    vtor = Validator()
 
209
    newval1 = vtor.check('integer', value1)
 
210
    newval2 = vtor.check('boolean', value2)
 
211
    # etc ...
 
212
 
 
213
    {-coloring}
 
214
 
 
215
.. note::
 
216
 
 
217
    Of course, if these checks fail they raise exceptions. So you should wrap
 
218
    them in ``try...except`` blocks. Better still,  use ConfigObj for a higher
 
219
    level interface.
 
220
 
 
221
 
 
222
Using Validator
 
223
===============
 
224
 
 
225
Using ``Validator`` is very easy. It has one public attribute and one public
 
226
method.
 
227
 
 
228
Shown below are the different steps in using ``Validator``.
 
229
 
 
230
The only additional thing you need to know, is about `Writing check
 
231
functions`_.
 
232
 
 
233
Instantiate
 
234
-----------
 
235
 
 
236
.. raw:: html
 
237
 
 
238
    {+coloring}
 
239
 
 
240
    from validate import Validator
 
241
    vtor = Validator()
 
242
 
 
243
    {-coloring}
 
244
 
 
245
or even :
 
246
 
 
247
.. raw:: html
 
248
 
 
249
    {+coloring}
 
250
 
 
251
    from validate import Validator
 
252
    #
 
253
    fdict = {
 
254
        'check_name1': function1,
 
255
        'check_name2': function2,
 
256
        'check_name3': function3,
 
257
    }
 
258
    #
 
259
    vtor = Validator(fdict)
 
260
 
 
261
    {-coloring}
 
262
 
 
263
The second method adds a set of your functions as soon as your validator is
 
264
created. They are stored in the ``vtor.functions`` dictionary. The 'key' you
 
265
give them in this dictionary is the name you use in your checks (not the
 
266
original function name).
 
267
 
 
268
Dictionary keys/functions you pass in can override the built-in ones if you
 
269
want.
 
270
 
 
271
 
 
272
Adding functions
 
273
----------------
 
274
 
 
275
The code shown above, for adding functions on instantiation, has exactly the
 
276
same effect as the following code :
 
277
 
 
278
.. raw:: html
 
279
 
 
280
    {+coloring}
 
281
 
 
282
    from validate import Validator
 
283
    #
 
284
    vtor = Validator()
 
285
    vtor.functions['check_name1'] = function1
 
286
    vtor.functions['check_name2'] = function2
 
287
    vtor.functions['check_name3'] = function3
 
288
 
 
289
    {-coloring}
 
290
 
 
291
``vtor.functions`` is just a dictionary that maps names to functions, so we
 
292
could also have called ``vtor.functions.update(fdict)``.
 
293
 
 
294
 
 
295
Writing the check
 
296
-----------------
 
297
 
 
298
As we've heard, the checks map to the names in the ``functions`` dictionary.
 
299
You've got a full list of `The standard functions`_ and the arguments they
 
300
take.
 
301
 
 
302
If you're using ``Validator`` from ConfigObj, then your checks will look like
 
303
: ::
 
304
 
 
305
    keyword = int_list(max=6)
 
306
 
 
307
but the check part will be identical .
 
308
 
 
309
 
 
310
The check method
 
311
----------------
 
312
 
 
313
If you're not using ``Validator`` from ConfigObj, then you'll need to call the
 
314
``check`` method yourself.
 
315
 
 
316
If the check fails then it will raise an exception, so you'll want to trap
 
317
that. Here's the basic example :
 
318
 
 
319
.. raw:: html
 
320
 
 
321
    {+coloring}
 
322
 
 
323
    from validate import Validator, ValidateError
 
324
    #
 
325
    vtor = Validator()
 
326
    check = "integer(0, 9)"
 
327
    value = 3
 
328
    try:
 
329
        newvalue = vtor.check(check, value)
 
330
    except ValidateError:
 
331
        print 'Check Failed.'
 
332
    else:
 
333
        print 'Check passed.'
 
334
 
 
335
    {-coloring}
 
336
 
 
337
.. caution::
 
338
 
 
339
    Although the value can be a string, if it represents a list it should
 
340
    already have been turned into a list of strings.
 
341
 
 
342
 
 
343
Default Values
 
344
~~~~~~~~~~~~~~
 
345
 
 
346
Some values may not be available, and you may want to be able to specify a
 
347
default as part of the check.
 
348
 
 
349
You do this by passing the keyword ``missing=True`` to the ``check`` method, as
 
350
well as a ``default=value`` in the check. (Constructing these checks is done
 
351
automatically by ConfigObj: you only need to know about the ``default=value``
 
352
part) :
 
353
 
 
354
.. raw:: html
 
355
 
 
356
    {+coloring}
 
357
 
 
358
    check1 = 'integer(default=50)'
 
359
    check2 = 'option("val 1", "val 2", "val 3", default="val 1")'
 
360
 
 
361
    assert vtor.check(check1, '', missing=True) == 50
 
362
    assert vtor.check(check2, '', missing=True) == "val 1"
 
363
 
 
364
    {-coloring}
 
365
 
 
366
If you pass in ``missing=True`` to the check method, then the actual value is
 
367
ignored. If no default is specified in the check, a ``ValidateMissingValue``
 
368
exception is raised. If a default is specified then that is passed to the
 
369
check instead.
 
370
 
 
371
If the check has ``default=None`` (case sensitive) then ``vtor.check`` will
 
372
*always* return ``None`` (the object). This makes it easy to tell your program
 
373
that this check contains no useful value when missing, i.e. the value is
 
374
optional, and may be omitted without harm.
 
375
 
 
376
 
 
377
.. note:: 
 
378
 
 
379
    As of version 0.3.0, if you specify ``default='None'`` (note the quote marks
 
380
    around ``None``) then it will be interpreted as the string ``'None'``.
 
381
 
 
382
 
 
383
List Values
 
384
~~~~~~~~~~~
 
385
 
 
386
It's possible that you would like your default value to be a list. It's even
 
387
possible that you will write your own check functions - and would like to pass
 
388
them keyword arguments as lists from within the check.
 
389
 
 
390
To avoid confusing syntax with commas and quotes you use a list constructor to
 
391
specify that keyword arguments are lists. This includes the ``default`` value.
 
392
This makes checks look something like : ::
 
393
 
 
394
    checkname(default=list('val1', 'val2', 'val3'))
 
395
 
 
396
 
 
397
get_default_value
 
398
-----------------
 
399
 
 
400
``Validator`` instances have a ``get_default_value`` method. It takes a ``check`` string 
 
401
(the same string you would pass to the ``check`` method) and returns the default value,
 
402
converted to the right type. If the check doesn't define a default value then this method
 
403
raises a ``KeyError``.
 
404
 
 
405
If the ``check`` has been seen before then it will have been parsed and cached already, 
 
406
so this method is not expensive to call (however the conversion is done each time).
 
407
 
 
408
 
 
409
 
 
410
Validator Exceptions
 
411
====================
 
412
 
 
413
.. note::
 
414
 
 
415
    If you only use Validator through ConfigObj, it traps these Exceptions for
 
416
    you. You will still need to know about them for writing your own check
 
417
    functions.
 
418
 
 
419
``vtor.check`` indicates that the check has failed by raising an exception.
 
420
The appropriate error should be raised in the check function.
 
421
 
 
422
The base error class is ``ValidateError``. All errors (except for ``VdtParamError``) 
 
423
raised are sub-classes of this.
 
424
 
 
425
If an unrecognised check is specified then ``VdtUnknownCheckError`` is
 
426
raised.
 
427
 
 
428
There are also ``VdtTypeError`` and ``VdtValueError``.
 
429
 
 
430
If incorrect parameters are passed to a check function then it will (or should)
 
431
raise ``VdtParamError``. As this indicates *programmer* error, rather than an error
 
432
in the value, it is a subclass of ``SyntaxError`` instead of ``ValidateError``. 
 
433
 
 
434
.. note::
 
435
 
 
436
    This means it *won't* be caught by ConfigObj - but propagated instead.
 
437
 
 
438
If the value supplied is the wrong type, then the check should raise
 
439
``VdtTypeError``. e.g. the check requires the value to be an integer (or
 
440
representation of an integer) and something else was supplied.
 
441
 
 
442
If the value supplied is the right type, but an unacceptable value, then the
 
443
check should raise ``VdtValueError``. e.g. the check requires the value to
 
444
be an integer (or representation of an integer) less than ten and a higher
 
445
value was supplied.
 
446
 
 
447
Both ``VdtTypeError`` and ``VdtValueError`` are initialised with the
 
448
incorrect value. In other words you raise them like this :
 
449
 
 
450
.. raw:: html
 
451
 
 
452
    {+coloring}
 
453
 
 
454
    raise VdtTypeError(value)
 
455
    #
 
456
    raise VdtValueError(value)
 
457
 
 
458
    {-coloring}
 
459
 
 
460
``VdtValueError`` has the following subclasses, which should be raised if
 
461
they are more appropriate.
 
462
 
 
463
* ``VdtValueTooSmallError``
 
464
* ``VdtValueTooBigError``
 
465
* ``VdtValueTooShortError``
 
466
* ``VdtValueTooLongError``
 
467
 
 
468
 
 
469
Writing check functions
 
470
=======================
 
471
 
 
472
Writing check functions is easy.
 
473
 
 
474
The check function will receive the value as its first argument, followed by
 
475
any other parameters and keyword arguments.
 
476
 
 
477
If the check fails, it should raise a ``VdtTypeError`` or a
 
478
``VdtValueError`` (or an appropriate subclass).
 
479
 
 
480
All parameters and keyword arguments are *always* passed as strings. (Parsed
 
481
from the check string).
 
482
 
 
483
The value might be a string (or list of strings) and need
 
484
converting to the right type - alternatively it might already be a list of 
 
485
integers. Our function needs to be able to handle either.
 
486
 
 
487
If the check passes then it should return the value (possibly converted to the
 
488
right type).
 
489
 
 
490
And that's it !
 
491
 
 
492
 
 
493
Example
 
494
-------
 
495
 
 
496
Here is an example function that requires a list of integers. Each integer
 
497
must be between 0 and 99.
 
498
 
 
499
It takes a single argument specifying the length of the list. (Which allows us
 
500
to use the same check in more than one place). If the length can't be converted
 
501
to an integer then we need to raise ``VdtParamError``.
 
502
 
 
503
Next we check that the value is a list. Anything else should raise a
 
504
``VdtTypeError``. The list should also have 'length' entries. If the list
 
505
has more or less entries then we will need to raise a
 
506
``VdtValueTooShortError`` or a ``VdtValueTooLongError``.
 
507
 
 
508
Then we need to check every entry in the list. Each entry should be an integer
 
509
between 0 and 99, or a string representation of an integer between 0 and 99.
 
510
Any other type is a ``VdtTypeError``, any other value is a
 
511
``VdtValueError`` (either too big, or too small).
 
512
 
 
513
.. raw:: html
 
514
 
 
515
    {+coloring}
 
516
 
 
517
    def special_list(value, length):
 
518
        """
 
519
        Check that the supplied value is a list of integers,
 
520
        with 'length' entries, and each entry between 0 and 99.
 
521
        """
 
522
        # length is supplied as a string
 
523
        # we need to convert it to an integer
 
524
        try:
 
525
            length = int(length)
 
526
        except ValueError:
 
527
            raise VdtParamError('length', length)
 
528
        #
 
529
        # Check the supplied value is a list
 
530
        if not isinstance(value, list):
 
531
            raise VdtTypeError(value)
 
532
        #
 
533
        # check the length of the list is correct
 
534
        if len(value) > length:
 
535
            raise VdtValueTooLongError(value)
 
536
        elif len(value) < length:
 
537
            raise VdtValueTooShortError(value)
 
538
        #
 
539
        # Next, check every member in the list
 
540
        # converting strings as necessary
 
541
        out = []
 
542
        for entry in value:
 
543
            if not isinstance(entry, (str, unicode, int)):
 
544
                # a value in the list
 
545
                # is neither an integer nor a string
 
546
                raise VdtTypeError(value)
 
547
            elif isinstance(entry, (str, unicode)):
 
548
                if not entry.isdigit():
 
549
                    raise VdtTypeError(value)
 
550
                else:
 
551
                    entry = int(entry)
 
552
            if entry < 0:
 
553
                raise VdtValueTooSmallError(value)
 
554
            elif entry > 99:
 
555
                raise VdtValueTooBigError(value)
 
556
            out.append(entry)
 
557
        #
 
558
        # if we got this far, all is well
 
559
        # return the new list
 
560
        return out
 
561
 
 
562
    {-coloring}
 
563
 
 
564
If you are only using validate from ConfigObj then the error type (*TooBig*, 
 
565
*TooSmall*, etc) is lost - so you may only want to raise ``VdtValueError``.
 
566
 
 
567
.. caution::
 
568
 
 
569
    If your function raises an exception that isn't a subclass of 
 
570
    ``ValidateError``, then ConfigObj won't trap it. This means validation will 
 
571
    fail.
 
572
    
 
573
    This is why our function starts by checking the type of the value. If we 
 
574
    are passed the wrong type (e.g. an integer rather than a list) we get a 
 
575
    ``VdtTypeError`` rather than bombing out when we try to iterate over 
 
576
    the value.
 
577
 
 
578
If you are using validate in another circumstance you may want to create your 
 
579
own subclasses of ``ValidateError``, that convey more specific information.
 
580
 
 
581
 
 
582
Known Issues
 
583
============
 
584
 
 
585
The following parses and then blows up. The resulting error message
 
586
is confusing:
 
587
 
 
588
    ``checkname(default=list(1, 2, 3, 4)``
 
589
    
 
590
This is because it parses as: ``checkname(default="list(1", 2, 3, 4)``.
 
591
That isn't actually unreasonable, but the error message won't help you
 
592
work out what has happened.
 
593
    
 
594
 
 
595
TODO
 
596
====
 
597
 
 
598
* A regex check function ?
 
599
* A timestamp check function ? (Using the ``parse`` function from ``DateUtil`` perhaps).
 
600
 
 
601
 
 
602
ISSUES
 
603
======
 
604
 
 
605
.. note::
 
606
 
 
607
    Please file any bug reports to `Michael Foord`_ or the ConfigObj
 
608
    `Mailing List`_.
 
609
 
 
610
If we could pull tuples out of arguments, it would be easier
 
611
to specify arguments for 'mixed_lists'.
 
612
 
 
613
 
 
614
CHANGELOG
 
615
=========
 
616
 
 
617
2008/02/24 - Version 0.3.2
 
618
--------------------------
 
619
 
 
620
BUGFIX: Handling of None as default value fixed.
 
621
 
 
622
 
 
623
2008/02/05 - Version 0.3.1
 
624
--------------------------
 
625
 
 
626
BUGFIX: Unicode checks no longer broken.
 
627
 
 
628
 
 
629
2008/02/05 - Version 0.3.0
 
630
--------------------------
 
631
 
 
632
Improved performance with a parse cache.
 
633
 
 
634
New ``get_default_value`` method. Given a check it returns the default
 
635
value (converted to the correct type) or raises a ``KeyError`` if the
 
636
check doesn't specify a default.
 
637
 
 
638
Added 'tuple' check and corresponding 'is_tuple' function (which always returns a tuple).
 
639
 
 
640
BUGFIX: A quoted 'None' as a default value is no longer treated as None,
 
641
but as the string 'None'.
 
642
 
 
643
BUGFIX: We weren't unquoting keyword arguments of length two, so an
 
644
empty string didn't work as a default.
 
645
 
 
646
BUGFIX: Strings no longer pass the 'is_list' check. Additionally, the
 
647
list checks always return lists.
 
648
 
 
649
A couple of documentation bug fixes.
 
650
 
 
651
Removed CHANGELOG from module.
 
652
 
 
653
 
 
654
2007/02/04      Version 0.2.3
 
655
-----------------------------
 
656
 
 
657
Release of 0.2.3
 
658
 
 
659
 
 
660
2006/12/17      Version 0.2.3-alpha1
 
661
------------------------------------
 
662
 
 
663
By Nicola Larosa
 
664
 
 
665
Fixed validate doc to talk of ``boolean`` instead of ``bool``; changed the
 
666
``is_bool`` function to ``is_boolean`` (Sourceforge bug #1531525).
 
667
 
 
668
 
 
669
2006/04/29      Version 0.2.2
 
670
-----------------------------
 
671
 
 
672
Addressed bug where a string would pass the ``is_list`` test. (Thanks to
 
673
Konrad Wojas.)
 
674
 
 
675
 
 
676
2005/12/16      Version 0.2.1
 
677
-----------------------------
 
678
 
 
679
Fixed bug so we can handle keyword argument values with commas.
 
680
 
 
681
We now use a list constructor for passing list values to keyword arguments
 
682
(including ``default``) : ::
 
683
 
 
684
    default=list("val", "val", "val")
 
685
 
 
686
Added the ``_test`` test. {sm;:-)}
 
687
 
 
688
Moved a function call outside a try...except block.
 
689
 
 
690
 
 
691
2005/08/18      Version 0.2.0
 
692
-----------------------------
 
693
 
 
694
Updated by `Michael Foord`_ and `Nicola Larosa`_
 
695
 
 
696
Does type conversion as well.
 
697
 
 
698
 
 
699
2005/02/01      Version 0.1.0
 
700
-----------------------------
 
701
 
 
702
Initial version developed by `Michael Foord`_
 
703
and Mark Andrews.
 
704
 
 
705
.. note::
 
706
 
 
707
    Rendering this document with docutils also needs the
 
708
    textmacros module and the PySrc CSS stuff. See
 
709
    http://www.voidspace.org.uk/python/firedrop2/textmacros.shtml
 
710
 
 
711
 
 
712
.. raw:: html
 
713
 
 
714
    <div align="center">
 
715
        <p>
 
716
            <a href="http://www.python.org">
 
717
                <img src="images/new_python.gif" width="100" height="103" border="0" 
 
718
                    alt="Powered by Python" />
 
719
            </a>
 
720
            <a href="http://sourceforge.net">
 
721
                <img src="http://sourceforge.net/sflogo.php?group_id=123265&amp;type=1" width="88" height="31" border="0" alt="SourceForge.net Logo" />
 
722
            </a>
 
723
            <a href="http://www.opensource.org">
 
724
                <img src="images/osi-certified-120x100.gif" width="120" height="100" border="0"
 
725
                    alt="Certified Open Source"/>
 
726
            </a>
 
727
        </p>
 
728
        <p>
 
729
            <a href="http://www.voidspace.org.uk/python/index.shtml">
 
730
                <img src="images/pythonbanner.gif" width="468" height="60" 
 
731
                alt="Python on Voidspace" border="0" />
 
732
            </a>
 
733
        </p>
 
734
    </div>
 
735