Source code for enaml.core.funchelper

#------------------------------------------------------------------------------
#  Copyright (c) 2012, Enthought, Inc.
#  All rights reserved.
#------------------------------------------------------------------------------
from types import FunctionType
from ctypes import (
    pythonapi, py_object, c_int, c_size_t, Structure, ARRAY, c_void_p
)


PyEval_EvalCodeEx = pythonapi.PyEval_EvalCodeEx
PyEval_EvalCodeEx.restype = py_object
PyEval_EvalCodeEx.argtypes = [
    py_object,      # code object
    py_object,      # globals dict
    py_object,      # locals mapping
    c_void_p,       # args array (PyObject**)
    c_int,          # num args
    c_void_p,       # keywords array (PyObject**)
    c_int,          # num keywords
    c_void_p,       # defaults array (PyObject**)
    c_int,          # num defaults
    py_object,      # closure
]


class PyTupleObject(Structure):
    _fields_ = [
        ('ob_refcnt', c_size_t),
        ('ob_type', py_object),
        ('ob_size', c_size_t),
        ('ob_item', ARRAY(py_object, 1)),
    ]
OB_ITEM_OFFSET = PyTupleObject.ob_item.offset


[docs]def call_func(func, args, kwargs, f_locals=None): """ Call a function which has been modified by the Enaml compiler to support tracing and dynamic scoping. Parameters ---------- func : types.FunctionType The Python function to call. args : tuple The tuple of arguments to pass to the function. kwargs : dict The dictionary of keywords to pass to the function. f_locals : mapping, optional An optional locals mapping to use with the function. Returns ------- result : object The result of calling the function. """ if not isinstance(func, FunctionType): raise TypeError('function must be a Python function') if not isinstance(args, tuple): raise TypeError('arguments must be a tuple') if not isinstance(kwargs, dict): raise TypeError('keywords must be a dict') if f_locals is None: f_locals = py_object() elif not hasattr(f_locals, '__getitem__'): raise TypeError('locals must be a mapping') num_args = len(args) args_array = c_void_p(id(args) + OB_ITEM_OFFSET) if kwargs: keywords = [] for key, value in kwargs.iteritems: keywords.append(key) keywords.append(value) keywords = tuple(keywords) num_keywords = len(keywords) / 2 else: keywords = () num_keywords = 0 keywords_array = c_void_p(id(keywords) + OB_ITEM_OFFSET) defaults = func.func_defaults or () num_defaults = len(defaults) defaults_array = c_void_p(id(defaults) + OB_ITEM_OFFSET) result = PyEval_EvalCodeEx( func.func_code, func.func_globals, f_locals, args_array, num_args, keywords_array, num_keywords, defaults_array, num_defaults, func.func_closure ) return result # Use the faster version of `call_func` if it's available.
try: from enaml.extensions.funchelper import call_func except ImportError: pass