def generate_arg_type_test(self, arg, code):
# Generate type test for one argument.
if arg.type.typeobj_is_available():
+ code.globalstate.use_utility_code(arg_type_test_utility_code)
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.entry.cname
code.putln(
else:
error(arg.pos, "Cannot test type of extern C class "
"without type object name specification")
+
+ def generate_arg_none_check(self, arg, code):
+ # Generate None check for one argument.
+ code.globalstate.use_utility_code(arg_type_test_utility_code)
+ code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % arg.entry.cname)
+ code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%s' must not be None"); %s''' % (
+ arg.name,
+ code.error_goto(arg.pos)))
+ code.putln('}')
def generate_wrapper_functions(self, code):
pass
for arg in self.type.args:
if arg.needs_type_test:
self.generate_arg_type_test(arg, code)
+ elif arg.type.is_pyobject and not arg.accept_none:
+ self.generate_arg_none_check(arg, code)
def error_value(self):
if self.return_type.is_pyobject:
arg.needs_conversion = 0
arg.needs_type_test = 0
arg.is_generic = 1
- if arg.type.is_extension_type or arg.type.is_builtin_type:
+ if arg.type.is_pyobject:
if arg.or_none:
arg.accept_none = True
elif arg.not_none:
arg.accept_none = False
- else:
+ elif arg.type.is_extension_type or arg.type.is_builtin_type:
# default depends on compiler directive
arg.accept_none = allow_none_for_extension_args
+ else:
+ # probably just a plain 'object'
+ arg.accept_none = True
else:
- arg.accept_none = True
+ arg.accept_none = True # won't be used, but must be there
if arg.not_none:
- error(self.pos, "Only extension type arguments can have 'not None'")
+ error(self.pos, "Only Python type arguments can have 'not None'")
if arg.or_none:
- error(self.pos, "Only extension type arguments can have 'or None'")
+ error(self.pos, "Only Python type arguments can have 'or None'")
def analyse_signature(self, env):
- any_type_tests_needed = 0
if self.entry.is_special:
self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
if not arg.type.same_as(arg.hdr_type):
if arg.hdr_type.is_pyobject and arg.type.is_pyobject:
arg.needs_type_test = 1
- any_type_tests_needed = 1
else:
arg.needs_conversion = 1
if arg.needs_conversion:
if arg.is_generic and \
(arg.type.is_extension_type or arg.type.is_builtin_type):
arg.needs_type_test = 1
- any_type_tests_needed = 1
- if any_type_tests_needed:
- env.use_utility_code(arg_type_test_utility_code)
def bad_signature(self):
sig = self.entry.signature
for arg in self.args:
if arg.needs_type_test:
self.generate_arg_type_test(arg, code)
-
+ elif not arg.accept_none and arg.type.is_pyobject:
+ self.generate_arg_none_check(arg, code)
+
def error_value(self):
return self.entry.signature.error_value
-def eggs(int x not None, y not None):
+def eggs(int x not None, char* y not None):
pass
_ERRORS = u"""
-1:0: Only extension type arguments can have 'not None'
-1:0: Only extension type arguments can have 'not None'
+1:0: Only Python type arguments can have 'not None'
+1:0: Only Python type arguments can have 'not None'
"""
# defaults, without 'not/or None'
-def ext_default(MyExtType x):
+def ext_default(MyExtType x): # currently behaves like 'or None'
"""
>>> ext_default(MyExtType())
123
# defaults, without 'not/or None'
-def builtin_default(list L):
+def builtin_default(list L): # currently behaves like 'or None'
"""
>>> builtin_default([123])
123
return litem(L, 0)
-## builtin type 'object' (which includes None!) - currently unclear!
-
-## def object_or_none(object o or None):
-## """
-## >>> object_or_none([])
-## list
-## >>> object_or_none(None)
-## NoneType
-## """
-## return type(o).__name__
-
-## def object_not_none(object o not None):
-## """
-## >>> object_not_none([123])
-## 123
-## >>> object_not_none(None)
-## Traceback (most recent call last):
-## TypeError: Argument 'o' has incorrect type (expected object, got NoneType)
-## """
-## return type(o).__name__
+## builtin type 'object' - isinstance(None, object) is True!
+
+def object_default(object o): # behaves like 'or None'
+ """
+ >>> object_default(object())
+ 'object'
+ >>> object_default([])
+ 'list'
+ >>> object_default(None)
+ 'NoneType'
+ """
+ return type(o).__name__
+
+def object_or_none(object o or None):
+ """
+ >>> object_or_none(object())
+ 'object'
+ >>> object_or_none([])
+ 'list'
+ >>> object_or_none(None)
+ 'NoneType'
+ """
+ return type(o).__name__
+
+def object_not_none(object o not None):
+ """
+ >>> object_not_none(object())
+ 'object'
+ >>> object_not_none([])
+ 'list'
+ >>> object_not_none(None)
+ Traceback (most recent call last):
+ TypeError: Argument 'o' must not be None
+ """
+ return type(o).__name__
+
+
+## untyped 'object' - isinstance(None, object) is True!
+
+def notype_default(o): # behaves like 'or None'
+ """
+ >>> notype_default(object())
+ 'object'
+ >>> notype_default([])
+ 'list'
+ >>> notype_default(None)
+ 'NoneType'
+ """
+ return type(o).__name__
+
+def notype_or_none(o or None):
+ """
+ >>> notype_or_none(object())
+ 'object'
+ >>> notype_or_none([])
+ 'list'
+ >>> notype_or_none(None)
+ 'NoneType'
+ """
+ return type(o).__name__
+
+def notype_not_none(o not None):
+ """
+ >>> notype_not_none(object())
+ 'object'
+ >>> notype_not_none([])
+ 'list'
+ >>> notype_not_none(None)
+ Traceback (most recent call last):
+ TypeError: Argument 'o' must not be None
+ """
+ return type(o).__name__