]> granicus.if.org Git - python/commitdiff
Issue #20381: Fix sanity checking on default arguments when c_default is
authorZachary Ware <zachary.ware@gmail.com>
Sat, 25 Jan 2014 04:52:30 +0000 (22:52 -0600)
committerZachary Ware <zachary.ware@gmail.com>
Sat, 25 Jan 2014 04:52:30 +0000 (22:52 -0600)
also specified.

Misc/NEWS
Tools/clinic/clinic.py

index a8cd06c07aa37d9f6be0fc759ea2f7e04be6d747..a8e251a1e7b379032334b7803dbda17fba24fd1e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -141,6 +141,11 @@ Tests
 
 Tools/Demos
 -----------
+
+- Issue #20381: Argument Clinic now sanity checks the default argument when
+  c_default is also specified, providing a nice failure message for
+  disallowed values.
+
 - Issue #20189: Argument Clinic now ensures that parser functions for
   __new__ are always of type newfunc, the type of the tp_new slot.
   Similarly, parser functions for __init__ are now always of type initproc,
index 8bf89777e79ffcbc6062f1f5ec34a3a520d87f0f..d33abaed2a7585907847aaa0ce9dd4b284b11641 100755 (executable)
@@ -3279,11 +3279,11 @@ class DSLParser:
                 fail("You can't specify py_default without specifying a default value!")
         else:
             default = default.strip()
+            bad = False
             ast_input = "x = {}".format(default)
             try:
                 module = ast.parse(ast_input)
 
-                bad = False
                 if 'c_default' not in kwargs:
                     # we can only represent very simple data values in C.
                     # detect whether default is okay, via a blacklist
@@ -3317,8 +3317,16 @@ class DSLParser:
                     bad = blacklist.bad
                 else:
                     # if they specify a c_default, we can be more lenient about the default value.
-                    # but at least ensure that we can turn it into text and reconstitute it correctly.
-                    bad = default != repr(eval(default))
+                    # but at least make an attempt at ensuring it's a valid expression.
+                    try:
+                        value = eval(default)
+                        if value == unspecified:
+                            fail("'unspecified' is not a legal default value!")
+                    except NameError:
+                        pass # probably a named constant
+                    except Exception as e:
+                        fail("Malformed expression given as default value\n"
+                             "{!r} caused {!r}".format(default, e))
                 if bad:
                     fail("Unsupported expression as default value: " + repr(default))