217 lines
6.8 KiB
Python
217 lines
6.8 KiB
Python
import sys
|
|
from typehandlers.codesink import CodeSink
|
|
from typehandlers.base import TypeLookupError, TypeConfigurationError, CodeGenerationError, NotSupportedError, \
|
|
Parameter, ReturnValue
|
|
import version
|
|
import settings
|
|
import warnings
|
|
|
|
|
|
def write_preamble(code_sink, min_python_version=None):
|
|
"""
|
|
Write a preamble, containing includes, #define's and typedef's
|
|
necessary to correctly compile the code with the given minimum python
|
|
version.
|
|
"""
|
|
if min_python_version is None:
|
|
min_python_version = settings.min_python_version
|
|
assert isinstance(code_sink, CodeSink)
|
|
assert isinstance(min_python_version, tuple)
|
|
|
|
if __debug__:
|
|
## Gracefully allow code migration
|
|
if hasattr(code_sink, "have_written_preamble"):
|
|
warnings.warn("Duplicate call to write_preamble detected. "
|
|
"Note that there has been an API change in PyBindGen "
|
|
"and directly calling write_preamble should no longer be done "
|
|
"as it is done by PyBindGen itself.",
|
|
DeprecationWarning, stacklevel=2)
|
|
return
|
|
else:
|
|
setattr(code_sink, "have_written_preamble", None)
|
|
|
|
code_sink.writeln('''/* This file was generated by PyBindGen %s */
|
|
#define PY_SSIZE_T_CLEAN
|
|
#include <Python.h>
|
|
#include <stddef.h>
|
|
''' % '.'.join([str(x) for x in version.__version__]))
|
|
|
|
if min_python_version < (2, 4):
|
|
code_sink.writeln(r'''
|
|
#if PY_VERSION_HEX < 0x02040000
|
|
|
|
#define Py_CLEAR(op) \
|
|
do { \
|
|
if (op) { \
|
|
PyObject *tmp = (PyObject *)(op); \
|
|
(op) = NULL; \
|
|
Py_DECREF(tmp); \
|
|
} \
|
|
} while (0)
|
|
|
|
|
|
#define Py_VISIT(op) \
|
|
do { \
|
|
if (op) { \
|
|
int vret = visit((PyObject *)(op), arg); \
|
|
if (vret) \
|
|
return vret; \
|
|
} \
|
|
} while (0)
|
|
|
|
#endif
|
|
|
|
''')
|
|
|
|
if min_python_version < (2, 5):
|
|
code_sink.writeln(r'''
|
|
#if PY_VERSION_HEX < 0x02050000
|
|
|
|
typedef int Py_ssize_t;
|
|
# define PY_SSIZE_T_MAX INT_MAX
|
|
# define PY_SSIZE_T_MIN INT_MIN
|
|
typedef inquiry lenfunc;
|
|
typedef intargfunc ssizeargfunc;
|
|
typedef intobjargproc ssizeobjargproc;
|
|
|
|
#endif
|
|
''')
|
|
|
|
code_sink.writeln(r'''
|
|
#if __GNUC__ > 2
|
|
# define PYBINDGEN_UNUSED(param) param __attribute__((__unused__))
|
|
#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
|
# define PYBINDGEN_UNUSED(param) __attribute__((__unused__)) param
|
|
#else
|
|
# define PYBINDGEN_UNUSED(param)
|
|
#endif /* !__GNUC__ */
|
|
''')
|
|
|
|
|
|
|
|
def get_mangled_name(base_name, template_args):
|
|
"""for internal pybindgen use"""
|
|
assert isinstance(base_name, basestring)
|
|
assert isinstance(template_args, (tuple, list))
|
|
|
|
if template_args:
|
|
return '%s__lt__%s__gt__' % (base_name, '_'.join(
|
|
[arg.replace(' ', '_').replace(':', '_') for arg in template_args]))
|
|
else:
|
|
return base_name
|
|
|
|
|
|
class SkipWrapper(Exception):
|
|
"""Exception that is raised to signal a wrapper failed to generate but
|
|
must simply be skipped.
|
|
for internal pybindgen use"""
|
|
|
|
def call_with_error_handling(callable, args, kwargs, wrapper,
|
|
exceptions_to_handle=(TypeConfigurationError,
|
|
CodeGenerationError,
|
|
NotSupportedError)):
|
|
"""for internal pybindgen use"""
|
|
if settings.error_handler is None:
|
|
return callable(*args, **kwargs)
|
|
else:
|
|
try:
|
|
return callable(*args, **kwargs)
|
|
except Exception, ex:
|
|
if isinstance(ex, exceptions_to_handle):
|
|
dummy1, dummy2, traceback = sys.exc_info()
|
|
if settings.error_handler.handle_error(wrapper, ex, traceback):
|
|
raise SkipWrapper
|
|
else:
|
|
raise
|
|
else:
|
|
raise
|
|
|
|
|
|
def ascii(value):
|
|
"""
|
|
ascii(str_or_unicode_or_None) -> str_or_None
|
|
|
|
Make sure the value is either str or unicode object, and if it is
|
|
unicode convert it to ascii. Also, None is an accepted value, and
|
|
returns itself.
|
|
"""
|
|
if value is None:
|
|
return value
|
|
elif isinstance(value, str):
|
|
return value
|
|
elif isinstance(value, unicode):
|
|
return value.encode('ascii')
|
|
else:
|
|
raise TypeError("value must be str or ascii string contained in a unicode object")
|
|
|
|
|
|
def param(*args, **kwargs):
|
|
"""
|
|
Simplified syntax for representing a parameter with delayed lookup.
|
|
|
|
Parameters are the same as L{Parameter.new}.
|
|
"""
|
|
return (args + (kwargs,))
|
|
|
|
|
|
def retval(*args, **kwargs):
|
|
"""
|
|
Simplified syntax for representing a return value with delayed lookup.
|
|
|
|
Parameters are the same as L{ReturnValue.new}.
|
|
"""
|
|
return (args + (kwargs,))
|
|
|
|
|
|
def parse_param_spec(param_spec):
|
|
if isinstance(param_spec, tuple):
|
|
assert len(param_spec) >= 2
|
|
if isinstance(param_spec[-1], dict):
|
|
kwargs = param_spec[-1]
|
|
args = param_spec[:-1]
|
|
else:
|
|
kwargs = dict()
|
|
args = param_spec
|
|
else:
|
|
raise TypeError("Could not parse `%r' as a Parameter" % param_spec)
|
|
return args, kwargs
|
|
|
|
|
|
def parse_retval_spec(retval_spec):
|
|
if isinstance(retval_spec, tuple):
|
|
assert len(retval_spec) >= 1
|
|
if isinstance(retval_spec[-1], dict):
|
|
kwargs = retval_spec[-1]
|
|
args = retval_spec[:-1]
|
|
else:
|
|
kwargs = dict()
|
|
args = retval_spec
|
|
elif isinstance(retval_spec, str):
|
|
kwargs = dict()
|
|
args = (retval_spec,)
|
|
else:
|
|
raise TypeError("Could not parse `%r' as a ReturnValue" % retval_spec)
|
|
return args, kwargs
|
|
|
|
|
|
def eval_param(param_value, wrapper=None):
|
|
if isinstance(param_value, Parameter):
|
|
return param_value
|
|
else:
|
|
args, kwargs = parse_param_spec(param_value)
|
|
return call_with_error_handling(Parameter.new, args, kwargs, wrapper,
|
|
exceptions_to_handle=(TypeConfigurationError,
|
|
NotSupportedError,
|
|
TypeLookupError))
|
|
|
|
|
|
def eval_retval(retval_value, wrapper=None):
|
|
if isinstance(retval_value, ReturnValue):
|
|
return retval_value
|
|
else:
|
|
args, kwargs = parse_retval_spec(retval_value)
|
|
return call_with_error_handling(ReturnValue.new, args, kwargs, wrapper,
|
|
exceptions_to_handle=(TypeConfigurationError,
|
|
NotSupportedError,
|
|
TypeLookupError))
|