Merge pull request #1759 from Kodiologist/no-py34

Drop support for Python 3.4
This commit is contained in:
Kodi Arfer 2019-03-18 11:16:35 -04:00 committed by GitHub
commit 808f81f7e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 125 additions and 136 deletions

View File

@ -2,7 +2,6 @@ sudo: false
language: python
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- pypy

View File

@ -3,6 +3,10 @@
Unreleased
==============================
Removals
------------------------------
* Python 3.4 is no longer supported.
New Features
------------------------------
* Format strings with embedded Hy code (e.g., `f"The sum is {(+ x y)}"`)

View File

@ -4,7 +4,7 @@ import importlib
import py
import pytest
import hy
from hy._compat import PY3, PY35, PY36
from hy._compat import PY3, PY36
NATIVE_TESTS = os.path.join("", "tests", "native_tests", "")
@ -13,7 +13,6 @@ _fspath_pyimport = py.path.local.pyimport
def pytest_ignore_collect(path, config):
return (("py3_only" in path.basename and not PY3) or
("py35_only" in path.basename and not PY35) or
("py36_only" in path.basename and not PY36) or None)

View File

@ -1678,20 +1678,14 @@ object (respectively) to provide positional or keywords arguments
=> (f #* [1 2] #** {"c" 3 "d" 4})
[1, 2, 3, 4]
With Python 3, you can unpack in an assignment list (:pep:`3132`).
With Python 3, unpacking is allowed in more contexts, and you can unpack
more than once in one expression (:pep:`3132`, :pep:`448`).
.. code-block:: clj
=> (setv [a #* b c] [1 2 3 4 5])
=> [a b c]
[1, [2, 3, 4], 5]
With Python 3.5 or greater, unpacking is allowed in more contexts than just
function calls, and you can unpack more than once in the same expression
(:pep:`448`).
.. code-block:: clj
=> [#* [1 2] #* [3 4]]
[1, 2, 3, 4]
=> {#** {1 2} #** {3 4}}

View File

@ -9,7 +9,6 @@ except ImportError:
import sys, keyword, textwrap
PY3 = sys.version_info[0] >= 3
PY35 = sys.version_info >= (3, 5)
PY36 = sys.version_info >= (3, 6)
PY37 = sys.version_info >= (3, 7)

View File

@ -15,7 +15,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,
PY35, PY36, reraise)
PY36, reraise)
from hy.macros import require, load_macros, macroexpand, tag_macroexpand
import hy.core
@ -106,7 +106,7 @@ def ast_str(x, piecewise=False):
_special_form_compilers = {}
_model_compilers = {}
_decoratables = (ast.FunctionDef, ast.ClassDef)
if PY35:
if PY3:
_decoratables += (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
@ -279,7 +279,7 @@ class Result(object):
var.arg = new_name
elif isinstance(var, ast.FunctionDef):
var.name = new_name
elif PY35 and isinstance(var, ast.AsyncFunctionDef):
elif PY3 and isinstance(var, ast.AsyncFunctionDef):
var.name = new_name
else:
raise TypeError("Don't know how to rename a %s!" % (
@ -475,7 +475,7 @@ class HyASTCompiler(object):
exprs_iter = iter(exprs)
for expr in exprs_iter:
if not PY35 and oldpy_unpack and is_unpack("iterable", expr):
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")
@ -485,7 +485,7 @@ class HyASTCompiler(object):
elif is_unpack("mapping", expr):
ret += self.compile(expr[1])
if PY35:
if PY3:
if dict_display:
compiled_exprs.append(None)
compiled_exprs.append(ret.force_expr)
@ -912,7 +912,7 @@ class HyASTCompiler(object):
ret += self.compile(arg)
return ret + asty.Yield(expr, value=ret.force_expr)
@special([(PY3, "yield-from"), (PY35, "await")], [FORM])
@special([(PY3, "yield-from"), (PY3, "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 +991,7 @@ class HyASTCompiler(object):
fn.stmts[-1].decorator_list = decs + fn.stmts[-1].decorator_list
return ret + fn
@special(["with*", (PY35, "with/a*")],
@special(["with*", (PY3, "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
@ -1348,11 +1348,11 @@ class HyASTCompiler(object):
"|": ast.BitOr,
"^": ast.BitXor,
"&": ast.BitAnd}
if PY35:
if PY3:
m_ops["@"] = ast.MatMult
@special(["+", "*", "|"], [many(FORM)])
@special(["-", "/", "&", (PY35, "@")], [oneplus(FORM)])
@special(["-", "/", "&", (PY3, "@")], [oneplus(FORM)])
@special(["**", "//", "<<", ">>"], [times(2, Inf, FORM)])
@special(["%", "^"], [times(2, 2, FORM)])
def compile_maths_expression(self, expr, root, args):
@ -1478,7 +1478,7 @@ class HyASTCompiler(object):
NASYM = some(lambda x: isinstance(x, HySymbol) and x not in (
"&optional", "&rest", "&kwonly", "&kwargs"))
@special(["fn", "fn*", (PY35, "fn/a")], [
@special(["fn", "fn*", (PY3, "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.

View File

@ -5,7 +5,7 @@
;;;; Hy shadow functions
(import operator)
(import [hy._compat [PY3 PY35]])
(import [hy._compat [PY3]])
(require [hy.core.bootstrap [*]])
@ -60,7 +60,7 @@
"Shadowed `%` operator takes `x` modulo `y`."
(% x y))
(if PY35
(if PY3
(defn @ [a1 &rest a-rest]
"Shadowed `@` operator matrix multiples `a1` by each `a-rest`."
(reduce operator.matmul a-rest a1)))
@ -173,5 +173,5 @@
'and 'or 'not
'is 'is-not 'in 'not-in
'get])
(if (not PY35)
(if (not PY3)
(.remove EXPORTS '@))

View File

@ -79,7 +79,6 @@ setup(
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",

View File

@ -11,7 +11,7 @@
pytest)
(import sys)
(import [hy._compat [PY3 PY35 PY37]])
(import [hy._compat [PY3 PY37]])
(defn test-sys-argv []
"NATIVE: test sys.argv"
@ -1550,7 +1550,7 @@ cee\"} dee" "ey bee\ncee dee"))
(defn test-disassemble []
"NATIVE: Test the disassemble function"
(assert (= (disassemble '(do (leaky) (leaky) (macros))) (cond
[PY35 "Module(
[PY3 "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=[]))])"]

View File

@ -2,7 +2,7 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
(import [hy._compat [PY35]])
(import [hy._compat [PY3]])
(setv square (fn [x]
(* x x)))
@ -191,7 +191,7 @@
(defn test-matmul []
"NATIVE: test matrix multiplication"
(if PY35
(if PY3
(assert (= (@ first-test-matrix second-test-matrix)
product-of-test-matrices))
;; Python <= 3.4
@ -205,6 +205,6 @@
(setv matrix first-test-matrix
matmul-attempt (try (@= matrix second-test-matrix)
(except [e [Exception]] e)))
(if PY35
(if PY3
(assert (= product-of-test-matrices matrix))
(assert (isinstance matmul-attempt NameError))))

View File

@ -2,7 +2,7 @@
;; This file is part of Hy, which is free software licensed under the Expat
;; license. See the LICENSE.
(import pytest [hy._compat [PY35]])
(import pytest [hy._compat [PY3]])
(defmacro op-and-shadow-test [op &rest body]
; Creates two tests with the given `body`, one where all occurrences
@ -102,7 +102,7 @@
(forbid (f 1 2 3)))
(when PY35 (op-and-shadow-test @
(when PY3 (op-and-shadow-test @
(defclass C [object] [
__init__ (fn [self content] (setv self.content content))
__matmul__ (fn [self other] (C (+ self.content other.content)))])

View File

@ -1,103 +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.5.
;; conftest.py skips this file when running on Python <3.5.
(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))))))

View File

@ -107,3 +107,101 @@
(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))))))