From 26a1e5c455d382a4d739816d2255bb3cfb3b0fe2 Mon Sep 17 00:00:00 2001 From: davidcellis Date: Wed, 22 Feb 2017 21:03:15 +0000 Subject: [PATCH 1/7] Make pathlib objects work with ConfigParser.read as single arguments. --- Lib/configparser.py | 3 ++- Lib/test/test_configparser.py | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/configparser.py b/Lib/configparser.py index af5aca1feae34a4..ff97cdc9abbc76b 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -143,6 +143,7 @@ import functools import io import itertools +import os import re import sys import warnings @@ -687,7 +688,7 @@ def read(self, filenames, encoding=None): Return list of successfully read files. """ - if isinstance(filenames, str): + if isinstance(filenames, (str, bytes, os.PathLike)): filenames = [filenames] read_ok = [] for filename in filenames: diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 696f642621e0fa0..125afe08ba58cf1 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -2,6 +2,7 @@ import configparser import io import os +import pathlib import textwrap import unittest import warnings @@ -720,6 +721,11 @@ def test_read_returns_file_list(self): parsed_files = cf.read(file1) self.assertEqual(parsed_files, [file1]) self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") + # check when we pass only a Path object + cf = self.newconfig() + parsed_files = cf.read(pathlib.Path(file1)) + self.assertEqual(parsed_files, [pathlib.Path(file1)]) + self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") # check when we pass only missing files: cf = self.newconfig() parsed_files = cf.read(["nonexistent-file"]) From bc9d94c670b48e2fb29b8e83dd80a19362b82abf Mon Sep 17 00:00:00 2001 From: davidcellis Date: Thu, 23 Feb 2017 06:42:53 +0000 Subject: [PATCH 2/7] Removed check for bytes. Formatting consistency in test. --- Lib/configparser.py | 2 +- Lib/test/test_configparser.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/configparser.py b/Lib/configparser.py index ff97cdc9abbc76b..452288467736db3 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -688,7 +688,7 @@ def read(self, filenames, encoding=None): Return list of successfully read files. """ - if isinstance(filenames, (str, bytes, os.PathLike)): + if isinstance(filenames, (str, os.PathLike)): filenames = [filenames] read_ok = [] for filename in filenames: diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 125afe08ba58cf1..0770e64244d0545 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -721,7 +721,7 @@ def test_read_returns_file_list(self): parsed_files = cf.read(file1) self.assertEqual(parsed_files, [file1]) self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") - # check when we pass only a Path object + # check when we pass only a Path object: cf = self.newconfig() parsed_files = cf.read(pathlib.Path(file1)) self.assertEqual(parsed_files, [pathlib.Path(file1)]) From 9d506a878c3dc3fa0504c9452affe2575f5cc2b6 Mon Sep 17 00:00:00 2001 From: davidcellis Date: Thu, 23 Feb 2017 19:26:32 +0000 Subject: [PATCH 3/7] Documentation for ConfigParser.read now mentions path-like objects. Added paragraph breaks to aid readability. --- Doc/library/configparser.rst | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index c0ffded7bc38e85..7f6ed142412637e 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -988,13 +988,16 @@ ConfigParser Objects .. method:: read(filenames, encoding=None) 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` + filenames which were successfully parsed. + + If *filenames* is a string or :term:`path-like object`, 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 @@ -1011,6 +1014,9 @@ ConfigParser Objects The *encoding* parameter. Previously, all files were read using the default encoding for :func:`open`. + .. versionadded:: 3.6.1 + The *filenames* parameter accepts a :term:`path-like object`. + .. method:: read_file(f, source=None) From e30f2f880e270722329484ead9895701eda66519 Mon Sep 17 00:00:00 2001 From: davidcellis Date: Thu, 23 Feb 2017 19:28:24 +0000 Subject: [PATCH 4/7] Document bpo-29623 in NEWS --- Misc/NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index e515e6a32962e74..083d530e1926439 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,8 @@ Core and Builtins - bpo-28598: Support __rmod__ for subclasses of str being called before str.__mod__. Patch by Martijn Pieters. +- bpo 29623: Allow use of path-like object as a single argument in + configparser.ConfigParser.read - bpo-29607: Fix stack_effect computation for CALL_FUNCTION_EX. Patch by Matthieu Dartiailh. From 139d636139e348d10ad5bc00a8c1e1f766aa639c Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 26 Feb 2017 15:29:50 +0300 Subject: [PATCH 5/7] Move NEWS entry to Library section --- Misc/NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index 083d530e1926439..80ec4afb0825629 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -293,6 +293,8 @@ Library - Issue #16285: urrlib.parse.quote is now based on RFC 3986 and hence includes '~' in the set of characters that is not quoted by default. Patch by Christian Theune and Ratnadeep Debnath. +- bpo 29623: Allow use of path-like object as a single argument in + ConfigParser.read(). Patch by David Ellis. - bpo-29532: Altering a kwarg dictionary passed to functools.partial() no longer affects a partial object after creation. From 6b172f1121254efab47a3ef3be856315893b6337 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 3 Mar 2017 17:40:52 +0300 Subject: [PATCH 6/7] address my review comments --- Lib/configparser.py | 2 ++ Lib/test/test_configparser.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/configparser.py b/Lib/configparser.py index 452288467736db3..230ab2b017eade3 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -697,6 +697,8 @@ def read(self, filenames, encoding=None): self._read(fp, filename) except OSError: continue + if isinstance(filename, os.PathLike): + filename = os.fspath(filename) read_ok.append(filename) return read_ok diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 0770e64244d0545..72c3f19fb41f569 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -724,7 +724,12 @@ def test_read_returns_file_list(self): # check when we pass only a Path object: cf = self.newconfig() parsed_files = cf.read(pathlib.Path(file1)) - self.assertEqual(parsed_files, [pathlib.Path(file1)]) + self.assertEqual(parsed_files, [file1]) + self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") + # check when we passed both a filename and a Path object: + cf = self.newconfig() + parsed_files = cf.read([pathlib.Path(file1), file1]) + self.assertEqual(parsed_files, [file1, file1]) self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") # check when we pass only missing files: cf = self.newconfig() From d98948e307d898398d751ca352d3cdd0e13ba151 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 3 Mar 2017 18:11:00 +0300 Subject: [PATCH 7/7] Fix Misc/NEWS --- Misc/NEWS | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 80ec4afb0825629..3421cbd75b10f18 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,8 +22,6 @@ Core and Builtins - bpo-28598: Support __rmod__ for subclasses of str being called before str.__mod__. Patch by Martijn Pieters. -- bpo 29623: Allow use of path-like object as a single argument in - configparser.ConfigParser.read - bpo-29607: Fix stack_effect computation for CALL_FUNCTION_EX. Patch by Matthieu Dartiailh. @@ -261,6 +259,9 @@ Extension Modules Library ------- +- bpo-29623: Allow use of path-like object as a single argument in + ConfigParser.read(). Patch by David Ellis. + - bpo-9303: Migrate sqlite3 module to _v2 API. Patch by Aviv Palivoda. - bpo-28963: Fix out of bound iteration in asyncio.Future.remove_done_callback @@ -293,8 +294,6 @@ Library - Issue #16285: urrlib.parse.quote is now based on RFC 3986 and hence includes '~' in the set of characters that is not quoted by default. Patch by Christian Theune and Ratnadeep Debnath. -- bpo 29623: Allow use of path-like object as a single argument in - ConfigParser.read(). Patch by David Ellis. - bpo-29532: Altering a kwarg dictionary passed to functools.partial() no longer affects a partial object after creation.