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

View File

@ -2,6 +2,8 @@
# This file is part of Hy, which is free software licensed under the Expat
# license. See the LICENSE.
from __future__ import absolute_import
from hy.compiler import hy_compile, HyTypeError
from hy.models import HyObject, HyExpression, HySymbol, replace_hy_obj
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
# license. See the LICENSE.
from inspect import getargspec, formatargspec
import hy.inspect
from hy.models import replace_hy_obj, HyExpression, HySymbol
from hy.errors import HyTypeError, HyMacroExpansionError
from collections import defaultdict
@ -36,8 +35,7 @@ def macro(name):
def _(fn):
fn.__name__ = '({})'.format(name)
try:
argspec = getargspec(fn)
fn._hy_macro_pass_compiler = argspec.keywords is not None
fn._hy_macro_pass_compiler = hy.inspect.has_kwargs(fn)
except Exception:
# An exception might be raised if fn has arguments with
# 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
# raised later on while expanding a macro might not make sense at all.
argspec = getargspec(fn)
formatted_args = formatargspec(*argspec)
formatted_args = hy.inspect.format_args(fn)
fn_str = 'lambda {}: None'.format(
formatted_args.lstrip('(').rstrip(')'))
empty_fn = eval(fn_str)