Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
b6a6f5f8
Kaydet (Commit)
b6a6f5f8
authored
Ara 03, 2010
tarafından
Łukasz Langa
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue 10499: Modular interpolation in configparser
üst
ecace28e
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
652 additions
and
458 deletions
+652
-458
configparser.rst
Doc/library/configparser.rst
+259
-224
fileformats.rst
Doc/library/fileformats.rst
+1
-1
configparser.py
Lib/configparser.py
+309
-231
test_cfgparser.py
Lib/test/test_cfgparser.py
+75
-2
NEWS
Misc/NEWS
+8
-0
No files found.
Doc/library/configparser.rst
Dosyayı görüntüle @
b6a6f5f8
...
...
@@ -17,11 +17,10 @@
single: ini file
single: Windows ini file
This module provides the classes :class:`RawConfigParser` and
:class:`SafeConfigParser`. They implement a basic configuration
language which provides a structure similar to what's found in Microsoft
Windows INI files. You can use this to write Python programs which can be
customized by end users easily.
This module provides the :class:`SafeConfigParser` class which implements
a basic configuration language which provides a structure similar to what's
found in Microsoft Windows INI files. You can use this to write Python
programs which can be customized by end users easily.
.. note::
...
...
@@ -34,6 +33,10 @@ customized by end users easily.
Support for a creating Unix shell-like mini-languages which can be used
as an alternate format for application configuration files.
Module :mod:`json`
The json module implements a subset of JavaScript syntax which can also
be used for this purpose.
Quick Start
-----------
...
...
@@ -43,17 +46,17 @@ Let's take a very basic configuration file that looks like this:
.. code-block:: ini
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
Port = 50022
ForwardX11 = no
The structure of INI files is described `in the following section
<#supported-ini-file-structure>`_. Essentially, the file
...
...
@@ -64,7 +67,7 @@ creating the above configuration file programatically.
.. doctest::
>>> import configparser
>>> config = configparser.
Raw
ConfigParser()
>>> config = configparser.
Safe
ConfigParser()
>>> config['DEFAULT'] = {'ServerAliveInterval': '45',
... 'Compression': 'yes',
... 'CompressionLevel': '9'}
...
...
@@ -89,7 +92,7 @@ back and explore the data it holds.
.. doctest::
>>> import configparser
>>> config = configparser.
Raw
ConfigParser()
>>> config = configparser.
Safe
ConfigParser()
>>> config.sections()
[]
>>> config.read('example.ini')
...
...
@@ -233,23 +236,26 @@ by a whitespace character to be recognized as a comment. For backwards
compatibility, by default only ``;`` starts an inline comment, while
``#`` does not [1]_.
On top of the core functionality, :class:`SafeConfigParser` supports
interpolation. This means values can contain format strings which refer to
other values in the same section, or values in a special ``DEFAULT`` section
[1]_. Additional defaults can be provided on initialization.
For example:
.. code-block:: ini
[Paths]
home_dir: /Users
my_dir: %(home_dir)s/lumberjack
my_pictures: %(my_dir)s/Pictures
[Simple Values]
key: value
spaces in keys: allowed
spaces in values: allowed as well
you can also use = to delimit keys from values
[All Values Are Strings]
values like this: 1000000
or this: 3.14159265359
are they treated as numbers? : no
integers, floats and booleans are held as: strings
can use the API to get converted values directly: true
[Multiline Values]
chorus: I'm a lumberjack, and I'm okay
I sleep all night and I work all day
I sleep all night and I work all day
[No Values]
key_without_value
...
...
@@ -262,28 +268,92 @@ For example:
multiline ;comment
value! ;comment
[Sections Can Be Indented]
can_values_be_as_well = True
does_that_mean_anything_special = False
purpose = formatting for readability
multiline_values = are
handled just fine as
long as they are indented
deeper than the first line
of a value
# Did I mention we can indent comments, too?
In the example above, :class:`SafeConfigParser` would resolve ``%(home_dir)s``
to the value of ``home_dir`` (``/Users`` in this case). ``%(my_dir)s`` in
effect would resolve to ``/Users/lumberjack``. All interpolations are done on
demand so keys used in the chain of references do not have to be specified in
any specific order in the configuration file.
:class:`RawConfigParser` would simply return ``%(my_dir)s/Pictures`` as the
value of ``my_pictures`` and ``%(home_dir)s/lumberjack`` as the value of
``my_dir``. Other features presented in the example are handled in the same
manner by both parsers.
[Sections Can Be Indented]
can_values_be_as_well = True
does_that_mean_anything_special = False
purpose = formatting for readability
multiline_values = are
handled just fine as
long as they are indented
deeper than the first line
of a value
# Did I mention we can indent comments, too?
Interpolation of values
-----------------------
On top of the core functionality, :class:`SafeConfigParser` supports
interpolation. This means values can be preprocessed before returning them
from ``get()`` calls.
.. class:: BasicInterpolation()
The default implementation used by :class:`SafeConfigParser`. It enables
values to contain format strings which refer to other values in the same
section, or values in the special default section [1]_. Additional default
values can be provided on initialization.
For example:
.. code-block:: ini
[Paths]
home_dir: /Users
my_dir: %(home_dir)s/lumberjack
my_pictures: %(my_dir)s/Pictures
In the example above, :class:`SafeConfigParser` with *interpolation* set to
``BasicInterpolation()`` would resolve ``%(home_dir)s`` to the value of
``home_dir`` (``/Users`` in this case). ``%(my_dir)s`` in effect would
resolve to ``/Users/lumberjack``. All interpolations are done on demand so
keys used in the chain of references do not have to be specified in any
specific order in the configuration file.
With ``interpolation`` set to ``None``, the parser would simply return
``%(my_dir)s/Pictures`` as the value of ``my_pictures`` and
``%(home_dir)s/lumberjack`` as the value of ``my_dir``.
.. class:: ExtendedInterpolation()
An alternative handler for interpolation which implements a more advanced
syntax, used for instance in ``zc.buildout``. Extended interpolation is
using ``${section:option}`` to denote a value from a foreign section.
Interpolation can span multiple levels. For convenience, if the ``section:``
part is omitted, interpolation defaults to the current section (and possibly
the default values from the special section).
For example, the configuration specified above with basic interpolation,
would look like this with extended interpolation:
.. code-block:: ini
[Paths]
home_dir: /Users
my_dir: ${home_dir}/lumberjack
my_pictures: ${my_dir}/Pictures
Values from other sections can be fetched as well:
.. code-block:: ini
[Common]
home_dir: /Users
library_dir: /Library
system_dir: /System
macports_dir: /opt/local
[Frameworks]
Python: 3.2
path: ${Common:system_dir}/Library/Frameworks/
[Arthur]
nickname: Two Sheds
last_name: Jackson
my_dir: ${Common:home_dir}/twosheds
my_pictures: ${my_dir}/Pictures
python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}
Mapping Protocol Access
-----------------------
...
...
@@ -350,9 +420,9 @@ the :meth:`__init__` options:
* *defaults*, default value: ``None``
This option accepts a dictionary of key-value pairs which will be initially
put in the ``DEFAULT
SECT``. This makes for an elegant way to support concise
con
figuration files that don't specify values which are the same as the
documented default.
put in the ``DEFAULT
`` section. This makes for an elegant way to support
con
cise configuration files that don't specify values which are the same as
the
documented default.
Hint: if you want to specify default values for a specific section, use
:meth:`read_dict` before you read the actual file.
...
...
@@ -374,7 +444,7 @@ the :meth:`__init__` options:
.. doctest::
>>> parser = configparser.
Raw
ConfigParser()
>>> parser = configparser.
Safe
ConfigParser()
>>> parser.read_dict({'section1': {'key1': 'value1',
... 'key2': 'value2',
... 'key3': 'value3'},
...
...
@@ -395,7 +465,7 @@ the :meth:`__init__` options:
.. doctest::
>>> from collections import OrderedDict
>>> parser = configparser.
Raw
ConfigParser()
>>> parser = configparser.
Safe
ConfigParser()
>>> parser.read_dict(
... OrderedDict((
... ('s1',
...
...
@@ -441,7 +511,7 @@ the :meth:`__init__` options:
... skip-bdb
... skip-innodb # we don't need ACID today
... """
>>> config = configparser.
Raw
ConfigParser(allow_no_value=True)
>>> config = configparser.
Safe
ConfigParser(allow_no_value=True)
>>> config.read_string(sample_config)
>>> # Settings with values are treated as before:
...
...
@@ -464,7 +534,7 @@ the :meth:`__init__` options:
This means values (but not keys) can contain the delimiters.
See also the *space_around_delimiters* argument to
:meth:`
Raw
ConfigParser.write`.
:meth:`
Safe
ConfigParser.write`.
* *comment_prefixes*, default value: ``_COMPATIBLE`` (``'#'`` valid on empty
lines, ``';'`` valid also on non-empty lines)
...
...
@@ -512,6 +582,31 @@ the :meth:`__init__` options:
will make empty lines split keys every time. In the example above, it would
produce two keys, ``key`` and ``this``.
* *default_section*, default value: ``configparser.DEFAULTSECT`` (that is:
``"DEFAULT"``)
The convention of allowing a special section of default values for other
sections or interpolation purposes is a powerful concept of this library,
letting users create complex declarative configurations. This section is
normally called ``"DEFAULT"`` but this can be customized to point to any
other valid section name. Some typical values include: ``"general"`` or
``"common"``. The name provided is used for recognizing default sections when
reading from any source and is used when writing configuration back to
a file. Its current value can be retrieved using the
``parser_instance.default_section`` attribute and may be modified at runtime
(i.e. to convert files from one format to another).
* *interpolation*, default value: ``configparser.BasicInterpolation``
Interpolation behaviour may be customized by providing a custom handler
through the *interpolation* argument. ``None`` can be used to turn off
interpolation completely, ``ExtendedInterpolation()`` provides a more
advanced variant inspired by ``zc.buildout``. More on the subject in the
`dedicated documentation section <#interpolation-of-values>`_.
.. note:: :class:`RawConfigParser` is using ``None`` by default and
:class:`ConfigParser` is using ``configparser.BrokenInterpolation``.
More advanced customization may be achieved by overriding default values of
these parser attributes. The defaults are defined on the classes, so they
...
...
@@ -527,7 +622,7 @@ may be overriden by subclasses or by attribute assignment.
.. doctest::
>>> custom = configparser.
Raw
ConfigParser()
>>> custom = configparser.
Safe
ConfigParser()
>>> custom['section1'] = {'funky': 'nope'}
>>> custom['section1'].getboolean('funky')
Traceback (most recent call last):
...
...
@@ -557,7 +652,7 @@ may be overriden by subclasses or by attribute assignment.
... [Section2]
... AnotherKey = Value
... """
>>> typical = configparser.
Raw
ConfigParser()
>>> typical = configparser.
Safe
ConfigParser()
>>> typical.read_string(config)
>>> list(typical['Section1'].keys())
['key']
...
...
@@ -623,8 +718,7 @@ An example of reading the configuration file again::
if config.getboolean('Section1', 'bool'):
print(config.get('Section1', 'foo'))
To get interpolation, use :class:`SafeConfigParser` or, if
you absolutely have to, a :class:`ConfigParser`::
To get interpolation, use :class:`SafeConfigParser`::
import configparser
...
...
@@ -672,14 +766,14 @@ used in interpolation if an option used is not defined elsewhere. ::
print(config.get('Section1', 'foo')) # -> "Life is hard!"
.. _
raw
configparser-objects:
.. _
safe
configparser-objects:
Raw
ConfigParser Objects
-----------------------
Safe
ConfigParser Objects
-----------------------
-
.. class::
RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True
)
.. class::
SafeConfigParser(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
basic
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
will be used to create the dictionary objects for the list of sections, for
the options within a section, and for the default values.
...
...
@@ -698,16 +792,33 @@ RawConfigParser Objects
(default: ``True``), each empty line marks the end of an option. Otherwise,
internal empty lines of a multiline option are kept as part of the value.
When *allow_no_value* is ``True`` (default: ``False``), options without
values are accepted; the value presented for these is ``None``.
values are accepted; the value held for these is ``None`` and they are
serialized without the trailing delimiter.
When *default_section* is given, it specifies the name for the special
section holding default values for other sections and interpolation purposes
(normally named ``"DEFAULT"``). This value can be retrieved and changed on
runtime using the ``default_section`` instance attribute.
Interpolation behaviour may be customized by providing a custom handler
through the *interpolation* argument. ``None`` can be used to turn off
interpolation completely, ``ExtendedInterpolation()`` provides a more
advanced variant inspired by ``zc.buildout``. More on the subject in the
`dedicated documentation section <#interpolation-of-values>`_.
This class does not support the magical interpolation behavior.
All option names used in interpolation will be passed through the
:meth:`optionxform` method just like any other option name reference. For
example, using the default implementation of :meth:`optionxform` (which
converts option names to lower case), the values ``foo %(bar)s`` and ``foo
%(BAR)s`` are equivalent.
.. versionchanged:: 3.1
The default *dict_type* is :class:`collections.OrderedDict`.
.. versionchanged:: 3.2
*allow_no_value*, *delimiters*, *comment_prefixes*, *strict* and
*empty_lines_in_values* were added.
*allow_no_value*, *delimiters*, *comment_prefixes*, *strict*,
*empty_lines_in_values*, *default_section* and *interpolation* were
added.
.. method:: defaults()
...
...
@@ -717,22 +828,21 @@ RawConfigParser Objects
.. method:: sections()
Return a list of the sections available;
``DEFAULT`` is not included in
the list.
Return a list of the sections available;
the *default section* is not
included in
the list.
.. method:: add_section(section)
Add a section named *section* to the instance. If a section by the given
name already exists, :exc:`DuplicateSectionError` is raised. If the name
``DEFAULT`` (or any of it's case-insensitive variants) is passed,
:exc:`ValueError` is raised.
name already exists, :exc:`DuplicateSectionError` is raised. If the
*default section* name is passed, :exc:`ValueError` is raised.
.. method:: has_section(section)
Indicates whether the named
section is present in the configuration. The
``DEFAULT`` section
is not acknowledged.
Indicates whether the named
*section* is present in the configuration.
The *default section*
is not acknowledged.
.. method:: options(section)
...
...
@@ -742,7 +852,7 @@ RawConfigParser Objects
.. method:: has_option(section, option)
If the given
section exists, and contains the given option
, return
If the given
*section* exists, and contains the given *option*
, return
:const:`True`; otherwise return :const:`False`.
...
...
@@ -750,19 +860,20 @@ RawConfigParser Objects
Attempt to read and parse a list of filenames, returning a list of
filenames which were successfully parsed. If *filenames* is a string, it
is treated as a single filename. If a file named in *filenames* cannot be
opened, that file will be ignored. This is designed so that you can
specify a list of potential configuration file locations (for example, the
current directory, the user's home directory, and some system-wide
directory), and all existing configuration files in the list will be read.
If none of the named files exist, the :class:`ConfigParser` instance will
contain an empty dataset. An application which requires initial values to
be loaded from a file should load the required file or files using
:meth:`read_file` before calling :meth:`read` for any optional files::
is treated as a single filename. If a file named in *filenames* cannot
be opened, that file will be ignored. This is designed so that you can
specify a list of potential configuration file locations (for example,
the current directory, the user's home directory, and some system-wide
directory), and all existing configuration files in the list will be
read. If none of the named files exist, the :class:`ConfigParser`
instance will contain an empty dataset. An application which requires
initial values to be loaded from a file should load the required file or
files using :meth:`read_file` before calling :meth:`read` for any
optional files::
import configparser, os
config = configparser.ConfigParser()
config = configparser.
Safe
ConfigParser()
config.read_file(open('defaults.cfg'))
config.read(['site.cfg', os.path.expanduser('~/.myapp.cfg')],
encoding='cp1250')
...
...
@@ -810,7 +921,8 @@ RawConfigParser Objects
.. versionadded:: 3.2
.. method:: get(section, option, [vars, fallback])
.. method:: get(section, option, raw=False, [vars, fallback])
Get an *option* value for the named *section*. If *vars* is provided, it
must be a dictionary. The *option* is looked up in *vars* (if provided),
...
...
@@ -818,58 +930,54 @@ RawConfigParser Objects
and *fallback* is provided, it is used as a fallback value. ``None`` can
be provided as a *fallback* value.
All the ``'%'`` interpolations are expanded in the return values, unless
the *raw* argument is true. Values for interpolation keys are looked up
in the same manner as the option.
.. versionchanged:: 3.2
Arguments *
vars* and *fallback* are keyword only to protect users from
trying to use the third argument as the *fallback* fallback (especially
when using the mapping protocol).
Arguments *
raw*, *vars* and *fallback* are keyword only to protect
users from trying to use the third argument as the *fallback* fallback
(especially
when using the mapping protocol).
.. method:: getint(section, option, [vars, fallback])
.. method:: getint(section, option,
raw=False,
[vars, fallback])
A convenience method which coerces the *option* in the specified *section*
to an integer. See :meth:`get` for explanation of *vars* and *fallback*.
to an integer. See :meth:`get` for explanation of *raw*, *vars* and
*fallback*.
.. method:: getfloat(section, option, [vars, fallback])
.. method:: getfloat(section, option,
raw=False,
[vars, fallback])
A convenience method which coerces the *option* in the specified *section*
to a floating point number. See :meth:`get` for explanation of *
vars* and
*fallback*.
to a floating point number. See :meth:`get` for explanation of *
raw*,
*
vars* and *
fallback*.
.. method:: getboolean(section, option, [vars, fallback])
.. method:: getboolean(section, option,
raw=False,
[vars, fallback])
A convenience method which coerces the *option* in the specified *section*
to a Boolean value. Note that the accepted values for the option are
``
"1"``, ``"yes"``, ``"true"``, and ``"on"
``, which cause this method to
return ``True``, and ``
"0"``, ``"no"``, ``"false"``, and ``"off"
``, which
``
'1'``, ``'yes'``, ``'true'``, and ``'on'
``, which cause this method to
return ``True``, and ``
'0'``, ``'no'``, ``'false'``, and ``'off'
``, which
cause it to return ``False``. These string values are checked in a
case-insensitive manner. Any other value will cause it to raise
:exc:`ValueError`.
See :meth:`get` for explanation of
*vars* and
:exc:`ValueError`.
See :meth:`get` for explanation of *raw*,
*vars* and
*fallback*.
.. method:: items(section)
.. method:: items(section
, raw=False, vars=None
)
Return a list of *name*, *value* pairs for each option in the given
*section*.
Return a list of *name*, *value* pairs for the options in the given
*section*. Optional arguments have the same meaning as for the
:meth:`get` method.
.. method:: set(section, option, value)
If the given section exists, set the given option to the specified value;
otherwise raise :exc:`NoSectionError`. While it is possible to use
:class:`RawConfigParser` (or :class:`ConfigParser` with *raw* parameters
set to true) for *internal* storage of non-string values, full
functionality (including interpolation and output to files) can only be
achieved using string values.
.. note::
This method lets users assign non-string values to keys internally.
This behaviour is unsupported and will cause errors when attempting to
write to a file or get it in non-raw mode. **Use the mapping protocol
API** which does not allow such assignments to take place.
otherwise raise :exc:`NoSectionError`. *value* must be a string; if not,
:exc:`TypeError` is raised.
.. method:: write(fileobject, space_around_delimiters=True)
...
...
@@ -921,134 +1029,61 @@ RawConfigParser Objects
Use :meth:`read_file` instead.
.. _configparser-objects:
ConfigParser Objects
--------------------
.. warning::
Whenever you can, consider using :class:`SafeConfigParser` which adds
validation and escaping for the interpolation.
The :class:`ConfigParser` class extends some methods of the
:class:`RawConfigParser` interface, adding some optional arguments.
.. class:: ConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=True)
Derived class of :class:`RawConfigParser` that implements the magical
interpolation feature and adds optional arguments to the :meth:`get` and
:meth:`items` methods.
:class:`SafeConfigParser` is generally recommended over this class if you
need interpolation.
The values in *defaults* must be appropriate for the ``%()s`` string
interpolation.
All option names used in interpolation will be passed through the
:meth:`optionxform` method just like any other option name reference. For
example, using the default implementation of :meth:`optionxform` (which
converts option names to lower case), the values ``foo %(bar)s`` and ``foo
%(BAR)s`` are equivalent.
.. versionchanged:: 3.1
The default *dict_type* is :class:`collections.OrderedDict`.
.. versionchanged:: 3.2
*allow_no_value*, *delimiters*, *comment_prefixes*,
*strict* and *empty_lines_in_values* were added.
.. method:: get(section, option, raw=False, [vars, fallback])
Get an *option* value for the named *section*. If *vars* is provided, it
must be a dictionary. The *option* is looked up in *vars* (if provided),
*section*, and in *DEFAULTSECT* in that order. If the key is not found
and *fallback* is provided, it is used as a fallback value. ``None`` can
be provided as a *fallback* value.
All the ``'%'`` interpolations are expanded in the return values, unless
the *raw* argument is true. Values for interpolation keys are looked up
in the same manner as the option.
.. versionchanged:: 3.2
Arguments *raw*, *vars* and *fallback* are keyword only to protect
users from trying to use the third argument as the *fallback* fallback
(especially when using the mapping protocol).
.. method:: getint(section, option, raw=False, [vars, fallback])
A convenience method which coerces the *option* in the specified *section*
to an integer. See :meth:`get` for explanation of *raw*, *vars* and
*fallback*.
.. method:: getfloat(section, option, raw=False, [vars, fallback])
A convenience method which coerces the *option* in the specified *section*
to a floating point number. See :meth:`get` for explanation of *raw*,
*vars* and *fallback*.
.. method:: getboolean(section, option, raw=False, [vars, fallback])
A convenience method which coerces the *option* in the specified *section*
to a Boolean value. Note that the accepted values for the option are
``'1'``, ``'yes'``, ``'true'``, and ``'on'``, which cause this method to
return ``True``, and ``'0'``, ``'no'``, ``'false'``, and ``'off'``, which
cause it to return ``False``. These string values are checked in a
case-insensitive manner. Any other value will cause it to raise
:exc:`ValueError`. See :meth:`get` for explanation of *raw*, *vars* and
*fallback*.
.. method:: items(section, raw=False, vars=None)
Return a list of *name*, *value* pairs for the options in the given
*section*. Optional arguments have the same meaning as for the
:meth:`get` method.
.. data:: MAX_INTERPOLATION_DEPTH
The maximum depth for recursive interpolation for :meth:`get` when the *raw*
parameter is false. This is relevant only for the :class:`ConfigParser` class.
parameter is false. This is relevant only when the default *interpolation*
is used.
.. _
safe
configparser-objects:
.. _
raw
configparser-objects:
Safe
ConfigParser Objects
-----------------------
-
Raw
ConfigParser Objects
-----------------------
.. class::
SafeConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=_COMPATIBLE, strict=False, empty_lines_in_values=Tru
e)
.. 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=Non
e)
Derived class of :class:`ConfigParser` that implements a variant of the
magical interpolation feature. This implementation is more predictable as
it validates the interpolation syntax used within a configuration file.
This class also enables escaping the interpolation character (a key can have
``%`` as part of the value by specifying ``%%`` in the file).
Legacy variant of the :class:`SafeConfigParser` with interpolation disabled
by default and an unsafe ``set`` method.
Applications that don't require interpolation should use
:class:`RawConfigParser`, otherwise :class:`SafeConfigParser` is the best
option.
.. note::
Consider using :class:`SafeConfigParser` instead which checks types of
the values to be stored internally. If you don't want interpolation, you
can use ``SafeConfigParser(interpolation=None)``.
.. versionchanged:: 3.1
The default *dict_type* is :class:`collections.OrderedDict`.
.. versionchanged:: 3.2
*allow_no_value*, *delimiters*, *comment_prefixes*, *strict* and
*empty_lines_in_values* were added.
.. method:: set(section, option, value)
If the given section exists, set the given option to the specified value;
otherwise raise :exc:`NoSectionError`. While it is possible to use
:class:`RawConfigParser` (or :class:`ConfigParser` with *raw* parameters
set to true) for *internal* storage of non-string values, full
functionality (including interpolation and output to files) can only be
achieved using string values.
This method lets users assign non-string values to keys internally. This
behaviour is unsupported and will cause errors when attempting to write
to a file or get it in non-raw mode. **Use the mapping protocol API**
which does not allow such assignments to take place.
The :class:`SafeConfigParser` class implements the same extended interface
as :class:`ConfigParser`, with the following addition:
.. method:: set(section, option, value)
.. _configparser-objects:
If the given section exists, set the given option to the specified value;
otherwise raise :exc:`NoSectionError`. *value* must be a string; if not,
:exc:`TypeError` is raised.
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
...
...
Doc/library/fileformats.rst
Dosyayı görüntüle @
b6a6f5f8
...
...
@@ -5,7 +5,7 @@ File Formats
************
The modules described in this chapter parse various miscellaneous file formats
that aren't markup languages
or are
related to e-mail.
that aren't markup languages
and are not
related to e-mail.
.. toctree::
...
...
Lib/configparser.py
Dosyayı görüntüle @
b6a6f5f8
...
...
@@ -4,23 +4,13 @@ A configuration file consists of sections, lead by a "[section]" header,
and followed by "name: value" entries, with continuations and such in
the style of RFC 822.
The option values can contain format strings which refer to other values in
the same section, or values in a special [DEFAULT] section.
For example:
something:
%(dir)
s/whatever
would resolve the "
%(dir)
s" to the value of dir. All reference
expansions are done late, on demand.
Intrinsic defaults can be specified by passing them into the
ConfigParser constructor as a dictionary.
Safe
ConfigParser constructor as a dictionary.
class:
ConfigParser -- responsible for parsing a list of
configuration files, and managing the parsed database.
Safe
ConfigParser -- responsible for parsing a list of
configuration files, and managing the parsed database.
methods:
...
...
@@ -316,7 +306,7 @@ class ParsingError(Error):
def
filename
(
self
):
"""Deprecated, use `source'."""
warnings
.
warn
(
"Th
is
'filename' attribute will be removed in future versions. "
"Th
e
'filename' attribute will be removed in future versions. "
"Use 'source' instead."
,
DeprecationWarning
,
stacklevel
=
2
)
...
...
@@ -362,6 +352,204 @@ _COMPATIBLE = object()
_UNSET
=
object
()
class
Interpolation
:
"""Dummy interpolation that passes the value through with no changes."""
def
before_get
(
self
,
parser
,
section
,
option
,
value
,
defaults
):
return
value
def
before_set
(
self
,
parser
,
section
,
option
,
value
):
return
value
def
before_read
(
self
,
parser
,
section
,
option
,
value
):
return
value
def
before_write
(
self
,
parser
,
section
,
option
,
value
):
return
value
class
BasicInterpolation
(
Interpolation
):
"""Interpolation as implemented in the classic SafeConfigParser.
The option values can contain format strings which refer to other values in
the same section, or values in the special default section.
For example:
something:
%(dir)
s/whatever
would resolve the "
%(dir)
s" to the value of dir. All reference
expansions are done late, on demand. If a user needs to use a bare
%
in
a configuration file, she can escape it by writing
%%
. Other other
%
usage
is considered a user error and raises `InterpolationSyntaxError'."""
_KEYCRE
=
re
.
compile
(
r"
%
\(([^)]+)\)s"
)
def
before_get
(
self
,
parser
,
section
,
option
,
value
,
defaults
):
L
=
[]
self
.
_interpolate_some
(
parser
,
option
,
L
,
value
,
section
,
defaults
,
1
)
return
''
.
join
(
L
)
def
before_set
(
self
,
parser
,
section
,
option
,
value
):
tmp_value
=
value
.
replace
(
'
%%
'
,
''
)
# escaped percent signs
tmp_value
=
self
.
_KEYCRE
.
sub
(
''
,
tmp_value
)
# valid syntax
if
'
%
'
in
tmp_value
:
raise
ValueError
(
"invalid interpolation syntax in
%
r at "
"position
%
d"
%
(
value
,
tmp_value
.
find
(
'
%
'
)))
return
value
def
_interpolate_some
(
self
,
parser
,
option
,
accum
,
rest
,
section
,
map
,
depth
):
if
depth
>
MAX_INTERPOLATION_DEPTH
:
raise
InterpolationDepthError
(
option
,
section
,
rest
)
while
rest
:
p
=
rest
.
find
(
"
%
"
)
if
p
<
0
:
accum
.
append
(
rest
)
return
if
p
>
0
:
accum
.
append
(
rest
[:
p
])
rest
=
rest
[
p
:]
# p is no longer used
c
=
rest
[
1
:
2
]
if
c
==
"
%
"
:
accum
.
append
(
"
%
"
)
rest
=
rest
[
2
:]
elif
c
==
"("
:
m
=
self
.
_KEYCRE
.
match
(
rest
)
if
m
is
None
:
raise
InterpolationSyntaxError
(
option
,
section
,
"bad interpolation variable reference
%
r"
%
rest
)
var
=
parser
.
optionxform
(
m
.
group
(
1
))
rest
=
rest
[
m
.
end
():]
try
:
v
=
map
[
var
]
except
KeyError
:
raise
InterpolationMissingOptionError
(
option
,
section
,
rest
,
var
)
if
"
%
"
in
v
:
self
.
_interpolate_some
(
parser
,
option
,
accum
,
v
,
section
,
map
,
depth
+
1
)
else
:
accum
.
append
(
v
)
else
:
raise
InterpolationSyntaxError
(
option
,
section
,
"'
%%
' must be followed by '
%%
' or '(', "
"found:
%
r"
%
(
rest
,))
class
ExtendedInterpolation
(
Interpolation
):
"""Advanced variant of interpolation, supports the syntax used by
`zc.buildout'. Enables interpolation between sections."""
_KEYCRE
=
re
.
compile
(
r"\$\{([^}]+)\}"
)
def
before_get
(
self
,
parser
,
section
,
option
,
value
,
defaults
):
L
=
[]
self
.
_interpolate_some
(
parser
,
option
,
L
,
value
,
section
,
defaults
,
1
)
return
''
.
join
(
L
)
def
before_set
(
self
,
parser
,
section
,
option
,
value
):
tmp_value
=
value
.
replace
(
'$$'
,
''
)
# escaped dollar signs
tmp_value
=
self
.
_KEYCRE
.
sub
(
''
,
tmp_value
)
# valid syntax
if
'$'
in
tmp_value
:
raise
ValueError
(
"invalid interpolation syntax in
%
r at "
"position
%
d"
%
(
value
,
tmp_value
.
find
(
'
%
'
)))
return
value
def
_interpolate_some
(
self
,
parser
,
option
,
accum
,
rest
,
section
,
map
,
depth
):
if
depth
>
MAX_INTERPOLATION_DEPTH
:
raise
InterpolationDepthError
(
option
,
section
,
rest
)
while
rest
:
p
=
rest
.
find
(
"$"
)
if
p
<
0
:
accum
.
append
(
rest
)
return
if
p
>
0
:
accum
.
append
(
rest
[:
p
])
rest
=
rest
[
p
:]
# p is no longer used
c
=
rest
[
1
:
2
]
if
c
==
"$"
:
accum
.
append
(
"$"
)
rest
=
rest
[
2
:]
elif
c
==
"{"
:
m
=
self
.
_KEYCRE
.
match
(
rest
)
if
m
is
None
:
raise
InterpolationSyntaxError
(
option
,
section
,
"bad interpolation variable reference
%
r"
%
rest
)
path
=
parser
.
optionxform
(
m
.
group
(
1
))
.
split
(
':'
)
rest
=
rest
[
m
.
end
():]
sect
=
section
opt
=
option
try
:
if
len
(
path
)
==
1
:
opt
=
path
[
0
]
v
=
map
[
opt
]
elif
len
(
path
)
==
2
:
sect
=
path
[
0
]
opt
=
path
[
1
]
v
=
parser
.
get
(
sect
,
opt
,
raw
=
True
)
else
:
raise
InterpolationSyntaxError
(
option
,
section
,
"More than one ':' found:
%
r"
%
(
rest
,))
except
KeyError
:
raise
InterpolationMissingOptionError
(
option
,
section
,
rest
,
var
)
if
"$"
in
v
:
self
.
_interpolate_some
(
parser
,
opt
,
accum
,
v
,
sect
,
dict
(
parser
.
items
(
sect
,
raw
=
True
)),
depth
+
1
)
else
:
accum
.
append
(
v
)
else
:
raise
InterpolationSyntaxError
(
option
,
section
,
"'$' must be followed by '$' or '{', "
"found:
%
r"
%
(
rest
,))
class
BrokenInterpolation
(
Interpolation
):
"""Deprecated interpolation as implemented in the classic ConfigParser.
Use BasicInterpolation or ExtendedInterpolation instead."""
_KEYCRE
=
re
.
compile
(
r"
%
\(([^)]*)\)s|."
)
def
before_get
(
self
,
parser
,
section
,
option
,
value
,
vars
):
rawval
=
value
depth
=
MAX_INTERPOLATION_DEPTH
while
depth
:
# Loop through this until it's done
depth
-=
1
if
value
and
"
%
("
in
value
:
replace
=
functools
.
partial
(
self
.
_interpolation_replace
,
parser
=
parser
)
value
=
self
.
_KEYCRE
.
sub
(
replace
,
value
)
try
:
value
=
value
%
vars
except
KeyError
as
e
:
raise
InterpolationMissingOptionError
(
option
,
section
,
rawval
,
e
.
args
[
0
])
else
:
break
if
value
and
"
%
("
in
value
:
raise
InterpolationDepthError
(
option
,
section
,
rawval
)
return
value
def
before_set
(
self
,
parser
,
section
,
option
,
value
):
return
value
@staticmethod
def
_interpolation_replace
(
match
,
parser
):
s
=
match
.
group
(
1
)
if
s
is
None
:
return
match
.
group
()
else
:
return
"
%%
(
%
s)s"
%
parser
.
optionxform
(
s
)
class
RawConfigParser
(
MutableMapping
):
"""ConfigParser that does not do interpolation."""
...
...
@@ -388,7 +576,8 @@ class RawConfigParser(MutableMapping):
# space/tab
(?P<value>.*))?$ # everything up to eol
"""
# Interpolation algorithm to be used if the user does not specify another
_DEFAULT_INTERPOLATION
=
Interpolation
()
# Compiled regular expression for matching sections
SECTCRE
=
re
.
compile
(
_SECT_TMPL
,
re
.
VERBOSE
)
# Compiled regular expression for matching options with typical separators
...
...
@@ -406,7 +595,15 @@ class RawConfigParser(MutableMapping):
allow_no_value
=
False
,
*
,
delimiters
=
(
'='
,
':'
),
comment_prefixes
=
_COMPATIBLE
,
strict
=
False
,
empty_lines_in_values
=
True
,
default_section
=
DEFAULTSECT
):
default_section
=
DEFAULTSECT
,
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
.
_sections
=
self
.
_dict
()
self
.
_defaults
=
self
.
_dict
()
...
...
@@ -435,7 +632,11 @@ class RawConfigParser(MutableMapping):
self
.
_strict
=
strict
self
.
_allow_no_value
=
allow_no_value
self
.
_empty_lines_in_values
=
empty_lines_in_values
self
.
_default_section
=
default_section
if
interpolation
is
_UNSET
:
self
.
_interpolation
=
self
.
_DEFAULT_INTERPOLATION
else
:
self
.
_interpolation
=
interpolation
self
.
default_section
=
default_section
def
defaults
(
self
):
return
self
.
_defaults
...
...
@@ -451,7 +652,7 @@ class RawConfigParser(MutableMapping):
Raise DuplicateSectionError if a section by the specified name
already exists. Raise ValueError if name is DEFAULT.
"""
if
section
==
self
.
_
default_section
:
if
section
==
self
.
default_section
:
raise
ValueError
(
'Invalid section name:
%
s'
%
section
)
if
section
in
self
.
_sections
:
...
...
@@ -555,7 +756,7 @@ class RawConfigParser(MutableMapping):
)
self
.
read_file
(
fp
,
source
=
filename
)
def
get
(
self
,
section
,
option
,
*
,
vars
=
None
,
fallback
=
_UNSET
):
def
get
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
"""Get an option value for a given section.
If `vars' is provided, it must be a dictionary. The option is looked up
...
...
@@ -563,7 +764,12 @@ class RawConfigParser(MutableMapping):
If the key is not found and `fallback' is provided, it is used as
a fallback value. `None' can be provided as a `fallback' value.
Arguments `vars' and `fallback' are keyword only.
If interpolation is enabled and the optional argument `raw' is False,
all interpolations are expanded in the return values.
Arguments `raw', `vars', and `fallback' are keyword only.
The section DEFAULT is special.
"""
try
:
d
=
self
.
_unify_values
(
section
,
vars
)
...
...
@@ -574,61 +780,90 @@ class RawConfigParser(MutableMapping):
return
fallback
option
=
self
.
optionxform
(
option
)
try
:
return
d
[
option
]
value
=
d
[
option
]
except
KeyError
:
if
fallback
is
_UNSET
:
raise
NoOptionError
(
option
,
section
)
else
:
return
fallback
def
items
(
self
,
section
):
try
:
d2
=
self
.
_sections
[
section
]
except
KeyError
:
if
section
!=
self
.
_default_section
:
raise
NoSectionError
(
section
)
d2
=
self
.
_dict
()
d
=
self
.
_defaults
.
copy
()
d
.
update
(
d2
)
return
d
.
items
()
if
raw
or
value
is
None
:
return
value
else
:
return
self
.
_interpolation
.
before_get
(
self
,
section
,
option
,
value
,
d
)
def
_get
(
self
,
section
,
conv
,
option
,
**
kwargs
):
return
conv
(
self
.
get
(
section
,
option
,
**
kwargs
))
def
getint
(
self
,
section
,
option
,
*
,
vars
=
None
,
fallback
=
_UNSET
):
def
getint
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
try
:
return
self
.
_get
(
section
,
int
,
option
,
vars
=
vars
)
return
self
.
_get
(
section
,
int
,
option
,
raw
=
raw
,
vars
=
vars
)
except
(
NoSectionError
,
NoOptionError
):
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
def
getfloat
(
self
,
section
,
option
,
*
,
vars
=
None
,
fallback
=
_UNSET
):
def
getfloat
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
try
:
return
self
.
_get
(
section
,
float
,
option
,
vars
=
vars
)
return
self
.
_get
(
section
,
float
,
option
,
raw
=
raw
,
vars
=
vars
)
except
(
NoSectionError
,
NoOptionError
):
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
def
getboolean
(
self
,
section
,
option
,
*
,
vars
=
None
,
fallback
=
_UNSET
):
def
getboolean
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
try
:
return
self
.
_get
(
section
,
self
.
_convert_to_boolean
,
option
,
vars
=
vars
)
raw
=
raw
,
vars
=
vars
)
except
(
NoSectionError
,
NoOptionError
):
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
def
items
(
self
,
section
,
raw
=
False
,
vars
=
None
):
"""Return a list of (name, value) tuples for each option in a section.
All
%
interpolations are expanded in the return values, based on the
defaults passed into the constructor, unless the optional argument
`raw' is true. Additional substitutions may be provided using the
`vars' argument, which must be a dictionary whose contents overrides
any pre-existing defaults.
The section DEFAULT is special.
"""
d
=
self
.
_defaults
.
copy
()
try
:
d
.
update
(
self
.
_sections
[
section
])
except
KeyError
:
if
section
!=
self
.
default_section
:
raise
NoSectionError
(
section
)
# Update with the entry specific variables
if
vars
:
for
key
,
value
in
vars
.
items
():
d
[
self
.
optionxform
(
key
)]
=
value
options
=
list
(
d
.
keys
())
if
raw
:
return
[(
option
,
d
[
option
])
for
option
in
options
]
else
:
return
[(
option
,
self
.
_interpolation
.
before_get
(
self
,
section
,
option
,
d
[
option
],
d
))
for
option
in
options
]
def
optionxform
(
self
,
optionstr
):
return
optionstr
.
lower
()
def
has_option
(
self
,
section
,
option
):
"""Check for the existence of a given option in a given section."""
if
not
section
or
section
==
self
.
_
default_section
:
if
not
section
or
section
==
self
.
default_section
:
option
=
self
.
optionxform
(
option
)
return
option
in
self
.
_defaults
elif
section
not
in
self
.
_sections
:
...
...
@@ -640,7 +875,10 @@ class RawConfigParser(MutableMapping):
def
set
(
self
,
section
,
option
,
value
=
None
):
"""Set an option."""
if
not
section
or
section
==
self
.
_default_section
:
if
value
:
value
=
self
.
_interpolation
.
before_set
(
self
,
section
,
option
,
value
)
if
not
section
or
section
==
self
.
default_section
:
sectdict
=
self
.
_defaults
else
:
try
:
...
...
@@ -660,7 +898,7 @@ class RawConfigParser(MutableMapping):
else
:
d
=
self
.
_delimiters
[
0
]
if
self
.
_defaults
:
self
.
_write_section
(
fp
,
self
.
_
default_section
,
self
.
_write_section
(
fp
,
self
.
default_section
,
self
.
_defaults
.
items
(),
d
)
for
section
in
self
.
_sections
:
self
.
_write_section
(
fp
,
section
,
...
...
@@ -670,6 +908,8 @@ class RawConfigParser(MutableMapping):
"""Write a single section to the specified `fp'."""
fp
.
write
(
"[{}]
\n
"
.
format
(
section_name
))
for
key
,
value
in
section_items
:
value
=
self
.
_interpolation
.
before_write
(
self
,
section_name
,
key
,
value
)
if
value
is
not
None
or
not
self
.
_allow_no_value
:
value
=
delimiter
+
str
(
value
)
.
replace
(
'
\n
'
,
'
\n\t
'
)
else
:
...
...
@@ -679,7 +919,7 @@ class RawConfigParser(MutableMapping):
def
remove_option
(
self
,
section
,
option
):
"""Remove an option."""
if
not
section
or
section
==
self
.
_
default_section
:
if
not
section
or
section
==
self
.
default_section
:
sectdict
=
self
.
_defaults
else
:
try
:
...
...
@@ -701,7 +941,7 @@ class RawConfigParser(MutableMapping):
return
existed
def
__getitem__
(
self
,
key
):
if
key
!=
self
.
_
default_section
and
not
self
.
has_section
(
key
):
if
key
!=
self
.
default_section
and
not
self
.
has_section
(
key
):
raise
KeyError
(
key
)
return
self
.
_proxies
[
key
]
...
...
@@ -715,21 +955,21 @@ class RawConfigParser(MutableMapping):
self
.
read_dict
({
key
:
value
})
def
__delitem__
(
self
,
key
):
if
key
==
self
.
_
default_section
:
if
key
==
self
.
default_section
:
raise
ValueError
(
"Cannot remove the default section."
)
if
not
self
.
has_section
(
key
):
raise
KeyError
(
key
)
self
.
remove_section
(
key
)
def
__contains__
(
self
,
key
):
return
key
==
self
.
_
default_section
or
self
.
has_section
(
key
)
return
key
==
self
.
default_section
or
self
.
has_section
(
key
)
def
__len__
(
self
):
return
len
(
self
.
_sections
)
+
1
# the default section
def
__iter__
(
self
):
# XXX does it break when underlying container state changed?
return
itertools
.
chain
((
self
.
_
default_section
,),
self
.
_sections
.
keys
())
return
itertools
.
chain
((
self
.
default_section
,),
self
.
_sections
.
keys
())
def
_read
(
self
,
fp
,
fpname
):
"""Parse a sectioned configuration file.
...
...
@@ -801,7 +1041,7 @@ class RawConfigParser(MutableMapping):
lineno
)
cursect
=
self
.
_sections
[
sectname
]
elements_added
.
add
(
sectname
)
elif
sectname
==
self
.
_
default_section
:
elif
sectname
==
self
.
default_section
:
cursect
=
self
.
_defaults
else
:
cursect
=
self
.
_dict
()
...
...
@@ -836,7 +1076,7 @@ class RawConfigParser(MutableMapping):
cursect
[
optname
]
=
[
optval
]
else
:
# valueless option handling
cursect
[
optname
]
=
optval
cursect
[
optname
]
=
None
else
:
# a non-fatal parsing error occurred. set up the
# exception but keep going. the exception will be
...
...
@@ -849,12 +1089,16 @@ class RawConfigParser(MutableMapping):
self
.
_join_multiline_values
()
def
_join_multiline_values
(
self
):
all_sections
=
itertools
.
chain
((
self
.
_defaults
,),
self
.
_sections
.
values
())
for
options
in
all_sections
:
defaults
=
self
.
default_section
,
self
.
_defaults
all_sections
=
itertools
.
chain
((
defaults
,),
self
.
_sections
.
items
())
for
section
,
options
in
all_sections
:
for
name
,
val
in
options
.
items
():
if
isinstance
(
val
,
list
):
options
[
name
]
=
'
\n
'
.
join
(
val
)
.
rstrip
()
val
=
'
\n
'
.
join
(
val
)
.
rstrip
()
options
[
name
]
=
self
.
_interpolation
.
before_read
(
self
,
section
,
name
,
val
)
def
_handle_error
(
self
,
exc
,
fpname
,
lineno
,
line
):
if
not
exc
:
...
...
@@ -871,7 +1115,7 @@ class RawConfigParser(MutableMapping):
try
:
d
.
update
(
self
.
_sections
[
section
])
except
KeyError
:
if
section
!=
self
.
_
default_section
:
if
section
!=
self
.
default_section
:
raise
NoSectionError
(
section
)
# Update with the entry specific variables
if
vars
:
...
...
@@ -906,197 +1150,31 @@ class RawConfigParser(MutableMapping):
raise
TypeError
(
"option values must be strings"
)
class
ConfigParser
(
RawConfigParser
):
"""ConfigParser implementing interpolation."""
def
get
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
"""Get an option value for a given section.
If `vars' is provided, it must be a dictionary. The option is looked up
in `vars' (if provided), `section', and in `DEFAULTSECT' in that order.
If the key is not found and `fallback' is provided, it is used as
a fallback value. `None' can be provided as a `fallback' value.
All
%
interpolations are expanded in the return values, unless the
optional argument `raw' is true. Values for interpolation keys are
looked up in the same manner as the option.
Arguments `raw', `vars', and `fallback' are keyword only.
The section DEFAULT is special.
"""
try
:
d
=
self
.
_unify_values
(
section
,
vars
)
except
NoSectionError
:
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
option
=
self
.
optionxform
(
option
)
try
:
value
=
d
[
option
]
except
KeyError
:
if
fallback
is
_UNSET
:
raise
NoOptionError
(
option
,
section
)
else
:
return
fallback
if
raw
or
value
is
None
:
return
value
else
:
return
self
.
_interpolate
(
section
,
option
,
value
,
d
)
_DEFAULT_INTERPOLATION
=
BrokenInterpolation
()
def
getint
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
try
:
return
self
.
_get
(
section
,
int
,
option
,
raw
=
raw
,
vars
=
vars
)
except
(
NoSectionError
,
NoOptionError
):
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
def
getfloat
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
try
:
return
self
.
_get
(
section
,
float
,
option
,
raw
=
raw
,
vars
=
vars
)
except
(
NoSectionError
,
NoOptionError
):
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
def
getboolean
(
self
,
section
,
option
,
*
,
raw
=
False
,
vars
=
None
,
fallback
=
_UNSET
):
try
:
return
self
.
_get
(
section
,
self
.
_convert_to_boolean
,
option
,
raw
=
raw
,
vars
=
vars
)
except
(
NoSectionError
,
NoOptionError
):
if
fallback
is
_UNSET
:
raise
else
:
return
fallback
def
items
(
self
,
section
,
raw
=
False
,
vars
=
None
):
"""Return a list of (name, value) tuples for each option in a section.
All
%
interpolations are expanded in the return values, based on the
defaults passed into the constructor, unless the optional argument
`raw' is true. Additional substitutions may be provided using the
`vars' argument, which must be a dictionary whose contents overrides
any pre-existing defaults.
The section DEFAULT is special.
"""
d
=
self
.
_defaults
.
copy
()
try
:
d
.
update
(
self
.
_sections
[
section
])
except
KeyError
:
if
section
!=
self
.
_default_section
:
raise
NoSectionError
(
section
)
# Update with the entry specific variables
if
vars
:
for
key
,
value
in
vars
.
items
():
d
[
self
.
optionxform
(
key
)]
=
value
options
=
list
(
d
.
keys
())
if
raw
:
return
[(
option
,
d
[
option
])
for
option
in
options
]
else
:
return
[(
option
,
self
.
_interpolate
(
section
,
option
,
d
[
option
],
d
))
for
option
in
options
]
def
_interpolate
(
self
,
section
,
option
,
rawval
,
vars
):
# do the string interpolation
value
=
rawval
depth
=
MAX_INTERPOLATION_DEPTH
while
depth
:
# Loop through this until it's done
depth
-=
1
if
value
and
"
%
("
in
value
:
value
=
self
.
_KEYCRE
.
sub
(
self
.
_interpolation_replace
,
value
)
try
:
value
=
value
%
vars
except
KeyError
as
e
:
raise
InterpolationMissingOptionError
(
option
,
section
,
rawval
,
e
.
args
[
0
])
else
:
break
if
value
and
"
%
("
in
value
:
raise
InterpolationDepthError
(
option
,
section
,
rawval
)
return
value
_KEYCRE
=
re
.
compile
(
r"
%
\(([^)]*)\)s|."
)
def
_interpolation_replace
(
self
,
match
):
s
=
match
.
group
(
1
)
if
s
is
None
:
return
match
.
group
()
else
:
return
"
%%
(
%
s)s"
%
self
.
optionxform
(
s
)
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."""
def
_interpolate
(
self
,
section
,
option
,
rawval
,
vars
):
# do the string interpolation
L
=
[]
self
.
_interpolate_some
(
option
,
L
,
rawval
,
section
,
vars
,
1
)
return
''
.
join
(
L
)
_interpvar_re
=
re
.
compile
(
r"
%
\(([^)]+)\)s"
)
def
_interpolate_some
(
self
,
option
,
accum
,
rest
,
section
,
map
,
depth
):
if
depth
>
MAX_INTERPOLATION_DEPTH
:
raise
InterpolationDepthError
(
option
,
section
,
rest
)
while
rest
:
p
=
rest
.
find
(
"
%
"
)
if
p
<
0
:
accum
.
append
(
rest
)
return
if
p
>
0
:
accum
.
append
(
rest
[:
p
])
rest
=
rest
[
p
:]
# p is no longer used
c
=
rest
[
1
:
2
]
if
c
==
"
%
"
:
accum
.
append
(
"
%
"
)
rest
=
rest
[
2
:]
elif
c
==
"("
:
m
=
self
.
_interpvar_re
.
match
(
rest
)
if
m
is
None
:
raise
InterpolationSyntaxError
(
option
,
section
,
"bad interpolation variable reference
%
r"
%
rest
)
var
=
self
.
optionxform
(
m
.
group
(
1
))
rest
=
rest
[
m
.
end
():]
try
:
v
=
map
[
var
]
except
KeyError
:
raise
InterpolationMissingOptionError
(
option
,
section
,
rest
,
var
)
if
"
%
"
in
v
:
self
.
_interpolate_some
(
option
,
accum
,
v
,
section
,
map
,
depth
+
1
)
else
:
accum
.
append
(
v
)
else
:
raise
InterpolationSyntaxError
(
option
,
section
,
"'
%%
' must be followed by '
%%
' or '(', "
"found:
%
r"
%
(
rest
,))
_DEFAULT_INTERPOLATION
=
BasicInterpolation
()
def
set
(
self
,
section
,
option
,
value
=
None
):
"""Set an option. Extend ConfigParser.set: check for string values."""
"""Set an option. Extends RawConfigParser.set by validating type and
interpolation syntax on the value."""
self
.
_validate_value_type
(
value
)
# check for bad percent signs
if
value
:
tmp_value
=
value
.
replace
(
'
%%
'
,
''
)
# escaped percent signs
tmp_value
=
self
.
_interpvar_re
.
sub
(
''
,
tmp_value
)
# valid syntax
if
'
%
'
in
tmp_value
:
raise
ValueError
(
"invalid interpolation syntax in
%
r at "
"position
%
d"
%
(
value
,
tmp_value
.
find
(
'
%
'
)))
ConfigParser
.
set
(
self
,
section
,
option
,
value
)
super
()
.
set
(
section
,
option
,
value
)
class
SectionProxy
(
MutableMapping
):
...
...
Lib/test/test_cfgparser.py
Dosyayı görüntüle @
b6a6f5f8
...
...
@@ -4,6 +4,7 @@ import io
import
os
import
unittest
import
textwrap
import
warnings
from
test
import
support
...
...
@@ -32,6 +33,7 @@ class CfgParserTestCaseClass(unittest.TestCase):
dict_type
=
configparser
.
_default_dict
strict
=
False
default_section
=
configparser
.
DEFAULTSECT
interpolation
=
configparser
.
_UNSET
def
newconfig
(
self
,
defaults
=
None
):
arguments
=
dict
(
...
...
@@ -43,8 +45,12 @@ class CfgParserTestCaseClass(unittest.TestCase):
dict_type
=
self
.
dict_type
,
strict
=
self
.
strict
,
default_section
=
self
.
default_section
,
interpolation
=
self
.
interpolation
,
)
return
self
.
config_class
(
**
arguments
)
with
warnings
.
catch_warnings
():
warnings
.
simplefilter
(
"ignore"
,
category
=
DeprecationWarning
)
instance
=
self
.
config_class
(
**
arguments
)
return
instance
def
fromstring
(
self
,
string
,
defaults
=
None
):
cf
=
self
.
newconfig
(
defaults
)
...
...
@@ -847,6 +853,70 @@ class SafeConfigParserTestCase(ConfigParserTestCase):
cf
=
self
.
newconfig
()
self
.
assertRaises
(
ValueError
,
cf
.
add_section
,
self
.
default_section
)
class
SafeConfigParserTestCaseExtendedInterpolation
(
BasicTestCase
):
config_class
=
configparser
.
SafeConfigParser
interpolation
=
configparser
.
ExtendedInterpolation
()
default_section
=
'common'
def
test_extended_interpolation
(
self
):
cf
=
self
.
fromstring
(
textwrap
.
dedent
(
"""
[common]
favourite Beatle = Paul
favourite color = green
[tom]
favourite band = ${favourite color} day
favourite pope = John ${favourite Beatle} II
sequel = ${favourite pope}I
[ambv]
favourite Beatle = George
son of Edward VII = ${favourite Beatle} V
son of George V = ${son of Edward VII}I
[stanley]
favourite Beatle = ${ambv:favourite Beatle}
favourite pope = ${tom:favourite pope}
favourite color = black
favourite state of mind = paranoid
favourite movie = soylent ${common:favourite color}
favourite song = ${favourite color} sabbath - ${favourite state of mind}
"""
)
.
strip
())
eq
=
self
.
assertEqual
eq
(
cf
[
'common'
][
'favourite Beatle'
],
'Paul'
)
eq
(
cf
[
'common'
][
'favourite color'
],
'green'
)
eq
(
cf
[
'tom'
][
'favourite Beatle'
],
'Paul'
)
eq
(
cf
[
'tom'
][
'favourite color'
],
'green'
)
eq
(
cf
[
'tom'
][
'favourite band'
],
'green day'
)
eq
(
cf
[
'tom'
][
'favourite pope'
],
'John Paul II'
)
eq
(
cf
[
'tom'
][
'sequel'
],
'John Paul III'
)
eq
(
cf
[
'ambv'
][
'favourite Beatle'
],
'George'
)
eq
(
cf
[
'ambv'
][
'favourite color'
],
'green'
)
eq
(
cf
[
'ambv'
][
'son of Edward VII'
],
'George V'
)
eq
(
cf
[
'ambv'
][
'son of George V'
],
'George VI'
)
eq
(
cf
[
'stanley'
][
'favourite Beatle'
],
'George'
)
eq
(
cf
[
'stanley'
][
'favourite color'
],
'black'
)
eq
(
cf
[
'stanley'
][
'favourite state of mind'
],
'paranoid'
)
eq
(
cf
[
'stanley'
][
'favourite movie'
],
'soylent green'
)
eq
(
cf
[
'stanley'
][
'favourite pope'
],
'John Paul II'
)
eq
(
cf
[
'stanley'
][
'favourite song'
],
'black sabbath - paranoid'
)
def
test_endless_loop
(
self
):
cf
=
self
.
fromstring
(
textwrap
.
dedent
(
"""
[one for you]
ping = ${one for me:pong}
[one for me]
pong = ${one for you:ping}
"""
)
.
strip
())
with
self
.
assertRaises
(
configparser
.
InterpolationDepthError
):
cf
[
'one for you'
][
'ping'
]
class
SafeConfigParserTestCaseNonStandardDelimiters
(
SafeConfigParserTestCase
):
delimiters
=
(
':='
,
'$'
)
comment_prefixes
=
(
'//'
,
'"'
)
...
...
@@ -910,7 +980,9 @@ class Issue7005TestCase(unittest.TestCase):
def
prepare
(
self
,
config_class
):
# This is the default, but that's the point.
cp
=
config_class
(
allow_no_value
=
False
)
with
warnings
.
catch_warnings
():
warnings
.
simplefilter
(
"ignore"
,
category
=
DeprecationWarning
)
cp
=
config_class
(
allow_no_value
=
False
)
cp
.
add_section
(
"section"
)
cp
.
set
(
"section"
,
"option"
,
None
)
sio
=
io
.
StringIO
()
...
...
@@ -978,6 +1050,7 @@ def test_main():
RawConfigParserTestCaseNonStandardDelimiters
,
RawConfigParserTestSambaConf
,
SafeConfigParserTestCase
,
SafeConfigParserTestCaseExtendedInterpolation
,
SafeConfigParserTestCaseNonStandardDelimiters
,
SafeConfigParserTestCaseNoValue
,
SafeConfigParserTestCaseTrickyFile
,
...
...
Misc/NEWS
Dosyayı görüntüle @
b6a6f5f8
...
...
@@ -149,6 +149,14 @@ Library
- Issue #10467: Fix BytesIO.readinto() after seeking into a position after the
end of the file.
- configparser: the ConfigParser class has been deprecated in favor of
SafeConfigParser. Usage of RawConfigParser is now discouraged for new
projects in favor of SafeConfigParser(interpolation=None).
- Issue #10499: configparser supports pluggable interpolation handlers. New
interpolation handler added (ExtendedInterpolation) which supports the syntax
used by zc.buildout (e.g. interpolation between sections).
- Issue #1682942: configparser supports alternative option/value delimiters.
- Issue #5412: configparser supports mapping protocol access.
...
...
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