integrate backcall
This commit is contained in:
parent
927a43933c
commit
1ff06fd2e0
@ -688,7 +688,6 @@ if (PYTHONLIBS_FOUND AND SWIG_FOUND)
|
|||||||
find_python_module(jupyter)
|
find_python_module(jupyter)
|
||||||
find_python_module(wheel)
|
find_python_module(wheel)
|
||||||
find_python_module(setuptools)
|
find_python_module(setuptools)
|
||||||
find_python_module(backcall)
|
|
||||||
if (PY_JUPYTER AND PY_WHEEL AND PY_SETUPTOOLS AND PY_BACKCALL)
|
if (PY_JUPYTER AND PY_WHEEL AND PY_SETUPTOOLS AND PY_BACKCALL)
|
||||||
add_subdirectory(packages/python/yap_kernel)
|
add_subdirectory(packages/python/yap_kernel)
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
@ -19,7 +19,6 @@ requirements:
|
|||||||
- libxml2
|
- libxml2
|
||||||
- backcall
|
- backcall
|
||||||
run:
|
run:
|
||||||
- backcall
|
|
||||||
- jupyterlab
|
- jupyterlab
|
||||||
- python
|
- python
|
||||||
- readline
|
- readline
|
||||||
|
@ -67,7 +67,7 @@ setup_args = dict(
|
|||||||
version = version_ns['__version__'],
|
version = version_ns['__version__'],
|
||||||
scripts = glob(pjoin('scripts', '*')),
|
scripts = glob(pjoin('scripts', '*')),
|
||||||
packages = packages,
|
packages = packages,
|
||||||
py_modules = ['yap_kernel_launcher'],
|
py_modules = ['yap_kernel_launcher','backcall'],
|
||||||
package_data = package_data,
|
package_data = package_data,
|
||||||
#package_dir = {'':here},
|
#package_dir = {'':here},
|
||||||
description = "YAP Kernel for Jupyter",
|
description = "YAP Kernel for Jupyter",
|
||||||
|
109
packages/python/yap_kernel/yap_ipython/core/backcall.py
Normal file
109
packages/python/yap_kernel/yap_ipython/core/backcall.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Created on Mon Jan 13 18:17:15 2014
|
||||||
|
|
||||||
|
@author: takluyver
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
PY3 = (sys.version_info[0] >= 3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from inspect import signature, Parameter # Python >= 3.3
|
||||||
|
except ImportError:
|
||||||
|
from ._signatures import signature, Parameter
|
||||||
|
|
||||||
|
if PY3:
|
||||||
|
from functools import wraps
|
||||||
|
else:
|
||||||
|
from functools import wraps as _wraps
|
||||||
|
def wraps(f):
|
||||||
|
def dec(func):
|
||||||
|
_wraps(f)(func)
|
||||||
|
func.__wrapped__ = f
|
||||||
|
return func
|
||||||
|
|
||||||
|
return dec
|
||||||
|
|
||||||
|
def callback_prototype(prototype):
|
||||||
|
"""Decorator to process a callback prototype.
|
||||||
|
|
||||||
|
A callback prototype is a function whose signature includes all the values
|
||||||
|
that will be passed by the callback API in question.
|
||||||
|
|
||||||
|
The original function will be returned, with a ``prototype.adapt`` attribute
|
||||||
|
which can be used to prepare third party callbacks.
|
||||||
|
"""
|
||||||
|
protosig = signature(prototype)
|
||||||
|
positional, keyword = [], []
|
||||||
|
for name, param in protosig.parameters.items():
|
||||||
|
if param.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD):
|
||||||
|
raise TypeError("*args/**kwargs not supported in prototypes")
|
||||||
|
|
||||||
|
if (param.default is not Parameter.empty) \
|
||||||
|
or (param.kind == Parameter.KEYWORD_ONLY):
|
||||||
|
keyword.append(name)
|
||||||
|
else:
|
||||||
|
positional.append(name)
|
||||||
|
|
||||||
|
kwargs = dict.fromkeys(keyword)
|
||||||
|
def adapt(callback):
|
||||||
|
"""Introspect and prepare a third party callback."""
|
||||||
|
sig = signature(callback)
|
||||||
|
try:
|
||||||
|
# XXX: callback can have extra optional parameters - OK?
|
||||||
|
sig.bind(*positional, **kwargs)
|
||||||
|
return callback
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Match up arguments
|
||||||
|
unmatched_pos = positional[:]
|
||||||
|
unmatched_kw = kwargs.copy()
|
||||||
|
unrecognised = []
|
||||||
|
# TODO: unrecognised parameters with default values - OK?
|
||||||
|
for name, param in sig.parameters.items():
|
||||||
|
# print(name, param.kind) #DBG
|
||||||
|
if param.kind == Parameter.POSITIONAL_ONLY:
|
||||||
|
if len(unmatched_pos) > 0:
|
||||||
|
unmatched_pos.pop(0)
|
||||||
|
else:
|
||||||
|
unrecognised.append(name)
|
||||||
|
elif param.kind == Parameter.POSITIONAL_OR_KEYWORD:
|
||||||
|
if (param.default is not Parameter.empty) and (name in unmatched_kw):
|
||||||
|
unmatched_kw.pop(name)
|
||||||
|
elif len(unmatched_pos) > 0:
|
||||||
|
unmatched_pos.pop(0)
|
||||||
|
else:
|
||||||
|
unrecognised.append(name)
|
||||||
|
elif param.kind == Parameter.VAR_POSITIONAL:
|
||||||
|
unmatched_pos = []
|
||||||
|
elif param.kind == Parameter.KEYWORD_ONLY:
|
||||||
|
if name in unmatched_kw:
|
||||||
|
unmatched_kw.pop(name)
|
||||||
|
else:
|
||||||
|
unrecognised.append(name)
|
||||||
|
else: # VAR_KEYWORD
|
||||||
|
unmatched_kw = {}
|
||||||
|
|
||||||
|
# print(unmatched_pos, unmatched_kw, unrecognised) #DBG
|
||||||
|
|
||||||
|
if unrecognised:
|
||||||
|
raise TypeError("Function {!r} had unmatched arguments: {}".format(callback, unrecognised))
|
||||||
|
|
||||||
|
n_positional = len(positional) - len(unmatched_pos)
|
||||||
|
|
||||||
|
@wraps(callback)
|
||||||
|
def adapted(*args, **kwargs):
|
||||||
|
"""Wrapper for third party callbacks that discards excess arguments"""
|
||||||
|
# print(args, kwargs)
|
||||||
|
args = args[:n_positional]
|
||||||
|
for name in unmatched_kw:
|
||||||
|
# XXX: Could name not be in kwargs?
|
||||||
|
kwargs.pop(name)
|
||||||
|
# print(args, kwargs, unmatched_pos, cut_positional, unmatched_kw)
|
||||||
|
return callback(*args, **kwargs)
|
||||||
|
|
||||||
|
return adapted
|
||||||
|
|
||||||
|
prototype.adapt = adapt
|
||||||
|
return prototype
|
@ -1,4 +1,4 @@
|
|||||||
from backcall import callback_prototype
|
from yap_ipython.core.backcall import callback_prototype
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
import nose.tools as nt
|
import nose.tools as nt
|
||||||
|
Reference in New Issue
Block a user