~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Patch Queue Manager
  • Date: 2016-04-21 04:10:52 UTC
  • mfrom: (6616.1.1 fix-en-user-guide)
  • Revision ID: pqm@pqm.ubuntu.com-20160421041052-clcye7ns1qcl2n7w
(richard-wilbur) Ensure build of English use guide always uses English text
 even when user's locale specifies a different language. (Jelmer Vernooij)

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