132 lines
3.8 KiB
Python
132 lines
3.8 KiB
Python
import sys
|
|
from typehandlers.codesink import CodeSink
|
|
from typehandlers.base import TypeConfigurationError, CodeGenerationError, NotSupportedError
|
|
import version
|
|
import settings
|
|
|
|
|
|
def write_preamble(code_sink, min_python_version=(2, 3)):
|
|
"""
|
|
Write a preamble, containing includes, #define's and typedef's
|
|
necessary to correctly compile the code with the given minimum python
|
|
version.
|
|
"""
|
|
|
|
assert isinstance(code_sink, CodeSink)
|
|
assert isinstance(min_python_version, tuple)
|
|
|
|
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")
|
|
|