Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
c264c098
Commit
c264c098
authored
Nov 20, 2010
by
Łukasz Langa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
configparser: the name of the DEFAULT section is now customizable
parent
b357fb7b
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
40 additions
and
33 deletions
+40
-33
Lib/configparser.py
Lib/configparser.py
+19
-17
Lib/test/test_cfgparser.py
Lib/test/test_cfgparser.py
+21
-16
No files found.
Lib/configparser.py
View file @
c264c098
...
@@ -406,12 +406,13 @@ class RawConfigParser(MutableMapping):
...
@@ -406,12 +406,13 @@ class RawConfigParser(MutableMapping):
def __init__(self, defaults=None, dict_type=_default_dict,
def __init__(self, defaults=None, dict_type=_default_dict,
allow_no_value=False, *, delimiters=('=', ':'),
allow_no_value=False, *, delimiters=('=', ':'),
comment_prefixes=_COMPATIBLE, strict=False,
comment_prefixes=_COMPATIBLE, strict=False,
empty_lines_in_values=True):
empty_lines_in_values=True,
default_section=DEFAULTSECT):
self._dict = dict_type
self._dict = dict_type
self._sections = self._dict()
self._sections = self._dict()
self._defaults = self._dict()
self._defaults = self._dict()
self._proxies = self._dict()
self._proxies = self._dict()
self._proxies[
DEFAULTSECT] = SectionProxy(self, DEFAULTSECT
)
self._proxies[
default_section] = SectionProxy(self, default_section
)
if defaults:
if defaults:
for key, value in defaults.items():
for key, value in defaults.items():
self._defaults[self.optionxform(key)] = value
self._defaults[self.optionxform(key)] = value
...
@@ -435,6 +436,7 @@ class RawConfigParser(MutableMapping):
...
@@ -435,6 +436,7 @@ class RawConfigParser(MutableMapping):
self._strict = strict
self._strict = strict
self._allow_no_value = allow_no_value
self._allow_no_value = allow_no_value
self._empty_lines_in_values = empty_lines_in_values
self._empty_lines_in_values = empty_lines_in_values
self._default_section=default_section
def defaults(self):
def defaults(self):
return self._defaults
return self._defaults
...
@@ -448,10 +450,9 @@ class RawConfigParser(MutableMapping):
...
@@ -448,10 +450,9 @@ class RawConfigParser(MutableMapping):
"""Create a new section in the configuration.
"""Create a new section in the configuration.
Raise DuplicateSectionError if a section by the specified name
Raise DuplicateSectionError if a section by the specified name
already exists. Raise ValueError if name is DEFAULT or any of it's
already exists. Raise ValueError if name is DEFAULT.
case-insensitive variants.
"""
"""
if section
.upper() == DEFAULTSECT
:
if section
== self._default_section
:
raise ValueError('Invalid section name: %s' % section)
raise ValueError('Invalid section name: %s' % section)
if section in self._sections:
if section in self._sections:
...
@@ -587,7 +588,7 @@ class RawConfigParser(MutableMapping):
...
@@ -587,7 +588,7 @@ class RawConfigParser(MutableMapping):
try:
try:
d2 = self._sections[section]
d2 = self._sections[section]
except KeyError:
except KeyError:
if section !=
DEFAULTSECT
:
if section !=
self._default_section
:
raise NoSectionError(section)
raise NoSectionError(section)
d2 = self._dict()
d2 = self._dict()
d = self._defaults.copy()
d = self._defaults.copy()
...
@@ -632,7 +633,7 @@ class RawConfigParser(MutableMapping):
...
@@ -632,7 +633,7 @@ class RawConfigParser(MutableMapping):
def has_option(self, section, option):
def has_option(self, section, option):
"""Check for the existence of a given option in a given section."""
"""Check for the existence of a given option in a given section."""
if not section or section ==
DEFAULTSECT
:
if not section or section ==
self._default_section
:
option = self.optionxform(option)
option = self.optionxform(option)
return option in self._defaults
return option in self._defaults
elif section not in self._sections:
elif section not in self._sections:
...
@@ -644,7 +645,7 @@ class RawConfigParser(MutableMapping):
...
@@ -644,7 +645,7 @@ class RawConfigParser(MutableMapping):
def set(self, section, option, value=None):
def set(self, section, option, value=None):
"""Set an option."""
"""Set an option."""
if not section or section ==
DEFAULTSECT
:
if not section or section ==
self._default_section
:
sectdict = self._defaults
sectdict = self._defaults
else:
else:
try:
try:
...
@@ -664,7 +665,8 @@ class RawConfigParser(MutableMapping):
...
@@ -664,7 +665,8 @@ class RawConfigParser(MutableMapping):
else:
else:
d = self._delimiters[0]
d = self._delimiters[0]
if self._defaults:
if self._defaults:
self._write_section(fp, DEFAULTSECT, self._defaults.items(), d)
self._write_section(fp, self._default_section,
self._defaults.items(), d)
for section in self._sections:
for section in self._sections:
self._write_section(fp, section,
self._write_section(fp, section,
self._sections[section].items(), d)
self._sections[section].items(), d)
...
@@ -684,7 +686,7 @@ class RawConfigParser(MutableMapping):
...
@@ -684,7 +686,7 @@ class RawConfigParser(MutableMapping):
def remove_option(self, section, option):
def remove_option(self, section, option):
"""Remove an option."""
"""Remove an option."""
if not section or section ==
DEFAULTSECT
:
if not section or section ==
self._default_section
:
sectdict = self._defaults
sectdict = self._defaults
else:
else:
try:
try:
...
@@ -706,7 +708,7 @@ class RawConfigParser(MutableMapping):
...
@@ -706,7 +708,7 @@ class RawConfigParser(MutableMapping):
return existed
return existed
def __getitem__(self, key):
def __getitem__(self, key):
if key !=
DEFAULTSECT
and not self.has_section(key):
if key !=
self._default_section
and not self.has_section(key):
raise KeyError(key)
raise KeyError(key)
return self._proxies[key]
return self._proxies[key]
...
@@ -720,21 +722,21 @@ class RawConfigParser(MutableMapping):
...
@@ -720,21 +722,21 @@ class RawConfigParser(MutableMapping):
self.read_dict({key: value})
self.read_dict({key: value})
def __delitem__(self, key):
def __delitem__(self, key):
if key ==
DEFAULTSECT
:
if key ==
self._default_section
:
raise ValueError("
Cannot
remove
the
default
section
.
")
raise ValueError("
Cannot
remove
the
default
section
.
")
if not self.has_section(key):
if not self.has_section(key):
raise KeyError(key)
raise KeyError(key)
self.remove_section(key)
self.remove_section(key)
def __contains__(self, key):
def __contains__(self, key):
return key ==
DEFAULTSECT
or self.has_section(key)
return key ==
self._default_section
or self.has_section(key)
def __len__(self):
def __len__(self):
return len(self._sections) + 1 # the default section
return len(self._sections) + 1 # the default section
def __iter__(self):
def __iter__(self):
# XXX does it break when underlying container state changed?
# XXX does it break when underlying container state changed?
return itertools.chain((
DEFAULTSECT
,), self._sections.keys())
return itertools.chain((
self._default_section
,), self._sections.keys())
def _read(self, fp, fpname):
def _read(self, fp, fpname):
"""Parse a sectioned configuration file.
"""Parse a sectioned configuration file.
...
@@ -806,7 +808,7 @@ class RawConfigParser(MutableMapping):
...
@@ -806,7 +808,7 @@ class RawConfigParser(MutableMapping):
lineno)
lineno)
cursect = self._sections[sectname]
cursect = self._sections[sectname]
elements_added.add(sectname)
elements_added.add(sectname)
elif sectname ==
DEFAULTSECT
:
elif sectname ==
self._default_section
:
cursect = self._defaults
cursect = self._defaults
else:
else:
cursect = self._dict()
cursect = self._dict()
...
@@ -877,7 +879,7 @@ class RawConfigParser(MutableMapping):
...
@@ -877,7 +879,7 @@ class RawConfigParser(MutableMapping):
try:
try:
d.update(self._sections[section])
d.update(self._sections[section])
except KeyError:
except KeyError:
if section !=
DEFAULTSECT
:
if section !=
self._default_section
:
raise NoSectionError(section)
raise NoSectionError(section)
# Update with the entry specific variables
# Update with the entry specific variables
if vars:
if vars:
...
@@ -999,7 +1001,7 @@ class ConfigParser(RawConfigParser):
...
@@ -999,7 +1001,7 @@ class ConfigParser(RawConfigParser):
try:
try:
d.update(self._sections[section])
d.update(self._sections[section])
except KeyError:
except KeyError:
if section !=
DEFAULTSECT
:
if section !=
self._default_section
:
raise NoSectionError(section)
raise NoSectionError(section)
# Update with the entry specific variables
# Update with the entry specific variables
if vars:
if vars:
...
...
Lib/test/test_cfgparser.py
View file @
c264c098
...
@@ -31,6 +31,7 @@ class CfgParserTestCaseClass(unittest.TestCase):
...
@@ -31,6 +31,7 @@ class CfgParserTestCaseClass(unittest.TestCase):
empty_lines_in_values
=
True
empty_lines_in_values
=
True
dict_type
=
configparser
.
_default_dict
dict_type
=
configparser
.
_default_dict
strict
=
False
strict
=
False
default_section
=
configparser
.
DEFAULTSECT
def
newconfig
(
self
,
defaults
=
None
):
def
newconfig
(
self
,
defaults
=
None
):
arguments
=
dict
(
arguments
=
dict
(
...
@@ -41,6 +42,7 @@ class CfgParserTestCaseClass(unittest.TestCase):
...
@@ -41,6 +42,7 @@ class CfgParserTestCaseClass(unittest.TestCase):
empty_lines_in_values
=
self
.
empty_lines_in_values
,
empty_lines_in_values
=
self
.
empty_lines_in_values
,
dict_type
=
self
.
dict_type
,
dict_type
=
self
.
dict_type
,
strict
=
self
.
strict
,
strict
=
self
.
strict
,
default_section
=
self
.
default_section
,
)
)
return
self
.
config_class
(
**
arguments
)
return
self
.
config_class
(
**
arguments
)
...
@@ -76,7 +78,7 @@ class BasicTestCase(CfgParserTestCaseClass):
...
@@ -76,7 +78,7 @@ class BasicTestCase(CfgParserTestCaseClass):
# mapping access
# mapping access
L
=
[
section
for
section
in
cf
]
L
=
[
section
for
section
in
cf
]
L
.
sort
()
L
.
sort
()
E
.
append
(
configparser
.
DEFAULTSECT
)
E
.
append
(
self
.
default_section
)
E
.
sort
()
E
.
sort
()
eq
(
L
,
E
)
eq
(
L
,
E
)
...
@@ -365,7 +367,7 @@ boolean {0[0]} NO
...
@@ -365,7 +367,7 @@ boolean {0[0]} NO
L
.
sort
()
L
.
sort
()
eq
=
self
.
assertEqual
eq
=
self
.
assertEqual
elem_eq
=
self
.
assertItemsEqual
elem_eq
=
self
.
assertItemsEqual
eq
(
L
,
[
"A"
,
"B"
,
configparser
.
DEFAULTSECT
,
"a"
]
)
eq
(
L
,
sorted
([
"A"
,
"B"
,
self
.
default_section
,
"a"
])
)
eq
(
cf
[
"a"
].
keys
(),
{
"b"
})
eq
(
cf
[
"a"
].
keys
(),
{
"b"
})
eq
(
cf
[
"a"
][
"b"
],
"value"
,
eq
(
cf
[
"a"
][
"b"
],
"value"
,
"could not locate option, expecting case-insensitive option names"
)
"could not locate option, expecting case-insensitive option names"
)
...
@@ -399,11 +401,11 @@ boolean {0[0]} NO
...
@@ -399,11 +401,11 @@ boolean {0[0]} NO
def
test_default_case_sensitivity
(
self
):
def
test_default_case_sensitivity
(
self
):
cf
=
self
.
newconfig
({
"foo"
:
"Bar"
})
cf
=
self
.
newconfig
({
"foo"
:
"Bar"
})
self
.
assertEqual
(
self
.
assertEqual
(
cf
.
get
(
"DEFAULT"
,
"Foo"
),
"Bar"
,
cf
.
get
(
self
.
default_section
,
"Foo"
),
"Bar"
,
"could not locate option, expecting case-insensitive option names"
)
"could not locate option, expecting case-insensitive option names"
)
cf
=
self
.
newconfig
({
"Foo"
:
"Bar"
})
cf
=
self
.
newconfig
({
"Foo"
:
"Bar"
})
self
.
assertEqual
(
self
.
assertEqual
(
cf
.
get
(
"DEFAULT"
,
"Foo"
),
"Bar"
,
cf
.
get
(
self
.
default_section
,
"Foo"
),
"Bar"
,
"could not locate option, expecting case-insensitive defaults"
)
"could not locate option, expecting case-insensitive defaults"
)
def
test_parse_errors
(
self
):
def
test_parse_errors
(
self
):
...
@@ -530,7 +532,7 @@ boolean {0[0]} NO
...
@@ -530,7 +532,7 @@ boolean {0[0]} NO
"[Long Line]
\
n
"
"[Long Line]
\
n
"
"foo{0[0]} this line is much, much longer than my editor
\
n
"
"foo{0[0]} this line is much, much longer than my editor
\
n
"
" likes it.
\
n
"
" likes it.
\
n
"
"[
DEFAULT
]
\
n
"
"[
{default_section}
]
\
n
"
"foo{0[1]} another very
\
n
"
"foo{0[1]} another very
\
n
"
" long line
\
n
"
" long line
\
n
"
"[Long Line - With Comments!]
\
n
"
"[Long Line - With Comments!]
\
n
"
...
@@ -538,7 +540,8 @@ boolean {0[0]} NO
...
@@ -538,7 +540,8 @@ boolean {0[0]} NO
" also {comment} place
\
n
"
" also {comment} place
\
n
"
" comments {comment} in
\
n
"
" comments {comment} in
\
n
"
" multiline {comment} values"
" multiline {comment} values"
"
\
n
"
.
format
(
self
.
delimiters
,
comment
=
self
.
comment_prefixes
[
0
])
"
\
n
"
.
format
(
self
.
delimiters
,
comment
=
self
.
comment_prefixes
[
0
],
default_section
=
self
.
default_section
)
)
)
if
self
.
allow_no_value
:
if
self
.
allow_no_value
:
config_string
+=
(
config_string
+=
(
...
@@ -550,7 +553,7 @@ boolean {0[0]} NO
...
@@ -550,7 +553,7 @@ boolean {0[0]} NO
output
=
io
.
StringIO
()
output
=
io
.
StringIO
()
cf
.
write
(
output
)
cf
.
write
(
output
)
expect_string
=
(
expect_string
=
(
"[
DEFAULT
]
\
n
"
"[
{default_section}
]
\
n
"
"foo {equals} another very
\
n
"
"foo {equals} another very
\
n
"
"
\
t
long line
\
n
"
"
\
t
long line
\
n
"
"
\
n
"
"
\
n
"
...
@@ -563,7 +566,8 @@ boolean {0[0]} NO
...
@@ -563,7 +566,8 @@ boolean {0[0]} NO
"
\
t
also
\
n
"
"
\
t
also
\
n
"
"
\
t
comments
\
n
"
"
\
t
comments
\
n
"
"
\
t
multiline
\
n
"
"
\
t
multiline
\
n
"
"
\
n
"
.
format
(
equals
=
self
.
delimiters
[
0
])
"
\
n
"
.
format
(
equals
=
self
.
delimiters
[
0
],
default_section
=
self
.
default_section
)
)
)
if
self
.
allow_no_value
:
if
self
.
allow_no_value
:
expect_string
+=
(
expect_string
+=
(
...
@@ -724,6 +728,9 @@ class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase):
...
@@ -724,6 +728,9 @@ class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase):
delimiters
=
(
':='
,
'$'
)
delimiters
=
(
':='
,
'$'
)
comment_prefixes
=
(
'//'
,
'"'
)
comment_prefixes
=
(
'//'
,
'"'
)
class
ConfigParserTestCaseNonStandardDefaultSection
(
ConfigParserTestCase
):
default_section
=
'general'
class
MultilineValuesTestCase
(
BasicTestCase
):
class
MultilineValuesTestCase
(
BasicTestCase
):
config_class
=
configparser
.
ConfigParser
config_class
=
configparser
.
ConfigParser
wonderful_spam
=
(
"I'm having spam spam spam spam "
wonderful_spam
=
(
"I'm having spam spam spam spam "
...
@@ -851,13 +858,9 @@ class SafeConfigParserTestCase(ConfigParserTestCase):
...
@@ -851,13 +858,9 @@ class SafeConfigParserTestCase(ConfigParserTestCase):
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
1.0
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
1.0
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
object
())
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
object
())
def
test_add_section_default_1
(
self
):
def
test_add_section_default
(
self
):
cf
=
self
.
newconfig
()
self
.
assertRaises
(
ValueError
,
cf
.
add_section
,
"default"
)
def
test_add_section_default_2
(
self
):
cf
=
self
.
newconfig
()
cf
=
self
.
newconfig
()
self
.
assertRaises
(
ValueError
,
cf
.
add_section
,
"DEFAULT"
)
self
.
assertRaises
(
ValueError
,
cf
.
add_section
,
self
.
default_section
)
class
SafeConfigParserTestCaseNonStandardDelimiters
(
SafeConfigParserTestCase
):
class
SafeConfigParserTestCaseNonStandardDelimiters
(
SafeConfigParserTestCase
):
delimiters
=
(
':='
,
'$'
)
delimiters
=
(
':='
,
'$'
)
...
@@ -884,11 +887,12 @@ class SafeConfigParserTestCaseTrickyFile(CfgParserTestCaseClass):
...
@@ -884,11 +887,12 @@ class SafeConfigParserTestCaseTrickyFile(CfgParserTestCaseClass):
'no values here'
,
'no values here'
,
'tricky interpolation'
,
'tricky interpolation'
,
'more interpolation'
])
'more interpolation'
])
self
.
assertEqual
(
cf
.
getint
(
'DEFAULT'
,
'go'
,
self
.
assertEqual
(
cf
.
getint
(
self
.
default_section
,
'go'
,
vars
=
{
'interpolate'
:
'-1'
}),
-
1
)
vars
=
{
'interpolate'
:
'-1'
}),
-
1
)
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
):
# no interpolation will happen
# no interpolation will happen
cf
.
getint
(
'DEFAULT'
,
'go'
,
raw
=
True
,
vars
=
{
'interpolate'
:
'-1'
})
cf
.
getint
(
self
.
default_section
,
'go'
,
raw
=
True
,
vars
=
{
'interpolate'
:
'-1'
})
self
.
assertEqual
(
len
(
cf
.
get
(
'strange'
,
'other'
).
split
(
'
\
n
'
)),
4
)
self
.
assertEqual
(
len
(
cf
.
get
(
'strange'
,
'other'
).
split
(
'
\
n
'
)),
4
)
self
.
assertEqual
(
len
(
cf
.
get
(
'corruption'
,
'value'
).
split
(
'
\
n
'
)),
10
)
self
.
assertEqual
(
len
(
cf
.
get
(
'corruption'
,
'value'
).
split
(
'
\
n
'
)),
10
)
longname
=
'yeah, sections can be indented as well'
longname
=
'yeah, sections can be indented as well'
...
@@ -997,6 +1001,7 @@ def test_main():
...
@@ -997,6 +1001,7 @@ def test_main():
Issue7005TestCase
,
Issue7005TestCase
,
StrictTestCase
,
StrictTestCase
,
CompatibleTestCase
,
CompatibleTestCase
,
ConfigParserTestCaseNonStandardDefaultSection
,
)
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment