diff --git a/.travis.yml b/.travis.yml
index 4234503..f7fe97b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,12 +2,10 @@ sudo: false
dist: xenial
language: python
python:
- - "2.7"
- "3.5"
- "3.6"
- "3.7"
- 3.8-dev
- - pypy2.7-6.0
- pypy3.5-6.0
install:
- pip install -r requirements-travis.txt
diff --git a/NEWS.rst b/NEWS.rst
index 94db065..00103d4 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -1,5 +1,12 @@
.. default-role:: code
+Unreleased
+==============================
+
+Removals
+------------------------------
+* Python 2 is no longer supported.
+
0.17.0
==============================
diff --git a/conftest.py b/conftest.py
index 9f65b48..7ded83e 100644
--- a/conftest.py
+++ b/conftest.py
@@ -4,7 +4,7 @@ import importlib
import py
import pytest
import hy
-from hy._compat import PY3, PY36, PY38
+from hy._compat import PY36, PY38
NATIVE_TESTS = os.path.join("", "tests", "native_tests", "")
@@ -12,8 +12,7 @@ _fspath_pyimport = py.path.local.pyimport
def pytest_ignore_collect(path, config):
- return (("py3_only" in path.basename and not PY3) or
- ("py36_only" in path.basename and not PY36) or
+ return (("py36_only" in path.basename and not PY36) or
("py38_only" in path.basename and not PY38) or None)
diff --git a/docs/conf.py b/docs/conf.py
index 682dbcf..f4ae994 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -52,5 +52,4 @@ html_context = dict(
hy_descriptive_version = hy_descriptive_version)
intersphinx_mapping = dict(
- py2 = ('https://docs.python.org/2/', None),
- py = ('https://docs.python.org/3/', None))
+ py = ('https://docs.python.org/3/', None))
diff --git a/docs/language/api.rst b/docs/language/api.rst
index 2a690f6..6b243ba 100644
--- a/docs/language/api.rst
+++ b/docs/language/api.rst
@@ -564,8 +564,6 @@ requires.
File "", line 1, in
TypeError: compare() missing 1 required keyword-only argument: 'keyfn'
- Availability: Python 3.
-
&kwargs
Like ``&rest``, but for keyword arugments.
The following parameter will contain 0 or more keyword arguments.
@@ -1057,7 +1055,7 @@ if / if* / if-not
``if / if* / if-not`` respect Python *truthiness*, that is, a *test* fails if it
evaluates to a "zero" (including values of ``len`` zero, ``None``, and
``False``), and passes otherwise, but values with a ``__bool__`` method
-(``__nonzero__`` in Python 2) can overrides this.
+can override this.
The ``if`` macro is for conditionally selecting an expression for evaluation.
The result of the selected expression becomes the result of the entire ``if``
@@ -1296,19 +1294,12 @@ fact, these forms are implemented as generator functions whenever they
contain Python statements, with the attendant consequences for calling
``return``. By contrast, ``for`` shares the caller's scope.
-.. note:: An exception to the above scoping rules occurs on Python 2 for
- ``lfor`` specifically (and not ``sfor``, ``gfor``, or ``dfor``) when
- Hy can implement the ``lfor`` as a Python list comprehension. Then,
- variables will leak to the surrounding scope.
-
nonlocal
--------
.. versionadded:: 0.11.1
-**PYTHON 3.0 AND UP ONLY!**
-
``nonlocal`` can be used to mark a symbol as not local to the current scope.
The parameters are the names of symbols to mark as nonlocal. This is necessary
to modify variables through nested ``fn`` scopes:
@@ -1693,7 +1684,7 @@ object (respectively) to provide positional or keywords arguments
=> (f #* [1 2] #** {"c" 3 "d" 4})
[1, 2, 3, 4]
-With Python 3, unpacking is allowed in more contexts, and you can unpack
+Unpacking is allowed in a variety of contexts, and you can unpack
more than once in one expression (:pep:`3132`, :pep:`448`).
.. code-block:: clj
@@ -2038,8 +2029,6 @@ yield-from
.. versionadded:: 0.9.13
-**PYTHON 3.3 AND UP ONLY!**
-
``yield-from`` is used to call a subgenerator. This is useful if you
want your coroutine to be able to delegate its processes to another
coroutine, say, if using something fancy like
diff --git a/docs/language/core.rst b/docs/language/core.rst
index 7e42691..cabb420 100644
--- a/docs/language/core.rst
+++ b/docs/language/core.rst
@@ -240,19 +240,6 @@ otherwise ``False``. Return ``True`` if *coll* is empty.
True
-.. _exec-fn:
-
-exec
-----
-
-Equivalent to Python 3's built-in function :py:func:`exec`.
-
-.. code-block:: clj
-
- => (exec "print(a + b)" {"a" 1} {"b" 2})
- 3
-
-
.. _float?-fn:
float?
@@ -385,8 +372,7 @@ integer?
Usage: ``(integer? x)``
-Returns `True` if *x* is an integer. For Python 2, this is
-either ``int`` or ``long``. For Python 3, this is ``int``.
+Returns `True` if *x* is an integer (``int``).
.. code-block:: hy
@@ -924,7 +910,7 @@ string?
Usage: ``(string? x)``
-Returns ``True`` if *x* is a string.
+Returns ``True`` if *x* is a string (``str``).
.. code-block:: hy
diff --git a/docs/language/internals.rst b/docs/language/internals.rst
index 1cd32ad..a89b356 100644
--- a/docs/language/internals.rst
+++ b/docs/language/internals.rst
@@ -120,9 +120,7 @@ HyString
~~~~~~~~
``hy.models.HyString`` represents string literals (including bracket strings),
-which compile down to unicode string literals in Python. ``HyStrings`` inherit
-unicode objects in Python 2, and string objects in Python 3 (and are therefore
-not encoding-dependent).
+which compile down to unicode string literals (``str``) in Python.
``HyString``\s are immutable.
@@ -140,15 +138,15 @@ HyBytes
~~~~~~~
``hy.models.HyBytes`` is like ``HyString``, but for sequences of bytes.
-It inherits from ``bytes`` on Python 3 and ``str`` on Python 2.
+It inherits from ``bytes``.
.. _hy_numeric_models:
Numeric Models
~~~~~~~~~~~~~~
-``hy.models.HyInteger`` represents integer literals (using the
-``long`` type on Python 2, and ``int`` on Python 3).
+``hy.models.HyInteger`` represents integer literals, using the ``int``
+type.
``hy.models.HyFloat`` represents floating-point literals.
diff --git a/docs/language/syntax.rst b/docs/language/syntax.rst
index 2414499..16ed838 100644
--- a/docs/language/syntax.rst
+++ b/docs/language/syntax.rst
@@ -10,7 +10,7 @@ An identifier consists of a nonempty sequence of Unicode characters that are not
numeric literals
----------------
-In addition to regular numbers, standard notation from Python 3 for non-base 10
+In addition to regular numbers, standard notation from Python for non-base 10
integers is used. ``0x`` for Hex, ``0o`` for Octal, ``0b`` for Binary.
.. code-block:: clj
@@ -60,13 +60,9 @@ Plain string literals support :ref:`a variety of backslash escapes
literally, prefix the string with ``r``, as in ``r"slash\not"``. Bracket
strings are always raw strings and don't allow the ``r`` prefix.
-Whether running under Python 2 or Python 3, Hy treats all string literals as
-sequences of Unicode characters by default, and allows you to prefix a plain
-string literal (but not a bracket string) with ``b`` to treat it as a sequence
-of bytes. So when running under Python 3, Hy translates ``"foo"`` and
-``b"foo"`` to the identical Python code, but when running under Python 2,
-``"foo"`` is translated to ``u"foo"`` and ``b"foo"`` is translated to
-``"foo"``.
+Like Python, Hy treats all string literals as sequences of Unicode characters
+by default. You may prefix a plain string literal (but not a bracket string)
+with ``b`` to treat it as a sequence of bytes.
Unlike Python, Hy only recognizes string prefixes (``r``, etc.) in lowercase.
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index 68f2eae..167cad4 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -39,7 +39,6 @@ into the making of Hy.
+ Look like a Lisp; DTRT with it (e.g. dashes turn to underscores).
+ We're still Python. Most of the internals translate 1:1 to Python internals.
+ Use Unicode everywhere.
-+ Fix the bad decisions in Python 2 when we can (see ``true_division``).
+ When in doubt, defer to Python.
+ If you're still unsure, defer to Clojure.
+ If you're even more unsure, defer to Common Lisp.
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index 96f8f7f..09cbd52 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -25,9 +25,6 @@ This is pretty cool because it means Hy is several things:
comfort of Python!
- For everyone: a pleasant language that has a lot of neat ideas!
-Now this tutorial assumes you're running Hy on Python 3. So know things
-are a bit different if you're still using Python 2.
-
Basic intro to Lisp for Pythonistas
===================================
diff --git a/hy/_compat.py b/hy/_compat.py
index a2ab7a5..70a3187 100644
--- a/hy/_compat.py
+++ b/hy/_compat.py
@@ -2,108 +2,15 @@
# This file is part of Hy, which is free software licensed under the Expat
# license. See the LICENSE.
-try:
- import __builtin__ as builtins
-except ImportError:
- import builtins # NOQA
-import sys, keyword, textwrap
+import sys
-PY3 = sys.version_info[0] >= 3
PY36 = sys.version_info >= (3, 6)
PY37 = sys.version_info >= (3, 7)
PY38 = sys.version_info >= (3, 8)
-# The value of UCS4 indicates whether Unicode strings are stored as UCS-4.
-# It is always true on Pythons >= 3.3, which use USC-4 on all systems.
-UCS4 = sys.maxunicode == 0x10FFFF
-str_type = str if PY3 else unicode # NOQA
-bytes_type = bytes if PY3 else str # NOQA
-long_type = int if PY3 else long # NOQA
-string_types = str if PY3 else basestring # NOQA
-
-#
-# Inspired by the same-named `six` functions.
-#
-if PY3:
- raise_src = textwrap.dedent('''
- def raise_from(value, from_value):
- raise value from from_value
- ''')
-
- def reraise(exc_type, value, traceback=None):
- try:
- raise value.with_traceback(traceback)
- finally:
- traceback = None
-
- code_obj_args = ['argcount', 'kwonlyargcount', 'nlocals', 'stacksize',
- 'flags', 'code', 'consts', 'names', 'varnames',
- 'filename', 'name', 'firstlineno', 'lnotab', 'freevars',
- 'cellvars']
-else:
- def raise_from(value, from_value=None):
- raise value
-
- raise_src = textwrap.dedent('''
- def reraise(exc_type, value, traceback=None):
- try:
- raise exc_type, value, traceback
- finally:
- traceback = None
- ''')
-
- code_obj_args = ['argcount', 'nlocals', 'stacksize', 'flags', 'code',
- 'consts', 'names', 'varnames', 'filename', 'name',
- 'firstlineno', 'lnotab', 'freevars', 'cellvars']
-
-raise_code = compile(raise_src, __file__, 'exec')
-exec(raise_code)
-
-
-def rename_function(func, new_name):
- """Creates a copy of a function and [re]sets the name at the code-object
- level.
- """
- c = func.__code__
- new_code = type(c)(*[getattr(c, 'co_{}'.format(a))
- if a != 'name' else str(new_name)
- for a in code_obj_args])
-
- _fn = type(func)(new_code, func.__globals__, str(new_name),
- func.__defaults__, func.__closure__)
- _fn.__dict__.update(func.__dict__)
-
- return _fn
-
-
-def isidentifier(x):
- if x in ('True', 'False', 'None', 'print'):
- # `print` is special-cased here because Python 2's
- # keyword.iskeyword will count it as a keyword, but we
- # use the __future__ feature print_function, which makes
- # it a non-keyword.
- return True
- if keyword.iskeyword(x):
- return False
- if PY3:
- return x.isidentifier()
- if x.rstrip() != x:
- return False
- import tokenize as T
- from io import StringIO
+def reraise(exc_type, value, traceback=None):
try:
- tokens = list(T.generate_tokens(StringIO(x).readline))
- except (T.TokenError, IndentationError):
- return False
- # Some versions of Python 2.7 (including one that made it into
- # Ubuntu 18.10) have a Python 3 backport that adds a NEWLINE
- # token. Remove it if it's present.
- # https://bugs.python.org/issue33899
- tokens = [t for t in tokens if t[0] != T.NEWLINE]
- return len(tokens) == 2 and tokens[0][0] == T.NAME
-
-try:
- FileNotFoundError = FileNotFoundError
-except NameError:
- FileNotFoundError = IOError
+ raise value.with_traceback(traceback)
+ finally:
+ traceback = None
diff --git a/hy/cmdline.py b/hy/cmdline.py
index d38ec08..4c0c1fa 100644
--- a/hy/cmdline.py
+++ b/hy/cmdline.py
@@ -19,6 +19,7 @@ import time
import linecache
import hashlib
import codeop
+import builtins
import astor.code_gen
@@ -35,7 +36,6 @@ from hy.importer import runhy
from hy.completer import completion, Completer
from hy.macros import macro, require
from hy.models import HyExpression, HyString, HySymbol
-from hy._compat import builtins, PY3, FileNotFoundError
sys.last_type = None
@@ -256,7 +256,7 @@ class HyREPL(code.InteractiveConsole, object):
module, f = '.'.join(parts[:-1]), parts[-1]
self.output_fn = getattr(importlib.import_module(module), f)
else:
- self.output_fn = __builtins__[mangle(output_fn)]
+ self.output_fn = getattr(builtins, mangle(output_fn))
# Pre-mangle symbols for repl recent results: *1, *2, *3
self._repl_results_symbols = [mangle("*{}".format(i + 1)) for i in range(3)]
@@ -661,7 +661,7 @@ def hy2py_main():
if options.with_source:
# need special printing on Windows in case the
# codepage doesn't support utf-8 characters
- if PY3 and platform.system() == "Windows":
+ if platform.system() == "Windows":
for h in hst:
try:
print(h)
@@ -676,7 +676,7 @@ def hy2py_main():
_ast = hy_compile(hst, '__main__', filename=filename, source=source)
if options.with_ast:
- if PY3 and platform.system() == "Windows":
+ if platform.system() == "Windows":
_print_for_windows(astor.dump_tree(_ast))
else:
print(astor.dump_tree(_ast))
@@ -684,7 +684,7 @@ def hy2py_main():
print()
if not options.without_python:
- if PY3 and platform.system() == "Windows":
+ if platform.system() == "Windows":
_print_for_windows(astor.code_gen.to_source(_ast))
else:
print(astor.code_gen.to_source(_ast))
diff --git a/hy/compiler.py b/hy/compiler.py
index 9a20daf..7638893 100755
--- a/hy/compiler.py
+++ b/hy/compiler.py
@@ -14,8 +14,7 @@ from hy.errors import (HyCompileError, HyTypeError, HyLanguageError,
from hy.lex import mangle, unmangle, hy_parse, parse_one_thing, LexException
-from hy._compat import (string_types, str_type, bytes_type, long_type, PY3,
- PY36, PY38, reraise)
+from hy._compat import (PY36, PY38, reraise)
from hy.macros import require, load_macros, macroexpand, tag_macroexpand
import hy.core
@@ -29,15 +28,12 @@ import types
import ast
import sys
import copy
+import builtins
import __future__
from collections import defaultdict
from functools import reduce
-if PY3:
- import builtins
-else:
- import __builtin__ as builtins
Inf = float('inf')
@@ -99,15 +95,12 @@ def calling_module(n=1):
def ast_str(x, piecewise=False):
if piecewise:
return ".".join(ast_str(s) if s else "" for s in x.split("."))
- x = mangle(x)
- return x if PY3 else x.encode('UTF8')
+ return mangle(x)
_special_form_compilers = {}
_model_compilers = {}
-_decoratables = (ast.FunctionDef, ast.ClassDef)
-if PY3:
- _decoratables += (ast.AsyncFunctionDef,)
+_decoratables = (ast.FunctionDef, ast.ClassDef, ast.AsyncFunctionDef)
# _bad_roots are fake special operators, which are used internally
# by other special forms (e.g., `except` in `try`) but can't be
# used to construct special forms themselves.
@@ -179,7 +172,7 @@ class Result(object):
object gets added to a Result object, it gets converted on-the-fly.
"""
__slots__ = ("imports", "stmts", "temp_variables",
- "_expr", "__used_expr", "contains_yield")
+ "_expr", "__used_expr")
def __init__(self, *args, **kwargs):
if args:
@@ -190,14 +183,12 @@ class Result(object):
self.stmts = []
self.temp_variables = []
self._expr = None
- self.contains_yield = False
self.__used_expr = False
# XXX: Make sure we only have AST where we should.
for kwarg in kwargs:
- if kwarg not in ["imports", "contains_yield", "stmts", "expr",
- "temp_variables"]:
+ if kwarg not in ["imports", "stmts", "expr", "temp_variables"]:
raise TypeError(
"%s() got an unexpected keyword argument '%s'" % (
self.__class__.__name__, kwarg))
@@ -277,9 +268,7 @@ class Result(object):
if isinstance(var, ast.Name):
var.id = new_name
var.arg = new_name
- elif isinstance(var, ast.FunctionDef):
- var.name = new_name
- elif PY3 and isinstance(var, ast.AsyncFunctionDef):
+ elif isinstance(var, (ast.FunctionDef, ast.AsyncFunctionDef)):
var.name = new_name
else:
raise TypeError("Don't know how to rename a %s!" % (
@@ -315,22 +304,17 @@ class Result(object):
result.stmts = self.stmts + other.stmts
result.expr = other.expr
result.temp_variables = other.temp_variables
- result.contains_yield = False
- if self.contains_yield or other.contains_yield:
- result.contains_yield = True
return result
def __str__(self):
return (
- "Result(imports=[%s], stmts=[%s], "
- "expr=%s, contains_yield=%s)"
- ) % (
+ "Result(imports=[%s], stmts=[%s], expr=%s)"
+ % (
", ".join(ast.dump(x) for x in self.imports),
", ".join(ast.dump(x) for x in self.stmts),
- ast.dump(self.expr) if self.expr else None,
- self.contains_yield
- )
+ ast.dump(self.expr) if self.expr else None
+ ))
def is_unpack(kind, x):
@@ -390,11 +374,7 @@ class HyASTCompiler(object):
for stdlib_module in hy.core.STDLIB:
mod = importlib.import_module(stdlib_module)
for e in map(ast_str, getattr(mod, 'EXPORTS', [])):
- if getattr(mod, e) is not getattr(builtins, e, ''):
- # Don't bother putting a name in _stdlib if it
- # points to a builtin with the same name. This
- # prevents pointless imports.
- self._stdlib[e] = stdlib_module
+ self._stdlib[e] = stdlib_module
def get_anon_var(self):
self.anon_var_count += 1
@@ -458,8 +438,7 @@ class HyASTCompiler(object):
def _syntax_error(self, expr, message):
return HySyntaxError(message, expr, self.filename, self.source)
- def _compile_collect(self, exprs, with_kwargs=False, dict_display=False,
- oldpy_unpack=False):
+ def _compile_collect(self, exprs, with_kwargs=False, dict_display=False):
"""Collect the expression contexts from a list of compiled expression.
This returns a list of the expression contexts, and the sum of the
@@ -469,34 +448,18 @@ class HyASTCompiler(object):
compiled_exprs = []
ret = Result()
keywords = []
- oldpy_starargs = None
- oldpy_kwargs = None
exprs_iter = iter(exprs)
for expr in exprs_iter:
- if not PY3 and oldpy_unpack and is_unpack("iterable", expr):
- if oldpy_starargs:
- raise self._syntax_error(expr,
- "Pythons < 3.5 allow only one `unpack-iterable` per call")
- oldpy_starargs = self.compile(expr[1])
- ret += oldpy_starargs
- oldpy_starargs = oldpy_starargs.force_expr
-
- elif is_unpack("mapping", expr):
+ if is_unpack("mapping", expr):
ret += self.compile(expr[1])
- if PY3:
- if dict_display:
- compiled_exprs.append(None)
- compiled_exprs.append(ret.force_expr)
- elif with_kwargs:
- keywords.append(asty.keyword(
- expr, arg=None, value=ret.force_expr))
- elif oldpy_unpack:
- if oldpy_kwargs:
- raise self._syntax_error(expr,
- "Pythons < 3.5 allow only one `unpack-mapping` per call")
- oldpy_kwargs = ret.force_expr
+ if dict_display:
+ compiled_exprs.append(None)
+ compiled_exprs.append(ret.force_expr)
+ elif with_kwargs:
+ keywords.append(asty.keyword(
+ expr, arg=None, value=ret.force_expr))
elif with_kwargs and isinstance(expr, HyKeyword):
try:
@@ -512,7 +475,7 @@ class HyASTCompiler(object):
compiled_value = self.compile(value)
ret += compiled_value
- arg = str_type(expr)[1:]
+ arg = str(expr)[1:]
keywords.append(asty.keyword(
expr, arg=ast_str(arg), value=compiled_value.force_expr))
@@ -520,10 +483,7 @@ class HyASTCompiler(object):
ret += self.compile(expr)
compiled_exprs.append(ret.force_expr)
- if oldpy_unpack:
- return compiled_exprs, ret, keywords, oldpy_starargs, oldpy_kwargs
- else:
- return compiled_exprs, ret, keywords
+ return compiled_exprs, ret, keywords
def _compile_branch(self, exprs):
"""Make a branch out of an iterable of Result objects
@@ -564,7 +524,7 @@ class HyASTCompiler(object):
new_name = ast.Subscript(value=name.value, slice=name.slice)
elif isinstance(name, ast.Attribute):
new_name = ast.Attribute(value=name.value, attr=name.attr)
- elif PY3 and isinstance(name, ast.Starred):
+ elif isinstance(name, ast.Starred):
new_name = ast.Starred(
value=self._storeize(expr, name.value, func))
else:
@@ -650,23 +610,10 @@ class HyASTCompiler(object):
@special("unpack-iterable", [FORM])
def compile_unpack_iterable(self, expr, root, arg):
- if not PY3:
- raise self._syntax_error(expr,
- "`unpack-iterable` isn't allowed here")
ret = self.compile(arg)
ret += asty.Starred(expr, value=ret.force_expr, ctx=ast.Load())
return ret
- @special([(not PY3, "exec*")], [FORM, maybe(FORM), maybe(FORM)])
- # Under Python 3, `exec` is a function rather than a statement type, so Hy
- # doesn't need a special form for it.
- def compile_exec(self, expr, root, body, globals_, locals_):
- return asty.Exec(
- expr,
- body=self.compile(body).force_expr,
- globals=self.compile(globals_).force_expr if globals_ is not None else None,
- locals=self.compile(locals_).force_expr if locals_ is not None else None)
-
@special("do", [many(FORM)])
def compile_do(self, expr, root, body):
return self._compile_branch(body)
@@ -681,9 +628,6 @@ class HyASTCompiler(object):
exc = exc.force_expr
if cause is not None:
- if not PY3:
- raise self._syntax_error(expr,
- "raise from only supported in python 3")
cause = self.compile(cause)
ret += cause
cause = cause.force_expr
@@ -739,35 +683,17 @@ class HyASTCompiler(object):
returnable = Result(
expr=asty.Name(expr, id=return_var.id, ctx=ast.Load()),
- temp_variables=[return_var],
- contains_yield=body.contains_yield)
+ temp_variables=[return_var])
body += body.expr_as_stmt() if orelse else asty.Assign(
expr, targets=[return_var], value=body.force_expr)
body = body.stmts or [asty.Pass(expr)]
- if PY3:
- # Python 3.3 features a merge of TryExcept+TryFinally into Try.
- x = asty.Try(
- expr,
- body=body,
- handlers=handlers,
- orelse=orelse,
- finalbody=finalbody)
- elif finalbody and handlers:
- x = asty.TryFinally(
- expr,
- body=[asty.TryExcept(
- expr,
- body=body,
- handlers=handlers,
- orelse=orelse)],
- finalbody=finalbody)
- elif finalbody:
- x = asty.TryFinally(
- expr, body=body, finalbody=finalbody)
- else:
- x = asty.TryExcept(
- expr, body=body, handlers=handlers, orelse=orelse)
+ x = asty.Try(
+ expr,
+ body=body,
+ handlers=handlers,
+ orelse=orelse,
+ finalbody=finalbody)
return handler_results + x + returnable
def _compile_catch_expression(self, expr, var, exceptions, body):
@@ -784,9 +710,7 @@ class HyASTCompiler(object):
name = None
if len(exceptions) == 2:
- name = exceptions[0]
- name = (ast_str(name) if PY3
- else self._storeize(name, self.compile(name)))
+ name = ast_str(exceptions[0])
exceptions_list = exceptions[-1] if exceptions else HyList()
if isinstance(exceptions_list, HyList):
@@ -900,19 +824,19 @@ class HyASTCompiler(object):
msg = self.compile(msg).force_expr
return ret + asty.Assert(expr, test=e, msg=msg)
- @special(["global", (PY3, "nonlocal")], [oneplus(SYM)])
+ @special(["global", "nonlocal"], [oneplus(SYM)])
def compile_global_or_nonlocal(self, expr, root, syms):
node = asty.Global if root == "global" else asty.Nonlocal
return node(expr, names=list(map(ast_str, syms)))
@special("yield", [maybe(FORM)])
def compile_yield_expression(self, expr, root, arg):
- ret = Result(contains_yield=(not PY3))
+ ret = Result()
if arg is not None:
ret += self.compile(arg)
return ret + asty.Yield(expr, value=ret.force_expr)
- @special([(PY3, "yield-from"), (PY3, "await")], [FORM])
+ @special(["yield-from", "await"], [FORM])
def compile_yield_from_or_await_expression(self, expr, root, arg):
ret = Result() + self.compile(arg)
node = asty.YieldFrom if root == "yield-from" else asty.Await
@@ -991,7 +915,7 @@ class HyASTCompiler(object):
fn.stmts[-1].decorator_list = decs + fn.stmts[-1].decorator_list
return ret + fn
- @special(["with*", (PY3, "with/a*")],
+ @special(["with*", "with/a*"],
[brackets(FORM, maybe(FORM)), many(FORM)])
def compile_with_expression(self, expr, root, args, body):
thing, ctx = (None, args[0]) if args[1] is None else args
@@ -1015,14 +939,11 @@ class HyASTCompiler(object):
the_with = node(expr,
context_expr=ctx.force_expr,
optional_vars=thing,
- body=body.stmts)
-
- if PY3:
- the_with.items = [ast.withitem(context_expr=ctx.force_expr,
- optional_vars=thing)]
+ body=body.stmts,
+ items=[ast.withitem(context_expr=ctx.force_expr,
+ optional_vars=thing)])
ret = Result(stmts=[initial_assign]) + ctx + the_with
- ret.contains_yield = ret.contains_yield or body.contains_yield
# And make our expression context our temp variable
expr_name = asty.Name(expr, id=ast_str(var), ctx=ast.Load())
@@ -1096,7 +1017,6 @@ class HyASTCompiler(object):
# The desired comprehension can't be expressed as a
# real Python comprehension. We'll write it as a nested
# loop in a function instead.
- contains_yield = []
def f(parts):
# This function is called recursively to construct
# the nested loop.
@@ -1104,8 +1024,6 @@ class HyASTCompiler(object):
if is_for:
if body:
bd = self._compile_branch(body)
- if bd.contains_yield:
- contains_yield.append(True)
return bd + bd.expr_as_stmt()
return Result(stmts=[asty.Pass(expr)])
if node_class is asty.DictComp:
@@ -1136,16 +1054,14 @@ class HyASTCompiler(object):
else:
raise ValueError("can't happen")
if is_for:
- ret = f(parts)
- ret.contains_yield = bool(contains_yield)
- return ret
+ return f(parts)
fname = self.get_anon_var()
# Define the generator function.
ret = Result() + asty.FunctionDef(
expr,
name=fname,
args=ast.arguments(
- args=[], vararg=None, kwarg=None,
+ args=[], vararg=None, kwarg=None, posonlyargs=[],
kwonlyargs=[], kw_defaults=[], defaults=[]),
body=f(parts).stmts,
decorator_list=[])
@@ -1347,18 +1263,17 @@ class HyASTCompiler(object):
">>": ast.RShift,
"|": ast.BitOr,
"^": ast.BitXor,
- "&": ast.BitAnd}
- if PY3:
- m_ops["@"] = ast.MatMult
+ "&": ast.BitAnd,
+ "@": ast.MatMult}
@special(["+", "*", "|"], [many(FORM)])
- @special(["-", "/", "&", (PY3, "@")], [oneplus(FORM)])
+ @special(["-", "/", "&", "@"], [oneplus(FORM)])
@special(["**", "//", "<<", ">>"], [times(2, Inf, FORM)])
@special(["%", "^"], [times(2, 2, FORM)])
def compile_maths_expression(self, expr, root, args):
if len(args) == 0:
# Return the identity element for this operator.
- return asty.Num(expr, n=long_type(
+ return asty.Num(expr, n=(
{"+": 0, "|": 0, "*": 1}[root]))
if len(args) == 1:
@@ -1411,9 +1326,7 @@ class HyASTCompiler(object):
def _compile_assign(self, root, name, result):
str_name = "%s" % name
- if str_name in (["None"] + (["True", "False"] if PY3 else [])):
- # Python 2 allows assigning to True and False, although
- # this is rarely wise.
+ if str_name in ("None", "True", "False"):
raise self._syntax_error(name,
"Can't assign to `%s'" % str_name)
@@ -1477,13 +1390,12 @@ class HyASTCompiler(object):
expr, test=cond_compiled.force_expr,
body=body.stmts or [asty.Pass(expr)],
orelse=orel.stmts)
- ret.contains_yield = body.contains_yield
return ret
NASYM = some(lambda x: isinstance(x, HySymbol) and x not in (
"&optional", "&rest", "&kwonly", "&kwargs"))
- @special(["fn", "fn*", (PY3, "fn/a")], [
+ @special(["fn", "fn*", "fn/a"], [
# The starred version is for internal use (particularly, in the
# definition of `defn`). It ensures that a FunctionDef is
# produced rather than a Lambda.
@@ -1501,29 +1413,19 @@ class HyASTCompiler(object):
mandatory, optional, rest, kwonly, kwargs = params
optional, defaults, ret = self._parse_optional_args(optional)
- if kwonly is not None and not PY3:
- raise self._syntax_error(params,
- "&kwonly parameters require Python 3")
kwonly, kw_defaults, ret2 = self._parse_optional_args(kwonly, True)
ret += ret2
main_args = mandatory + optional
- if PY3:
- # Python 3.4+ requires that args are an ast.arg object, rather
- # than an ast.Name or bare string.
- main_args, kwonly, [rest], [kwargs] = (
- [[x and asty.arg(x, arg=ast_str(x), annotation=None)
- for x in o]
- for o in (main_args or [], kwonly or [], [rest], [kwargs])])
- else:
- main_args = [asty.Name(x, id=ast_str(x), ctx=ast.Param())
- for x in main_args]
- rest = rest and ast_str(rest)
- kwargs = kwargs and ast_str(kwargs)
+ main_args, kwonly, [rest], [kwargs] = (
+ [[x and asty.arg(x, arg=ast_str(x), annotation=None)
+ for x in o]
+ for o in (main_args or [], kwonly or [], [rest], [kwargs])])
args = ast.arguments(
args=main_args, defaults=defaults,
vararg=rest,
+ posonlyargs=[],
kwonlyargs=kwonly, kw_defaults=kw_defaults,
kwarg=kwargs)
@@ -1533,13 +1435,7 @@ class HyASTCompiler(object):
return ret + asty.Lambda(expr, args=args, body=body.force_expr)
if body.expr:
- if body.contains_yield and not PY3:
- # Prior to PEP 380 (introduced in Python 3.3)
- # generators may not have a value in a return
- # statement.
- body += body.expr_as_stmt()
- else:
- body += asty.Return(body.expr, value=body.expr)
+ body += asty.Return(body.expr, value=body.expr)
name = self.get_anon_var()
@@ -1585,7 +1481,7 @@ class HyASTCompiler(object):
base_list, docstring, attrs, body = rest or ([[]], None, None, [])
bases_expr, bases, keywords = (
- self._compile_collect(base_list[0], with_kwargs=PY3))
+ self._compile_collect(base_list[0], with_kwargs=True))
bodyr = Result()
@@ -1754,16 +1650,14 @@ class HyASTCompiler(object):
# a typecheck, eg (type :foo)
with_kwargs = root not in (
"type", "HyKeyword", "keyword", "name", "keyword?", "identity")
- args, ret, keywords, oldpy_star, oldpy_kw = self._compile_collect(
- args, with_kwargs, oldpy_unpack=True)
+ args, ret, keywords = self._compile_collect(args, with_kwargs)
return func + ret + asty.Call(
- expr, func=func.expr, args=args, keywords=keywords,
- starargs=oldpy_star, kwargs=oldpy_kw)
+ expr, func=func.expr, args=args, keywords=keywords)
@builds_model(HyInteger, HyFloat, HyComplex)
def compile_numeric_literal(self, x):
- f = {HyInteger: long_type,
+ f = {HyInteger: int,
HyFloat: float,
HyComplex: complex}[type(x)]
return asty.Num(x, n=f(x))
@@ -1810,9 +1704,9 @@ class HyASTCompiler(object):
def compile_string(self, string):
if type(string) is HyString and string.is_format:
# This is a format string (a.k.a. an f-string).
- return self._format_string(string, str_type(string))
- node = asty.Bytes if PY3 and type(string) is HyBytes else asty.Str
- f = bytes_type if type(string) is HyBytes else str_type
+ return self._format_string(string, str(string))
+ node = asty.Bytes if type(string) is HyBytes else asty.Str
+ f = bytes if type(string) is HyBytes else str
return node(string, s=f(string))
def _format_string(self, string, rest, allow_recursion=True):
@@ -1859,7 +1753,7 @@ class HyASTCompiler(object):
try:
model, item = parse_one_thing(item)
except (ValueError, LexException) as e:
- raise self._syntax_error(string, "f-string: " + str_type(e))
+ raise self._syntax_error(string, "f-string: " + str(e))
# Look for a conversion character.
item = item.lstrip()
@@ -1933,7 +1827,7 @@ def get_compiler_module(module=None, compiler=None, calling_frame=False):
module = getattr(compiler, 'module', None) or module
- if isinstance(module, string_types):
+ if isinstance(module, str):
if module.startswith('<') and module.endswith('>'):
module = types.ModuleType(module)
else:
@@ -2098,7 +1992,7 @@ def hy_compile(tree, module, root=ast.Module, get_expr=False,
"""
module = get_compiler_module(module, compiler, False)
- if isinstance(module, string_types):
+ if isinstance(module, str):
if module.startswith('<') and module.endswith('>'):
module = types.ModuleType(module)
else:
diff --git a/hy/completer.py b/hy/completer.py
index 38cf8eb..b1969c1 100644
--- a/hy/completer.py
+++ b/hy/completer.py
@@ -6,10 +6,10 @@ import contextlib
import os
import re
import sys
+import builtins
import hy.macros
import hy.compiler
-from hy._compat import builtins, string_types
docomplete = True
@@ -78,7 +78,7 @@ class Completer(object):
matches = []
for p in self.path:
for k in p.keys():
- if isinstance(k, string_types):
+ if isinstance(k, str):
k = k.replace("_", "-")
if k.startswith(text):
matches.append(k)
@@ -89,7 +89,7 @@ class Completer(object):
matches = []
for p in self.tag_path:
for k in p.keys():
- if isinstance(k, string_types):
+ if isinstance(k, str):
if k.startswith(text):
matches.append("#{}".format(k))
return matches
diff --git a/hy/contrib/hy_repr.hy b/hy/contrib/hy_repr.hy
index c99a45a..3baaebb 100644
--- a/hy/contrib/hy_repr.hy
+++ b/hy/contrib/hy_repr.hy
@@ -7,7 +7,7 @@
re
datetime
collections
- [hy._compat [PY3 PY36 str-type bytes-type long-type]]
+ [hy._compat [PY36]]
[hy.models [HyObject HyExpression HySymbol HyKeyword HyInteger HyFloat HyComplex HyList HyDict HySet HyString HyBytes]])
(try
@@ -84,10 +84,10 @@
(+ "(" (-cat x) ")"))))
(hy-repr-register [HySymbol HyKeyword] str)
-(hy-repr-register [str-type bytes-type] (fn [x]
+(hy-repr-register [str bytes] (fn [x]
(setv r (.lstrip (-base-repr x) "ub"))
(+
- (if (instance? bytes-type x) "b" "")
+ (if (instance? bytes x) "b" "")
(if (.startswith "\"" r)
; If Python's built-in repr produced a double-quoted string, use
; that.
@@ -96,10 +96,6 @@
; convert it.
(+ "\"" (.replace (cut r 1 -1) "\"" "\\\"") "\"")))))
(hy-repr-register bool str)
-(if (not PY3) (hy-repr-register int (fn [x]
- (.format "(int {})" (-base-repr x)))))
-(if (not PY3) (hy-repr-register long_type (fn [x]
- (.rstrip (-base-repr x) "L"))))
(hy-repr-register float (fn [x]
(if
(isnan x) "NaN"
@@ -131,7 +127,7 @@
(-repr-time-innards x))))
(defn -repr-time-innards [x]
(.rstrip (+ " " (.join " " (filter identity [
- (if x.microsecond (str-type x.microsecond))
+ (if x.microsecond (str x.microsecond))
(if (not (none? x.tzinfo)) (+ ":tzinfo " (hy-repr x.tzinfo)))
(if (and PY36 (!= x.fold 0)) (+ ":fold " (hy-repr x.fold)))])))))
(defn -strftime-0 [x fmt]
diff --git a/hy/contrib/profile.hy b/hy/contrib/profile.hy
index 8ff2ed6..cea3435 100644
--- a/hy/contrib/profile.hy
+++ b/hy/contrib/profile.hy
@@ -19,9 +19,7 @@
`(do
(import cProfile pstats)
- (if-python2
- (import [StringIO [StringIO]])
- (import [io [StringIO]]))
+ (import [io [StringIO]])
(setv ~g!hy-pr (.Profile cProfile))
(.enable ~g!hy-pr)
diff --git a/hy/core/bootstrap.hy b/hy/core/bootstrap.hy
index 0d3d737..d5b7e19 100644
--- a/hy/core/bootstrap.hy
+++ b/hy/core/bootstrap.hy
@@ -77,10 +77,3 @@
(if (not (isinstance lambda-list hy.HyList))
(macro-error name "defn/a takes a parameter list as second argument"))
`(setv ~name (fn/a ~lambda-list ~@body)))
-
-(defmacro if-python2 [python2-form python3-form]
- "If running on python2, execute python2-form, else, execute python3-form"
- (import sys)
- (if (< (get sys.version_info 0) 3)
- python2-form
- python3-form))
diff --git a/hy/core/language.hy b/hy/core/language.hy
index 53af7fb..80cba83 100644
--- a/hy/core/language.hy
+++ b/hy/core/language.hy
@@ -11,7 +11,7 @@
(import [fractions [Fraction :as fraction]])
(import operator) ; shadow not available yet
(import sys)
-(import [hy._compat [long-type]]) ; long for python2, int for python3
+(import [collections.abc :as cabc])
(import [hy.models [HySymbol HyKeyword]])
(import [hy.lex [tokenize mangle unmangle read read-str]])
(import [hy.lex.exceptions [LexException PrematureEndOfInput]])
@@ -21,10 +21,6 @@
(require [hy.core.bootstrap [*]])
-(if-python2
- (import [collections :as cabc])
- (import [collections.abc :as cabc]))
-
(defn butlast [coll]
"Return an iterator of all but the last item in `coll`."
(drop-last 1 coll))
@@ -86,47 +82,12 @@ If the second argument `codegen` is true, generate python code instead."
(yield val)
(.add seen val)))))
-(if-python2
- (setv
- remove itertools.ifilterfalse
- zip-longest itertools.izip_longest
- ;; not builtin in Python3
- reduce reduce
- ;; hy is more like Python3
- filter itertools.ifilter
- input raw_input
- map itertools.imap
- range xrange
- zip itertools.izip)
- (setv
- remove itertools.filterfalse
- zip-longest itertools.zip_longest
- ;; was builtin in Python2
- reduce functools.reduce
- ;; Someone can import these directly from `hy.core.language`;
- ;; we'll make some duplicates.
- filter filter
- input input
- map map
- range range
- zip zip))
-
-(if-python2
- (defn exec [$code &optional $globals $locals]
- "Execute Python code.
-
-The parameter names contain weird characters to discourage calling this
-function with keyword arguments, which isn't supported by Python 3's `exec`."
- (if
- (none? $globals) (do
- (setv frame (._getframe sys (int 1)))
- (try
- (setv $globals frame.f_globals $locals frame.f_locals)
- (finally (del frame))))
- (none? $locals)
- (setv $locals $globals))
- (exec* $code $globals $locals))
- (setv exec exec))
+(setv
+ remove itertools.filterfalse
+ zip-longest itertools.zip_longest
+ ;; was builtin in Python2
+ reduce functools.reduce
+ accumulate itertools.accumulate)
;; infinite iterators
(setv
@@ -152,18 +113,6 @@ function with keyword arguments, which isn't supported by Python 3's `exec`."
permutations itertools.permutations
product itertools.product)
-;; also from itertools, but not in Python2, and without func option until 3.3
-(defn accumulate [iterable &optional [func operator.add]]
- "Accumulate `func` on `iterable`.
-
-Return series of accumulated sums (or other binary function results)."
- (setv it (iter iterable)
- total (next it))
- (yield total)
- (for [element it]
- (setv total (func total element))
- (yield total)))
-
(defn drop [count coll]
"Drop `count` elements from `coll` and yield back the rest."
(islice coll count None))
@@ -252,13 +201,9 @@ Return series of accumulated sums (or other binary function results)."
"Perform `isinstance` with reversed arguments."
(isinstance x klass))
-(defn integer [x]
- "Return Hy kind of integer for `x`."
- (long-type x))
-
(defn integer? [x]
"Check if `x` is an integer."
- (isinstance x (, int long-type)))
+ (isinstance x int))
(defn integer-char? [x]
"Check if char `x` parses as an integer."
@@ -388,17 +333,9 @@ with overlap."
"Return the first logical true value of applying `pred` in `coll`, else None."
(first (filter None (map pred coll))))
-(defn string [x]
- "Cast `x` as the current python version's string implementation."
- (if-python2
- (unicode x)
- (str x)))
-
(defn string? [x]
"Check if `x` is a string."
- (if-python2
- (isinstance x (, str unicode))
- (isinstance x str)))
+ (isinstance x str))
(defn take [count coll]
"Take `count` elements from `coll`."
@@ -433,7 +370,7 @@ Strings numbers and even objects with the __name__ magic will work."
(HyKeyword (unmangle value))
(try
(unmangle (.__name__ value))
- (except [] (HyKeyword (string value)))))))
+ (except [] (HyKeyword (str value)))))))
(defn name [value]
"Convert `value` to a string.
@@ -446,7 +383,7 @@ Even objects with the __name__ magic will work."
(unmangle value)
(try
(unmangle (. value __name__))
- (except [] (string value))))))
+ (except [] (str value))))))
(defn xor [a b]
"Perform exclusive or between `a` and `b`."
@@ -457,11 +394,11 @@ Even objects with the __name__ magic will work."
(setv EXPORTS
'[*map accumulate butlast calling-module calling-module-name chain coll?
combinations comp complement compress constantly count cycle dec distinct
- disassemble drop drop-last drop-while empty? eval even? every? exec first
- filter flatten float? fraction gensym group-by identity inc input instance?
- integer integer? integer-char? interleave interpose islice iterable?
+ disassemble drop drop-last drop-while empty? eval even? every? first
+ flatten float? fraction gensym group-by identity inc instance?
+ integer? integer-char? interleave interpose islice iterable?
iterate iterator? juxt keyword keyword? last list? macroexpand
- macroexpand-1 mangle map merge-with multicombinations name neg? none? nth
- numeric? odd? partition permutations pos? product range read read-str
- remove repeat repeatedly rest reduce second some string string? symbol?
- take take-nth take-while tuple? unmangle xor tee zero? zip zip-longest])
+ macroexpand-1 mangle merge-with multicombinations name neg? none? nth
+ numeric? odd? partition permutations pos? product read read-str
+ remove repeat repeatedly rest reduce second some string? symbol?
+ take take-nth take-while tuple? unmangle xor tee zero? zip-longest])
diff --git a/hy/core/shadow.hy b/hy/core/shadow.hy
index 2135400..74ab08f 100644
--- a/hy/core/shadow.hy
+++ b/hy/core/shadow.hy
@@ -5,12 +5,10 @@
;;;; Hy shadow functions
(import operator)
-(import [hy._compat [PY3]])
(require [hy.core.bootstrap [*]])
-(if PY3
- (import [functools [reduce]]))
+(import [functools [reduce]])
(defn + [&rest args]
"Shadowed `+` operator adds `args`."
@@ -60,10 +58,9 @@
"Shadowed `%` operator takes `x` modulo `y`."
(% x y))
-(if PY3
- (defn @ [a1 &rest a-rest]
- "Shadowed `@` operator matrix multiples `a1` by each `a-rest`."
- (reduce operator.matmul a-rest a1)))
+(defn @ [a1 &rest a-rest]
+ "Shadowed `@` operator matrix multiples `a1` by each `a-rest`."
+ (reduce operator.matmul a-rest a1))
(defn << [a1 a2 &rest a-rest]
"Shadowed `<<` operator performs left-shift on `a1` by `a2`, ..., `a-rest`."
@@ -173,5 +170,3 @@
'and 'or 'not
'is 'is-not 'in 'not-in
'get])
-(if (not PY3)
- (.remove EXPORTS '@))
diff --git a/hy/importer.py b/hy/importer.py
index 6d31004..f54803d 100644
--- a/hy/importer.py
+++ b/hy/importer.py
@@ -19,33 +19,6 @@ from contextlib import contextmanager
from hy.compiler import hy_compile, hy_ast_compile_flags
from hy.lex import hy_parse
-from hy._compat import PY3
-
-
-def cache_from_source(source_path):
- """Get the cached bytecode file name for a given source file name.
-
- This function's name is set to mirror Python 3.x's
- `importlib.util.cache_from_source`, which is also used when available.
-
- Parameters
- ----------
- source_path : str
- Path of the source file
-
- Returns
- -------
- out : str
- Path of the corresponding bytecode file that may--or may
- not--actually exist.
- """
- if PY3:
- return importlib.util.cache_from_source(source_path)
- else:
- # If source_path has a file extension, replace it with ".pyc".
- # Otherwise, just append ".pyc".
- d, f = os.path.split(source_path)
- return os.path.join(d, re.sub(r"(?:\.[^.]+)?\Z", ".pyc", f))
@contextmanager
@@ -135,370 +108,41 @@ def _get_code_from_file(run_name, fname=None,
source = f.read().decode('utf-8')
code = compile(source, fname, 'exec')
- return (code, fname) if PY3 else code
+ return (code, fname)
-if PY3:
- importlib.machinery.SOURCE_SUFFIXES.insert(0, '.hy')
- _py_source_to_code = importlib.machinery.SourceFileLoader.source_to_code
+importlib.machinery.SOURCE_SUFFIXES.insert(0, '.hy')
+_py_source_to_code = importlib.machinery.SourceFileLoader.source_to_code
- def _could_be_hy_src(filename):
- return (os.path.isfile(filename) and
- (filename.endswith('.hy') or
- not any(filename.endswith(ext)
- for ext in importlib.machinery.SOURCE_SUFFIXES[1:])))
+def _could_be_hy_src(filename):
+ return (os.path.isfile(filename) and
+ (filename.endswith('.hy') or
+ not any(filename.endswith(ext)
+ for ext in importlib.machinery.SOURCE_SUFFIXES[1:])))
- def _hy_source_to_code(self, data, path, _optimize=-1):
- if _could_be_hy_src(path):
- source = data.decode("utf-8")
- hy_tree = hy_parse(source, filename=path)
- with loader_module_obj(self) as module:
- data = hy_compile(hy_tree, module)
+def _hy_source_to_code(self, data, path, _optimize=-1):
+ if _could_be_hy_src(path):
+ source = data.decode("utf-8")
+ hy_tree = hy_parse(source, filename=path)
+ with loader_module_obj(self) as module:
+ data = hy_compile(hy_tree, module)
- return _py_source_to_code(self, data, path, _optimize=_optimize)
+ return _py_source_to_code(self, data, path, _optimize=_optimize)
- importlib.machinery.SourceFileLoader.source_to_code = _hy_source_to_code
+importlib.machinery.SourceFileLoader.source_to_code = _hy_source_to_code
- # This is actually needed; otherwise, pre-created finders assigned to the
- # current dir (i.e. `''`) in `sys.path` will not catch absolute imports of
- # directory-local modules!
- sys.path_importer_cache.clear()
+# This is actually needed; otherwise, pre-created finders assigned to the
+# current dir (i.e. `''`) in `sys.path` will not catch absolute imports of
+# directory-local modules!
+sys.path_importer_cache.clear()
- # Do this one just in case?
- importlib.invalidate_caches()
-
- # XXX: These and the 2.7 counterparts below aren't truly cross-compliant.
- # They're useful for testing, though.
- HyImporter = importlib.machinery.FileFinder
- HyLoader = importlib.machinery.SourceFileLoader
-
-else:
- import imp
- import py_compile
- import marshal
- import struct
- import traceback
-
- from pkgutil import ImpImporter, ImpLoader
-
- def _could_be_hy_src(filename):
- return (filename.endswith('.hy') or
- (os.path.isfile(filename) and
- not any(filename.endswith(s[0]) for s in imp.get_suffixes())))
-
- class HyLoader(ImpLoader, object):
- def __init__(self, fullname, filename, fileobj=None, etc=None):
- """This constructor is designed for some compatibility with
- SourceFileLoader."""
- if etc is None and filename is not None:
- if _could_be_hy_src(filename):
- etc = ('.hy', 'U', imp.PY_SOURCE)
- if fileobj is None:
- fileobj = io.open(filename, 'rU', encoding='utf-8')
-
- super(HyLoader, self).__init__(fullname, fileobj, filename, etc)
-
- def __getattr__(self, item):
- # We add these for Python >= 3.4 Loader interface compatibility.
- if item == 'path':
- return self.filename
- elif item == 'name':
- return self.fullname
- else:
- return super(HyLoader, self).__getattr__(item)
-
- def exec_module(self, module, fullname=None):
- fullname = self._fix_name(fullname)
- code = self.get_code(fullname)
- eval(code, module.__dict__)
-
- def load_module(self, fullname=None):
- """Same as `pkgutil.ImpLoader`, with an extra check for Hy
- source and the option to not run `self.exec_module`."""
- fullname = self._fix_name(fullname)
- ext_type = self.etc[0]
- mod_type = self.etc[2]
- mod = None
- pkg_path = os.path.join(self.filename, '__init__.hy')
- if ext_type == '.hy' or (
- mod_type == imp.PKG_DIRECTORY and
- os.path.isfile(pkg_path)):
-
- was_in_sys = fullname in sys.modules
- if was_in_sys:
- mod = sys.modules[fullname]
- else:
- mod = sys.modules.setdefault(
- fullname, types.ModuleType(fullname))
-
- # TODO: Should we set these only when not in `sys.modules`?
- if mod_type == imp.PKG_DIRECTORY:
- mod.__file__ = pkg_path
- mod.__path__ = [self.filename]
- mod.__package__ = fullname
- else:
- # mod.__path__ = self.filename
- mod.__file__ = self.get_filename(fullname)
- mod.__package__ = '.'.join(fullname.split('.')[:-1])
-
- mod.__name__ = fullname
-
- try:
- self.exec_module(mod, fullname=fullname)
- except Exception:
- # Follow Python 2.7 logic and only remove a new, bad
- # module; otherwise, leave the old--and presumably
- # good--module in there.
- if not was_in_sys:
- del sys.modules[fullname]
- raise
-
- if mod is None:
- self._reopen()
- try:
- mod = imp.load_module(fullname, self.file, self.filename,
- self.etc)
- finally:
- if self.file:
- self.file.close()
-
- mod.__loader__ = self
- return mod
-
- def _reopen(self):
- """Same as `pkgutil.ImpLoader`, with an extra check for Hy
- source"""
- if self.file and self.file.closed:
- ext_type = self.etc[0]
- if ext_type == '.hy':
- self.file = io.open(self.filename, 'rU', encoding='utf-8')
- else:
- super(HyLoader, self)._reopen()
-
- def byte_compile_hy(self, fullname=None):
- fullname = self._fix_name(fullname)
- if fullname is None:
- fullname = self.fullname
-
- hy_source = self.get_source(fullname)
- hy_tree = hy_parse(hy_source, filename=self.filename)
-
- with loader_module_obj(self) as module:
- hy_ast = hy_compile(hy_tree, module)
-
- code = compile(hy_ast, self.filename, 'exec',
- hy_ast_compile_flags)
-
- if not sys.dont_write_bytecode:
- try:
- hyc_compile(code, module=fullname)
- except IOError:
- pass
- return code
-
- def get_code(self, fullname=None):
- """Same as `pkgutil.ImpLoader`, with an extra check for Hy
- source"""
- fullname = self._fix_name(fullname)
- ext_type = self.etc[0]
- if ext_type == '.hy':
- # Looks like we have to manually check for--and update--
- # the bytecode.
- t_py = long(os.stat(self.filename).st_mtime)
- pyc_file = cache_from_source(self.filename)
- if os.path.isfile(pyc_file):
- t_pyc = long(os.stat(pyc_file).st_mtime)
-
- if t_pyc is not None and t_pyc >= t_py:
- with open(pyc_file, 'rb') as f:
- if f.read(4) == imp.get_magic():
- t = struct.unpack(' 1
+ if isinstance(number, str) and len(number) > 1
else number)
-class HyInteger(HyObject, long_type):
+class HyInteger(HyObject, int):
"""
Internal representation of a Hy Integer. May raise a ValueError as if
- int(foo) was called, given HyInteger(foo). On python 2.x long will
- be used instead
+ int(foo) was called, given HyInteger(foo).
"""
def __new__(cls, number, *args, **kwargs):
- if isinstance(number, string_types):
+ if isinstance(number, str):
number = strip_digit_separators(number)
bases = {"0x": 16, "0o": 8, "0b": 2}
for leader, base in bases.items():
if number.startswith(leader):
# We've got a string, known leader, set base.
- number = long_type(number, base=base)
+ number = int(number, base=base)
break
else:
# We've got a string, no known leader; base 10.
- number = long_type(number, base=10)
+ number = int(number, base=10)
else:
# We've got a non-string; convert straight.
- number = long_type(number)
+ number = int(number)
return super(HyInteger, cls).__new__(cls, number)
_wrappers[int] = HyInteger
-if not PY3: # do not add long on python3
- _wrappers[long_type] = HyInteger
def check_inf_nan_cap(arg, value):
- if isinstance(arg, string_types):
+ if isinstance(arg, str):
if isinf(value) and "i" in arg.lower() and "Inf" not in arg:
raise ValueError('Inf must be capitalized as "Inf"')
if isnan(value) and "NaN" not in arg:
@@ -233,7 +229,7 @@ class HyComplex(HyObject, complex):
"""
def __new__(cls, real, imag=0, *args, **kwargs):
- if isinstance(real, string_types):
+ if isinstance(real, str):
value = super(HyComplex, cls).__new__(
cls, strip_digit_separators(real)
)
diff --git a/setup.py b/setup.py
index 71afe86..bd6718e 100755
--- a/setup.py
+++ b/setup.py
@@ -80,8 +80,6 @@ setup(
"Operating System :: OS Independent",
"Programming Language :: Lisp",
"Programming Language :: Python",
- "Programming Language :: Python :: 2",
- "Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
diff --git a/tests/compilers/test_ast.py b/tests/compilers/test_ast.py
index 9d004da..70ac563 100644
--- a/tests/compilers/test_ast.py
+++ b/tests/compilers/test_ast.py
@@ -10,7 +10,7 @@ from hy.compiler import hy_compile, hy_eval
from hy.errors import HyCompileError, HyLanguageError, HyError
from hy.lex import hy_parse
from hy.lex.exceptions import LexException, PrematureEndOfInput
-from hy._compat import PY3, PY36
+from hy._compat import PY36
import ast
import pytest
@@ -121,9 +121,8 @@ def test_ast_good_raise():
can_compile("(raise e)")
-if PY3:
- def test_ast_raise_from():
- can_compile("(raise Exception :from NameError)")
+def test_ast_raise_from():
+ can_compile("(raise Exception :from NameError)")
def test_ast_bad_raise():
@@ -205,16 +204,16 @@ def test_ast_bad_global():
cant_compile("(global (foo))")
-if PY3:
- def test_ast_good_nonlocal():
- "Make sure AST can compile valid nonlocal"
- can_compile("(nonlocal a)")
- can_compile("(nonlocal foo bar)")
+def test_ast_good_nonlocal():
+ "Make sure AST can compile valid nonlocal"
+ can_compile("(nonlocal a)")
+ can_compile("(nonlocal foo bar)")
- def test_ast_bad_nonlocal():
- "Make sure AST can't compile invalid nonlocal"
- cant_compile("(nonlocal)")
- cant_compile("(nonlocal (foo))")
+
+def test_ast_bad_nonlocal():
+ "Make sure AST can't compile invalid nonlocal"
+ cant_compile("(nonlocal)")
+ cant_compile("(nonlocal (foo))")
def test_ast_good_defclass():
@@ -226,7 +225,6 @@ def test_ast_good_defclass():
can_compile("(defclass a [] None (print \"foo\"))")
-@pytest.mark.skipif(not PY3, reason="Python 3 supports class keywords")
def test_ast_good_defclass_with_metaclass():
"Make sure AST can compile valid defclass with keywords"
can_compile("(defclass a [:metaclass b])")
@@ -299,21 +297,6 @@ import a dotted name."""
cant_compile("(require [spam [foo.bar]])")
-def test_ast_no_pointless_imports():
- def contains_import_from(code):
- return any([isinstance(node, ast.ImportFrom)
- for node in can_compile(code).body])
- # `reduce` is a builtin in Python 2, but not Python 3.
- # The version of `map` that returns an iterator is a builtin in
- # Python 3, but not Python 2.
- if PY3:
- assert contains_import_from("reduce")
- assert not contains_import_from("map")
- else:
- assert not contains_import_from("reduce")
- assert contains_import_from("map")
-
-
def test_ast_good_get():
"Make sure AST can compile valid get"
can_compile("(get x y)")
@@ -454,29 +437,20 @@ def test_lambda_list_keywords_kwargs():
def test_lambda_list_keywords_kwonly():
- """Ensure we can compile functions with &kwonly if we're on Python
- 3, or fail with an informative message on Python 2."""
kwonly_demo = "(fn [&kwonly a [b 2]] (print 1) (print a b))"
- if PY3:
- code = can_compile(kwonly_demo)
- for i, kwonlyarg_name in enumerate(('a', 'b')):
- assert kwonlyarg_name == code.body[0].args.kwonlyargs[i].arg
- assert code.body[0].args.kw_defaults[0] is None
- assert code.body[0].args.kw_defaults[1].n == 2
- else:
- exception = cant_compile(kwonly_demo)
- assert isinstance(exception, HyLanguageError)
- message = exception.args[0]
- assert message == "&kwonly parameters require Python 3"
+ code = can_compile(kwonly_demo)
+ for i, kwonlyarg_name in enumerate(('a', 'b')):
+ assert kwonlyarg_name == code.body[0].args.kwonlyargs[i].arg
+ assert code.body[0].args.kw_defaults[0] is None
+ assert code.body[0].args.kw_defaults[1].n == 2
def test_lambda_list_keywords_mixed():
""" Ensure we can mix them up."""
can_compile("(fn [x &rest xs &kwargs kw] (list x xs kw))")
cant_compile("(fn [x &rest xs &fasfkey {bar \"baz\"}])")
- if PY3:
- can_compile("(fn [x &rest xs &kwonly kwoxs &kwargs kwxs]"
- " (list x xs kwxs kwoxs))")
+ can_compile("(fn [x &rest xs &kwonly kwoxs &kwargs kwxs]"
+ " (list x xs kwxs kwoxs))")
def test_missing_keyword_argument_value():
@@ -504,11 +478,11 @@ def test_ast_unicode_strings():
def test_ast_unicode_vs_bytes():
- assert s('"hello"') == u"hello"
- assert type(s('"hello"')) is (str if PY3 else unicode) # noqa
- assert s('b"hello"') == (eval('b"hello"') if PY3 else "hello")
- assert type(s('b"hello"')) is (bytes if PY3 else str)
- assert s('b"\\xa0"') == (bytes([160]) if PY3 else chr(160))
+ assert s('"hello"') == "hello"
+ assert type(s('"hello"')) is str
+ assert s('b"hello"') == b"hello"
+ assert type(s('b"hello"')) is bytes
+ assert s('b"\\xa0"') == bytes([160])
@pytest.mark.skipif(not PY36, reason='f-strings require Python 3.6+')
@@ -528,7 +502,7 @@ def test_ast_bracket_string():
assert s(r'#[my delim[fizzle]my delim]') == 'fizzle'
assert s(r'#[[]]') == ''
assert s(r'#[my delim[]my delim]') == ''
- assert type(s('#[X[hello]X]')) is (str if PY3 else unicode) # noqa
+ assert type(s('#[X[hello]X]')) is str
assert s(r'#[X[raw\nstring]X]') == 'raw\\nstring'
assert s(r'#[foozle[aa foozli bb ]foozle]') == 'aa foozli bb '
assert s(r'#[([unbalanced](]') == 'unbalanced'
@@ -623,30 +597,6 @@ def test_lots_of_comment_lines():
can_compile(1000 * ";\n")
-def test_exec_star():
-
- code = can_compile('(exec* "print(5)")').body[0]
- assert type(code) == (ast.Expr if PY3 else ast.Exec)
- if not PY3:
- assert code.body.s == "print(5)"
- assert code.globals is None
- assert code.locals is None
-
- code = can_compile('(exec* "print(a)" {"a" 3})').body[0]
- assert type(code) == (ast.Expr if PY3 else ast.Exec)
- if not PY3:
- assert code.body.s == "print(a)"
- assert code.globals.keys[0].s == "a"
- assert code.locals is None
-
- code = can_compile('(exec* "print(a + b)" {"a" "x"} {"b" "y"})').body[0]
- assert type(code) == (ast.Expr if PY3 else ast.Exec)
- if not PY3:
- assert code.body.s == "print(a + b)"
- assert code.globals.keys[0].s == "a"
- assert code.locals.keys[0].s == "b"
-
-
def test_compiler_macro_tag_try():
"""Check that try forms within defmacro/deftag are compiled correctly"""
# https://github.com/hylang/hy/issues/1350
@@ -654,13 +604,11 @@ def test_compiler_macro_tag_try():
can_compile("(deftag foo [] (try None (except [] None)) `())")
-@pytest.mark.skipif(not PY3, reason="Python 3 required")
def test_ast_good_yield_from():
"Make sure AST can compile valid yield-from"
can_compile("(yield-from [1 2])")
-@pytest.mark.skipif(not PY3, reason="Python 3 required")
def test_ast_bad_yield_from():
"Make sure AST can't compile invalid yield-from"
cant_compile("(yield-from)")
diff --git a/tests/compilers/test_compiler.py b/tests/compilers/test_compiler.py
index bbb2970..9648c8f 100644
--- a/tests/compilers/test_compiler.py
+++ b/tests/compilers/test_compiler.py
@@ -6,7 +6,6 @@ import ast
from hy import compiler
from hy.models import HyExpression, HyList, HySymbol, HyInteger
-from hy._compat import PY3
def make_expression(*args):
@@ -64,12 +63,5 @@ def test_compiler_yield_return():
assert len(body) == 2
assert isinstance(body[0], ast.Expr)
assert isinstance(body[0].value, ast.Yield)
-
- if PY3:
- # From 3.3+, the final statement becomes a return value
- assert isinstance(body[1], ast.Return)
- assert isinstance(body[1].value, ast.BinOp)
- else:
- # In earlier versions, the expression is not returned
- assert isinstance(body[1], ast.Expr)
- assert isinstance(body[1].value, ast.BinOp)
+ assert isinstance(body[1], ast.Return)
+ assert isinstance(body[1].value, ast.BinOp)
diff --git a/tests/importer/test_importer.py b/tests/importer/test_importer.py
index dea1baf..a823c41 100644
--- a/tests/importer/test_importer.py
+++ b/tests/importer/test_importer.py
@@ -18,7 +18,7 @@ from hy.lex import hy_parse
from hy.errors import HyLanguageError
from hy.lex.exceptions import PrematureEndOfInput
from hy.compiler import hy_eval, hy_compile
-from hy.importer import HyLoader, cache_from_source
+from hy.importer import HyLoader
try:
from importlib import reload
@@ -101,7 +101,7 @@ def test_import_autocompiles():
f.write(b'(defn pyctest [s] (+ "X" s "Y"))')
f.flush()
- pyc_path = cache_from_source(f.name)
+ pyc_path = importlib.util.cache_from_source(f.name)
try:
os.remove(pyc_path)
@@ -144,7 +144,7 @@ def test_reload():
def unlink(filename):
os.unlink(source)
- bytecode = cache_from_source(source)
+ bytecode = importlib.util.cache_from_source(source)
if os.path.isfile(bytecode):
os.unlink(bytecode)
diff --git a/tests/native_tests/comprehensions.hy b/tests/native_tests/comprehensions.hy
index 9d97cbd..206de29 100644
--- a/tests/native_tests/comprehensions.hy
+++ b/tests/native_tests/comprehensions.hy
@@ -1,7 +1,6 @@
(import
types
- pytest
- [hy._compat [PY3]])
+ pytest)
(defn test-comprehension-types []
@@ -134,8 +133,7 @@
; An `lfor` that gets compiled to a real comprehension
(setv x 0)
(assert (= (lfor x [1 2 3] (inc x)) [2 3 4]))
- (assert (= x (if PY3 0 3)))
- ; Python 2 list comprehensions leak their variables.
+ (assert (= x 0))
; An `lfor` that gets compiled to a loop
(setv x 0 l [])
diff --git a/tests/native_tests/contrib/hy_repr.hy b/tests/native_tests/contrib/hy_repr.hy
index 7867181..4a0a1ec 100644
--- a/tests/native_tests/contrib/hy_repr.hy
+++ b/tests/native_tests/contrib/hy_repr.hy
@@ -3,7 +3,7 @@
;; license. See the LICENSE.
(import
- [hy._compat [PY3 PY36 PY37]]
+ [hy._compat [PY36 PY37]]
[math [isnan]]
[hy.contrib.hy-repr [hy-repr hy-repr-register]])
@@ -79,10 +79,10 @@
(assert (is (type (get orig 1)) float))
(assert (is (type (get result 1)) HyFloat)))
-(when PY3 (defn test-dict-views []
+(defn test-dict-views []
(assert (= (hy-repr (.keys {1 2})) "(dict-keys [1])"))
(assert (= (hy-repr (.values {1 2})) "(dict-values [2])"))
- (assert (= (hy-repr (.items {1 2})) "(dict-items [(, 1 2)])"))))
+ (assert (= (hy-repr (.items {1 2})) "(dict-items [(, 1 2)])")))
(defn test-datetime []
(import [datetime :as D])
@@ -91,9 +91,8 @@
"(datetime.datetime 2009 1 15 15 27 5)"))
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 123))
"(datetime.datetime 2009 1 15 15 27 5 123)"))
- (when PY3
- (assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 123 :tzinfo D.timezone.utc))
- "(datetime.datetime 2009 1 15 15 27 5 123 :tzinfo datetime.timezone.utc)")))
+ (assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 123 :tzinfo D.timezone.utc))
+ "(datetime.datetime 2009 1 15 15 27 5 123 :tzinfo datetime.timezone.utc)"))
(when PY36
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 :fold 1))
"(datetime.datetime 2009 1 15 15 27 5 :fold 1)"))
@@ -114,17 +113,11 @@
(defn test-collections []
(import collections)
(assert (= (hy-repr (collections.defaultdict :a 8))
- (if PY3
- "(defaultdict None {\"a\" 8})"
- "(defaultdict None {b\"a\" 8})")))
+ "(defaultdict None {\"a\" 8})"))
(assert (= (hy-repr (collections.defaultdict int :a 8))
- (if PY3
- "(defaultdict {\"a\" 8})"
- "(defaultdict {b\"a\" 8})")))
+ "(defaultdict {\"a\" 8})"))
(assert (= (hy-repr (collections.Counter [15 15 15 15]))
- (if PY3
- "(Counter {15 4})"
- "(Counter {15 (int 4)})")))
+ "(Counter {15 4})"))
(setv C (collections.namedtuple "Fooey" ["cd" "a_b"]))
(assert (= (hy-repr (C 11 12))
"(Fooey :cd 11 :a_b 12)")))
@@ -155,9 +148,8 @@
(setv mo (re.search "b+" "aaaabbbccc"))
(assert (= (hy-repr mo)
(.format
- #[[<{} object; :span {} :match "bbb">]]
- (if PY37 "re.Match" (+ (. (type mo) __module__) ".SRE_Match"))
- (if PY3 "(, 4 7)" "(, (int 4) (int 7))")))))
+ #[[<{} object; :span (, 4 7) :match "bbb">]]
+ (if PY37 "re.Match" (+ (. (type mo) __module__) ".SRE_Match"))))))
(defn test-hy-repr-custom []
diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy
index 39a389c..0618766 100644
--- a/tests/native_tests/core.hy
+++ b/tests/native_tests/core.hy
@@ -2,8 +2,6 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
-(import [hy._compat [PY3]])
-
;;;; some simple helpers
(defn assert-true [x]
@@ -287,7 +285,7 @@ result['y in globals'] = 'y' in globals()")
(setv s3 (gensym "xx"))
(assert (= 0 (.find s2 "_xx\uffff")))
(assert (not (= s2 s3)))
- (assert (not (= (string s2) (string s3)))))
+ (assert (not (= (str s2) (str s3)))))
(defn test-identity []
"NATIVE: testing the identity function"
@@ -324,8 +322,8 @@ result['y in globals'] = 'y' in globals()")
(assert-true (integer? 0))
(assert-true (integer? 3))
(assert-true (integer? -3))
- (assert-true (integer? (integer "-3")))
- (assert-true (integer? (integer 3)))
+ (assert-true (integer? (int "-3")))
+ (assert-true (integer? (int 3)))
(assert-false (integer? 4.2))
(assert-false (integer? None))
(assert-false (integer? "foo")))
@@ -334,7 +332,7 @@ result['y in globals'] = 'y' in globals()")
"NATIVE: testing the integer-char? function"
(assert-true (integer-char? "1"))
(assert-true (integer-char? "-1"))
- (assert-true (integer-char? (str (integer 300))))
+ (assert-true (integer-char? (str (int 300))))
(assert-false (integer-char? "foo"))
(assert-false (integer-char? None)))
@@ -429,8 +427,7 @@ result['y in globals'] = 'y' in globals()")
(assert-true (neg? -2))
(assert-false (neg? 1))
(assert-false (neg? 0))
- (when PY3
- (assert-requires-num neg?)))
+ (assert-requires-num neg?))
(defn test-zero []
"NATIVE: testing the zero? function"
@@ -519,8 +516,7 @@ result['y in globals'] = 'y' in globals()")
(assert-true (pos? 2))
(assert-false (pos? -1))
(assert-false (pos? 0))
- (when PY3
- (assert-requires-num pos?)))
+ (assert-requires-num pos?))
(defn test-remove []
"NATIVE: testing the remove function"
diff --git a/tests/native_tests/extra/reserved.hy b/tests/native_tests/extra/reserved.hy
index ca67577..b1b9c7a 100644
--- a/tests/native_tests/extra/reserved.hy
+++ b/tests/native_tests/extra/reserved.hy
@@ -2,13 +2,12 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
-(import [hy.extra.reserved [names]] [hy._compat [PY3]])
+(import [hy.extra.reserved [names]])
(defn test-reserved []
(assert (is (type (names)) frozenset))
(assert (in "and" (names)))
- (when PY3
- (assert (in "False" (names))))
+ (assert (in "False" (names)))
(assert (in "pass" (names)))
(assert (in "class" (names)))
(assert (in "defclass" (names)))
diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy
index 687376c..5593d01 100644
--- a/tests/native_tests/language.hy
+++ b/tests/native_tests/language.hy
@@ -11,7 +11,7 @@
pytest)
(import sys)
-(import [hy._compat [PY3 PY37 PY38]])
+(import [hy._compat [PY38]])
(defn test-sys-argv []
"NATIVE: test sys.argv"
@@ -71,13 +71,12 @@
(except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))
(try (eval '(defn None [] (print "hello")))
(except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))
- (when PY3
- (try (eval '(setv False 1))
- (except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))
- (try (eval '(setv True 0))
- (except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))
- (try (eval '(defn True [] (print "hello")))
- (except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))))
+ (try (eval '(setv False 1))
+ (except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))
+ (try (eval '(setv True 0))
+ (except [e [SyntaxError]] (assert (in "Can't assign to" (str e)))))
+ (try (eval '(defn True [] (print "hello")))
+ (except [e [SyntaxError]] (assert (in "Can't assign to" (str e))))))
(defn test-setv-pairs []
@@ -513,9 +512,7 @@
(setv passed False)
(try
(raise)
- ;; Python 2 raises IndexError here (due to the previous test)
- ;; Python 3 raises RuntimeError
- (except [[IndexError RuntimeError]]
+ (except [RuntimeError]
(setv passed True)))
(assert passed)
@@ -747,16 +744,11 @@
(defn test-yield-with-return []
"NATIVE: test yield with return"
(defn gen [] (yield 3) "goodbye")
- (if PY3
- (do (setv gg (gen))
- (assert (= 3 (next gg)))
- (try (next gg)
- (except [e StopIteration] (assert (hasattr e "value"))
- (assert (= (getattr e "value") "goodbye")))))
- (do (setv gg (gen))
- (assert (= 3 (next gg)))
- (try (next gg)
- (except [e StopIteration] (assert (not (hasattr e "value"))))))))
+ (setv gg (gen))
+ (assert (= 3 (next gg)))
+ (try (next gg)
+ (except [e StopIteration] (assert (hasattr e "value"))
+ (assert (= (getattr e "value") "goodbye")))))
(defn test-yield-in-try []
@@ -1242,19 +1234,14 @@ cee\"} dee" "ey bee\ncee dee"))
; Conversion characters and format specifiers
(setv p:9 "other")
(setv !r "bar")
- (defn u [s]
- ; Add a "u" prefix for Python 2.
- (if PY3
- s
- (.replace (.replace s "'" "u'" 1) " " " " 1)))
- (assert (= f"a{p !r}" (u "a'xyzzy'")))
+ (assert (= f"a{p !r}" "a'xyzzy'"))
(assert (= f"a{p :9}" "axyzzy "))
(assert (= f"a{p:9}" "aother"))
- (assert (= f"a{p !r :9}" (u "a'xyzzy' ")))
- (assert (= f"a{p !r:9}" (u "a'xyzzy' ")))
+ (assert (= f"a{p !r :9}" "a'xyzzy' "))
+ (assert (= f"a{p !r:9}" "a'xyzzy' "))
(assert (= f"a{p:9 :9}" "aother "))
(assert (= f"a{!r}" "abar"))
- (assert (= f"a{!r !r}" (u "a'bar'")))
+ (assert (= f"a{!r !r}" "a'bar'"))
; Fun with `r`
(assert (= f"hello {r\"\\n\"}" r"hello \n"))
@@ -1278,7 +1265,7 @@ cee\"} dee" "ey bee\ncee dee"))
(assert (= f"{(C) : {(str (+ 1 1)) !r :x<5}}" "C[ '2'xx]"))
; Format bracket strings
- (assert (= #[f[a{p !r :9}]f] (u "a'xyzzy' ")))
+ (assert (= #[f[a{p !r :9}]f] "a'xyzzy' "))
(assert (= #[f-string[result: {value :{width}.{precision}}]f-string]
"result: 12.34")))
@@ -1482,11 +1469,6 @@ cee\"} dee" "ey bee\ncee dee"))
(assert (= y [5])))
-(defn test-string []
- (assert (string? (string "a")))
- (assert (string? (string 1)))
- (assert (= u"unicode" (string "unicode"))))
-
(defn test-del []
"NATIVE: Test the behavior of del"
(setv foo 42)
@@ -1549,17 +1531,12 @@ cee\"} dee" "ey bee\ncee dee"))
(defn test-disassemble []
"NATIVE: Test the disassemble function"
- (assert (= (disassemble '(do (leaky) (leaky) (macros))) (cond
- [PY3 (.format "Module(
+ (assert (= (disassemble '(do (leaky) (leaky) (macros)))
+ (.format "Module(
body=[Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[])),
Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[])),
Expr(value=Call(func=Name(id='macros'), args=[], keywords=[]))]{})"
- (if PY38 ",\n type_ignores=[]" ""))]
- [True "Module(
- body=[
- Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),
- Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),
- Expr(value=Call(func=Name(id='macros'), args=[], keywords=[], starargs=None, kwargs=None))])"])))
+ (if PY38 ",\n type_ignores=[]" ""))))
(assert (= (disassemble '(do (leaky) (leaky) (macros)) True)
"leaky()
leaky()
@@ -1597,9 +1574,7 @@ macros()
(defn test-read []
"NATIVE: test that read takes something for stdin and reads"
- (if-python2
- (import [StringIO [StringIO]])
- (import [io [StringIO]]))
+ (import [io [StringIO]])
(import [hy.models [HyExpression]])
(setv stdin-buffer (StringIO "(+ 2 2)\n(- 2 2)"))
@@ -1716,3 +1691,204 @@ macros()
"Make sure relative imports work properly"
(import [..resources [tlib]])
(assert (= tlib.SECRET-MESSAGE "Hello World")))
+
+
+(defn test-exception-cause []
+ (try (raise ValueError :from NameError)
+ (except [e [ValueError]]
+ (assert (= (type (. e __cause__)) NameError)))))
+
+
+(defn test-kwonly []
+ "NATIVE: test keyword-only arguments"
+ ;; keyword-only with default works
+ (defn kwonly-foo-default-false [&kwonly [foo False]] foo)
+ (assert (= (kwonly-foo-default-false) False))
+ (assert (= (kwonly-foo-default-false :foo True) True))
+ ;; keyword-only without default ...
+ (defn kwonly-foo-no-default [&kwonly foo] foo)
+ (setv attempt-to-omit-default (try
+ (kwonly-foo-no-default)
+ (except [e [Exception]] e)))
+ ;; works
+ (assert (= (kwonly-foo-no-default :foo "quux") "quux"))
+ ;; raises TypeError with appropriate message if not supplied
+ (assert (isinstance attempt-to-omit-default TypeError))
+ (assert (in "missing 1 required keyword-only argument: 'foo'"
+ (. attempt-to-omit-default args [0])))
+ ;; keyword-only with other arg types works
+ (defn function-of-various-args [a b &rest args &kwonly foo &kwargs kwargs]
+ (, a b args foo kwargs))
+ (assert (= (function-of-various-args 1 2 3 4 :foo 5 :bar 6 :quux 7)
+ (, 1 2 (, 3 4) 5 {"bar" 6 "quux" 7}))))
+
+
+(defn test-extended-unpacking-1star-lvalues []
+ (setv [x #*y] [1 2 3 4])
+ (assert (= x 1))
+ (assert (= y [2 3 4]))
+ (setv [a #*b c] "ghijklmno")
+ (assert (= a "g"))
+ (assert (= b (list "hijklmn")))
+ (assert (= c "o")))
+
+
+(defn test-yield-from []
+ "NATIVE: testing yield from"
+ (defn yield-from-test []
+ (for [i (range 3)]
+ (yield i))
+ (yield-from [1 2 3]))
+ (assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
+
+
+(defn test-yield-from-exception-handling []
+ "NATIVE: Ensure exception handling in yield from works right"
+ (defn yield-from-subgenerator-test []
+ (yield 1)
+ (yield 2)
+ (yield 3)
+ (assert 0))
+ (defn yield-from-test []
+ (for [i (range 3)]
+ (yield i))
+ (try
+ (yield-from (yield-from-subgenerator-test))
+ (except [e AssertionError]
+ (yield 4))))
+ (assert (= (list (yield-from-test)) [0 1 2 1 2 3 4])))
+
+(require [hy.contrib.walk [let]])
+
+(defn test-let-optional []
+ (let [a 1
+ b 6
+ d 2]
+ (defn foo [&kwonly [a a] b [c d]]
+ (, a b c))
+ (assert (= (foo :b "b")
+ (, 1 "b" 2)))
+ (assert (= (foo :b 20 :a 10 :c 30)
+ (, 10 20 30)))))
+
+(defn test-pep-3115 []
+ (defclass member-table [dict]
+ [--init-- (fn [self] (setv self.member-names []))
+
+ --setitem-- (fn [self key value]
+ (if (not-in key self)
+ (.append self.member-names key))
+ (dict.--setitem-- self key value))])
+
+ (defclass OrderedClass [type]
+ [--prepare-- (classmethod (fn [metacls name bases] (member-table)))
+
+ --new-- (fn [cls name bases classdict]
+ (setv result (type.--new-- cls name bases (dict classdict)))
+ (setv result.member-names classdict.member-names)
+ result)])
+
+ (defclass MyClass [:metaclass OrderedClass]
+ [method1 (fn [self] (pass))
+ method2 (fn [self] (pass))])
+
+ (assert (= (. (MyClass) member-names)
+ ["__module__" "__qualname__" "method1" "method2"])))
+
+
+(import [asyncio [get-event-loop sleep]])
+
+
+(defn test-unpacking-pep448-1star []
+ (setv l [1 2 3])
+ (setv p [4 5])
+ (assert (= ["a" #*l "b" #*p #*l] ["a" 1 2 3 "b" 4 5 1 2 3]))
+ (assert (= (, "a" #*l "b" #*p #*l) (, "a" 1 2 3 "b" 4 5 1 2 3)))
+ (assert (= #{"a" #*l "b" #*p #*l} #{"a" "b" 1 2 3 4 5}))
+ (defn f [&rest args] args)
+ (assert (= (f "a" #*l "b" #*p #*l) (, "a" 1 2 3 "b" 4 5 1 2 3)))
+ (assert (= (+ #*l #*p) 15))
+ (assert (= (and #*l) 3)))
+
+
+(defn test-unpacking-pep448-2star []
+ (setv d1 {"a" 1 "b" 2})
+ (setv d2 {"c" 3 "d" 4})
+ (assert (= {1 "x" #**d1 #**d2 2 "y"} {"a" 1 "b" 2 "c" 3 "d" 4 1 "x" 2 "y"}))
+ (defn fun [&optional a b c d e f] [a b c d e f])
+ (assert (= (fun #**d1 :e "eee" #**d2) [1 2 3 4 "eee" None])))
+
+
+(defn run-coroutine [coro]
+ "Run a coroutine until its done in the default event loop."""
+ (.run_until_complete (get-event-loop) (coro)))
+
+
+(defn test-fn/a []
+ (assert (= (run-coroutine (fn/a [] (await (sleep 0)) [1 2 3]))
+ [1 2 3])))
+
+
+(defn test-defn/a []
+ (defn/a coro-test []
+ (await (sleep 0))
+ [1 2 3])
+ (assert (= (run-coroutine coro-test) [1 2 3])))
+
+
+(defn test-decorated-defn/a []
+ (defn decorator [func] (fn/a [] (/ (await (func)) 2)))
+
+ #@(decorator
+ (defn/a coro-test []
+ (await (sleep 0))
+ 42))
+ (assert (= (run-coroutine coro-test) 21)))
+
+
+(defclass AsyncWithTest []
+ (defn --init-- [self val]
+ (setv self.val val)
+ None)
+
+ (defn/a --aenter-- [self]
+ self.val)
+
+ (defn/a --aexit-- [self tyle value traceback]
+ (setv self.val None)))
+
+
+(defn test-single-with/a []
+ (run-coroutine
+ (fn/a []
+ (with/a [t (AsyncWithTest 1)]
+ (assert (= t 1))))))
+
+(defn test-two-with/a []
+ (run-coroutine
+ (fn/a []
+ (with/a [t1 (AsyncWithTest 1)
+ t2 (AsyncWithTest 2)]
+ (assert (= t1 1))
+ (assert (= t2 2))))))
+
+(defn test-thrice-with/a []
+ (run-coroutine
+ (fn/a []
+ (with/a [t1 (AsyncWithTest 1)
+ t2 (AsyncWithTest 2)
+ t3 (AsyncWithTest 3)]
+ (assert (= t1 1))
+ (assert (= t2 2))
+ (assert (= t3 3))))))
+
+(defn test-quince-with/a []
+ (run-coroutine
+ (fn/a []
+ (with/a [t1 (AsyncWithTest 1)
+ t2 (AsyncWithTest 2)
+ t3 (AsyncWithTest 3)
+ _ (AsyncWithTest 4)]
+ (assert (= t1 1))
+ (assert (= t2 2))
+ (assert (= t3 3))))))
diff --git a/tests/native_tests/mangling.hy b/tests/native_tests/mangling.hy
index 832d236..22c1942 100644
--- a/tests/native_tests/mangling.hy
+++ b/tests/native_tests/mangling.hy
@@ -3,9 +3,6 @@
;; license. See the LICENSE.
-(import [hy._compat [PY3]])
-
-
(defn test-hyphen []
(setv a-b 1)
(assert (= a-b 1))
@@ -63,9 +60,7 @@
(defn test-higher-unicode []
(setv 😂 "emoji")
(assert (= 😂 "emoji"))
- (if PY3
- (assert (= hyx_Xface_with_tears_of_joyX "emoji"))
- (assert (= hyx_XU1f602X "emoji"))))
+ (assert (= hyx_Xface_with_tears_of_joyX "emoji")))
(defn test-nameless-unicode []
diff --git a/tests/native_tests/mathematics.hy b/tests/native_tests/mathematics.hy
index aa4ad78..8ad8797 100644
--- a/tests/native_tests/mathematics.hy
+++ b/tests/native_tests/mathematics.hy
@@ -2,8 +2,6 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
-(import [hy._compat [PY3]])
-
(setv square (fn [x]
(* x x)))
@@ -191,20 +189,12 @@
(defn test-matmul []
"NATIVE: test matrix multiplication"
- (if PY3
- (assert (= (@ first-test-matrix second-test-matrix)
- product-of-test-matrices))
- ;; Python <= 3.4
- (do
- (setv matmul-attempt (try (@ first-test-matrix second-test-matrix)
- (except [e [Exception]] e)))
- (assert (isinstance matmul-attempt NameError)))))
+ (assert (= (@ first-test-matrix second-test-matrix)
+ product-of-test-matrices)))
(defn test-augassign-matmul []
"NATIVE: test augmented-assignment matrix multiplication"
(setv matrix first-test-matrix
matmul-attempt (try (@= matrix second-test-matrix)
(except [e [Exception]] e)))
- (if PY3
- (assert (= product-of-test-matrices matrix))
- (assert (isinstance matmul-attempt NameError))))
+ (assert (= product-of-test-matrices matrix)))
diff --git a/tests/native_tests/native_macros.hy b/tests/native_tests/native_macros.hy
index 835939e..61001db 100644
--- a/tests/native_tests/native_macros.hy
+++ b/tests/native_tests/native_macros.hy
@@ -140,11 +140,6 @@
(assert initialized)
(assert (test-initialized))
-(defn test-if-python2 []
- (import sys)
- (assert (= (get sys.version_info 0)
- (if-python2 2 3))))
-
(defn test-gensym-in-macros []
(import ast)
(import [astor.code-gen [to-source]])
@@ -409,9 +404,9 @@ in expansions."
Additionally, we confirm that `require` statements are executed via loaded bytecode."
(import os sys marshal types)
- (import [hy.importer [cache-from-source]])
+ (import importlib)
- (setv pyc-file (cache-from-source
+ (setv pyc-file (importlib.util.cache-from-source
(os.path.realpath
(os.path.join
"tests" "resources" "macro_with_require.hy"))))
diff --git a/tests/native_tests/operators.hy b/tests/native_tests/operators.hy
index cb0851e..6f2ea4a 100644
--- a/tests/native_tests/operators.hy
+++ b/tests/native_tests/operators.hy
@@ -2,8 +2,6 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
-(import pytest [hy._compat [PY3]])
-
(defmacro op-and-shadow-test [op &rest body]
; Creates two tests with the given `body`, one where all occurrences
; of the symbol `f` are syntactically replaced with `op` (a test of
@@ -102,14 +100,14 @@
(forbid (f 1 2 3)))
-(when PY3 (op-and-shadow-test @
+(op-and-shadow-test @
(defclass C [object] [
__init__ (fn [self content] (setv self.content content))
__matmul__ (fn [self other] (C (+ self.content other.content)))])
(forbid (f))
(assert (do (setv c (C "a")) (is (f c) c)))
(assert (= (. (f (C "b") (C "c")) content) "bc"))
- (assert (= (. (f (C "d") (C "e") (C "f")) content) "def"))))
+ (assert (= (. (f (C "d") (C "e") (C "f")) content) "def")))
(op-and-shadow-test <<
diff --git a/tests/native_tests/py3_only_tests.hy b/tests/native_tests/py3_only_tests.hy
deleted file mode 100644
index 4c79ad5..0000000
--- a/tests/native_tests/py3_only_tests.hy
+++ /dev/null
@@ -1,207 +0,0 @@
-;; Copyright 2019 the authors.
-;; This file is part of Hy, which is free software licensed under the Expat
-;; license. See the LICENSE.
-
-;; Tests where the emitted code relies on Python 3.
-;; conftest.py skips this file when running on Python 2.
-
-
-(defn test-exception-cause []
- (try (raise ValueError :from NameError)
- (except [e [ValueError]]
- (assert (= (type (. e __cause__)) NameError)))))
-
-
-(defn test-kwonly []
- "NATIVE: test keyword-only arguments"
- ;; keyword-only with default works
- (defn kwonly-foo-default-false [&kwonly [foo False]] foo)
- (assert (= (kwonly-foo-default-false) False))
- (assert (= (kwonly-foo-default-false :foo True) True))
- ;; keyword-only without default ...
- (defn kwonly-foo-no-default [&kwonly foo] foo)
- (setv attempt-to-omit-default (try
- (kwonly-foo-no-default)
- (except [e [Exception]] e)))
- ;; works
- (assert (= (kwonly-foo-no-default :foo "quux") "quux"))
- ;; raises TypeError with appropriate message if not supplied
- (assert (isinstance attempt-to-omit-default TypeError))
- (assert (in "missing 1 required keyword-only argument: 'foo'"
- (. attempt-to-omit-default args [0])))
- ;; keyword-only with other arg types works
- (defn function-of-various-args [a b &rest args &kwonly foo &kwargs kwargs]
- (, a b args foo kwargs))
- (assert (= (function-of-various-args 1 2 3 4 :foo 5 :bar 6 :quux 7)
- (, 1 2 (, 3 4) 5 {"bar" 6 "quux" 7}))))
-
-
-(defn test-extended-unpacking-1star-lvalues []
- (setv [x #*y] [1 2 3 4])
- (assert (= x 1))
- (assert (= y [2 3 4]))
- (setv [a #*b c] "ghijklmno")
- (assert (= a "g"))
- (assert (= b (list "hijklmn")))
- (assert (= c "o")))
-
-
-(defn test-yield-from []
- "NATIVE: testing yield from"
- (defn yield-from-test []
- (for [i (range 3)]
- (yield i))
- (yield-from [1 2 3]))
- (assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
-
-
-(defn test-yield-from-exception-handling []
- "NATIVE: Ensure exception handling in yield from works right"
- (defn yield-from-subgenerator-test []
- (yield 1)
- (yield 2)
- (yield 3)
- (assert 0))
- (defn yield-from-test []
- (for [i (range 3)]
- (yield i))
- (try
- (yield-from (yield-from-subgenerator-test))
- (except [e AssertionError]
- (yield 4))))
- (assert (= (list (yield-from-test)) [0 1 2 1 2 3 4])))
-
-(require [hy.contrib.walk [let]])
-
-(defn test-let-optional []
- (let [a 1
- b 6
- d 2]
- (defn foo [&kwonly [a a] b [c d]]
- (, a b c))
- (assert (= (foo :b "b")
- (, 1 "b" 2)))
- (assert (= (foo :b 20 :a 10 :c 30)
- (, 10 20 30)))))
-
-(defn test-pep-3115 []
- (defclass member-table [dict]
- [--init-- (fn [self] (setv self.member-names []))
-
- --setitem-- (fn [self key value]
- (if (not-in key self)
- (.append self.member-names key))
- (dict.--setitem-- self key value))])
-
- (defclass OrderedClass [type]
- [--prepare-- (classmethod (fn [metacls name bases] (member-table)))
-
- --new-- (fn [cls name bases classdict]
- (setv result (type.--new-- cls name bases (dict classdict)))
- (setv result.member-names classdict.member-names)
- result)])
-
- (defclass MyClass [:metaclass OrderedClass]
- [method1 (fn [self] (pass))
- method2 (fn [self] (pass))])
-
- (assert (= (. (MyClass) member-names)
- ["__module__" "__qualname__" "method1" "method2"])))
-
-
-(import [asyncio [get-event-loop sleep]])
-
-
-(defn test-unpacking-pep448-1star []
- (setv l [1 2 3])
- (setv p [4 5])
- (assert (= ["a" #*l "b" #*p #*l] ["a" 1 2 3 "b" 4 5 1 2 3]))
- (assert (= (, "a" #*l "b" #*p #*l) (, "a" 1 2 3 "b" 4 5 1 2 3)))
- (assert (= #{"a" #*l "b" #*p #*l} #{"a" "b" 1 2 3 4 5}))
- (defn f [&rest args] args)
- (assert (= (f "a" #*l "b" #*p #*l) (, "a" 1 2 3 "b" 4 5 1 2 3)))
- (assert (= (+ #*l #*p) 15))
- (assert (= (and #*l) 3)))
-
-
-(defn test-unpacking-pep448-2star []
- (setv d1 {"a" 1 "b" 2})
- (setv d2 {"c" 3 "d" 4})
- (assert (= {1 "x" #**d1 #**d2 2 "y"} {"a" 1 "b" 2 "c" 3 "d" 4 1 "x" 2 "y"}))
- (defn fun [&optional a b c d e f] [a b c d e f])
- (assert (= (fun #**d1 :e "eee" #**d2) [1 2 3 4 "eee" None])))
-
-
-(defn run-coroutine [coro]
- "Run a coroutine until its done in the default event loop."""
- (.run_until_complete (get-event-loop) (coro)))
-
-
-(defn test-fn/a []
- (assert (= (run-coroutine (fn/a [] (await (sleep 0)) [1 2 3]))
- [1 2 3])))
-
-
-(defn test-defn/a []
- (defn/a coro-test []
- (await (sleep 0))
- [1 2 3])
- (assert (= (run-coroutine coro-test) [1 2 3])))
-
-
-(defn test-decorated-defn/a []
- (defn decorator [func] (fn/a [] (/ (await (func)) 2)))
-
- #@(decorator
- (defn/a coro-test []
- (await (sleep 0))
- 42))
- (assert (= (run-coroutine coro-test) 21)))
-
-
-(defclass AsyncWithTest []
- (defn --init-- [self val]
- (setv self.val val)
- None)
-
- (defn/a --aenter-- [self]
- self.val)
-
- (defn/a --aexit-- [self tyle value traceback]
- (setv self.val None)))
-
-
-(defn test-single-with/a []
- (run-coroutine
- (fn/a []
- (with/a [t (AsyncWithTest 1)]
- (assert (= t 1))))))
-
-(defn test-two-with/a []
- (run-coroutine
- (fn/a []
- (with/a [t1 (AsyncWithTest 1)
- t2 (AsyncWithTest 2)]
- (assert (= t1 1))
- (assert (= t2 2))))))
-
-(defn test-thrice-with/a []
- (run-coroutine
- (fn/a []
- (with/a [t1 (AsyncWithTest 1)
- t2 (AsyncWithTest 2)
- t3 (AsyncWithTest 3)]
- (assert (= t1 1))
- (assert (= t2 2))
- (assert (= t3 3))))))
-
-(defn test-quince-with/a []
- (run-coroutine
- (fn/a []
- (with/a [t1 (AsyncWithTest 1)
- t2 (AsyncWithTest 2)
- t3 (AsyncWithTest 3)
- _ (AsyncWithTest 4)]
- (assert (= t1 1))
- (assert (= t2 2))
- (assert (= t3 3))))))
diff --git a/tests/test_bin.py b/tests/test_bin.py
index 06b3af9..1af7ffe 100644
--- a/tests/test_bin.py
+++ b/tests/test_bin.py
@@ -8,14 +8,12 @@ import os
import re
import shlex
import subprocess
+import builtins
-from hy.importer import cache_from_source
-from hy._compat import PY3
+from importlib.util import cache_from_source
import pytest
-from hy._compat import builtins
-
hy_dir = os.environ.get('HY_DIR', '')
@@ -497,9 +495,8 @@ def test_bin_hy_tracebacks():
os.environ['HY_DEBUG'] = ''
def req_err(x):
- assert x == '{}HyRequireError: No module named {}'.format(
- 'hy.errors.' if PY3 else '',
- (repr if PY3 else str)('not_a_real_module'))
+ assert (x == 'hy.errors.HyRequireError: No module named '
+ "'not_a_real_module'")
# Modeled after
# > python -c 'import not_a_real_module'
@@ -512,7 +509,7 @@ def test_bin_hy_tracebacks():
del error_lines[-1]
assert len(error_lines) <= 10
# Rough check for the internal traceback filtering
- req_err(error_lines[4 if PY3 else -1])
+ req_err(error_lines[4])
_, error = run_cmd('hy -c "(require not-a-real-module)"', expect=1)
error_lines = error.splitlines()
@@ -522,7 +519,7 @@ def test_bin_hy_tracebacks():
output, error = run_cmd('hy -i "(require not-a-real-module)"')
assert output.startswith('=> ')
print(error.splitlines())
- req_err(error.splitlines()[2 if PY3 else -3])
+ req_err(error.splitlines()[2])
# Modeled after
# > python -c 'print("hi'
@@ -535,9 +532,8 @@ def test_bin_hy_tracebacks():
r'Traceback \(most recent call last\):\n'
r' File "(?:|string-[0-9a-f]+)", line 1\n'
r' \(print "\n'
- r' \^\n' +
- r'{}PrematureEndOfInput: Partial string literal\n'.format(
- r'hy\.lex\.exceptions\.' if PY3 else ''))
+ r' \^\n'
+ r'hy.lex.exceptions.PrematureEndOfInput: Partial string literal\n')
assert re.search(peoi_re, error)
# Modeled after
diff --git a/tests/test_models.py b/tests/test_models.py
index fd1b615..b9e6a90 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -5,14 +5,13 @@
import copy
import hy
from clint.textui.colored import clean
-from hy._compat import long_type, str_type
from hy.models import (wrap_value, replace_hy_obj, HyString, HyInteger, HyList,
HyDict, HySet, HyExpression, HyComplex, HyFloat, pretty)
-def test_wrap_long_type():
+def test_wrap_int():
""" Test conversion of integers."""
- wrapped = wrap_value(long_type(0))
+ wrapped = wrap_value(0)
assert type(wrapped) == HyInteger
@@ -26,27 +25,27 @@ def test_wrap_tuple():
def test_wrap_nested_expr():
""" Test conversion of HyExpressions with embedded non-HyObjects."""
- wrapped = wrap_value(HyExpression([long_type(0)]))
+ wrapped = wrap_value(HyExpression([0]))
assert type(wrapped) == HyExpression
assert type(wrapped[0]) == HyInteger
assert wrapped == HyExpression([HyInteger(0)])
-def test_replace_long_type():
+def test_replace_int():
""" Test replacing integers."""
- replaced = replace_hy_obj(long_type(0), HyInteger(13))
+ replaced = replace_hy_obj(0, HyInteger(13))
assert replaced == HyInteger(0)
def test_replace_string_type():
"""Test replacing python string"""
- replaced = replace_hy_obj(str_type("foo"), HyString("bar"))
+ replaced = replace_hy_obj("foo", HyString("bar"))
assert replaced == HyString("foo")
def test_replace_tuple():
""" Test replacing tuples."""
- replaced = replace_hy_obj((long_type(0), ), HyInteger(13))
+ replaced = replace_hy_obj((0, ), HyInteger(13))
assert type(replaced) == HyList
assert type(replaced[0]) == HyInteger
assert replaced == HyList([HyInteger(0)])