1919import io
2020import re
2121import logging
22- from collections import MutableMapping
2322try :
2423 from collections import OrderedDict
2524except ImportError :
@@ -67,7 +66,7 @@ def keys(self):
6766 iteritems = DictMixin .iteritems
6867
6968
70- __version__ = "0.5.1 "
69+ __version__ = "0.7.0 "
7170__project__ = "Inirama"
7271__author__ = "Kirill Klenov <horneds@gmail.com>"
7372__license__ = "BSD"
@@ -170,7 +169,9 @@ class INIScanner(Scanner):
170169 ('SECTION' , re .compile (r'\[[^]]+\]' )),
171170 ('IGNORE' , re .compile (r'[ \r\t\n]+' )),
172171 ('COMMENT' , re .compile (r'[;#].*' )),
173- ('KEY' , re .compile (r'[\w_]+\s*[:=].*' ))]
172+ ('KEY' , re .compile (r'[\w_]+\s*[:=].*' )),
173+ ('CONTINUATION' , re .compile (r'.*' ))
174+ ]
174175
175176 ignore = ['IGNORE' ]
176177
@@ -183,43 +184,20 @@ def pre_scan(self):
183184undefined = object ()
184185
185186
186- class Section (MutableMapping ):
187+ class Section (OrderedDict ):
187188
188189 """ Representation of INI section. """
189190
190191 def __init__ (self , namespace , * args , ** kwargs ):
191192 super (Section , self ).__init__ (* args , ** kwargs )
192193 self .namespace = namespace
193- self .__storage__ = dict ()
194194
195195 def __setitem__ (self , name , value ):
196196 value = str (value )
197197 if value .isdigit ():
198198 value = int (value )
199199
200- self .__storage__ [name ] = value
201-
202- def __getitem__ (self , name ):
203- return self .__storage__ [name ]
204-
205- def __delitem__ (self , name ):
206- del self .__storage__ [name ]
207-
208- def __len__ (self ):
209- return len (self .__storage__ )
210-
211- def __iter__ (self ):
212- return iter (self .__storage__ )
213-
214- def __repr__ (self ):
215- return "<{0} {1}>" .format (self .__class__ .__name__ , str (dict (self )))
216-
217- def iteritems (self ):
218- """ Impletment iteritems. """
219-
6D38
for key in self .__storage__ .keys ():
220- yield key , self [key ]
221-
222- items = lambda s : list (s .iteritems ())
200+ super (Section , self ).__setitem__ (name , value )
223201
224202
225203class InterpolationSection (Section ):
@@ -246,19 +224,28 @@ def __interpolate__(self, math):
246224 except KeyError :
247225 return ''
248226
249- def __getitem__ (self , name ):
227+ def __getitem__ (self , name , raw = False ):
250228 value = super (InterpolationSection , self ).__getitem__ (name )
251- sample = undefined
252- while sample != value :
253- try :
254- sample , value = value , self .var_re .sub (
255- self .__interpolate__ , value)
256- except RuntimeError :
257- message = "Interpolation failed: {0}" .format (name )
258- NS_LOGGER .error (message )
259- raise ValueError (message )
229+ if not raw :
230+ sample = undefined
231+ while sample != value :
232+ try :
233+ sample , value = value , self .var_re .sub (
234+ self .__interpolate__ , value )
235+ except RuntimeError :
236+ message = "Interpolation failed: {0}" .format (name )
237+ NS_LOGGER .error (message )
238+ raise ValueError (message )
260239 return value
261240
241+ def iteritems (self , raw = False ):
242+ """ Iterate self items. """
243+
244+ for key in self :
245+ yield key , self .__getitem__ (key , raw = raw )
246+
247+ items = iteritems
248+
262249
263250class Namespace (object ):
264251
@@ -356,6 +343,7 @@ def parse(self, source, update=True, **params):
356343 scanner .scan ()
357344
358345 section = self .default_section
346+ name = None
359347
360348 for token in scanner .tokens :
361349 if token [0 ] == 'KEY' :
@@ -368,6 +356,13 @@ def parse(self, source, update=True, **params):
368356 elif token [0 ] == 'SECTION' :
369357 section = token [1 ].strip ('[]' )
370358
359+ elif token [0 ] == 'CONTINUATION' :
360+ if not name :
361+ raise SyntaxError (
362+ "SyntaxError[@char {0}: {1}]" .format (
363+ token [2 ], "Bad continuation." ))
364+ self [section ][name ] += '\n ' + token [1 ].strip ()
365+
371366 def __getitem__ (self , name ):
372367 """ Look name in self sections.
373368
@@ -406,4 +401,4 @@ class InterpolationNamespace(Namespace):
406401
407402 section_type = InterpolationSection
408403
409- # lint_ignore=W0201,R0924,F0401
404+ # pylama:ignore=D,W02,E731,W0621
0 commit comments