Add a hy.introspect module to deal with getargspec deprecation

This commit is contained in:
Simon Gomizelj 2018-02-08 21:46:03 -05:00
parent 97d7bbb96b
commit ef2f435647
4 changed files with 47 additions and 11 deletions

View File

@ -16,6 +16,7 @@ from hy._compat import (
raise_empty) raise_empty)
from hy.macros import require, macroexpand, tag_macroexpand from hy.macros import require, macroexpand, tag_macroexpand
import hy.importer import hy.importer
import hy.inspect
import traceback import traceback
import importlib import importlib
@ -24,7 +25,6 @@ import ast
import sys import sys
import keyword import keyword
import copy import copy
import inspect
from collections import defaultdict from collections import defaultdict
from cmath import isnan from cmath import isnan
@ -441,10 +441,11 @@ class HyASTCompiler(object):
# _compile_table[atom_type] is a method for compiling this # _compile_table[atom_type] is a method for compiling this
# type of atom, so call it. If it has an extra parameter, # type of atom, so call it. If it has an extra parameter,
# pass in `atom_type`. # pass in `atom_type`.
arity = len(inspect.getargspec(_compile_table[atom_type])[0]) atom_compiler = _compile_table[atom_type]
ret = (_compile_table[atom_type](self, atom, atom_type) arity = hy.inspect.get_arity(atom_compiler)
ret = (atom_compiler(self, atom, atom_type)
if arity == 3 if arity == 3
else _compile_table[atom_type](self, atom)) else atom_compiler(self, atom))
if not isinstance(ret, Result): if not isinstance(ret, Result):
ret = Result() + ret ret = Result() + ret
return ret return ret

View File

@ -2,6 +2,8 @@
# This file is part of Hy, which is free software licensed under the Expat # This file is part of Hy, which is free software licensed under the Expat
# license. See the LICENSE. # license. See the LICENSE.
from __future__ import absolute_import
from hy.compiler import hy_compile, HyTypeError from hy.compiler import hy_compile, HyTypeError
from hy.models import HyObject, HyExpression, HySymbol, replace_hy_obj from hy.models import HyObject, HyExpression, HySymbol, replace_hy_obj
from hy.lex import tokenize, LexException from hy.lex import tokenize, LexException

37
hy/inspect.py Normal file
View File

@ -0,0 +1,37 @@
# Copyright 2018 the authors.
# This file is part of Hy, which is free software licensed under the Expat
# license. See the LICENSE.
from __future__ import absolute_import
import inspect
try:
# Check if we have the newer inspect.signature available.
# Otherwise fallback to the legacy getargspec.
inspect.signature # noqa
except AttributeError:
def get_arity(fn):
return len(inspect.getargspec(fn)[0])
def has_kwargs(fn):
argspec = inspect.getargspec(fn)
return argspec.keywords is not None
def format_args(fn):
argspec = inspect.getargspec(fn)
return inspect.formatargspec(*argspec)
else:
def get_arity(fn):
parameters = inspect.signature(fn).parameters
return sum(1 for param in parameters.values()
if param.kind == param.POSITIONAL_OR_KEYWORD)
def has_kwargs(fn):
parameters = inspect.signature(fn).parameters
return any(param.kind == param.VAR_KEYWORD
for param in parameters.values())
def format_args(fn):
return str(inspect.signature(fn))

View File

@ -2,9 +2,8 @@
# This file is part of Hy, which is free software licensed under the Expat # This file is part of Hy, which is free software licensed under the Expat
# license. See the LICENSE. # license. See the LICENSE.
from inspect import getargspec, formatargspec import hy.inspect
from hy.models import replace_hy_obj, HyExpression, HySymbol from hy.models import replace_hy_obj, HyExpression, HySymbol
from hy.errors import HyTypeError, HyMacroExpansionError from hy.errors import HyTypeError, HyMacroExpansionError
from collections import defaultdict from collections import defaultdict
@ -36,8 +35,7 @@ def macro(name):
def _(fn): def _(fn):
fn.__name__ = '({})'.format(name) fn.__name__ = '({})'.format(name)
try: try:
argspec = getargspec(fn) fn._hy_macro_pass_compiler = hy.inspect.has_kwargs(fn)
fn._hy_macro_pass_compiler = argspec.keywords is not None
except Exception: except Exception:
# An exception might be raised if fn has arguments with # An exception might be raised if fn has arguments with
# names that are invalid in Python. # names that are invalid in Python.
@ -136,9 +134,7 @@ def make_empty_fn_copy(fn):
# can continue running. Unfortunately, the error message that might get # can continue running. Unfortunately, the error message that might get
# raised later on while expanding a macro might not make sense at all. # raised later on while expanding a macro might not make sense at all.
argspec = getargspec(fn) formatted_args = hy.inspect.format_args(fn)
formatted_args = formatargspec(*argspec)
fn_str = 'lambda {}: None'.format( fn_str = 'lambda {}: None'.format(
formatted_args.lstrip('(').rstrip(')')) formatted_args.lstrip('(').rstrip(')'))
empty_fn = eval(fn_str) empty_fn = eval(fn_str)