Implement Python 2 exec
The implementation of `hy.core.language.exec` draws code from the `exec_` function in commit f574c7be6ebc80041ef58ca29588f310248ebed4 of the library Six, which is copyright 2010–2017 Benjamin Peterson and licensed under the Expat license.
This commit is contained in:
parent
3dcf91ab39
commit
ecc974de1e
1
NEWS
1
NEWS
@ -23,6 +23,7 @@ Changes from 0.13.0
|
|||||||
mistaken for shebang lines
|
mistaken for shebang lines
|
||||||
* Fixed a bug where REPL history wasn't saved if you quit the REPL with
|
* Fixed a bug where REPL history wasn't saved if you quit the REPL with
|
||||||
`(quit)` or `(exit)`
|
`(quit)` or `(exit)`
|
||||||
|
* `exec` now works under Python 2
|
||||||
|
|
||||||
Changes from 0.12.1
|
Changes from 0.12.1
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
import re, os, sys, time, cgi
|
import re, os, sys, time, cgi
|
||||||
sys.path.append(os.path.abspath(".."))
|
sys.path.append(os.path.abspath(".."))
|
||||||
|
|
||||||
|
extensions = ['sphinx.ext.intersphinx']
|
||||||
|
|
||||||
from get_version import __version__ as hy_version
|
from get_version import __version__ as hy_version
|
||||||
# Read the Docs might dirty its checkout, so strip the dirty flag.
|
# Read the Docs might dirty its checkout, so strip the dirty flag.
|
||||||
hy_version = re.sub('[+.]dirty\Z', '', hy_version)
|
hy_version = re.sub('[+.]dirty\Z', '', hy_version)
|
||||||
@ -48,3 +50,7 @@ html_show_sphinx = False
|
|||||||
|
|
||||||
html_context = dict(
|
html_context = dict(
|
||||||
hy_descriptive_version = hy_descriptive_version)
|
hy_descriptive_version = hy_descriptive_version)
|
||||||
|
|
||||||
|
intersphinx_mapping = dict(
|
||||||
|
py2 = ('https://docs.python.org/2', None),
|
||||||
|
py = ('https://docs.python.org/3', None))
|
||||||
|
@ -281,6 +281,19 @@ otherwise ``False``. Return ``True`` if *coll* is empty.
|
|||||||
True
|
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?-fn:
|
||||||
|
|
||||||
float?
|
float?
|
||||||
|
@ -778,6 +778,19 @@ class HyASTCompiler(object):
|
|||||||
def compile_unpack_mapping(self, expr):
|
def compile_unpack_mapping(self, expr):
|
||||||
raise HyTypeError(expr, "`unpack-mapping` isn't allowed here")
|
raise HyTypeError(expr, "`unpack-mapping` isn't allowed here")
|
||||||
|
|
||||||
|
@builds_if("exec*", not PY3)
|
||||||
|
# Under Python 3, `exec` is a function rather than a statement type, so Hy
|
||||||
|
# doesn't need a special form for it.
|
||||||
|
@checkargs(min=1, max=3)
|
||||||
|
def compile_exec(self, expr):
|
||||||
|
expr.pop(0)
|
||||||
|
return ast.Exec(
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column,
|
||||||
|
body=self.compile(expr.pop(0)).force_expr,
|
||||||
|
globals=self.compile(expr.pop(0)).force_expr if expr else None,
|
||||||
|
locals=self.compile(expr.pop(0)).force_expr if expr else None)
|
||||||
|
|
||||||
@builds("do")
|
@builds("do")
|
||||||
def compile_do(self, expression):
|
def compile_do(self, expression):
|
||||||
expression.pop(0)
|
expression.pop(0)
|
||||||
|
@ -117,6 +117,24 @@
|
|||||||
range range
|
range range
|
||||||
zip zip))
|
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))
|
||||||
|
(def exec exec))
|
||||||
|
|
||||||
;; infinite iterators
|
;; infinite iterators
|
||||||
(def
|
(def
|
||||||
count itertools.count
|
count itertools.count
|
||||||
@ -461,8 +479,8 @@
|
|||||||
(def *exports*
|
(def *exports*
|
||||||
'[*map accumulate butlast calling-module-name chain coll? combinations
|
'[*map accumulate butlast calling-module-name chain coll? combinations
|
||||||
comp complement compress cons cons? constantly count cycle dec distinct
|
comp complement compress cons cons? constantly count cycle dec distinct
|
||||||
disassemble drop drop-last drop-while empty? eval even? every? first filter
|
disassemble drop drop-last drop-while empty? eval even? every? exec first
|
||||||
flatten float? fraction gensym group-by identity inc input instance?
|
filter flatten float? fraction gensym group-by identity inc input instance?
|
||||||
integer integer? integer-char? interleave interpose islice iterable?
|
integer integer? integer-char? interleave interpose islice iterable?
|
||||||
iterate iterator? juxt keyword keyword? last list* macroexpand
|
iterate iterator? juxt keyword keyword? last list* macroexpand
|
||||||
macroexpand-1 map merge-with multicombinations name neg? none? nth
|
macroexpand-1 map merge-with multicombinations name neg? none? nth
|
||||||
|
@ -593,3 +593,27 @@ def test_setv_builtins():
|
|||||||
def test_lots_of_comment_lines():
|
def test_lots_of_comment_lines():
|
||||||
# https://github.com/hylang/hy/issues/1313
|
# https://github.com/hylang/hy/issues/1313
|
||||||
can_compile(1000 * ";\n")
|
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"
|
||||||
|
@ -170,6 +170,49 @@
|
|||||||
(assert-false (every? even? [2 4 5]))
|
(assert-false (every? even? [2 4 5]))
|
||||||
(assert-true (every? even? [])))
|
(assert-true (every? even? [])))
|
||||||
|
|
||||||
|
(setv globalvar 1)
|
||||||
|
(defn test-exec []
|
||||||
|
(setv localvar 1)
|
||||||
|
(setv code "
|
||||||
|
result['localvar in locals'] = 'localvar' in locals()
|
||||||
|
result['localvar in globals'] = 'localvar' in globals()
|
||||||
|
result['globalvar in locals'] = 'globalvar' in locals()
|
||||||
|
result['globalvar in globals'] = 'globalvar' in globals()
|
||||||
|
result['x in locals'] = 'x' in locals()
|
||||||
|
result['x in globals'] = 'x' in globals()
|
||||||
|
result['y in locals'] = 'y' in locals()
|
||||||
|
result['y in globals'] = 'y' in globals()")
|
||||||
|
|
||||||
|
(setv result {})
|
||||||
|
(exec code)
|
||||||
|
(assert-true (get result "localvar in locals"))
|
||||||
|
(assert-false (get result "localvar in globals"))
|
||||||
|
(assert-false (get result "globalvar in locals"))
|
||||||
|
(assert-true (get result "globalvar in globals"))
|
||||||
|
(assert-false (or
|
||||||
|
(get result "x in locals") (get result "x in globals")
|
||||||
|
(get result "y in locals") (get result "y in globals")))
|
||||||
|
|
||||||
|
(setv result {})
|
||||||
|
(exec code {"x" 1 "result" result})
|
||||||
|
(assert-false (or
|
||||||
|
(get result "localvar in locals") (get result "localvar in globals")
|
||||||
|
(get result "globalvar in locals") (get result "globalvar in globals")))
|
||||||
|
(assert-true (and
|
||||||
|
(get result "x in locals") (get result "x in globals")))
|
||||||
|
(assert-false (or
|
||||||
|
(get result "y in locals") (get result "y in globals")))
|
||||||
|
|
||||||
|
(setv result {})
|
||||||
|
(exec code {"x" 1 "result" result} {"y" 1})
|
||||||
|
(assert-false (or
|
||||||
|
(get result "localvar in locals") (get result "localvar in globals")
|
||||||
|
(get result "globalvar in locals") (get result "globalvar in globals")))
|
||||||
|
(assert-false (get result "x in locals"))
|
||||||
|
(assert-true (get result "x in globals"))
|
||||||
|
(assert-true (get result "y in locals"))
|
||||||
|
(assert-false (get result "y in globals")))
|
||||||
|
|
||||||
(defn test-filter []
|
(defn test-filter []
|
||||||
"NATIVE: testing the filter function"
|
"NATIVE: testing the filter function"
|
||||||
(setv res (list (filter pos? [ 1 2 3 -4 5])))
|
(setv res (list (filter pos? [ 1 2 3 -4 5])))
|
||||||
|
Loading…
Reference in New Issue
Block a user