/[theodore]/pyBB/modules/configobj.pyc


UCC Code Repository

Contents of /pyBB/modules/configobj.pyc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations) (download) (as text)
Tue Jan 29 14:32:01 2008 UTC (12 years, 2 months ago) by svn-admin
File MIME type: application/octet-stream
File size: 63146 byte(s)
Re-import of repository after repository database corruption.

1 m
2 ,Gc@sdZdkZeid ZeddfjoedndkZdkZdklZdZ dZ
3 dZ dZ d d
4 d d d ddddddddddddfZ dZdZdZhde<de<de<d e<d!e<d"e<d#e<d$e<Zdefd%YZdefd&YZdefd'YZdefd(YZdefd)YZdefd*YZdefd+YZdefd,YZdefd-YZd.efd/YZ de fd0YZ!de"fd1YZ#d2Z$e%d3jod4Z&d5Z'd6Z(dk)Z)ei*i+d3Z,e,i-i.Z/e!e&i0d7deZ1e!e'i0d7deZ2e!e(i0d7deZ3e/i4hd8e<d9e1<d:e2<d;e3<e)i5e,d<e/ndS(=s
5 >>> z = ConfigObj()
6 >>> z['a'] = 'a'
7 >>> z['sect'] = {
8 ... 'subsect': {
9 ... 'a': 'fish',
10 ... 'b': 'wobble',
11 ... },
12 ... 'member': 'value',
13 ... }
14 >>> x = ConfigObj(z.write())
15 >>> z == x
16 1
17 NisPython v.2.2 or later needed(s StringTypesss4.0.0s5$Id: configobj.py 140 2005-10-20 10:04:58Z fuzzyman $srestructuredtext ent __version__tBOM_UTF8tDEFAULT_INDENT_TYPEtNUM_INDENT_SPACEStMAX_INTERPOL_DEPTHtConfigObjErrort NestingErrort
18 ParseErrortDuplicateErrortConfigspecErrort ConfigObjt SimpleValtInterpolationErrortInterpolationDepthErrortMissingInterpolationOptiontRepeatSectionErrort __docformat__t ii
19 t interpolationt raise_errorst list_valuest create_emptyt
20 file_errort
21 configspect stringifyt indent_typecBs tZdZdeddZRS(s
22 This is the base class for all errors that ConfigObj raises.
23 It is a subclass of SyntaxError.
24
25 >>> raise ConfigObjError
26 Traceback (most recent call last):
27 ConfigObjError
28 tcCs/||_||_||_ti||dS(N(tlinetselft line_numbertmessaget SyntaxErrort__init__(RRRR((t./modules/configobj.pyR _s   (t__name__t
29 __module__t__doc__tNoneR (((R!RVs cBstZdZRS(s
30 This error indicates a level of nesting that doesn't match.
31
32 >>> raise NestingError
33 Traceback (most recent call last):
34 NestingError
35 (R"R#R$(((R!Res cBstZdZRS(s
36 This error indicates that a line is badly written.
37 It is neither a valid ``key = value`` line,
38 nor a valid section marker line.
39
40 >>> raise ParseError
41 Traceback (most recent call last):
42 ParseError
43 (R"R#R$(((R!Rns cBstZdZRS(s
44 The keyword or section specified already exists.
45
46 >>> raise DuplicateError
47 Traceback (most recent call last):
48 DuplicateError
49 (R"R#R$(((R!Rys cBstZdZRS(s
50 An error occured whilst parsing a configspec.
51
52 >>> raise ConfigspecError
53 Traceback (most recent call last):
54 ConfigspecError
55 (R"R#R$(((R!R s cBstZdZRS(s,Base class for the two interpolation errors.(R"R#R$(((R!R s cBstZdZdZRS(s=Maximum interpolation depth exceeded in string interpolation.cCsti|d|dS(s
56 >>> raise InterpolationDepthError('yoda')
57 Traceback (most recent call last):
58 InterpolationDepthError: max interpolation depth exceeded in value "yoda".
59 s/max interpolation depth exceeded in value "%s".N(R R Rtoption(RR&((R!R s (R"R#R$R (((R!R s cBstZdZRS(s
60 This error indicates additional sections in a section with a
61 ``__many__`` (repeated) section.
62
63 >>> raise RepeatSectionError
64 Traceback (most recent call last):
65 RepeatSectionError
66 (R"R#R$(((R!Rs cBstZdZdZRS(s0A value specified for interpolation was missing.cCsti|d|dS(s
67 >>> raise MissingInterpolationOption('yoda')
68 Traceback (most recent call last):
69 MissingInterpolationOption: missing option "yoda" in interpolation.
70 s%missing option "%s" in interpolation.N(R R RR&(RR&((R!R s (R"R#R$R (((R!Rs tSectioncBstZdZeidZeedZdZdZ dZ
71 dZ dZ edZ d Zd
72 Zd Zd Zed ZdZdZdZdZdZeZdZdZeZdZdZeedZ dZ!dZ"RS(sO
73 A dictionary-like object that represents a section in a config file.
74
75 It does string interpolation if the 'interpolate' attribute
76 of the 'main' object is set to True.
77
78 Interpolation is tried first from the 'DEFAULT' section of this object,
79 next from the 'DEFAULT' section of the parent, lastly the main object.
80
81 A Section will behave like an ordered dictionary - following the
82 order of the ``scalars`` and ``sections`` attributes.
83 You can use this to change the order of members.
84
85 Iteration follows the order: scalars, then sections.
86 s%\(([^)]*)\)s|.cCs|djo
87 h}nti|||_||_||_g|_g|_ ||_
88 h|_ h|_ h|_ g|_x|D]}||||<qWdS(s
89 parent is the section above
90 depth is the depth level of this section
91 main is the main ConfigObj
92 indict is a dictionary to initialise the section with
93 N(tindictR%tdictR Rtparenttmaintdepthtscalarstsectionstnametcommentstinline_commentsRtdefaultstentry(RR*R,R+R(R/R3((R!R s" 
94            cCsbt}xU|oA|d8}|iddjo|ii|i|}q Pq Wt||S(sNicked from ConfigParser.is%(iN( RR,tvaluetfindRt_KEYCREtsubt_interpolation_replaceR (RR4R,((R!t _interpolates
95  cCs|id}|djo|iSnt|i_|idhi|}|djo"|i
96 idhi|}n|djo"|iidhi|}nt |i_|djot |n|SdS(RitDEFAULTN( tmatchtgrouptsR%tFalseRR+RtgettvalR*tTrueR(RR;R@R=((R!R8s   " "  cCsDti||}|iio!t|to|i |Sn|S(s+Fetch the item and do string interpolation.N(
97 R)t __getitem__RtkeyR@R+Rt
98 isinstancet StringTypesR9(RRCR@((R!RB s
99 c Cst|tptd|n|ii|pg|i|<d|i|<n||ijo|ii |nt|t o;|i|p|i i |nti|||n)t|toc|i|p|i i |n|id}ti||t |||id|d|n|i|p|ii |n|iipqt|toqt|ttfo6x@|D]'}t|tptd|qqWqtd|nti|||dS(s9
100 Correctly set a value.
101
102 Making dictionary values Section instances.
103 (We have to special case 'Section' instances - which are also dicts)
104
105 Keys must be strings.
106 Values need only be strings (or lists of strings) if
107 ``main.stringify`` is set.
108 sThe key "%s" is not a string.RiR(R/sValue is not a string "%s".N(RDRCREt
109 ValueErrorRR0thas_keyR1R2tremoveR4R'R.tappendR)t __setitem__R,t new_depthR+R-RtlistttupleR3t TypeError(RRCR4RKR3((R!RJsF
110     cCs\ti||||ijo|ii|n|ii||i|=|i|=dS(s-Remove items from the sequence when deleting.N( R)t __delitem__RRCR-RHR.R0R1(RRC((R!ROKs
111 cCs*y ||SWntj
112 o |SnXdS(s>A version of ``get`` that doesn't bypass string interpolation.N(RRCtKeyErrortdefault(RRCRQ((R!R?Us
113  cCs#x|D]}||||<qWdS(s2A version of update that uses our ``__setitem__``.N(R(R3R(RR(R3((R!tupdate\scGsti|||}||ijo(|i|=|i|=|ii |n9||i
114 jo(|i|=|i|=|i
115 i |n|i i o!t |to|i|Sn|S(RN(R)tpopRRCtargsR@R-R0R1RHR.R+RRDRER9(RRCRTR@((R!RSas
116 
117 
118 
119 cCsI|i|i}|p tdn|d}||}||=||fS(sPops the first (key,val)s": 'popitem(): dictionary is empty'iN(RR-R.tsequenceRPRCR@(RR@RCRU((R!tpopitemps 
120 
121 cCs>ti|g|_g|_h|_h|_h|_dS(s
122 A version of clear that also affects scalars/sections
123 Also clears comments and configspec.
124
125 Leaves other attributes alone :
126 depth/main/parent are not affected
127 N(R)tclearRR-R.R0R1R(R((R!RWzs     cCs8y ||SWn%tj
128 o|||<||SnXdS(s:A version of setdefault that sets sequence if appropriate.N(RRCRPRQ(RRCRQ((R!t
129 setdefaults  
130 cCst|i|i|iS(RN(tzipRR-R.tvalues(R((R!titemsscCs|i|iS(RN(RR-R.(R((R!tkeysscCs-g}|i|iD]}|||q~S(RN(t_[1]RR-R.RC(RR]RC((R!RZscCst|iS(RN(titerRR[(R((R!t iteritemsscCst|i|iS(RN(R^RR-R.(R((R!titerkeysscCst|iS(RN(R^RRZ(R((R!t
131 itervaluessc
132 CsPddig}|i|iD]'}|dt|t||fq~S(Ns{%s}s, s%s: %s(tjoinR]RR-R.RCtrepr(RR]RC((R!t__repr__scCsuh}xh|D]`}||}t|to|i}n't|ttfot|}n|||<q W|S(s0
133 Return a deepcopy of self as a dictionary.
134
135 All members that are ``Section`` instances are recursively turned to
136 ordinary dictionaries - by calling their ``dict`` method.
137
138 >>> n = a.dict()
139 >>> n == a
140 1
141 >>> n is a
142 0
143 N( tnewdictRR3t
144 this_entryRDR'R)RLRM(RReRfR3((R!R)s 
145 cCs||ijo |i}n+||ijo |i}ntd||i|}||}t i
146 ||t i ||||i ||i|||i|}|i|}|i|=|i|=||i|<||i|<dS(s
147 Change a keyname to another, without changing position in sequence.
148
149 Implemented so that transformations can be made on keys,
150 as well as on values. (used by encode and decode)
151
152 Also renames comments.
153 sKey "%s" not found.N(toldkeyRR-tthe_listR.RPtindextposR@R)RORJtnewkeyRHtinsertR0tcommR1tinline_comment(RRgRkRmR@RnRjRh((R!trenames$   
154    
155 
156  cKsh}xZ|iD]N}y||||||<Wqtj
157 o|oq_t||<qXqWx|i D]y}|oFy||||Wqtj
158 o|oqt||<qXn||i |d|d||||<qnW|S(s
159 Walk every member and call a function on the keyword and value.
160
161 Return a dictionary of the return values
162
163 If the function raises an exception, raise the errror
164 unless ``raise_errors=False``, in which case set the return value to
165 ``False``.
166
167 Any unrecognised keyword arguments you pass to walk, will be pased on
168 to the function you pass in.
169
170 Note: if ``call_on_sections`` is ``True`` then - on encountering a
171 subsection, *first* the function is called for the *whole* subsection,
172 and then recurses into it's members. This means your function must be
173 able to handle strings, dictionaries and lists. This allows you
174 to change the key of subsections as well as for ordinary members. The
175 return value when called on the whole subsection has to be discarded.
176
177 See the encode and decode methods for examples, including functions.
178 Rtcall_on_sectionsN( toutRR-R3tfunctiontkeywargst ExceptionRR>R.Rptwalk(RRrRRpRsR3Rq((R!Rus.   cCs#|d}|i|dtdS(sK
179 Decode all strings and values to unicode, using the specified encoding.
180
181 Works with subsections and list values.
182
183 Uses the ``walk`` method.
184
185 Testing ``encode`` and ``decode``.
186 >>> m = ConfigObj(a)
187 >>> m.decode('ascii')
188 >>> def testuni(val):
189 ... for entry in val:
190 ... if not isinstance(entry, unicode):
191 ... print >> sys.stderr, type(entry)
192 ... raise AssertionError, 'decode failed.'
193 ... if isinstance(val[entry], dict):
194 ... testuni(val[entry])
195 ... elif not isinstance(val[entry], unicode):
196 ... raise AssertionError, 'decode failed.'
197 >>> testuni(m)
198 >>> m.encode('ascii')
199 >>> a == m
200 1
201 cCs||}t|ttfo1g}xQ|D]}|i|i |q-Wn*t|t o
202 |}n|i |}|i |}|i |||||<dS(RN(tsectionRCR@RDRLRMtnewvalR3RItdecodetencodingR)RkRo(RvRCRyRkR@RwR3((R!Rx4s
203 
204 RpN(RyRxRRuRA(RRyRx((R!Rxs cCs#|d}|i|dtdS(s
205 Encode all strings and values from unicode,
206 using the specified encoding.
207
208 Works with subsections and list values.
209 Uses the ``walk`` method.
210 cCs||}t|ttfo1g}xQ|D]}|i|i |q-Wn*t|t o
211 |}n|i |}|i |}|i |||||<dS(RN(RvRCR@RDRLRMRwR3RItencodeRyR)RkRo(RvRCRyRkR@RwR3((R!RzMs
212 
213 RpN(RyRzRRuRA(RRyRz((R!RzEs (#R"R#R$tretcompileR6R%R R9R8RBRJROR?RRRSRVRWRXR[R\RZR_R`t__iter__RaRdt__str__R)RoRAR>RuRxRz(((R!R's8 #    9
214   
215           3 *cBstZdZeideiZeideiZeideiZeideiZ eideiZ
216 eidZ eidZ eidZ eid Zhd
217 e e f<d e ef<Zeed Zd ZdZdZdZedZdZdZdZdZdZdZdZdZdZ edZ!edZ"RS(s 
218 An object to read, create, and write config files.
219
220 Testing with duplicate keys and sections.
221
222 >>> c = '''
223 ... [hello]
224 ... member = value
225 ... [hello again]
226 ... member = value
227 ... [ "hello" ]
228 ... member = value
229 ... '''
230 >>> ConfigObj(c.split('\n'), raise_errors = True)
231 Traceback (most recent call last):
232 DuplicateError: Duplicate section name at line 5.
233
234 >>> d = '''
235 ... [hello]
236 ... member = value
237 ... [hello again]
238 ... member1 = value
239 ... member2 = value
240 ... 'member1' = value
241 ... [ "and again" ]
242 ... member = value
243 ... '''
244 >>> ConfigObj(d.split('\n'), raise_errors = True)
245 Traceback (most recent call last):
246 DuplicateError: Duplicate keyword name at line 6.
247 s^ # line start
248 (\s*) # indentation
249 ( # keyword
250 (?:".*?")| # double quotes
251 (?:'.*?')| # single quotes
252 (?:[^'"=].*?) # no quotes
253 )
254 \s*=\s* # divider
255 (.*) # value (including list values and comments)
256 $ # line end
257 s=^
258 (\s*) # 1: indentation
259 ((?:\[\s*)+) # 2: section marker open
260 ( # 3: section name open
261 (?:"\s*\S.*?\s*")| # at least one non-space with double quotes
262 (?:'\s*\S.*?\s*')| # at least one non-space with single quotes
263 (?:[^'"\s].*?) # at least one non-space unquoted
264 ) # section name close
265 ((?:\s*\])+) # 4: section marker close
266 \s*(\#.*)? # 5: optional comment
267 $s^
268 (?:
269 (?:
270 (
271 (?:
272 (?:
273 (?:".*?")| # double quotes
274 (?:'.*?')| # single quotes
275 (?:[^'",\#][^,\#]*?) # unquoted
276 )
277 \s*,\s* # comma
278 )* # match all list items ending in a comma (if any)
279 )
280 (
281 (?:".*?")| # double quotes
282 (?:'.*?')| # single quotes
283 (?:[^'",\#\s][^,]*?) # unquoted
284 )? # last item in a list - or string value
285 )|
286 (,) # alternatively a single comma - empty list
287 )
288 \s*(\#.*)? # optional comment
289 $s
290 (
291 (?:".*?")| # double quotes
292 (?:'.*?')| # single quotes
293 (?:[^'",\#].*?) # unquoted
294 )
295 \s*,\s* # comma
296 s^
297 (
298 (?:".*?")| # double quotes
299 (?:'.*?')| # single quotes
300 (?:[^'"\#].*?) # unquoted
301 )
302 \s*(\#.*)? # optional comment
303 $s^'''(.*?)'''\s*(#.*)?$s^"""(.*?)"""\s*(#.*)?$s^(.*?)'''\s*(#.*)?$s^(.*?)"""\s*(#.*)?$s'''s"""c
304 Ks|d jo
305 g}n|d jo
306 h}n|i|ti||d|ti }x8|i D]*} | |i jot d| qjqjW|i|g|_|d|_|d|_|d|_|d|_|d|_|d|_|d |_d |_g|_g|_t|totii||_tii|iot |ii!}q|iot"d
307 |iq|io*t |i}|i$d |i%ng}nt|t&t'fo d |_nt|t(ot|t)o|i(}nx|D]} || || <q.Wd |_|`|d d j o|i*|d n
308 d |_+d SnPt,|do6||_|i-d|i!}|ii-dn
309 t dg}|D]}||i0dq~}|o3|di1t2o|dd|d<t2|_n
310 d |_|i3||io+t4d}|i|_6||_7|n|`|d d jo d |_+n|i*|d d S(s{
311 Parse or create a config file object.
312
313 ``ConfigObj(infile=None, options=None, **kwargs)``
314 isUnrecognised option "%s".RRRRRRRsConfig file not found: "%s".RRNtseeksBinfile must be a filename, StringIO instance, or a file as a list.s
315 isParsing failed.(8tinfileR%toptionsRRtkwargsR'R RtOPTION_DEFAULTStcopyR2R\R3RNt_errorsRRRRRRRtBOMtinitial_commentt final_commentRDREtostpathtabspathtfilenametisfiletopent readlinestIOErrorthtwritetcloseRLRMR)R
316 t_handle_configspecRthasattrRR]Rtrstript
317 startswithRt_parseRterrorterrorstconfig(
318 RRRRRRR]R2RR3((R!R s 
319  
320                
321 
322  
323        *   
324    
325  cCsVg}t} |}t|d}d}t}x||jo|o
326 g}n|d7}||}|i }| p|i dot}|i|q1n| p||_g}t} nt}|ii|} | dj o| i\}}}} }|o!|idjo|d|_n|id}|| idjo|idt||q1n||i joLy|i!||i"}
327 Wqt#j
328 o |idt||q1qXnR||i jo |i"}
329 n5||i djo
330 |}
331 n|id t|||i$|}|
332 i%|o|id
333 t&||q1nt'|
334 ||d |}||
335 |<||
336 i(|<||
337 i)|<q1n|i*i|} | dj o[| i\}} }|o!|idjo|d|_n|d d dgjoXy%|i-||||\}}}Wqt#j
338 o |idt.||q1qXnIy|i/|\}}Wn,t#j
339 o |idt.||q1nX|i$| } |i%| o|idt&||q1n||| <||i(| <||i)| <q1n|idt.||q1W|idjo d|_n||_0dS(s
340 Actually parse the config file
341
342 Testing Interpolation
343
344 >>> c = ConfigObj()
345 >>> c['DEFAULT'] = {
346 ... 'b': 'goodbye',
347 ... 'userdir': 'c:\\home',
348 ... 'c': '%(d)s',
349 ... 'd': '%(c)s'
350 ... }
351 >>> c['section'] = {
352 ... 'a': '%(datadir)s\\some path\\file.py',
353 ... 'b': '%(userdir)s\\some path\\file.py',
354 ... 'c': 'Yo %(a)s',
355 ... 'd': '%(not_here)s',
356 ... 'e': '%(c)s',
357 ... }
358 >>> c['section']['DEFAULT'] = {
359 ... 'datadir': 'c:\\silly_test',
360 ... 'a': 'hello - %(b)s',
361 ... }
362 >>> c['section']['a'] == 'c:\\silly_test\\some path\\file.py'
363 1
364 >>> c['section']['b'] == 'c:\\home\\some path\\file.py'
365 1
366 >>> c['section']['c'] == 'Yo hello - goodbye'
367 1
368
369 Switching Interpolation Off
370
371 >>> c.interpolation = False
372 >>> c['section']['a'] == '%(datadir)s\\some path\\file.py'
373 1
374 >>> c['section']['b'] == '%(userdir)s\\some path\\file.py'
375 1
376 >>> c['section']['c'] == 'Yo %(a)s'
377 1
378
379 Testing the interpolation errors.
380
381 >>> c.interpolation = True
382 >>> c['section']['d']
383 Traceback (most recent call last):
384 MissingInterpolationOption: missing option "not_here" in interpolation.
385 >>> c['section']['e']
386 Traceback (most recent call last):
387 InterpolationDepthError: max interpolation depth exceeded in value "%(c)s".
388
389 Testing our quoting.
390
391 >>> i._quote('"""'''')
392 Traceback (most recent call last):
393 SyntaxError: EOF while scanning triple-quoted string
394 >>> try:
395 ... i._quote('\n', multiline=False)
396 ... except ConfigObjError, e:
397 ... e.msg
398 'Value "\n" cannot be safely quoted.'
399 >>> k._quote(' "' ', multiline=False)
400 Traceback (most recent call last):
401 SyntaxError: EOL while scanning single-quoted string
402
403 Testing with "stringify" off.
404 >>> c.stringify = False
405 >>> c['test'] = 1
406 Traceback (most recent call last):
407 TypeError: Value is not a string "1".
408 iit#it[t]s,Cannot compute the section depth at line %s.s(Cannot compute nesting level at line %s.sSection too nested at line %s.s"Duplicate section name at line %s.R/is"""s'''s Parse error in value at line %s.s"Duplicate keyword name at line %s.sInvalid line at line "%s".RN(1t comment_listR>t
409 done_startRt this_sectiontlenRtmaxlinet cur_indext reset_commentRtstriptslineRRIRRAt_sectionmarkerR;tmatR%tgroupstindentt sect_opent sect_namet
410 sect_closetcommentRtcountt cur_deptht _handle_errorRR,t _match_depthR*Rt_unquoteRGRR'R1R0t_keywordRCR4t
411 _multilineRt _handle_valueR(RRRRRRRRRRR*RRRCRRRRRR4((R!RCsF 
412 
413 
414    
415         
416      
417    %       
418     cCs]x8||ijo'||ijo
419 tn|i}qW|i|jo|SntdS(s
420 Given a section and a depth level, walk back through the sections
421 parents to see if the depth level matches a previous section.
422
423 Return a reference to the right section,
424 or raise a SyntaxError.
425 N(R,tsectR*R(RRR,((R!Rs
426 cCsN||}||}||||}|io
427 |n|i i
428 |dS(s
429 Handle an error according to the error settings.
430
431 Either raise the error or store it.
432 The error will have occured at ``cur_index``
433 N( RRRttextRt
434 ErrorClassRRRRRI(RRRRRRRR((R!R's
435 
436 
437 
438 cCs;|d|djo"|ddjo|dd!}n|S(s%Return an unquoted version of a valueiit"t'iN(RR(R4(RR4((R!R8s&c Cs<t|ttfo||pdSn3t|djo|i|ddtdSndig}
439 |D]}|
440 |i|dtqh~
441 Snt|t p+|i ot |}qtd|nd}d} d}d } d
442 }d }|pd Sn|o$d |jo d|jp
443 d|jpd|jotd|n|d| jo(|d| jod|jo
444 |}q4d |jod|jotd|q4d|jo
445 |}q4| }nd|iddjo'|iddjotd|n|iddjo
446 |}n|}||S(s
447 Return a safely quoted version of a value.
448
449 Raise a ConfigObjError if the value cannot be safely quoted.
450 If multiline is ``True`` (default) then use triple quotes
451 if necessary.
452
453 Don't quote values that don't need it.
454 Recursively quote members of a list and return a comma joined list.
455 Multiline is ``False`` for lists.
456 Obey list syntax for empty and single member lists.
457 t,iit multilinesValue "%s" is not a string.s'%s's"%s"s%ss
458 '"s"""%s"""s'''%s'''s""RRs
459 s#Value "%s" cannot be safely quoted.is"""s'''N(RDR4RLRMRRt_quoteR>RbR]R@RERtstrRNtsquottdquottnoquott wspace_plusttsquotttdquotRRtquotR5( RR4RRR@RRRRRR]R((R!R>sF ;
460 . /
461  
462 
463 ,
464 c
465 Cs{|ipR|ii|}|djo
466 tn|i\}}|i
467 ||fSn|i i|}|djo
468 tn|i\}}} }|djo|djo
469 tn| dj og|fSn|dj o|i
470 |}n|djo||fSn|ii|}g}|D]}||i
471 |q4~}|dj o||g7}n||fS(s
472
473 Given a value string, unquote, remove comment,
474 handle lists. (including empty and single member lists)
475
476 Testing list values.
477
478 >>> testconfig3 = '''
479 ... a = ,
480 ... b = test,
481 ... c = test1, test2 , test3
482 ... d = test1, test2, test3,
483 ... '''
484 >>> d = ConfigObj(testconfig3.split('\n'), raise_errors=True)
485 >>> d['a'] == []
486 1
487 >>> d['b'] == ['test']
488 1
489 >>> d['c'] == ['test1', 'test2', 'test3']
490 1
491 >>> d['d'] == ['test1', 'test2', 'test3']
492 1
493
494 Testing with list values off.
495
496 >>> e = ConfigObj(
497 ... testconfig3.split('\n'),
498 ... raise_errors=True,
499 ... list_values=False)
500 >>> e['a'] == ','
501 1
502 >>> e['b'] == 'test,'
503 1
504 >>> e['c'] == 'test1, test2 , test3'
505 1
506 >>> e['d'] == 'test1, test2, test3,'
507 1
508
509 Testing creating from a dictionary.
510
511 >>> f = {
512 ... 'key1': 'val1',
513 ... 'key2': 'val2',
514 ... 'section 1': {
515 ... 'key1': 'val1',
516 ... 'key2': 'val2',
517 ... 'section 1b': {
518 ... 'key1': 'val1',
519 ... 'key2': 'val2',
520 ... },
521 ... },
522 ... 'section 2': {
523 ... 'key1': 'val1',
524 ... 'key2': 'val2',
525 ... 'section 2b': {
526 ... 'key1': 'val1',
527 ... 'key2': 'val2',
528 ... },
529 ... },
530 ... 'key3': 'val3',
531 ... }
532 >>> g = ConfigObj(f)
533 >>> f == g
534 1
535
536 Testing we correctly detect badly built list values (4 of them).
537
538 >>> testconfig4 = '''
539 ... config = 3,4,,
540 ... test = 3,,4
541 ... fish = ,,
542 ... dummy = ,,hello, goodbye
543 ... '''
544 >>> try:
545 ... ConfigObj(testconfig4.split('\n'))
546 ... except ConfigObjError, e:
547 ... len(e.errors)
548 4
549
550 Testing we correctly detect badly quoted values (4 of them).
551
552 >>> testconfig5 = '''
553 ... config = "hello # comment
554 ... test = 'goodbye
555 ... fish = 'goodbye # comment
556 ... dummy = "hello again
557 ... '''
558 >>> try:
559 ... ConfigObj(testconfig5.split('\n'))
560 ... except ConfigObjError, e:
561 ... len(e.errors)
562 4
563 RN(RRt _nolistvalueR;R4RR%RRRRt _valueexptsinglet
564 empty_listt _listvalueexptfindallRhR]R@(
565 RR4RRR@RR]RRhR((R!R|s0\
566  
567  
568 
569    * c Cs@|d }|d}|i|d} |i|d}
570 | i|}|dj o't
571 |i } | i || Sn!|i|djo
572 tnx[||joG|d7}|d7}||} | i|djo|| 7}qPqWt|
573 i| }|djo
574 tn|i \}}||||fS(s
575 Extract the value, where we are in a multiline situation
576
577 Testing multiline values.
578
579 >>> i == {
580 ... 'name4': ' another single line value ',
581 ... 'multi section': {
582 ... 'name4': '\n Well, this is a\n multiline '
583 ... 'value\n ',
584 ... 'name2': '\n Well, this is a\n multiline '
585 ... 'value\n ',
586 ... 'name3': '\n Well, this is a\n multiline '
587 ... 'value\n ',
588 ... 'name1': '\n Well, this is a\n multiline '
589 ... 'value\n ',
590 ... },
591 ... 'name2': ' another single line value ',
592 ... 'name3': ' a single line value ',
593 ... 'name1': ' a single line value ',
594 ... }
595 1
596 iiiis
597 N(R4RtnewvalueRt _triple_quotet single_linet
598 multi_lineR;RR%RLRtretvalRIRR5RRRRR( RR4RRRRRRRRRRR((R!Rs4
599 
600   
601  
602 
603 
604  
605 cCsy"t|dtdtdt}WnItj
606 o}td|n&tj
607 o}td|nX|i ||dS(sParse the configspec.RRRsParsing configspec failed: %ssReading configspec failed: %sN(
608 R
609 RRAR>RteR RRt_set_configspec_value(RRR((R!R2scCsd|ijo5|d|id<t|idjo
610 tqEnx"|iD]}|||i|<qOWx[|iD]P}|djoqtn|i|ph||<n|i ||||qtWdS(s*Used to recursively set configspec values.t__many__iN(
611 RR.RvRRR-R3RGRR(RRRvR3((R!RBs
612 
613  c
614 Csy|i}|i}Wntj
615 oyg}|D]%} t|| t o || q2q2~}g}|D]%} t|| t p || qkqk~}nXd|jot
616 |djo
617 t nh}h}x"|D]} || }||| <qWx@|D]8} || }| djo||| <qn||| <qW||_xD|D]<} |i| ph|| <n|i|| || qLWdS(s3Dynamically assign configspec for repeated section.RiN(RR.t section_keysR-t scalar_keystAttributeErrorR]R3RDR)RRR@RvRGRt_handle_repeat(
618 RRvRR-R@RR.R]RR3((R!RRs8  9> 
619 
620 
621  
622  cCs,d||i|dt|i||fS(s.Write an individual line, for the write methods %s%s = %s%sRN(t indent_stringRRR3R>RfR(RRR3RfR((R!t _write_lineqscCs.d|d||i|dtd||fS(sWrite a section marker lines
623 %s%s%s%s%sRRRN(RR,RRR3R>R(RRR,R3R((R!t _write_markeryscCsY|pdSn|idjo
624 d}n dt}|idp|d7}n||S(sM
625 Deal with a comment.
626
627 >>> filename = a.filename
628 >>> a.filename = None
629 >>> values = a.write()
630 >>> index = 0
631 >>> while index < 23:
632 ... index += 1
633 ... line = values[index-1]
634 ... assert line.endswith('# comment ' + str(index))
635 >>> a.filename = filename
636
637 >>> start_comment = ['# Initial Comment', '', '#']
638 >>> end_comment = ['', '#', '# Final Comment']
639 >>> newconfig = start_comment + testconfig1.split('\n') + end_comment
640 >>> nc = ConfigObj(newconfig)
641 >>> nc.initial_comment
642 ['# Initial Comment', '', '#']
643 >>> nc.final_comment
644 ['', '#', '# Final Comment']
645 >>> nc.initial_comment == start_comment
646 1
647 >>> nc.final_comment == end_comment
648 1
649 Rs RRs# N(RRRtstartRR(RRR((R!t_handle_comments
650 
651 cCs^|idjodSn|idjo d|Sn|idjodt|SntdS(sW
652 Compute the indent string, according to current indent_type and depth
653 Rs RN(RRR,RR(RR,((R!t_compute_indent_strings c Csd}|idjo t|_ng} t}|djou|i }t
654 |_ |}t
655 }xT|i D]E}
656 |
657 i }|o|id od|
658 }
659 n| i|
660 qdWn|i|i} x|i|iD]}||ijoqnxX|i|D]I}|i}|o|id od|}n| i| |qW||} |i|i|}t| t o<| i|i!| | i||| i"|i#| q| i|i$| || |qW|pWxT|i%D]E}
661 |
662 i }|o|id od|
663 }
664 n| i|
665 qWn|djo ||_ n|p|i&djo| Snt|i&t'oMt(|i&d}|i#|i*pd|i#di+| |i,nD|i&i-d|i&i#|i*pd|i&i#di+| dS( sP
666 Write the current ConfigObj as a file
667
668 tekNico: FIXME: use StringIO instead of real files
669
670 >>> filename = a.filename
671 >>> a.filename = 'test.ini'
672 >>> a.write()
673 >>> a.filename = filename
674 >>> a == ConfigObj('test.ini', raise_errors=True)
675 1
676 >>> os.remove('test.ini')
677 >>> b.filename = 'test.ini'
678 >>> b.write()
679 >>> b == ConfigObj('test.ini', raise_errors=True)
680 1
681 >>> os.remove('test.ini')
682 >>> i.filename = 'test.ini'
683 >>> i.write()
684 >>> i == ConfigObj('test.ini', raise_errors=True)
685 1
686 >>> os.remove('test.ini')
687 >>> a = ConfigObj()
688 >>> a['DEFAULT'] = {'a' : 'fish'}
689 >>> a['a'] = '%(a)s'
690 >>> a.write()
691 ['a = %(a)s', '[DEFAULT]', 'a = fish']
692 ttestRs# twRs
693 iN(.tint_valRRR%RRqRAt return_listRvRR>RRRt stripped_lineRRIRR,RR-R.R3R2R0t comment_linetlstripRfRR1RRDR)RtextendRRRRRERRRRbRR( RRvRRR3RRRRRRRfRq((R!Rsv    
694   
695 
696 
697    cCs|tjo'|itjo tdn|}n|i}d|ijo6|d}
698 x%|iD]} |i || |
699 qaWnh}t } t }x|D]} | djoqn| |ij p | |ijot }t}nt}|| }y |i|| |d|}Wn&|ij
700 ot|| <t} nXt}t || <|ip|o|i oot|ttfo+g} |D]} | t| q~ }n+|o
701 |tjo
702 d}n t|}n||jp|o||| <nn|o | |ijo|ii| nqWxk|iD]`} |i||| }||| <|tjo
703 t} n$|t jo
704 t}n t} t}q:W| ot Sn|otSn|SdS(s9
705 Test the ConfigObj against a configspec.
706
707 It uses the ``validator`` object from *validate.py*.
708
709 To run ``validate`` on the current ConfigObj, call: ::
710
711 test = config.validate(validator)
712
713 (Normally having previously passed in the configspec when the ConfigObj
714 was created - you can dynamically assign a dictionary of checks to the
715 ``configspec`` attribute of a section though).
716
717 It returns ``True`` if everything passes, or a dictionary of
718 pass/fails (True/False). If every member of a subsection passes, it
719 will just have the value ``True``. (It also returns ``False`` if all
720 members fail).
721
722 In addition, it converts the values from strings to their native
723 types if their checks pass (and ``stringify`` is set).
724
725 >>> try:
726 ... from validate import Validator
727 ... except ImportError:
728 ... print >> sys.stderr, 'Cannot import the Validator object, skipping the realted tests'
729 ... else:
730 ... config = '''
731 ... test1=40
732 ... test2=hello
733 ... test3=3
734 ... test4=5.0
735 ... [section]
736 ... test1=40
737 ... test2=hello
738 ... test3=3
739 ... test4=5.0
740 ... [[sub section]]
741 ... test1=40
742 ... test2=hello
743 ... test3=3
744 ... test4=5.0
745 ... '''.split('\n')
746 ... configspec = '''
747 ... test1='integer(30,50)'
748 ... test2='string'
749 ... test3='integer'
750 ... test4='float(6.0)'
751 ... [section ]
752 ... test1='integer(30,50)'
753 ... test2='string'
754 ... test3='integer'
755 ... test4='float(6.0)'
756 ... [[sub section]]
757 ... test1='integer(30,50)'
758 ... test2='string'
759 ... test3='integer'
760 ... test4='float(6.0)'
761 ... '''.split('\n')
762 ... val = Validator()
763 ... c1 = ConfigObj(config, configspec=configspec)
764 ... test = c1.validate(val)
765 ... test == {
766 ... 'test1': True,
767 ... 'test2': True,
768 ... 'test3': True,
769 ... 'test4': False,
770 ... 'section': {
771 ... 'test1': True,
772 ... 'test2': True,
773 ... 'test3': True,
774 ... 'test4': False,
775 ... 'sub section': {
776 ... 'test1': True,
777 ... 'test2': True,
778 ... 'test3': True,
779 ... 'test4': False,
780 ... },
781 ... },
782 ... }
783 1
784 >>> val.check(c1.configspec['test4'], c1['test4'])
785 Traceback (most recent call last):
786 VdtValueTooSmallError: the value "5.0" is too small.
787
788 >>> val_test_config = '''
789 ... key = 0
790 ... key2 = 1.1
791 ... [section]
792 ... key = some text
793 ... key2 = 1.1, 3.0, 17, 6.8
794 ... [[sub-section]]
795 ... key = option1
796 ... key2 = True'''.split('\n')
797 >>> val_test_configspec = '''
798 ... key = integer
799 ... key2 = float
800 ... [section]
801 ... key = string
802 ... key2 = float_list(4)
803 ... [[sub-section]]
804 ... key = option(option1, option2)
805 ... key2 = boolean'''.split('\n')
806 >>> val_test = ConfigObj(val_test_config, configspec=val_test_configspec)
807 >>> val_test.validate(val)
808 1
809 >>> val_test['key'] = 'text not a digit'
810 >>> val_res = val_test.validate(val)
811 >>> val_res == {'key2': True, 'section': True, 'key': False}
812 1
813 >>> configspec = '''
814 ... test1='integer(30,50, default=40)'
815 ... test2='string(default="hello")'
816 ... test3='integer(default=3)'
817 ... test4='float(6.0, default=6.0)'
818 ... [section ]
819 ... test1='integer(30,50, default=40)'
820 ... test2='string(default="hello")'
821 ... test3='integer(default=3)'
822 ... test4='float(6.0, default=6.0)'
823 ... [[sub section]]
824 ... test1='integer(30,50, default=40)'
825 ... test2='string(default="hello")'
826 ... test3='integer(default=3)'
827 ... test4='float(6.0, default=6.0)'
828 ... '''.split('\n')
829 >>> default_test = ConfigObj(['test1=30'], configspec=configspec)
830 >>> default_test
831 {'test1': '30', 'section': {'sub section': {}}}
832 >>> default_test.validate(val)
833 1
834 >>> default_test == {
835 ... 'test1': 30,
836 ... 'test2': 'hello',
837 ... 'test3': 3,
838 ... 'test4': 6.0,
839 ... 'section': {
840 ... 'test1': 40,
841 ... 'test2': 'hello',
842 ... 'test3': 3,
843 ... 'test4': 6.0,
844 ... 'sub section': {
845 ... 'test1': 40,
846 ... 'test3': 3,
847 ... 'test2': 'hello',
848 ... 'test4': 6.0,
849 ... },
850 ... },
851 ... }
852 1
853
854 Now testing with repeated sections : BIG TEST
855
856 >>> repeated_1 = '''
857 ... [dogs]
858 ... [[__many__]] # spec for a dog
859 ... fleas = boolean(default=True)
860 ... tail = option(long, short, default=long)
861 ... name = string(default=rover)
862 ... [[[__many__]]] # spec for a puppy
863 ... name = string(default="son of rover")
864 ... age = float(default=0.0)
865 ... [cats]
866 ... [[__many__]] # spec for a cat
867 ... fleas = boolean(default=True)
868 ... tail = option(long, short, default=short)
869 ... name = string(default=pussy)
870 ... [[[__many__]]] # spec for a kitten
871 ... name = string(default="son of pussy")
872 ... age = float(default=0.0)
873 ... '''.split('\n')
874 >>> repeated_2 = '''
875 ... [dogs]
876 ...
877 ... # blank dogs with puppies
878 ... # should be filled in by the configspec
879 ... [[dog1]]
880 ... [[[puppy1]]]
881 ... [[[puppy2]]]
882 ... [[[puppy3]]]
883 ... [[dog2]]
884 ... [[[puppy1]]]
885 ... [[[puppy2]]]
886 ... [[[puppy3]]]
887 ... [[dog3]]
888 ... [[[puppy1]]]
889 ... [[[puppy2]]]
890 ... [[[puppy3]]]
891 ... [cats]
892 ...
893 ... # blank cats with kittens
894 ... # should be filled in by the configspec
895 ... [[cat1]]
896 ... [[[kitten1]]]
897 ... [[[kitten2]]]
898 ... [[[kitten3]]]
899 ... [[cat2]]
900 ... [[[kitten1]]]
901 ... [[[kitten2]]]
902 ... [[[kitten3]]]
903 ... [[cat3]]
904 ... [[[kitten1]]]
905 ... [[[kitten2]]]
906 ... [[[kitten3]]]
907 ... '''.split('\n')
908 >>> repeated_3 = '''
909 ... [dogs]
910 ...
911 ... [[dog1]]
912 ... [[dog2]]
913 ... [[dog3]]
914 ... [cats]
915 ...
916 ... [[cat1]]
917 ... [[cat2]]
918 ... [[cat3]]
919 ... '''.split('\n')
920 >>> repeated_4 = '''
921 ... [__many__]
922 ...
923 ... name = string(default=Michael)
924 ... age = float(default=0.0)
925 ... sex = option(m, f, default=m)
926 ... '''.split('\n')
927 >>> repeated_5 = '''
928 ... [cats]
929 ... [[__many__]]
930 ... fleas = boolean(default=True)
931 ... tail = option(long, short, default=short)
932 ... name = string(default=pussy)
933 ... [[[description]]]
934 ... height = float(default=3.3)
935 ... weight = float(default=6)
936 ... [[[[coat]]]]
937 ... fur = option(black, grey, brown, "tortoise shell", default=black)
938 ... condition = integer(0,10, default=5)
939 ... '''.split('\n')
940 >>> from validate import Validator
941 >>> val= Validator()
942 >>> repeater = ConfigObj(repeated_2, configspec=repeated_1)
943 >>> repeater.validate(val)
944 1
945 >>> repeater == {
946 ... 'dogs': {
947 ... 'dog1': {
948 ... 'fleas': True,
949 ... 'tail': 'long',
950 ... 'name': 'rover',
951 ... 'puppy1': {'name': 'son of rover', 'age': 0.0},
952 ... 'puppy2': {'name': 'son of rover', 'age': 0.0},
953 ... 'puppy3': {'name': 'son of rover', 'age': 0.0},
954 ... },
955 ... 'dog2': {
956 ... 'fleas': True,
957 ... 'tail': 'long',
958 ... 'name': 'rover',
959 ... 'puppy1': {'name': 'son of rover', 'age': 0.0},
960 ... 'puppy2': {'name': 'son of rover', 'age': 0.0},
961 ... 'puppy3': {'name': 'son of rover', 'age': 0.0},
962 ... },
963 ... 'dog3': {
964 ... 'fleas': True,
965 ... 'tail': 'long',
966 ... 'name': 'rover',
967 ... 'puppy1': {'name': 'son of rover', 'age': 0.0},
968 ... 'puppy2': {'name': 'son of rover', 'age': 0.0},
969 ... 'puppy3': {'name': 'son of rover', 'age': 0.0},
970 ... },
971 ... },
972 ... 'cats': {
973 ... 'cat1': {
974 ... 'fleas': True,
975 ... 'tail': 'short',
976 ... 'name': 'pussy',
977 ... 'kitten1': {'name': 'son of pussy', 'age': 0.0},
978 ... 'kitten2': {'name': 'son of pussy', 'age': 0.0},
979 ... 'kitten3': {'name': 'son of pussy', 'age': 0.0},
980 ... },
981 ... 'cat2': {
982 ... 'fleas': True,
983 ... 'tail': 'short',
984 ... 'name': 'pussy',
985 ... 'kitten1': {'name': 'son of pussy', 'age': 0.0},
986 ... 'kitten2': {'name': 'son of pussy', 'age': 0.0},
987 ... 'kitten3': {'name': 'son of pussy', 'age': 0.0},
988 ... },
989 ... 'cat3': {
990 ... 'fleas': True,
991 ... 'tail': 'short',
992 ... 'name': 'pussy',
993 ... 'kitten1': {'name': 'son of pussy', 'age': 0.0},
994 ... 'kitten2': {'name': 'son of pussy', 'age': 0.0},
995 ... 'kitten3': {'name': 'son of pussy', 'age': 0.0},
996 ... },
997 ... },
998 ... }
999 1
1000 >>> repeater = ConfigObj(repeated_3, configspec=repeated_1)
1001 >>> repeater.validate(val)
1002 1
1003 >>> repeater == {
1004 ... 'cats': {
1005 ... 'cat1': {'fleas': True, 'tail': 'short', 'name': 'pussy'},
1006 ... 'cat2': {'fleas': True, 'tail': 'short', 'name': 'pussy'},
1007 ... 'cat3': {'fleas': True, 'tail': 'short', 'name': 'pussy'},
1008 ... },
1009 ... 'dogs': {
1010 ... 'dog1': {'fleas': True, 'tail': 'long', 'name': 'rover'},
1011 ... 'dog2': {'fleas': True, 'tail': 'long', 'name': 'rover'},
1012 ... 'dog3': {'fleas': True, 'tail': 'long', 'name': 'rover'},
1013 ... },
1014 ... }
1015 1
1016 >>> repeater = ConfigObj(configspec=repeated_4)
1017 >>> repeater['Michael'] = {}
1018 >>> repeater.validate(val)
1019 1
1020 >>> repeater == {
1021 ... 'Michael': {'age': 0.0, 'name': 'Michael', 'sex': 'm'},
1022 ... }
1023 1
1024 >>> repeater = ConfigObj(repeated_3, configspec=repeated_5)
1025 >>> repeater == {
1026 ... 'dogs': {'dog1': {}, 'dog2': {}, 'dog3': {}},
1027 ... 'cats': {'cat1': {}, 'cat2': {}, 'cat3': {}},
1028 ... }
1029 1
1030 >>> repeater.validate(val)
1031 1
1032 >>> repeater == {
1033 ... 'dogs': {'dog1': {}, 'dog2': {}, 'dog3': {}},
1034 ... 'cats': {
1035 ... 'cat1': {
1036 ... 'fleas': True,
1037 ... 'tail': 'short',
1038 ... 'name': 'pussy',
1039 ... 'description': {
1040 ... 'weight': 6.0,
1041 ... 'height': 3.2999999999999998,
1042 ... 'coat': {'fur': 'black', 'condition': 5},
1043 ... },
1044 ... },
1045 ... 'cat2': {
1046 ... 'fleas': True,
1047 ... 'tail': 'short',
1048 ... 'name': 'pussy',
1049 ... 'description': {
1050 ... 'weight': 6.0,
1051 ... 'height': 3.2999999999999998,
1052 ... 'coat': {'fur': 'black', 'condition': 5},
1053 ... },
1054 ... },
1055 ... 'cat3': {
1056 ... 'fleas': True,
1057 ... 'tail': 'short',
1058 ... 'name': 'pussy',
1059 ... 'description': {
1060 ... 'weight': 6.0,
1061 ... 'height': 3.2999999999999998,
1062 ... 'coat': {'fur': 'black', 'condition': 5},
1063 ... },
1064 ... },
1065 ... },
1066 ... }
1067 1
1068
1069 Test that interpolation is preserved for validated string values.
1070 >>> t = ConfigObj()
1071 >>> t['DEFAULT'] = {}
1072 >>> t['DEFAULT']['test'] = 'a'
1073 >>> t['test'] = '%(test)s'
1074 >>> t['test']
1075 'a'
1076 >>> v = Validator()
1077 >>> t.configspec = {'test': 'string'}
1078 >>> t.validate(v)
1079 1
1080 >>> t.interpolation = False
1081 >>> t
1082 {'test': '%(test)s', 'DEFAULT': {'test': 'a'}}
1083
1084 FIXME: Above tests will fail if we couldn't import Validator (the ones
1085 that don't raise errors will produce different output and still fail as
1086 tests)
1087 sNo configspec supplied.RtmissingRN(RvR%RRRFt spec_sectiontmanyR.R3RRqRAtret_truet ret_falseR-R2RR@R>t validatortchecktbaseErrorClassRRDRLRMR]titemRRItvalidate(RRRvRRRqR@RRRRR]RR3((R!Rsv  
1088  
1089 
1090  !
1091 
1092  
1093  
1094  +
1095 
1096 
1097  
1098  
1099 
1100 (#R"R#R$R{R|tVERBOSERRRRRt_single_line_singlet_single_line_doublet_multi_line_singlet_multi_line_doubleRR%R RRRRRARRRRRRRRRRRR(((R!R
1101 ]sB         $n    > ~ 8     %  dcBs#tZdZdZedZRS(s
1102 A simple validator.
1103 Can be used to check that all members expected are present.
1104
1105 To use it, provide a configspec with all your members in (the value given
1106 will be ignored). Pass an instance of ``SimpleVal`` to the ``validate``
1107 method of your ``ConfigObj``. ``validate`` will return ``True`` if all
1108 members are present, or a dictionary with True/False meaning
1109 present/missing. (Whole missing sections will be replaced with ``False``)
1110
1111 >>> val = SimpleVal()
1112 >>> config = '''
1113 ... test1=40
1114 ... test2=hello
1115 ... test3=3
1116 ... test4=5.0
1117 ... [section]
1118 ... test1=40
1119 ... test2=hello
1120 ... test3=3
1121 ... test4=5.0
1122 ... [[sub section]]
1123 ... test1=40
1124 ... test2=hello
1125 ... test3=3
1126 ... test4=5.0
1127 ... '''.split('\n')
1128 >>> configspec = '''
1129 ... test1=''
1130 ... test2=''
1131 ... test3=''
1132 ... test4=''
1133 ... [section]
1134 ... test1=''
1135 ... test2=''
1136 ... test3=''
1137 ... test4=''
1138 ... [[sub section]]
1139 ... test1=''
1140 ... test2=''
1141 ... test3=''
1142 ... test4=''
1143 ... '''.split('\n')
1144 >>> o = ConfigObj(config, configspec=configspec)
1145 >>> o.validate(val)
1146 1
1147 >>> o = ConfigObj(configspec=configspec)
1148 >>> o.validate(val)
1149 0
1150 cCs t|_dS(N(RRR(R((R!R scCs|o |in|S(s9A dummy check method, always returns the value unchanged.N(RRRtmember(RRRR((R!Rs (R"R#R$R R>R(((R!R s 2 cCsdS(s
1151 Dummy function to hold some of the doctests.
1152
1153 >>> a.depth
1154 0
1155 >>> a == {
1156 ... 'key2': 'val',
1157 ... 'key1': 'val',
1158 ... 'lev1c': {
1159 ... 'lev2c': {
1160 ... 'lev3c': {
1161 ... 'key1': 'val',
1162 ... },
1163 ... },
1164 ... },
1165 ... 'lev1b': {
1166 ... 'key2': 'val',
1167 ... 'key1': 'val',
1168 ... 'lev2ba': {
1169 ... 'key1': 'val',
1170 ... },
1171 ... 'lev2bb': {
1172 ... 'key1': 'val',
1173 ... },
1174 ... },
1175 ... 'lev1a': {
1176 ... 'key2': 'val',
1177 ... 'key1': 'val',
1178 ... },
1179 ... }
1180 1
1181 >>> b.depth
1182 0
1183 >>> b == {
1184 ... 'key3': 'val3',
1185 ... 'key2': 'val2',
1186 ... 'key1': 'val1',
1187 ... 'section 1': {
1188 ... 'keys11': 'val1',
1189 ... 'keys13': 'val3',
1190 ... 'keys12': 'val2',
1191 ... },
1192 ... 'section 2': {
1193 ... 'section 2 sub 1': {
1194 ... 'fish': '3',
1195 ... },
1196 ... 'keys21': 'val1',
1197 ... 'keys22': 'val2',
1198 ... 'keys23': 'val3',
1199 ... },
1200 ... }
1201 1
1202 >>> t = '''
1203 ... 'a' = b # !"$%^&*(),::;'@~#= 33
1204 ... "b" = b #= 6, 33
1205 ... ''' .split('\n')
1206 >>> t2 = ConfigObj(t)
1207 >>> assert t2 == {'a': 'b', 'b': 'b'}
1208 >>> t2.inline_comments['b'] = ''
1209 >>> del t2['a']
1210 >>> assert t2.write() == ['','b = b', '']
1211 N((((R!t_doctest's>t__main__sy key1= val # comment 1
1212 key2= val # comment 2
1213 # comment 3
1214 [lev1a] # comment 4
1215 key1= val # comment 5
1216 key2= val # comment 6
1217 # comment 7
1218 [lev1b] # comment 8
1219 key1= val # comment 9
1220 key2= val # comment 10
1221 # comment 11
1222 [[lev2ba]] # comment 12
1223 key1= val # comment 13
1224 # comment 14
1225 [[lev2bb]] # comment 15
1226 key1= val # comment 16
1227 # comment 17
1228 [lev1c] # comment 18
1229 # comment 19
1230 [[lev2c]] # comment 20
1231 # comment 21
1232 [[[lev3c]]] # comment 22
1233 key1 = val # comment 23s key1 = 'val1'
1234 key2 = "val2"
1235 key3 = val3
1236 ["section 1"] # comment
1237 keys11 = val1
1238 keys12 = val2
1239 keys13 = val3
1240 [section 2]
1241 keys21 = val1
1242 keys22 = val2
1243 keys23 = val3
1244
1245 [['section 2 sub 1']]
1246 fish = 3
1247 sR
1248 name1 = """ a single line value """ # comment
1249 name2 = ''' another single line value ''' # comment
1250 name3 = """ a single line value """
1251 name4 = ''' another single line value '''
1252 [ "multi section" ]
1253 name1 = """
1254 Well, this is a
1255 multiline value
1256 """
1257 name2 = '''
1258 Well, this is a
1259 multiline value
1260 '''
1261 name3 = """
1262 Well, this is a
1263 multiline value
1264 """ # a comment
1265 name4 = '''
1266 Well, this is a
1267 multiline value
1268 ''' # I guess this is a comment too
1269 s
1270 tINTP_VERtatbtitglobs(6R$tsyst version_infoRt RuntimeErrorRR{ttypesRERRt __revision__Rt__all__RRRRAR>R%RRRRRRR R R RRR)R'R
1271 tobjectR RR"t testconfig1t testconfig2t testconfig6tdoctesttmodulesR?tmt__dict__RRtsplitRRRRRttestmod($R RRRRR RRRRRRRR R{RER RR
1272 RRRRRRRRRRRRR R RRR'((R!t?s\   9N      
1273  A @  1

Properties

Name Value
svn:mime-type application/octet-stream

Managed by UCC Webmasters ViewVC Help
Powered by ViewVC 1.1.26