summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2012-12-15 20:46:20 (GMT)
committerBenjamin Peterson <benjamin@python.org>2012-12-15 20:46:20 (GMT)
commit3a31ecd8276397fed6703581a07a47ed15b28299 (patch)
tree68194410d40269288057190b2baef8ca9b24cfdd
parent6a020e8065f13737ff5f1380c132be097b4b02f9 (diff)
parent74d6c250e1ce0e5efc03575eaaa1b8cab66241eb (diff)
downloadcpython-3a31ecd8276397fed6703581a07a47ed15b28299.zip
cpython-3a31ecd8276397fed6703581a07a47ed15b28299.tar.gz
cpython-3a31ecd8276397fed6703581a07a47ed15b28299.tar.bz2
merge heads
-rw-r--r--Doc/library/argparse.rst20
-rw-r--r--Lib/argparse.py16
-rw-r--r--Lib/test/test_argparse.py32
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
5 files changed, 60 insertions, 12 deletions
diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
index 9f6a1ea..584f4f7 100644
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -976,9 +976,9 @@ See the section on the default_ keyword argument for information on when the
``type`` argument is applied to default arguments.
To ease the use of various types of files, the argparse module provides the
-factory FileType which takes the ``mode=`` and ``bufsize=`` arguments of the
-:func:`open` function. For example, ``FileType('w')`` can be used to create a
-writable file::
+factory FileType which takes the ``mode=``, ``bufsize=``, ``encoding=`` and
+``errors=`` arguments of the :func:`open` function. For example,
+``FileType('w')`` can be used to create a writable file::
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar', type=argparse.FileType('w'))
@@ -1617,17 +1617,19 @@ Sub-commands
FileType objects
^^^^^^^^^^^^^^^^
-.. class:: FileType(mode='r', bufsize=None)
+.. class:: FileType(mode='r', bufsize=-1, encoding=None, errors=None)
The :class:`FileType` factory creates objects that can be passed to the type
argument of :meth:`ArgumentParser.add_argument`. Arguments that have
- :class:`FileType` objects as their type will open command-line arguments as files
- with the requested modes and buffer sizes::
+ :class:`FileType` objects as their type will open command-line arguments as
+ files with the requested modes, buffer sizes, encodings and error handling
+ (see the :func:`open` function for more details)::
>>> parser = argparse.ArgumentParser()
- >>> parser.add_argument('--output', type=argparse.FileType('wb', 0))
- >>> parser.parse_args(['--output', 'out'])
- Namespace(output=<_io.BufferedWriter name='out'>)
+ >>> parser.add_argument('--raw', type=argparse.FileType('wb', 0))
+ >>> parser.add_argument('out', type=argparse.FileType('w', encoding='UTF-8'))
+ >>> parser.parse_args(['--raw', 'raw.dat', 'file.txt'])
+ Namespace(out=<_io.TextIOWrapper name='file.txt' mode='w' encoding='UTF-8'>, raw=<_io.FileIO name='raw.dat' mode='wb'>)
FileType objects understand the pseudo-argument ``'-'`` and automatically
convert this into ``sys.stdin`` for readable :class:`FileType` objects and
diff --git a/Lib/argparse.py b/Lib/argparse.py
index 202f2cb..3b1a079 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1140,11 +1140,17 @@ class FileType(object):
same values as the builtin open() function.
- bufsize -- The file's desired buffer size. Accepts the same values as
the builtin open() function.
+ - encoding -- The file's encoding. Accepts the same values as the
+ the builtin open() function.
+ - errors -- A string indicating how encoding and decoding errors are to
+ be handled. Accepts the same value as the builtin open() function.
"""
- def __init__(self, mode='r', bufsize=-1):
+ def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None):
self._mode = mode
self._bufsize = bufsize
+ self._encoding = encoding
+ self._errors = errors
def __call__(self, string):
# the special argument "-" means sys.std{in,out}
@@ -1159,14 +1165,18 @@ class FileType(object):
# all other arguments are used as file names
try:
- return open(string, self._mode, self._bufsize)
+ return open(string, self._mode, self._bufsize, self._encoding,
+ self._errors)
except IOError as e:
message = _("can't open '%s': %s")
raise ArgumentTypeError(message % (string, e))
def __repr__(self):
args = self._mode, self._bufsize
- args_str = ', '.join(repr(arg) for arg in args if arg != -1)
+ kwargs = [('encoding', self._encoding), ('errors', self._errors)]
+ args_str = ', '.join([repr(arg) for arg in args if arg != -1] +
+ ['%s=%r' % (kw, arg) for kw, arg in kwargs
+ if arg is not None])
return '%s(%s)' % (type(self).__name__, args_str)
# ===========================
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index c06c940..00cde2e 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -14,6 +14,7 @@ import argparse
from io import StringIO
from test import support
+from unittest import mock
class StdIOBuffer(StringIO):
pass
@@ -1421,6 +1422,19 @@ class TestFileTypeRepr(TestCase):
type = argparse.FileType('wb', 1)
self.assertEqual("FileType('wb', 1)", repr(type))
+ def test_r_latin(self):
+ type = argparse.FileType('r', encoding='latin_1')
+ self.assertEqual("FileType('r', encoding='latin_1')", repr(type))
+
+ def test_w_big5_ignore(self):
+ type = argparse.FileType('w', encoding='big5', errors='ignore')
+ self.assertEqual("FileType('w', encoding='big5', errors='ignore')",
+ repr(type))
+
+ def test_r_1_replace(self):
+ type = argparse.FileType('r', 1, errors='replace')
+ self.assertEqual("FileType('r', 1, errors='replace')", repr(type))
+
class RFile(object):
seen = {}
@@ -1557,6 +1571,24 @@ class TestFileTypeWB(TempDirMixin, ParserTestCase):
]
+class TestFileTypeOpenArgs(TestCase):
+ """Test that open (the builtin) is correctly called"""
+
+ def test_open_args(self):
+ FT = argparse.FileType
+ cases = [
+ (FT('rb'), ('rb', -1, None, None)),
+ (FT('w', 1), ('w', 1, None, None)),
+ (FT('w', errors='replace'), ('w', -1, None, 'replace')),
+ (FT('wb', encoding='big5'), ('wb', -1, 'big5', None)),
+ (FT('w', 0, 'l1', 'strict'), ('w', 0, 'l1', 'strict')),
+ ]
+ with mock.patch('builtins.open') as m:
+ for type, args in cases:
+ type('foo')
+ m.assert_called_with('foo', *args)
+
+
class TestTypeCallable(ParserTestCase):
"""Test some callables as option/argument types"""
diff --git a/Misc/ACKS b/Misc/ACKS
index ac657c3..99b34a3 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -768,6 +768,7 @@ Laura Matson
Graham Matthews
Dieter Maurer
Daniel May
+Lucas Maystre
Arnaud Mazin
Rebecca McCreary
Kirk McDonald
diff --git a/Misc/NEWS b/Misc/NEWS
index 7b71524..d52a9d8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -167,6 +167,9 @@ Core and Builtins
Library
-------
+- Issue #11175: argparse.FileType now accepts encoding and errors
+ arguments. Patch by Lucas Maystre.
+
- Issue #16488: epoll() objects now support the `with` statement. Patch
by Serhiy Storchaka.