Reading multiline values using ConfigParser

P

Phoe6

Hi,
I have a configfile, in fact, I am providing a configfile in the
format:

[Information]
Name: Foo
Author: Bar

Testcases:
tct123
tct124
tct101

The last values is a multi-line.

ConfigParser is unable to recognize a multi-line value and splits out
error.

C:\ATF-Tasks>python CreateTask.py
Traceback (most recent call last):
File "CreateTask.py", line 13, in ?
config.read('TaskDetails.txt')
File "C:\Python24\lib\ConfigParser.py", line 267, in read
self._read(fp, filename)
File "C:\Python24\lib\ConfigParser.py", line 490, in _read
raise e
ConfigParser.ParsingError: File contains parsing errors:
TaskDetails.txt
[line 15]: 'tct123\n'
[line 16]: 'tct124\n'
[line 17]: 'tct101\n'

I am using ConfigParser in the following way:

config = ConfigParser.ConfigParser()
config.read('TaskDetails.txt')
config.get("Information","Testcases"):

Is there anyway, I can include multi-line value in the configfile? I
was thinking of following option:value for a portion of the file and
read the portion with multi-line as a normal file, but ConfigParser()
is not allowing multi-line value itself.

Any ideas/ Suggestions? :

Ofcourse, throw away ConfigParser and use your own parser is there,
but I would like to use that as the last option.

Thanks,
Senthil
 
P

Phoe6

Following the link to RFC 822 (http://www.faqs.org/rfcs/rfc822.html)
indicates that you can spread values out over multiple lines as long as
there is a space or tab character imeediately after the CRLF.

Thanks for the response. It did work!
config = ConfigParser()
config.read("Testcases.txt") ['Testcases.txt']
output = config.get("Information", "Testcases")
print output
tct123
tct124
tct125

However, as I am going to provide Testcases.txt to be "user editable",
I cannot assume or "ask users" to provide value testcases surronded by
spaces. I got to figure out a workaround here.

Thanks,
Senthil
 
C

Carsten Haese

Following the link to RFC 822 (http://www.faqs.org/rfcs/rfc822.html)
indicates that you can spread values out over multiple lines as long as
there is a space or tab character imeediately after the CRLF.

Thanks for the response. It did work!
config = ConfigParser()
config.read("Testcases.txt") ['Testcases.txt']
output = config.get("Information", "Testcases")
print output
tct123
tct124
tct125
output '\ntct123\ntct124\ntct125'

However, as I am going to provide Testcases.txt to be "user editable",
I cannot assume or "ask users" to provide value testcases surronded by
spaces. I got to figure out a workaround here.

Since you don't actually need a multi-line entry but rather a list of
single-line entries, you could ask your users to enter something like
this:

TestcaseCount=3
Testcase1=tct123
Testcase2=tct124
Testcase3=tct125

HTH,
 
L

Larry Bates

Phoe6 said:
Following the link to RFC 822 (http://www.faqs.org/rfcs/rfc822.html)
indicates that you can spread values out over multiple lines as long as
there is a space or tab character imeediately after the CRLF.

Thanks for the response. It did work!
config = ConfigParser()
config.read("Testcases.txt") ['Testcases.txt']
output = config.get("Information", "Testcases")
print output
tct123
tct124
tct125
'\ntct123\ntct124\ntct125'

However, as I am going to provide Testcases.txt to be "user editable",
I cannot assume or "ask users" to provide value testcases surronded by
spaces. I got to figure out a workaround here.

Thanks,
Senthil
I do this a lot and implement it as:

[Testcases]
case_001=tct123
case_002=tct124
case_003=tct101

Then it is pretty easy to do something in my code like:

section='Testcases'
cases=[x for x in INI.options(section) if x.startswith('case_')]

for case in cases:
casefile=INI.get(section, case)
#
# Process each casefile here
#

-Larry
 
P

Phoe6

Thanks for the response. It did work!
config = ConfigParser()
config.read("Testcases.txt") ['Testcases.txt']
output = config.get("Information", "Testcases")
print output
tct123
tct124
tct125
'\ntct123\ntct124\ntct125'

However, as I am going to provide Testcases.txt to be "user editable",
I cannot assume or "ask users" to provide value testcases surronded by
spaces. I got to figure out a workaround here.

Sounds like you're stuck modifying ConfigParser to do what you want, or
writing your own configuration file parsing utilities.
From looking through the ConfigParser source, looks like all the parsing

work is inside the _read method, so shouldn't be too painful to make a
subclass that does what you want.

I took the approach of Subclassing ConfigParser to support multiline
values without leading white-spaces, but am struct at which position
in _read I should modify to accomodate the non-leading whitespace
based multiline values.

I can guess, this portion in the _read function will require change,
any change to this affects the whole of parsing. :-( Can someone who
has done this before or understands ConfigParser better help me?

# Section I am talking about
if line[0].isspace() and cursect is not None and optname:

value = line.strip()
if value:
cursect[optname] = "%s\n%s" % (cursect[optname], value)


# _read method

def _read(self, fp, fpname):
cursect = None
optname = None
lineno = 0
e = None
while True:
line = fp.readline()
if not line:
break
lineno = lineno + 1
# comment or blank line?
if line.strip() == '' or line[0] in '#;':
continue
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
# no leading whitespace
continue
# continuation line
print "line:%s\tcursect:%s\toptname:%s"%(line,cursect,optname)

if line[0].isspace() and cursect is not None and optname:

value = line.strip()
if value:
cursect[optname] = "%s\n%s" % (cursect[optname], value)
# a section header or option header?
else:
# is it a section header?
mo = self.SECTCRE.match(line)
if mo:
sectname = mo.group('header')
if sectname in self._sections:
cursect = self._sections[sectname]
elif sectname == ConfigParser.DEFAULTSECT:
cursect = self._defaults
else:
cursect = {'__name__':sectname}
self._sections[sectname] = cursect
# So sections can't start with a continuation line
optname = None
elif cursect is None:
raise ConfigParser.MissingSectionHeaderError(fpname, lineno,
line)
# an option line?
else:
mo = self.OPTCRE.match(line)
if mo:
optname, vi, optval = mo.group('option','vi','value')
if vi in ('=',':') and ';' in optval:
# ';' is a comment delimiter only if it follows
# a spacing character
pos = optval.find(';')
if pos != -1 and optval[pos-1].isspace():
optval = optval[:pos]
optval = optval.strip()
# allow empty values
if optval == '""':
optval = ''
optname = self.optionxform(optname.rstrip())
cursect[optname] = optval
else:
if not e:
e = ConfigParser.ParsingError(fpname)
e.append(lineno, repr(line))
if e:
raise e
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,744
Latest member
CortneyMcK

Latest Threads

Top