Merge pull request #1500 from vodik/deprecations
Deal with some deprecation and resource warnings / fix (return) semantics
This commit is contained in:
commit
c1e5c3e48c
2
Makefile
2
Makefile
@ -64,7 +64,7 @@ ifeq (Python 2.6,$(findstring Python 2.6,$(shell python -V 2>&1)))
|
|||||||
endif
|
endif
|
||||||
$(pip) install -r requirements-travis.txt
|
$(pip) install -r requirements-travis.txt
|
||||||
$(pip) install coveralls
|
$(pip) install coveralls
|
||||||
$(pip) install --allow-all-external -e .
|
$(pip) install -e .
|
||||||
|
|
||||||
coveralls:
|
coveralls:
|
||||||
$(coveralls)
|
$(coveralls)
|
||||||
|
7
NEWS.rst
7
NEWS.rst
@ -1,5 +1,12 @@
|
|||||||
.. default-role:: code
|
.. default-role:: code
|
||||||
|
|
||||||
|
Unreleased
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
------------------------------
|
||||||
|
* Fix `(return)` so it works correctly to exit a Python 2 generator
|
||||||
|
|
||||||
0.14.0
|
0.14.0
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -2040,7 +2041,9 @@ class HyASTCompiler(object):
|
|||||||
@checkargs(max=1)
|
@checkargs(max=1)
|
||||||
def compile_return(self, expr):
|
def compile_return(self, expr):
|
||||||
ret = Result()
|
ret = Result()
|
||||||
if len(expr) > 1:
|
if len(expr) == 1:
|
||||||
|
return asty.Return(expr, value=None)
|
||||||
|
|
||||||
ret += self.compile(expr[1])
|
ret += self.compile(expr[1])
|
||||||
return ret + asty.Return(expr, value=ret.force_expr)
|
return ret + asty.Return(expr, value=ret.force_expr)
|
||||||
|
|
||||||
|
@ -29,15 +29,15 @@
|
|||||||
(try (while True
|
(try (while True
|
||||||
(yield (get self index))
|
(yield (get self index))
|
||||||
(setv index (inc index)))
|
(setv index (inc index)))
|
||||||
(except [_ IndexError]
|
(except [IndexError]
|
||||||
(raise StopIteration))))
|
(return))))
|
||||||
--len-- (fn [self]
|
--len-- (fn [self]
|
||||||
"length of the sequence, dangerous for infinite sequences"
|
"length of the sequence, dangerous for infinite sequences"
|
||||||
(setv index (. self high-water))
|
(setv index (. self high-water))
|
||||||
(try (while True
|
(try (while True
|
||||||
(get self index)
|
(get self index)
|
||||||
(setv index (inc index)))
|
(setv index (inc index)))
|
||||||
(except [_ IndexError]
|
(except [IndexError]
|
||||||
(len (. self cache)))))
|
(len (. self cache)))))
|
||||||
max-items-in-repr 10
|
max-items-in-repr 10
|
||||||
--str-- (fn [self]
|
--str-- (fn [self]
|
||||||
|
@ -422,7 +422,10 @@ Raises ValueError for (not (pos? n))."
|
|||||||
(for* [val citer]
|
(for* [val citer]
|
||||||
(yield val)
|
(yield val)
|
||||||
(for* [_ (range skip)]
|
(for* [_ (range skip)]
|
||||||
(next citer))))
|
(try
|
||||||
|
(next citer)
|
||||||
|
(except [StopIteration]
|
||||||
|
(return))))))
|
||||||
|
|
||||||
(defn zero? [n]
|
(defn zero? [n]
|
||||||
"Check if `n` equals 0."
|
"Check if `n` equals 0."
|
||||||
|
@ -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
37
hy/inspect.py
Normal 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))
|
10
hy/macros.py
10
hy/macros.py
@ -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)
|
||||||
|
@ -20,3 +20,6 @@ ignore_errors = True
|
|||||||
# Be sure to include Hy test functions whose names end with "?",
|
# Be sure to include Hy test functions whose names end with "?",
|
||||||
# which will be mangled to begin with "is_".
|
# which will be mangled to begin with "is_".
|
||||||
python_functions=test_* is_test_*
|
python_functions=test_* is_test_*
|
||||||
|
filterwarnings =
|
||||||
|
once::DeprecationWarning
|
||||||
|
once::PendingDeprecationWarning
|
||||||
|
@ -8,7 +8,7 @@ from __future__ import unicode_literals
|
|||||||
from hy import HyString
|
from hy import HyString
|
||||||
from hy.models import HyObject
|
from hy.models import HyObject
|
||||||
from hy.compiler import hy_compile
|
from hy.compiler import hy_compile
|
||||||
from hy.importer import import_buffer_to_hst
|
from hy.importer import hy_eval, import_buffer_to_hst
|
||||||
from hy.errors import HyCompileError, HyTypeError
|
from hy.errors import HyCompileError, HyTypeError
|
||||||
from hy.lex.exceptions import LexException
|
from hy.lex.exceptions import LexException
|
||||||
from hy._compat import PY3
|
from hy._compat import PY3
|
||||||
@ -30,6 +30,10 @@ def can_compile(expr):
|
|||||||
return hy_compile(import_buffer_to_hst(expr), "__main__")
|
return hy_compile(import_buffer_to_hst(expr), "__main__")
|
||||||
|
|
||||||
|
|
||||||
|
def can_eval(expr):
|
||||||
|
return hy_eval(import_buffer_to_hst(expr))
|
||||||
|
|
||||||
|
|
||||||
def cant_compile(expr):
|
def cant_compile(expr):
|
||||||
try:
|
try:
|
||||||
hy_compile(import_buffer_to_hst(expr), "__main__")
|
hy_compile(import_buffer_to_hst(expr), "__main__")
|
||||||
@ -664,3 +668,8 @@ def test_ast_good_yield_from():
|
|||||||
def test_ast_bad_yield_from():
|
def test_ast_bad_yield_from():
|
||||||
"Make sure AST can't compile invalid yield-from"
|
"Make sure AST can't compile invalid yield-from"
|
||||||
cant_compile("(yield-from)")
|
cant_compile("(yield-from)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_eval_generator_with_return():
|
||||||
|
"""Ensure generators with a return statement works."""
|
||||||
|
can_eval("(fn [] (yield 1) (yield 2) (return))")
|
||||||
|
@ -37,19 +37,9 @@ def run_cmd(cmd, stdin_data=None, expect=0, dontwritebytecode=False):
|
|||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
shell=False,
|
shell=False,
|
||||||
env=env)
|
env=env)
|
||||||
if stdin_data is not None:
|
output = p.communicate(input=stdin_data)
|
||||||
p.stdin.write(stdin_data)
|
assert p.wait() == expect
|
||||||
p.stdin.flush()
|
return output
|
||||||
p.stdin.close()
|
|
||||||
# Read stdout and stderr otherwise if the PIPE buffer is full, we might
|
|
||||||
# wait for ever…
|
|
||||||
stdout = ""
|
|
||||||
stderr = ""
|
|
||||||
while p.poll() is None:
|
|
||||||
stdout += p.stdout.read()
|
|
||||||
stderr += p.stderr.read()
|
|
||||||
assert p.returncode == expect
|
|
||||||
return stdout, stderr
|
|
||||||
|
|
||||||
|
|
||||||
def rm(fpath):
|
def rm(fpath):
|
||||||
|
@ -304,11 +304,11 @@ def test_nospace():
|
|||||||
|
|
||||||
def test_escapes():
|
def test_escapes():
|
||||||
""" Ensure we can escape things """
|
""" Ensure we can escape things """
|
||||||
entry = tokenize("(foo \"foo\\n\")")[0]
|
entry = tokenize(r"""(foo "foo\n")""")[0]
|
||||||
assert entry[1] == "foo\n"
|
assert entry[1] == "foo\n"
|
||||||
|
|
||||||
entry = tokenize("(foo \"foo\\s\")")[0]
|
entry = tokenize(r"""(foo r"foo\s")""")[0]
|
||||||
assert entry[1] == "foo\\s"
|
assert entry[1] == r"foo\s"
|
||||||
|
|
||||||
|
|
||||||
def test_unicode_escapes():
|
def test_unicode_escapes():
|
||||||
|
Loading…
Reference in New Issue
Block a user