Skip to content

Commit 21ce65a

Browse files
authored
[3.6] bpo-29623: Make PathLike objects work with ConfigParser.read() (#242) (#432)
(cherry picked from commit 85b8d01) Conflicts: Lib/test/test_configparser.py
1 parent c7ff163 commit 21ce65a

File tree

4 files changed

+31
-9
lines changed

4 files changed

+31
-9
lines changed

Doc/library/configparser.rst

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -983,13 +983,16 @@ ConfigParser Objects
983983
.. method:: read(filenames, encoding=None)
984984

985985
Attempt to read and parse a list of filenames, returning a list of
986-
filenames which were successfully parsed. If *filenames* is a string, it
987-
is treated as a single filename. If a file named in *filenames* cannot
988-
be opened, that file will be ignored. This is designed so that you can
989-
specify a list of potential configuration file locations (for example,
990-
the current directory, the user's home directory, and some system-wide
991-
directory), and all existing configuration files in the list will be
992-
read. If none of the named files exist, the :class:`ConfigParser`
986+
filenames which were successfully parsed.
987+
988+
If *filenames* is a string or :term:`path-like object`, it is treated as
989+
a single filename. If a file named in *filenames* cannot be opened, that
990+
file will be ignored. This is designed so that you can specify a list of
991+
potential configuration file locations (for example, the current
992+
directory, the user's home directory, and some system-wide directory),
993+
and all existing configuration files in the list will be read.
994+
995+
If none of the named files exist, the :class:`ConfigParser`
993996
instance will contain an empty dataset. An application which requires
994997
initial values to be loaded from a file should load the required file or
995998
files using :meth:`read_file` before calling :meth:`read` for any
@@ -1006,6 +1009,9 @@ ConfigParser Objects
10061009
The *encoding* parameter. Previously, all files were read using the
10071010
default encoding for :func:`open`.
10081011

1012+
.. versionadded:: 3.6.1
1013+
The *filenames* parameter accepts a :term:`path-like object`.
1014+
10091015

10101016
.. method:: read_file(f, source=None)
10111017

Lib/configparser.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
import functools
144144
import io
145145
import itertools
146+
import os
146147
import re
147148
import sys
148149
import warnings
@@ -687,7 +688,7 @@ def read(self, filenames, encoding=None):
687688
688689
Return list of successfully read files.
689690
"""
690-
if isinstance(filenames, str):
691+
if isinstance(filenames, (str, os.PathLike)):
691692
filenames = [filenames]
692693
read_ok = []
693694
for filename in filenames:
@@ -696,6 +697,8 @@ def read(self, filenames, encoding=None):
696697
self._read(fp, filename)
697698
except OSError:
698699
continue
700+
if isinstance(filename, os.PathLike):
701+
filename = os.fspath(filename)
699702
read_ok.append(filename)
700703
return read_ok
701704

Lib/test/test_configparser.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import configparser
33
import io
44
import os
5-
import sys
5+
import pathlib
66
import textwrap
77
import unittest
88
import warnings
@@ -721,6 +721,16 @@ def test_read_returns_file_list(self):
721721
parsed_files = cf.read(file1)
722722
self.assertEqual(parsed_files, [file1])
723723
self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
724+
# check when we pass only a Path object:
725+
cf = self.newconfig()
726+
parsed_files = cf.read(pathlib.Path(file1))
727+
self.assertEqual(parsed_files, [file1])
728+
self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
729+
# check when we passed both a filename and a Path object:
730+
cf = self.newconfig()
731+
parsed_files = cf.read([pathlib.Path(file1), file1])
732+
self.assertEqual(parsed_files, [file1, file1])
733+
self.assertEqual(cf.get("Foo Bar", "foo"), "newbar")
724734
# check when we pass only missing files:
725735
cf = self.newconfig()
726736
parsed_files = cf.read(["nonexistent-file"])

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ Extension Modules
8282
Library
8383
-------
8484

85+
- bpo-29623: Allow use of path-like object as a single argument in
86+
ConfigParser.read(). Patch by David Ellis.
87+
8588
- bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback
8689
implemented in C.
8790

0 commit comments

Comments
 (0)