mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Merged #11670 from 3.2
This commit is contained in:
commit
29050d7317
3 changed files with 82 additions and 9 deletions
|
@ -974,10 +974,8 @@ ConfigParser Objects
|
||||||
|
|
||||||
.. method:: read_file(f, source=None)
|
.. method:: read_file(f, source=None)
|
||||||
|
|
||||||
Read and parse configuration data from the file or file-like object in
|
Read and parse configuration data from *f* which must be an iterable
|
||||||
*f* (only the :meth:`readline` method is used). The file-like object
|
yielding Unicode strings (for example any file object).
|
||||||
must operate in text mode. Specifically, it must return strings from
|
|
||||||
:meth:`readline`.
|
|
||||||
|
|
||||||
Optional argument *source* specifies the name of the file being read. If
|
Optional argument *source* specifies the name of the file being read. If
|
||||||
not given and *f* has a :attr:`name` attribute, that is used for
|
not given and *f* has a :attr:`name` attribute, that is used for
|
||||||
|
@ -986,6 +984,27 @@ ConfigParser Objects
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
Replaces :meth:`readfp`.
|
Replaces :meth:`readfp`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Prior to Python 3.2, :meth:`readfp` consumed lines from the file-like
|
||||||
|
argument by calling its :meth:`~file.readline` method. For existing code
|
||||||
|
calling :meth:`readfp` with arguments which don't support iteration,
|
||||||
|
the following generator may be used as a wrapper around the file-like
|
||||||
|
object::
|
||||||
|
|
||||||
|
def readline_generator(f):
|
||||||
|
line = f.readline()
|
||||||
|
while line != '':
|
||||||
|
yield line
|
||||||
|
line = f.readline()
|
||||||
|
|
||||||
|
Before::
|
||||||
|
|
||||||
|
parser.readfp(f)
|
||||||
|
|
||||||
|
After::
|
||||||
|
|
||||||
|
parser.read_file(readline_generator(f))
|
||||||
|
|
||||||
.. method:: read_string(string, source='<string>')
|
.. method:: read_string(string, source='<string>')
|
||||||
|
|
||||||
|
|
|
@ -695,10 +695,10 @@ class RawConfigParser(MutableMapping):
|
||||||
def read_file(self, f, source=None):
|
def read_file(self, f, source=None):
|
||||||
"""Like read() but the argument must be a file-like object.
|
"""Like read() but the argument must be a file-like object.
|
||||||
|
|
||||||
The `f' argument must have a `readline' method. Optional second
|
The `f' argument must be iterable, returning one line at a time.
|
||||||
argument is the `source' specifying the name of the file being read. If
|
Optional second argument is the `source' specifying the name of the
|
||||||
not given, it is taken from f.name. If `f' has no `name' attribute,
|
file being read. If not given, it is taken from f.name. If `f' has no
|
||||||
`<???>' is used.
|
`name' attribute, `<???>' is used.
|
||||||
"""
|
"""
|
||||||
if source is None:
|
if source is None:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1235,6 +1235,59 @@ class CopyTestCase(BasicTestCase):
|
||||||
del section[default]
|
del section[default]
|
||||||
return cf_copy
|
return cf_copy
|
||||||
|
|
||||||
|
|
||||||
|
class FakeFile:
|
||||||
|
def __init__(self):
|
||||||
|
file_path = support.findfile("cfgparser.1")
|
||||||
|
with open(file_path) as f:
|
||||||
|
self.lines = f.readlines()
|
||||||
|
self.lines.reverse()
|
||||||
|
|
||||||
|
def readline(self):
|
||||||
|
if len(self.lines):
|
||||||
|
return self.lines.pop()
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def readline_generator(f):
|
||||||
|
"""As advised in Doc/library/configparser.rst."""
|
||||||
|
line = f.readline()
|
||||||
|
while line != '':
|
||||||
|
yield line
|
||||||
|
line = f.readline()
|
||||||
|
|
||||||
|
|
||||||
|
class ReadFileTestCase(unittest.TestCase):
|
||||||
|
def test_file(self):
|
||||||
|
file_path = support.findfile("cfgparser.1")
|
||||||
|
parser = configparser.ConfigParser()
|
||||||
|
with open(file_path) as f:
|
||||||
|
parser.read_file(f)
|
||||||
|
self.assertTrue("Foo Bar" in parser)
|
||||||
|
self.assertTrue("foo" in parser["Foo Bar"])
|
||||||
|
self.assertEqual(parser["Foo Bar"]["foo"], "newbar")
|
||||||
|
|
||||||
|
def test_iterable(self):
|
||||||
|
lines = textwrap.dedent("""
|
||||||
|
[Foo Bar]
|
||||||
|
foo=newbar""").strip().split('\n')
|
||||||
|
parser = configparser.ConfigParser()
|
||||||
|
parser.read_file(lines)
|
||||||
|
self.assertTrue("Foo Bar" in parser)
|
||||||
|
self.assertTrue("foo" in parser["Foo Bar"])
|
||||||
|
self.assertEqual(parser["Foo Bar"]["foo"], "newbar")
|
||||||
|
|
||||||
|
def test_readline_generator(self):
|
||||||
|
"""Issue #11670."""
|
||||||
|
parser = configparser.ConfigParser()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
parser.read_file(FakeFile())
|
||||||
|
parser.read_file(readline_generator(FakeFile()))
|
||||||
|
self.assertTrue("Foo Bar" in parser)
|
||||||
|
self.assertTrue("foo" in parser["Foo Bar"])
|
||||||
|
self.assertEqual(parser["Foo Bar"]["foo"], "newbar")
|
||||||
|
|
||||||
|
|
||||||
class CoverageOneHundredTestCase(unittest.TestCase):
|
class CoverageOneHundredTestCase(unittest.TestCase):
|
||||||
"""Covers edge cases in the codebase."""
|
"""Covers edge cases in the codebase."""
|
||||||
|
|
||||||
|
@ -1338,5 +1391,6 @@ def test_main():
|
||||||
CompatibleTestCase,
|
CompatibleTestCase,
|
||||||
CopyTestCase,
|
CopyTestCase,
|
||||||
ConfigParserTestCaseNonStandardDefaultSection,
|
ConfigParserTestCaseNonStandardDefaultSection,
|
||||||
|
ReadFileTestCase,
|
||||||
CoverageOneHundredTestCase,
|
CoverageOneHundredTestCase,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue