integrate backcall

This commit is contained in:
Vitor Santos Costa 2018-03-19 15:41:53 +00:00
parent 927a43933c
commit 1ff06fd2e0
5 changed files with 111 additions and 4 deletions

View File

@ -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 ()

View File

@ -19,7 +19,6 @@ requirements:
- libxml2 - libxml2
- backcall - backcall
run: run:
- backcall
- jupyterlab - jupyterlab
- python - python
- readline - readline

View File

@ -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",

View 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

View File

@ -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