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
3846d7ea
Commit
3846d7ea
authored
Dec 16, 2010
by
Łukasz Langa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Broken ConfigParser removed, SafeConfigParser renamed to ConfigParser.
Life is beatiful once again.
parent
1bd5c842
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
202 deletions
+155
-202
Doc/library/configparser.rst
Doc/library/configparser.rst
+39
-60
Lib/configparser.py
Lib/configparser.py
+22
-31
Lib/test/test_cfgparser.py
Lib/test/test_cfgparser.py
+94
-111
No files found.
Doc/library/configparser.rst
View file @
3846d7ea
...
@@ -17,10 +17,10 @@
...
@@ -17,10 +17,10 @@
single: ini file
single: ini file
single: Windows ini file
single: Windows ini file
This module provides the :class:`
SafeConfigParser` class which implements
This module provides the :class:`
ConfigParser` class which implements a basic
a basic configuration language which provides a structure similar to what's
configuration language which provides a structure similar to what's found in
found in Microsoft Windows INI files. You can use this to write Python
Microsoft Windows INI files. You can use this to write Python programs which
programs which
can be customized by end users easily.
can be customized by end users easily.
.. note::
.. note::
...
@@ -67,7 +67,7 @@ creating the above configuration file programatically.
...
@@ -67,7 +67,7 @@ creating the above configuration file programatically.
.. doctest::
.. doctest::
>>> import configparser
>>> import configparser
>>> config = configparser.
Safe
ConfigParser()
>>> config = configparser.ConfigParser()
>>> config['DEFAULT'] = {'ServerAliveInterval': '45',
>>> config['DEFAULT'] = {'ServerAliveInterval': '45',
... 'Compression': 'yes',
... 'Compression': 'yes',
... 'CompressionLevel': '9'}
... 'CompressionLevel': '9'}
...
@@ -92,7 +92,7 @@ back and explore the data it holds.
...
@@ -92,7 +92,7 @@ back and explore the data it holds.
.. doctest::
.. doctest::
>>> import configparser
>>> import configparser
>>> config = configparser.
Safe
ConfigParser()
>>> config = configparser.ConfigParser()
>>> config.sections()
>>> config.sections()
[]
[]
>>> config.read('example.ini')
>>> config.read('example.ini')
...
@@ -283,13 +283,13 @@ For example:
...
@@ -283,13 +283,13 @@ For example:
Interpolation of values
Interpolation of values
-----------------------
-----------------------
On top of the core functionality, :class:`
Safe
ConfigParser` supports
On top of the core functionality, :class:`ConfigParser` supports
interpolation. This means values can be preprocessed before returning them
interpolation. This means values can be preprocessed before returning them
from ``get()`` calls.
from ``get()`` calls.
.. class:: BasicInterpolation()
.. class:: BasicInterpolation()
The default implementation used by :class:`
Safe
ConfigParser`. It enables
The default implementation used by :class:`ConfigParser`. It enables
values to contain format strings which refer to other values in the same
values to contain format strings which refer to other values in the same
section, or values in the special default section [1]_. Additional default
section, or values in the special default section [1]_. Additional default
values can be provided on initialization.
values can be provided on initialization.
...
@@ -304,7 +304,7 @@ from ``get()`` calls.
...
@@ -304,7 +304,7 @@ from ``get()`` calls.
my_pictures: %(my_dir)s/Pictures
my_pictures: %(my_dir)s/Pictures
In the example above, :class:`
Safe
ConfigParser` with *interpolation* set to
In the example above, :class:`ConfigParser` with *interpolation* set to
``BasicInterpolation()`` would resolve ``%(home_dir)s`` to the value of
``BasicInterpolation()`` would resolve ``%(home_dir)s`` to the value of
``home_dir`` (``/Users`` in this case). ``%(my_dir)s`` in effect would
``home_dir`` (``/Users`` in this case). ``%(my_dir)s`` in effect would
resolve to ``/Users/lumberjack``. All interpolations are done on demand so
resolve to ``/Users/lumberjack``. All interpolations are done on demand so
...
@@ -444,7 +444,7 @@ the :meth:`__init__` options:
...
@@ -444,7 +444,7 @@ the :meth:`__init__` options:
.. doctest::
.. doctest::
>>> parser = configparser.
Safe
ConfigParser()
>>> parser = configparser.ConfigParser()
>>> parser.read_dict({'section1': {'key1': 'value1',
>>> parser.read_dict({'section1': {'key1': 'value1',
... 'key2': 'value2',
... 'key2': 'value2',
... 'key3': 'value3'},
... 'key3': 'value3'},
...
@@ -465,7 +465,7 @@ the :meth:`__init__` options:
...
@@ -465,7 +465,7 @@ the :meth:`__init__` options:
.. doctest::
.. doctest::
>>> from collections import OrderedDict
>>> from collections import OrderedDict
>>> parser = configparser.
Safe
ConfigParser()
>>> parser = configparser.ConfigParser()
>>> parser.read_dict(
>>> parser.read_dict(
... OrderedDict((
... OrderedDict((
... ('s1',
... ('s1',
...
@@ -511,7 +511,7 @@ the :meth:`__init__` options:
...
@@ -511,7 +511,7 @@ the :meth:`__init__` options:
... skip-bdb
... skip-bdb
... skip-innodb # we don't need ACID today
... skip-innodb # we don't need ACID today
... """
... """
>>> config = configparser.
Safe
ConfigParser(allow_no_value=True)
>>> config = configparser.ConfigParser(allow_no_value=True)
>>> config.read_string(sample_config)
>>> config.read_string(sample_config)
>>> # Settings with values are treated as before:
>>> # Settings with values are treated as before:
...
@@ -534,7 +534,7 @@ the :meth:`__init__` options:
...
@@ -534,7 +534,7 @@ the :meth:`__init__` options:
This means values (but not keys) can contain the delimiters.
This means values (but not keys) can contain the delimiters.
See also the *space_around_delimiters* argument to
See also the *space_around_delimiters* argument to
:meth:`
Safe
ConfigParser.write`.
:meth:`ConfigParser.write`.
* *comment_prefixes*, default value: ``_COMPATIBLE`` (``'#'`` valid on empty
* *comment_prefixes*, default value: ``_COMPATIBLE`` (``'#'`` valid on empty
lines, ``';'`` valid also on non-empty lines)
lines, ``';'`` valid also on non-empty lines)
...
@@ -604,8 +604,7 @@ the :meth:`__init__` options:
...
@@ -604,8 +604,7 @@ the :meth:`__init__` options:
advanced variant inspired by ``zc.buildout``. More on the subject in the
advanced variant inspired by ``zc.buildout``. More on the subject in the
`dedicated documentation section <#interpolation-of-values>`_.
`dedicated documentation section <#interpolation-of-values>`_.
.. note:: :class:`RawConfigParser` is using ``None`` by default and
.. note:: :class:`RawConfigParser` is using ``None`` by default.
:class:`ConfigParser` is using ``configparser.BrokenInterpolation``.
More advanced customization may be achieved by overriding default values of
More advanced customization may be achieved by overriding default values of
...
@@ -622,7 +621,7 @@ may be overriden by subclasses or by attribute assignment.
...
@@ -622,7 +621,7 @@ may be overriden by subclasses or by attribute assignment.
.. doctest::
.. doctest::
>>> custom = configparser.
Safe
ConfigParser()
>>> custom = configparser.ConfigParser()
>>> custom['section1'] = {'funky': 'nope'}
>>> custom['section1'] = {'funky': 'nope'}
>>> custom['section1'].getboolean('funky')
>>> custom['section1'].getboolean('funky')
Traceback (most recent call last):
Traceback (most recent call last):
...
@@ -652,7 +651,7 @@ may be overriden by subclasses or by attribute assignment.
...
@@ -652,7 +651,7 @@ may be overriden by subclasses or by attribute assignment.
... [Section2]
... [Section2]
... AnotherKey = Value
... AnotherKey = Value
... """
... """
>>> typical = configparser.
Safe
ConfigParser()
>>> typical = configparser.ConfigParser()
>>> typical.read_string(config)
>>> typical.read_string(config)
>>> list(typical['Section1'].keys())
>>> list(typical['Section1'].keys())
['key']
['key']
...
@@ -670,11 +669,11 @@ may be overriden by subclasses or by attribute assignment.
...
@@ -670,11 +669,11 @@ may be overriden by subclasses or by attribute assignment.
Legacy API Examples
Legacy API Examples
-------------------
-------------------
Mainly because of backwards compatibility concerns, :mod:`configparser`
provides
Mainly because of backwards compatibility concerns, :mod:`configparser`
also a legacy API with explicit ``get``/``set`` methods. While there are valid
provides also a legacy API with explicit ``get``/``set`` methods. While there
use cases for the methods outlined below, mapping protocol access is preferred
are valid use cases for the methods outlined below, mapping protocol access is
for new projects. The legacy API is at times more advanced, low-level and
preferred for new projects. The legacy API is at times more advanced,
downright counterintuitive.
low-level and
downright counterintuitive.
An example of writing to a configuration file::
An example of writing to a configuration file::
...
@@ -682,12 +681,11 @@ An example of writing to a configuration file::
...
@@ -682,12 +681,11 @@ An example of writing to a configuration file::
config = configparser.RawConfigParser()
config = configparser.RawConfigParser()
# Please note that using RawConfigParser's and the raw mode of
# Please note that using RawConfigParser's set functions, you can assign
# ConfigParser's respective set functions, you can assign non-string values
# non-string values to keys internally, but will receive an error when
# to keys internally, but will receive an error when attempting to write to
# attempting to write to a file or when you get it in non-raw mode. Setting
# a file or when you get it in non-raw mode. Setting values using the
# values using the mapping protocol or ConfigParser's set() does not allow
# mapping protocol or SafeConfigParser's set() does not allow such
# such assignments to take place.
# assignments to take place.
config.add_section('Section1')
config.add_section('Section1')
config.set('Section1', 'int', '15')
config.set('Section1', 'int', '15')
config.set('Section1', 'bool', 'true')
config.set('Section1', 'bool', 'true')
...
@@ -718,11 +716,11 @@ An example of reading the configuration file again::
...
@@ -718,11 +716,11 @@ An example of reading the configuration file again::
if config.getboolean('Section1', 'bool'):
if config.getboolean('Section1', 'bool'):
print(config.get('Section1', 'foo'))
print(config.get('Section1', 'foo'))
To get interpolation, use :class:`
Safe
ConfigParser`::
To get interpolation, use :class:`ConfigParser`::
import configparser
import configparser
cfg = configparser.
Safe
ConfigParser()
cfg = configparser.ConfigParser()
cfg.read('example.cfg')
cfg.read('example.cfg')
# Set the optional `raw` argument of get() to True if you wish to disable
# Set the optional `raw` argument of get() to True if you wish to disable
...
@@ -751,13 +749,13 @@ To get interpolation, use :class:`SafeConfigParser`::
...
@@ -751,13 +749,13 @@ To get interpolation, use :class:`SafeConfigParser`::
print(cfg.get('Section1', 'monster', fallback=None))
print(cfg.get('Section1', 'monster', fallback=None))
# -> None
# -> None
Default values are available in
all three types of ConfigParsers. They are
Default values are available in
both types of ConfigParsers. They are used in
used in
interpolation if an option used is not defined elsewhere. ::
interpolation if an option used is not defined elsewhere. ::
import configparser
import configparser
# New instance with 'bar' and 'baz' defaulting to 'Life' and 'hard' each
# New instance with 'bar' and 'baz' defaulting to 'Life' and 'hard' each
config = configparser.
Safe
ConfigParser({'bar': 'Life', 'baz': 'hard'})
config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'})
config.read('example.cfg')
config.read('example.cfg')
print(config.get('Section1', 'foo')) # -> "Python is fun!"
print(config.get('Section1', 'foo')) # -> "Python is fun!"
...
@@ -766,12 +764,12 @@ used in interpolation if an option used is not defined elsewhere. ::
...
@@ -766,12 +764,12 @@ used in interpolation if an option used is not defined elsewhere. ::
print(config.get('Section1', 'foo')) # -> "Life is hard!"
print(config.get('Section1', 'foo')) # -> "Life is hard!"
.. _
safe
configparser-objects:
.. _configparser-objects:
Safe
ConfigParser Objects
ConfigParser Objects
--------------------
----
--------------------
.. class::
Safe
ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation())
.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BasicInterpolation())
The main configuration parser. When *defaults* is given, it is initialized
The main configuration parser. When *defaults* is given, it is initialized
into the dictionary of intrinsic defaults. When *dict_type* is given, it
into the dictionary of intrinsic defaults. When *dict_type* is given, it
...
@@ -877,7 +875,7 @@ SafeConfigParser Objects
...
@@ -877,7 +875,7 @@ SafeConfigParser Objects
import configparser, os
import configparser, os
config = configparser.
Safe
ConfigParser()
config = configparser.ConfigParser()
config.read_file(open('defaults.cfg'))
config.read_file(open('defaults.cfg'))
config.read(['site.cfg', os.path.expanduser('~/.myapp.cfg')],
config.read(['site.cfg', os.path.expanduser('~/.myapp.cfg')],
encoding='cp1250')
encoding='cp1250')
...
@@ -1047,13 +1045,13 @@ RawConfigParser Objects
...
@@ -1047,13 +1045,13 @@ RawConfigParser Objects
.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None)
.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None)
Legacy variant of the :class:`
Safe
ConfigParser` with interpolation disabled
Legacy variant of the :class:`ConfigParser` with interpolation disabled
by default and unsafe ``add_section`` and ``set`` methods.
by default and unsafe ``add_section`` and ``set`` methods.
.. note::
.. note::
Consider using :class:`
Safe
ConfigParser` instead which checks types of
Consider using :class:`ConfigParser` instead which checks types of
the values to be stored internally. If you don't want interpolation, you
the values to be stored internally. If you don't want interpolation, you
can use ``
Safe
ConfigParser(interpolation=None)``.
can use ``ConfigParser(interpolation=None)``.
.. method:: add_section(section)
.. method:: add_section(section)
...
@@ -1081,25 +1079,6 @@ RawConfigParser Objects
...
@@ -1081,25 +1079,6 @@ RawConfigParser Objects
which does not allow such assignments to take place.
which does not allow such assignments to take place.
.. _configparser-objects:
ConfigParser Objects
--------------------
.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True, default_section=configparser.DEFAULTSECT, interpolation=BrokenInterpolation())
.. deprecated:: 3.2
Whenever you can, consider using :class:`SafeConfigParser`. The
:class:`ConfigParser` provides the same functionality but its
implementation is less predictable. It does not validate the
interpolation syntax used within a configuration file. It also does not
enable escaping the interpolation character (when using
:class:`SafeConfigParser`, a key can have ``%`` as part of the value by
specifying ``%%`` in the file). On top of that, this class doesn't ensure
whether values passed to the parser object are strings which may lead to
inconsistent internal state.
Exceptions
Exceptions
----------
----------
...
...
Lib/configparser.py
View file @
3846d7ea
...
@@ -5,11 +5,11 @@ and followed by "name: value" entries, with continuations and such in
...
@@ -5,11 +5,11 @@ and followed by "name: value" entries, with continuations and such in
the style of RFC 822.
the style of RFC 822.
Intrinsic defaults can be specified by passing them into the
Intrinsic defaults can be specified by passing them into the
Safe
ConfigParser constructor as a dictionary.
ConfigParser constructor as a dictionary.
class:
class:
Safe
ConfigParser -- responsible for parsing a list of
ConfigParser -- responsible for parsing a list of
configuration files, and managing the parsed database.
configuration files, and managing the parsed database.
methods:
methods:
...
@@ -265,9 +265,8 @@ class InterpolationMissingOptionError(InterpolationError):
...
@@ -265,9 +265,8 @@ class InterpolationMissingOptionError(InterpolationError):
class
InterpolationSyntaxError
(
InterpolationError
):
class
InterpolationSyntaxError
(
InterpolationError
):
"""Raised when the source text contains invalid syntax.
"""Raised when the source text contains invalid syntax.
Current implementation raises this exception only for SafeConfigParser
Current implementation raises this exception when the source text into
instances when the source text into which substitutions are made
which substitutions are made does not conform to the required syntax.
does not conform to the required syntax.
"""
"""
...
@@ -369,7 +368,7 @@ class Interpolation:
...
@@ -369,7 +368,7 @@ class Interpolation:
class
BasicInterpolation
(
Interpolation
):
class
BasicInterpolation
(
Interpolation
):
"""Interpolation as implemented in the classic
Safe
ConfigParser.
"""Interpolation as implemented in the classic ConfigParser.
The option values can contain format strings which refer to other values in
The option values can contain format strings which refer to other values in
the same section, or values in the special default section.
the same section, or values in the special default section.
...
@@ -512,8 +511,8 @@ class ExtendedInterpolation(Interpolation):
...
@@ -512,8 +511,8 @@ class ExtendedInterpolation(Interpolation):
"
found
:
%
r" % (rest,))
"
found
:
%
r" % (rest,))
class
Broken
Interpolation(Interpolation):
class
Legacy
Interpolation(Interpolation):
"""Deprecated interpolation
as implemented in the classic
ConfigParser.
"""Deprecated interpolation
used in old versions of
ConfigParser.
Use BasicInterpolation or ExtendedInterpolation instead."""
Use BasicInterpolation or ExtendedInterpolation instead."""
_KEYCRE = re.compile(r"
%
\
(([
^
)]
*
)
\
)
s
|
.
")
_KEYCRE = re.compile(r"
%
\
(([
^
)]
*
)
\
)
s
|
.
")
...
@@ -598,12 +597,6 @@ class RawConfigParser(MutableMapping):
...
@@ -598,12 +597,6 @@ class RawConfigParser(MutableMapping):
default_section=DEFAULTSECT,
default_section=DEFAULTSECT,
interpolation=_UNSET):
interpolation=_UNSET):
if self.__class__ is RawConfigParser:
warnings.warn(
"
The
RawConfigParser
class
will
be
removed
in
future
versions
.
"
"
Use
'SafeConfigParser(interpolation=None)'
instead
.
",
DeprecationWarning, stacklevel=2
)
self._dict = dict_type
self._dict = dict_type
self._sections = self._dict()
self._sections = self._dict()
self._defaults = self._dict()
self._defaults = self._dict()
...
@@ -1142,8 +1135,8 @@ class RawConfigParser(MutableMapping):
...
@@ -1142,8 +1135,8 @@ class RawConfigParser(MutableMapping):
- we allow valueless options but the value is not None
- we allow valueless options but the value is not None
For compatibility reasons this method is not used in classic set()
For compatibility reasons this method is not used in classic set()
for RawConfigParsers
and ConfigParsers. It is invoked in every
for RawConfigParsers
. It is invoked in every case for mapping protocol
case for mapping protocol access and in Safe
ConfigParser.set().
access and in
ConfigParser.set().
"""
"""
if not isinstance(section, str):
if not isinstance(section, str):
raise TypeError("
section
names
must
be
strings
")
raise TypeError("
section
names
must
be
strings
")
...
@@ -1157,21 +1150,6 @@ class RawConfigParser(MutableMapping):
...
@@ -1157,21 +1150,6 @@ class RawConfigParser(MutableMapping):
class ConfigParser(RawConfigParser):
class ConfigParser(RawConfigParser):
"""ConfigParser implementing interpolation."""
"""ConfigParser implementing interpolation."""
_DEFAULT_INTERPOLATION = BrokenInterpolation()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.__class__ is ConfigParser:
warnings.warn(
"
The
ConfigParser
class
will
be
removed
in
future
versions
.
"
"
Use
SafeConfigParser
instead
.
",
DeprecationWarning, stacklevel=2
)
class SafeConfigParser(ConfigParser):
"""ConfigParser implementing sane interpolation."""
_DEFAULT_INTERPOLATION = BasicInterpolation()
_DEFAULT_INTERPOLATION = BasicInterpolation()
def set(self, section, option, value=None):
def set(self, section, option, value=None):
...
@@ -1188,6 +1166,19 @@ class SafeConfigParser(ConfigParser):
...
@@ -1188,6 +1166,19 @@ class SafeConfigParser(ConfigParser):
super().add_section(section)
super().add_section(section)
class SafeConfigParser(ConfigParser):
"""ConfigParser alias for backwards compatibility purposes."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
warnings.warn(
"
The
SafeConfigParser
class
has
been
renamed
to
ConfigParser
"
"
in
Python
3.2
.
This
alias
will
be
removed
in
future
versions
.
"
"
Use
ConfigParser
directly
instead
.
",
DeprecationWarning, stacklevel=2
)
class SectionProxy(MutableMapping):
class SectionProxy(MutableMapping):
"""A proxy for a single section from a parser."""
"""A proxy for a single section from a parser."""
...
...
Lib/test/test_cfgparser.py
View file @
3846d7ea
...
@@ -5,7 +5,6 @@ import os
...
@@ -5,7 +5,6 @@ import os
import
sys
import
sys
import
textwrap
import
textwrap
import
unittest
import
unittest
import
warnings
from
test
import
support
from
test
import
support
...
@@ -48,8 +47,6 @@ class CfgParserTestCaseClass(unittest.TestCase):
...
@@ -48,8 +47,6 @@ class CfgParserTestCaseClass(unittest.TestCase):
default_section
=
self
.
default_section
,
default_section
=
self
.
default_section
,
interpolation
=
self
.
interpolation
,
interpolation
=
self
.
interpolation
,
)
)
with
warnings
.
catch_warnings
():
warnings
.
simplefilter
(
"ignore"
,
category
=
DeprecationWarning
)
instance
=
self
.
config_class
(
**
arguments
)
instance
=
self
.
config_class
(
**
arguments
)
return
instance
return
instance
...
@@ -708,11 +705,6 @@ class ConfigParserTestCase(BasicTestCase):
...
@@ -708,11 +705,6 @@ class ConfigParserTestCase(BasicTestCase):
config_class
=
configparser
.
ConfigParser
config_class
=
configparser
.
ConfigParser
def
test_interpolation
(
self
):
def
test_interpolation
(
self
):
rawval
=
{
configparser
.
ConfigParser
:
(
"something %(with11)s "
"lots of interpolation (11 steps)"
),
configparser
.
SafeConfigParser
:
"%(with1)s"
,
}
cf
=
self
.
get_interpolation_config
()
cf
=
self
.
get_interpolation_config
()
eq
=
self
.
assertEqual
eq
=
self
.
assertEqual
eq
(
cf
.
get
(
"Foo"
,
"bar"
),
"something with interpolation (1 step)"
)
eq
(
cf
.
get
(
"Foo"
,
"bar"
),
"something with interpolation (1 step)"
)
...
@@ -721,21 +713,25 @@ class ConfigParserTestCase(BasicTestCase):
...
@@ -721,21 +713,25 @@ class ConfigParserTestCase(BasicTestCase):
eq
(
cf
.
get
(
"Foo"
,
"bar10"
),
eq
(
cf
.
get
(
"Foo"
,
"bar10"
),
"something with lots of interpolation (10 steps)"
)
"something with lots of interpolation (10 steps)"
)
e
=
self
.
get_error
(
cf
,
configparser
.
InterpolationDepthError
,
"Foo"
,
"bar11"
)
e
=
self
.
get_error
(
cf
,
configparser
.
InterpolationDepthError
,
"Foo"
,
"bar11"
)
self
.
assertEqual
(
e
.
args
,
(
"bar11"
,
"Foo"
,
rawval
[
self
.
config_class
]))
if
self
.
interpolation
==
configparser
.
_UNSET
:
self
.
assertEqual
(
e
.
args
,
(
"bar11"
,
"Foo"
,
"%(with1)s"
))
elif
isinstance
(
self
.
interpolation
,
configparser
.
LegacyInterpolation
):
self
.
assertEqual
(
e
.
args
,
(
"bar11"
,
"Foo"
,
"something %(with11)s lots of interpolation (11 steps)"
))
def
test_interpolation_missing_value
(
self
):
def
test_interpolation_missing_value
(
self
):
rawval
=
{
configparser
.
ConfigParser
:
'%(reference)s'
,
configparser
.
SafeConfigParser
:
''
,
}
cf
=
self
.
get_interpolation_config
()
cf
=
self
.
get_interpolation_config
()
e
=
self
.
get_error
(
cf
,
configparser
.
InterpolationMissingOptionError
,
e
=
self
.
get_error
(
cf
,
configparser
.
InterpolationMissingOptionError
,
"Interpolation Error"
,
"name"
)
"Interpolation Error"
,
"name"
)
self
.
assertEqual
(
e
.
reference
,
"reference"
)
self
.
assertEqual
(
e
.
reference
,
"reference"
)
self
.
assertEqual
(
e
.
section
,
"Interpolation Error"
)
self
.
assertEqual
(
e
.
section
,
"Interpolation Error"
)
self
.
assertEqual
(
e
.
option
,
"name"
)
self
.
assertEqual
(
e
.
option
,
"name"
)
if
self
.
interpolation
==
configparser
.
_UNSET
:
self
.
assertEqual
(
e
.
args
,
(
'name'
,
'Interpolation Error'
,
self
.
assertEqual
(
e
.
args
,
(
'name'
,
'Interpolation Error'
,
rawval
[
self
.
config_class
],
'reference'
))
''
,
'reference'
))
elif
isinstance
(
self
.
interpolation
,
configparser
.
LegacyInterpolation
):
self
.
assertEqual
(
e
.
args
,
(
'name'
,
'Interpolation Error'
,
'%(reference)s'
,
'reference'
))
def
test_items
(
self
):
def
test_items
(
self
):
self
.
check_items_config
([(
'default'
,
'<default>'
),
self
.
check_items_config
([(
'default'
,
'<default>'
),
...
@@ -743,35 +739,75 @@ class ConfigParserTestCase(BasicTestCase):
...
@@ -743,35 +739,75 @@ class ConfigParserTestCase(BasicTestCase):
(
'key'
,
'|value|'
),
(
'key'
,
'|value|'
),
(
'name'
,
'value'
)])
(
'name'
,
'value'
)])
def
test_safe_interpolation
(
self
):
# See http://www.python.org/sf/511737
cf
=
self
.
fromstring
(
"[section]
\
n
"
"option1{eq}xxx
\
n
"
"option2{eq}%(option1)s/xxx
\
n
"
"ok{eq}%(option1)s/%%s
\
n
"
"not_ok{eq}%(option2)s/%%s"
.
format
(
eq
=
self
.
delimiters
[
0
]))
self
.
assertEqual
(
cf
.
get
(
"section"
,
"ok"
),
"xxx/%s"
)
if
self
.
interpolation
==
configparser
.
_UNSET
:
self
.
assertEqual
(
cf
.
get
(
"section"
,
"not_ok"
),
"xxx/xxx/%s"
)
elif
isinstance
(
self
.
interpolation
,
configparser
.
LegacyInterpolation
):
with
self
.
assertRaises
(
TypeError
):
cf
.
get
(
"section"
,
"not_ok"
)
def
test_set_malformatted_interpolation
(
self
):
cf
=
self
.
fromstring
(
"[sect]
\
n
"
"option1{eq}foo
\
n
"
.
format
(
eq
=
self
.
delimiters
[
0
]))
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"foo"
)
self
.
assertRaises
(
ValueError
,
cf
.
set
,
"sect"
,
"option1"
,
"%foo"
)
self
.
assertRaises
(
ValueError
,
cf
.
set
,
"sect"
,
"option1"
,
"foo%"
)
self
.
assertRaises
(
ValueError
,
cf
.
set
,
"sect"
,
"option1"
,
"f%oo"
)
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"foo"
)
# bug #5741: double percents are *not* malformed
cf
.
set
(
"sect"
,
"option2"
,
"foo%%bar"
)
self
.
assertEqual
(
cf
.
get
(
"sect"
,
"option2"
),
"foo%bar"
)
def
test_set_nonstring_types
(
self
):
def
test_set_nonstring_types
(
self
):
cf
=
self
.
fromstring
(
"[sect]
\
n
"
"option1{eq}foo
\
n
"
.
format
(
eq
=
self
.
delimiters
[
0
]))
# Check that we get a TypeError when setting non-string values
# in an existing section:
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option1"
,
1
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option1"
,
1.0
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option1"
,
object
())
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
1
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
1.0
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
object
())
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
123
,
"invalid opt name!"
)
self
.
assertRaises
(
TypeError
,
cf
.
add_section
,
123
)
def
test_add_section_default
(
self
):
cf
=
self
.
newconfig
()
cf
=
self
.
newconfig
()
cf
.
add_section
(
'non-string'
)
self
.
assertRaises
(
ValueError
,
cf
.
add_section
,
self
.
default_section
)
cf
.
set
(
'non-string'
,
'int'
,
1
)
cf
.
set
(
'non-string'
,
'list'
,
[
0
,
1
,
1
,
2
,
3
,
5
,
8
,
13
,
'%('
])
class
ConfigParserTestCaseLegacyInterpolation
(
ConfigParserTestCase
):
cf
.
set
(
'non-string'
,
'dict'
,
{
'pi'
:
3.14159
,
'%('
:
1
,
config_class
=
configparser
.
ConfigParser
'%(list)'
:
'%(list)'
})
interpolation
=
configparser
.
LegacyInterpolation
()
cf
.
set
(
'non-string'
,
'string_with_interpolation'
,
'%(list)s'
)
self
.
assertEqual
(
cf
.
get
(
'non-string'
,
'int'
,
raw
=
True
),
1
)
def
test_set_malformatted_interpolation
(
self
):
self
.
assertRaises
(
TypeError
,
cf
.
get
,
'non-string'
,
'int'
)
cf
=
self
.
fromstring
(
"[sect]
\
n
"
self
.
assertEqual
(
cf
.
get
(
'non-string'
,
'list'
,
raw
=
True
),
"option1{eq}foo
\
n
"
.
format
(
eq
=
self
.
delimiters
[
0
]))
[
0
,
1
,
1
,
2
,
3
,
5
,
8
,
13
,
'%('
])
self
.
assertRaises
(
TypeError
,
cf
.
get
,
'non-string'
,
'list'
)
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"foo"
)
self
.
assertEqual
(
cf
.
get
(
'non-string'
,
'dict'
,
raw
=
True
),
{
'pi'
:
3.14159
,
'%('
:
1
,
'%(list)'
:
'%(list)'
})
cf
.
set
(
"sect"
,
"option1"
,
"%foo"
)
self
.
assertRaises
(
TypeError
,
cf
.
get
,
'non-string'
,
'dict'
)
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"%foo"
)
self
.
assertEqual
(
cf
.
get
(
'non-string'
,
'string_with_interpolation'
,
cf
.
set
(
"sect"
,
"option1"
,
"foo%"
)
raw
=
True
),
'%(list)s'
)
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"foo%"
)
self
.
assertRaises
(
ValueError
,
cf
.
get
,
'non-string'
,
cf
.
set
(
"sect"
,
"option1"
,
"f%oo"
)
'string_with_interpolation'
,
raw
=
False
)
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"f%oo"
)
cf
.
add_section
(
123
)
cf
.
set
(
123
,
'this is sick'
,
True
)
# bug #5741: double percents are *not* malformed
self
.
assertEqual
(
cf
.
get
(
123
,
'this is sick'
,
raw
=
True
),
True
)
cf
.
set
(
"sect"
,
"option2"
,
"foo%%bar"
)
with
self
.
assertRaises
(
TypeError
):
self
.
assertEqual
(
cf
.
get
(
"sect"
,
"option2"
),
"foo%%bar"
)
cf
.
get
(
123
,
'this is sick'
)
cf
.
optionxform
=
lambda
x
:
x
cf
.
set
(
'non-string'
,
1
,
1
)
self
.
assertRaises
(
TypeError
,
cf
.
get
,
'non-string'
,
1
,
1
)
self
.
assertEqual
(
cf
.
get
(
'non-string'
,
1
,
raw
=
True
),
1
)
class
ConfigParserTestCaseNonStandardDelimiters
(
ConfigParserTestCase
):
class
ConfigParserTestCaseNonStandardDelimiters
(
ConfigParserTestCase
):
delimiters
=
(
':='
,
'$'
)
delimiters
=
(
':='
,
'$'
)
...
@@ -872,56 +908,8 @@ class RawConfigParserTestSambaConf(BasicTestCase):
...
@@ -872,56 +908,8 @@ class RawConfigParserTestSambaConf(BasicTestCase):
self
.
assertEqual
(
cf
.
get
(
"global"
,
"hosts allow"
),
"127."
)
self
.
assertEqual
(
cf
.
get
(
"global"
,
"hosts allow"
),
"127."
)
self
.
assertEqual
(
cf
.
get
(
"tmp"
,
"echo command"
),
"cat %s; rm %s"
)
self
.
assertEqual
(
cf
.
get
(
"tmp"
,
"echo command"
),
"cat %s; rm %s"
)
class
SafeConfigParserTestCase
(
ConfigParserTestCase
):
class
ConfigParserTestCaseExtendedInterpolation
(
BasicTestCase
):
config_class
=
configparser
.
SafeConfigParser
config_class
=
configparser
.
ConfigParser
def
test_safe_interpolation
(
self
):
# See http://www.python.org/sf/511737
cf
=
self
.
fromstring
(
"[section]
\
n
"
"option1{eq}xxx
\
n
"
"option2{eq}%(option1)s/xxx
\
n
"
"ok{eq}%(option1)s/%%s
\
n
"
"not_ok{eq}%(option2)s/%%s"
.
format
(
eq
=
self
.
delimiters
[
0
]))
self
.
assertEqual
(
cf
.
get
(
"section"
,
"ok"
),
"xxx/%s"
)
self
.
assertEqual
(
cf
.
get
(
"section"
,
"not_ok"
),
"xxx/xxx/%s"
)
def
test_set_malformatted_interpolation
(
self
):
cf
=
self
.
fromstring
(
"[sect]
\
n
"
"option1{eq}foo
\
n
"
.
format
(
eq
=
self
.
delimiters
[
0
]))
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"foo"
)
self
.
assertRaises
(
ValueError
,
cf
.
set
,
"sect"
,
"option1"
,
"%foo"
)
self
.
assertRaises
(
ValueError
,
cf
.
set
,
"sect"
,
"option1"
,
"foo%"
)
self
.
assertRaises
(
ValueError
,
cf
.
set
,
"sect"
,
"option1"
,
"f%oo"
)
self
.
assertEqual
(
cf
.
get
(
'sect'
,
"option1"
),
"foo"
)
# bug #5741: double percents are *not* malformed
cf
.
set
(
"sect"
,
"option2"
,
"foo%%bar"
)
self
.
assertEqual
(
cf
.
get
(
"sect"
,
"option2"
),
"foo%bar"
)
def
test_set_nonstring_types
(
self
):
cf
=
self
.
fromstring
(
"[sect]
\
n
"
"option1{eq}foo
\
n
"
.
format
(
eq
=
self
.
delimiters
[
0
]))
# Check that we get a TypeError when setting non-string values
# in an existing section:
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option1"
,
1
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option1"
,
1.0
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option1"
,
object
())
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
1
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
1.0
)
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
"option2"
,
object
())
self
.
assertRaises
(
TypeError
,
cf
.
set
,
"sect"
,
123
,
"invalid opt name!"
)
self
.
assertRaises
(
TypeError
,
cf
.
add_section
,
123
)
def
test_add_section_default
(
self
):
cf
=
self
.
newconfig
()
self
.
assertRaises
(
ValueError
,
cf
.
add_section
,
self
.
default_section
)
class
SafeConfigParserTestCaseExtendedInterpolation
(
BasicTestCase
):
config_class
=
configparser
.
SafeConfigParser
interpolation
=
configparser
.
ExtendedInterpolation
()
interpolation
=
configparser
.
ExtendedInterpolation
()
default_section
=
'common'
default_section
=
'common'
...
@@ -984,15 +972,11 @@ class SafeConfigParserTestCaseExtendedInterpolation(BasicTestCase):
...
@@ -984,15 +972,11 @@ class SafeConfigParserTestCaseExtendedInterpolation(BasicTestCase):
class
SafeConfigParserTestCaseNonStandardDelimiters
(
SafeConfigParserTestCase
):
class
ConfigParserTestCaseNoValue
(
ConfigParserTestCase
):
delimiters
=
(
':='
,
'$'
)
comment_prefixes
=
(
'//'
,
'"'
)
class
SafeConfigParserTestCaseNoValue
(
SafeConfigParserTestCase
):
allow_no_value
=
True
allow_no_value
=
True
class
Safe
ConfigParserTestCaseTrickyFile
(
CfgParserTestCaseClass
):
class
ConfigParserTestCaseTrickyFile
(
CfgParserTestCaseClass
):
config_class
=
configparser
.
Safe
ConfigParser
config_class
=
configparser
.
ConfigParser
delimiters
=
{
'='
}
delimiters
=
{
'='
}
comment_prefixes
=
{
'#'
}
comment_prefixes
=
{
'#'
}
allow_no_value
=
True
allow_no_value
=
True
...
@@ -1047,8 +1031,6 @@ class Issue7005TestCase(unittest.TestCase):
...
@@ -1047,8 +1031,6 @@ class Issue7005TestCase(unittest.TestCase):
def
prepare
(
self
,
config_class
):
def
prepare
(
self
,
config_class
):
# This is the default, but that's the point.
# This is the default, but that's the point.
with
warnings
.
catch_warnings
():
warnings
.
simplefilter
(
"ignore"
,
category
=
DeprecationWarning
)
cp
=
config_class
(
allow_no_value
=
False
)
cp
=
config_class
(
allow_no_value
=
False
)
cp
.
add_section
(
"section"
)
cp
.
add_section
(
"section"
)
cp
.
set
(
"section"
,
"option"
,
None
)
cp
.
set
(
"section"
,
"option"
,
None
)
...
@@ -1057,8 +1039,10 @@ class Issue7005TestCase(unittest.TestCase):
...
@@ -1057,8 +1039,10 @@ class Issue7005TestCase(unittest.TestCase):
return
sio
.
getvalue
()
return
sio
.
getvalue
()
def
test_none_as_value_stringified
(
self
):
def
test_none_as_value_stringified
(
self
):
output
=
self
.
prepare
(
configparser
.
ConfigParser
)
cp
=
configparser
.
ConfigParser
(
allow_no_value
=
False
)
self
.
assertEqual
(
output
,
self
.
expected_output
)
cp
.
add_section
(
"section"
)
with
self
.
assertRaises
(
TypeError
):
cp
.
set
(
"section"
,
"option"
,
None
)
def
test_none_as_value_stringified_raw
(
self
):
def
test_none_as_value_stringified_raw
(
self
):
output
=
self
.
prepare
(
configparser
.
RawConfigParser
)
output
=
self
.
prepare
(
configparser
.
RawConfigParser
)
...
@@ -1112,15 +1096,14 @@ def test_main():
...
@@ -1112,15 +1096,14 @@ def test_main():
support
.
run_unittest
(
support
.
run_unittest
(
ConfigParserTestCase
,
ConfigParserTestCase
,
ConfigParserTestCaseNonStandardDelimiters
,
ConfigParserTestCaseNonStandardDelimiters
,
ConfigParserTestCaseNoValue
,
ConfigParserTestCaseExtendedInterpolation
,
ConfigParserTestCaseLegacyInterpolation
,
ConfigParserTestCaseTrickyFile
,
MultilineValuesTestCase
,
MultilineValuesTestCase
,
RawConfigParserTestCase
,
RawConfigParserTestCase
,
RawConfigParserTestCaseNonStandardDelimiters
,
RawConfigParserTestCaseNonStandardDelimiters
,
RawConfigParserTestSambaConf
,
RawConfigParserTestSambaConf
,
SafeConfigParserTestCase
,
SafeConfigParserTestCaseExtendedInterpolation
,
SafeConfigParserTestCaseNonStandardDelimiters
,
SafeConfigParserTestCaseNoValue
,
SafeConfigParserTestCaseTrickyFile
,
SortedTestCase
,
SortedTestCase
,
Issue7005TestCase
,
Issue7005TestCase
,
StrictTestCase
,
StrictTestCase
,
...
@@ -1139,6 +1122,6 @@ def test_coverage(coverdir):
...
@@ -1139,6 +1122,6 @@ def test_coverage(coverdir):
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
if
"-c"
in
sys
.
argv
:
if
"-c"
in
sys
.
argv
:
test_coverage
(
'/tmp/c
md
.cover'
)
test_coverage
(
'/tmp/c
onfigparser
.cover'
)
else
:
else
:
test_main
()
test_main
()
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