# if we didn't consume all the argument strings, there were extras
extras.extend(arg_strings[stop_index:])
- # make sure all required actions were present
- required_actions = [_get_action_name(action) for action in self._actions
- if action.required and action not in seen_actions]
- # if we didn't use all the Positional objects, there were too few
- # arg strings supplied.
- if positionals:
- self.error(_('too few arguments'))
-
- # make sure all required actions were present, and convert defaults.
++ # make sure all required actions were present and also convert
++ # action defaults which were not given as arguments
++ required_actions = []
+ for action in self._actions:
+ if action not in seen_actions:
+ if action.required:
- name = _get_action_name(action)
- self.error(_('argument %s is required') % name)
++ required_actions.append(_get_action_name(action))
+ else:
+ # Convert action default now instead of doing it before
+ # parsing arguments to avoid calling convert functions
+ # twice (which may fail) if the argument was given, but
+ # only if it was defined already in the namespace
+ if (action.default is not None and
- hasattr(namespace, action.dest) and
- action.default is getattr(namespace, action.dest)):
++ hasattr(namespace, action.dest) and
++ action.default is getattr(namespace, action.dest)):
+ setattr(namespace, action.dest,
+ self._get_value(action, action.default))
+
+ if required_actions:
+ self.error(_('the following arguments are required: %s') %
+ ', '.join(required_actions))
+
# make sure all required groups had one option present
for group in self._mutually_exclusive_groups:
if group.required:
else:
self.fail()
+# =========================
+# MessageContentError tests
+# =========================
+
+class TestMessageContentError(TestCase):
+
+ def test_missing_argument_name_in_message(self):
+ parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
+ parser.add_argument('req_pos', type=str)
+ parser.add_argument('-req_opt', type=int, required=True)
+ parser.add_argument('need_one', type=str, nargs='+')
+
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args([])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertRegex(msg, 'req_opt')
+ self.assertRegex(msg, 'need_one')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args(['myXargument'])
+ msg = str(cm.exception)
+ self.assertNotIn(msg, 'req_pos')
+ self.assertRegex(msg, 'req_opt')
+ self.assertRegex(msg, 'need_one')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args(['myXargument', '-req_opt=1'])
+ msg = str(cm.exception)
+ self.assertNotIn(msg, 'req_pos')
+ self.assertNotIn(msg, 'req_opt')
+ self.assertRegex(msg, 'need_one')
+
+ def test_optional_optional_not_in_message(self):
+ parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
+ parser.add_argument('req_pos', type=str)
+ parser.add_argument('--req_opt', type=int, required=True)
+ parser.add_argument('--opt_opt', type=bool, nargs='?',
+ default=True)
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args([])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertRegex(msg, 'req_opt')
+ self.assertNotIn(msg, 'opt_opt')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args(['--req_opt=1'])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertNotIn(msg, 'req_opt')
+ self.assertNotIn(msg, 'opt_opt')
+
+ def test_optional_positional_not_in_message(self):
+ parser = ErrorRaisingArgumentParser(prog='PROG', usage='')
+ parser.add_argument('req_pos')
+ parser.add_argument('optional_positional', nargs='?', default='eggs')
+ with self.assertRaises(ArgumentParserError) as cm:
+ parser.parse_args([])
+ msg = str(cm.exception)
+ self.assertRegex(msg, 'req_pos')
+ self.assertNotIn(msg, 'optional_positional')
+
+
+ # ================================================
+ # Check that the type function is called only once
+ # ================================================
+
+ class TestTypeFunctionCallOnlyOnce(TestCase):
+
+ def test_type_function_call_only_once(self):
+ def spam(string_to_convert):
+ self.assertEqual(string_to_convert, 'spam!')
+ return 'foo_converted'
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--foo', type=spam, default='bar')
+ args = parser.parse_args('--foo spam!'.split())
+ self.assertEqual(NS(foo='foo_converted'), args)
+
+ # ================================================================
+ # Check that the type function is called with a non-string default
+ # ================================================================
+
+ class TestTypeFunctionCallWithNonStringDefault(TestCase):
+
+ def test_type_function_call_with_non_string_default(self):
+ def spam(int_to_convert):
+ self.assertEqual(int_to_convert, 0)
+ return 'foo_converted'
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--foo', type=spam, default=0)
+ args = parser.parse_args([])
+ self.assertEqual(NS(foo='foo_converted'), args)
+
# ======================
# parse_known_args tests
# ======================
- Issue #15801: Make sure mappings passed to '%' formatting are actually
subscriptable.
-- Issue #15726: Fix incorrect bounds checking in PyState_FindModule.
- Patch by Robin Schreiber.
-
-- Issue #15604: Update uses of PyObject_IsTrue() to check for and handle
- errors correctly. Patch by Serhiy Storchaka.
+Library
+-------
-- Issue #13119: sys.stdout and sys.stderr are now using "\r\n" newline on
- Windows, as Python 2.
++- Issue #12776,#11839: call argparse type function (specified by add_argument)
++ only once. Before, the type function was called twice in the case where the
++ default was specified and the argument was given as well. This was
++ especially problematic for the FileType type, as a default file would always
++ be opened, even if a file argument was specified on the command line.
+
-- Issue #14579: Fix CVE-2012-2135: vulnerability in the utf-16 decoder after
- error handling. Patch by Serhiy Storchaka.
+Extension Modules
+-----------------
-- Issue #15404: Refleak in PyMethodObject repr.
+Tests
+-----
-- Issue #15394: An issue in PyModule_Create that caused references to
- be leaked on some error paths has been fixed. Patch by Julia Lawall.
+Build
+-----
-- Issue #15368: An issue that caused bytecode generation to be
- non-deterministic when using randomized hashing (-R) has been fixed.
+- Issue #15819: Make sure we can build Python out-of-tree from a readonly
+ source directory. (Somewhat related to Issue #9860.)
-- Issue #15020: The program name used to search for Python's path is now
- "python3" under Unix, not "python".
+Documentation
+-------------
-- Issue #15033: Fix the exit status bug when modules invoked using -m swith,
- return the proper failure return value (1). Patch contributed by Jeff Knupp.
+- Issue #11964: Document a change in v3.2 to the behavior of the indent
+ parameter of json encoding operations.
-- Issue #12268: File readline, readlines and read() or readall() methods
- no longer lose data when an underlying read system call is interrupted.
- IOError is no longer raised due to a read system call returning EINTR
- from within these methods.
+Tools/Demos
+-----------
-- Issue #15142: Fix reference leak when deallocating instances of types
- created using PyType_FromSpec().
-- Issue #10053: Don't close FDs when FileIO.__init__ fails. Loosely based on
- the work by Hirokazu Yamamoto.
+What's New in Python 3.3.0 Release Candidate 2?
+===============================================
-- Issue #14775: Fix a potential quadratic dict build-up due to the garbage
- collector repeatedly trying to untrack dicts.
+*Release date: XX-Sep-2012*
-- Issue #14494: Fix __future__.py and its documentation to note that
- absolute imports are the default behavior in 3.0 instead of 2.7.
- Patch by Sven Marnach.
+Core and Builtins
+-----------------
-- Issue #14761: Fix potential leak on an error case in the import machinery.
+- Issue #15784: Modify OSError.__str__() to better distinguish between
+ errno error numbers and Windows error numbers.
-- Issue #14699: Fix calling the classmethod descriptor directly.
+- Issue #15781: Fix two small race conditions in import's module locking.
-- Issue #14433: Prevent msvcrt crash in interactive prompt when stdin
- is closed.
+Library
+-------
-- Issue #11603 (again): Setting __repr__ to __str__ now raises a RuntimeError
- when repr() or str() is called on such an object.
+- Issue #15828: Restore support for C extensions in imp.load_module()
-- Issue #14658: Fix binding a special method to a builtin implementation of a
- special method with a different name.
+- Issue #10650: Deprecate the watchexp parameter of the Decimal.quantize()
+ method.
-- Issue #14630: Fix a memory access bug for instances of a subclass of int
- with value 0.
+- Issue #15785: Modify window.get_wch() API of the curses module: return
+ a character for most keys, and an integer for special keys, instead of
+ always returning an integer. So it is now possible to distinguish special
+ keys like keypad keys.
-- Issue #14612: Fix jumping around with blocks by setting f_lineno.
-- Issue #14607: Fix keyword-only arguments which started with ``__``.
+What's New in Python 3.3.0 Release Candidate 1?
+===============================================
-- Issue #13889: Check and (if necessary) set FPU control word before calling
- any of the dtoa.c string <-> float conversion functions, on MSVC builds of
- Python. This fixes issues when embedding Python in a Delphi app.
+*Release date: 25-Aug-2012*
-- Issue #14474: Save and restore exception state in thread.start_new_thread()
- while writing error message if the thread leaves a unhandled exception.
+Core and Builtins
+-----------------
-- Issue #13019: Fix potential reference leaks in bytearray.extend(). Patch
- by Suman Saha.
+- Issue #15573: memoryview comparisons are now performed by value with full
+ support for any valid struct module format definition.
-- Issue #14378: Fix compiling ast.ImportFrom nodes with a "__future__" string as
- the module name that was not interned.
+- Issue #15316: When an item in the fromlist for __import__ doesn't exist,
+ don't raise an error, but if an exception is raised as part of an import do
+ let that propagate.
-- Issue #14331: Use significantly less stack space when importing modules by
- allocating path buffers on the heap instead of the stack.
+- Issue #15778: ensure that str(ImportError(msg)) returns a str
+ even when msg isn't a str.
-- Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not
- passed strings.
+- Issue #2051: Source file permission bits are once again correctly
+ copied to the cached bytecode file. (The migration to importlib
+ reintroduced this problem because these was no regression test. A test
+ has been added as part of this patch)
-- Issue #1469629: Allow cycles through an object's __dict__ slot to be
- collected. (For example if ``x.__dict__ is x``).
+- Issue #15761: Fix crash when PYTHONEXECUTABLE is set on Mac OS X.
-- Issue #14172: Fix reference leak when marshalling a buffer-like object
- (other than a bytes object).
+- Issue #15726: Fix incorrect bounds checking in PyState_FindModule.
+ Patch by Robin Schreiber.
-- Issue #13521: dict.setdefault() now does only one lookup for the given key,
- making it "atomic" for many purposes. Patch by Filip GruszczyĆski.
+- Issue #15604: Update uses of PyObject_IsTrue() to check for and handle
+ errors correctly. Patch by Serhiy Storchaka.
-- Issue #14471: Fix a possible buffer overrun in the winreg module.
+- Issue #14846: importlib.FileFinder now handles the case where the
+ directory being searched is removed after a previous import attempt
Library
-------