Merge branch 'master' into pr/237

This commit is contained in:
Paul Tagliamonte 2013-07-16 21:05:31 -04:00
commit 967bb95534
16 changed files with 252 additions and 71 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
*.pyc
*swp
*hy*egg*
*pyreadline*egg*
.tox
*pycache*
dist

View File

@ -8,7 +8,7 @@ python:
# command to install dependencies
install:
- pip install -r requirements.txt --use-mirrors
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install importlib unittest2 astor --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install argparse importlib unittest2 astor --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install astor --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi
- python setup.py -q install

View File

@ -14,4 +14,5 @@
* Thomas Ballinger <thomasballinger@gmail.com>
* Morten Linderud <mcfoxax@gmail.com>
* Guillermo Vayá <guivaya@gmail.com>
* Bob Tolbert <bob@tolbert.org>
* Ralph Möritz <ralph.moeritz@outlook.com>

8
bin/hy
View File

@ -1,8 +0,0 @@
#!/usr/bin/env python
import sys
from hy.cmdline import cmdline_handler
if __name__ == '__main__':
sys.exit(cmdline_handler("hy", sys.argv))

View File

@ -1,6 +0,0 @@
#!/usr/bin/env hy
(import sys)
(import [hy.importer [write-hy-as-pyc]])
(write-hy-as-pyc (get sys.argv 1))

View File

@ -177,7 +177,7 @@ Some example usage:
`do` can accept any number of arguments, from 1 to n.
def / setf / setv
def / setv
-----------------
`def` and `setv` are used to bind value, object or a function to a symbol. For

View File

@ -6,6 +6,6 @@
(with-as (ThreadPoolExecutor 10) executor
(setf jobs (list-comp (.submit executor task-to-do) (x (range 0 10))))
(setv jobs (list-comp (.submit executor task-to-do) (x (range 0 10))))
(for (future (as-completed jobs))
(.result future)))

View File

@ -24,7 +24,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
import optparse
import argparse
import code
import ast
import sys
@ -198,26 +198,40 @@ def run_icommand(source):
return run_repl(hr)
USAGE = "usage: %prog [-h | -i cmd | -c cmd | file | -]"
VERSION = "%prog " + hy.__version__
USAGE = "%(prog)s [-h | -i cmd | -c cmd | file | -] [arg] ..."
VERSION = "%(prog)s " + hy.__version__
EPILOG = """ file program read from script
- program read from stdin
[arg] ... arguments passed to program in sys.argv[1:]
"""
def cmdline_handler(scriptname, argv):
parser = optparse.OptionParser(usage=USAGE, version=VERSION)
parser.add_option(
"-c", dest="command", metavar="COMMAND",
help="program passed in as string")
parser.add_option(
"-i", dest="icommand", metavar="ICOMMAND",
help="program passed in as string, then stay in repl")
parser = argparse.ArgumentParser(
prog="hy",
usage=USAGE,
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=EPILOG)
parser.add_argument("-c", dest="command",
help="program passed in as a string")
parser.add_argument(
"-i", dest="icommand",
help="program passed in as a string, then stay in REPL")
# Hylarious way of adding non-option options to help text
parser.format_epilog = lambda self: EPILOG
parser.add_argument("-v", action="version", version=VERSION)
(options, args) = parser.parse_args()
# this will contain the script/program name and any arguments for it.
parser.add_argument('args', nargs=argparse.REMAINDER,
help=argparse.SUPPRESS)
# stash the hy exectuable in case we need it later
# mimics Python sys.executable
hy.executable = argv[0]
options = parser.parse_args(argv[1:])
# reset sys.argv like Python
sys.argv = options.args
if options.command:
# User did "hy -c ..."
@ -227,14 +241,25 @@ def cmdline_handler(scriptname, argv):
# User did "hy -i ..."
return run_icommand(options.icommand)
if args:
if args[0] == "-":
if options.args:
if options.args[0] == "-":
# Read the program from stdin
return run_command(sys.stdin.read())
else:
# User did "hy <filename>"
return run_file(args[0])
return run_file(options.args[0])
# User did NOTHING!
return run_repl()
# entry point for cmd line script "hy"
def hy_main():
sys.exit(cmdline_handler("hy", sys.argv))
# entry point for cmd line script "hyc"
def hyc_main():
from hy.importer import write_hy_as_pyc
write_hy_as_pyc(sys.argv[1])

View File

@ -1481,7 +1481,6 @@ class HyASTCompiler(object):
return func + ret
@builds("def")
@builds("setf")
@builds("setv")
@checkargs(2)
def compile_def_expression(self, expression):

View File

@ -128,10 +128,10 @@ def let_macro(variables, *body):
for var in variables:
if isinstance(var, list):
expr.append(HyExpression([HySymbol("setf"),
expr.append(HyExpression([HySymbol("setv"),
var[0], var[1]]))
else:
expr.append(HyExpression([HySymbol("setf"),
expr.append(HyExpression([HySymbol("setv"),
var, HySymbol("None")]))
return HyExpression([expr + list(body)])

116
make.bat Normal file
View File

@ -0,0 +1,116 @@
@ECHO OFF
REM Make batch file for Hy development
if "%1" == "" goto help
if "%1" == "help" (
:help
echo. No default step. Use setup.py
echo.
echo. Other targets:
echo.
echo. - docs
echo. - full
echo.
echo. - dev "test & flake"
echo. - flake
echo. - test
echo. - diff
echo. - tox
echo. - d
echo. - r
echo.
goto end
)
if "%1" == "docs" (
:docs
echo.docs not yet supported under Windows
goto :EOF
)
if "%1" == "upload" (
:upload
python setup.py sdist upload
goto :EOF
)
if "%1" == "clear" (
:clear
cls
goto :EOF
)
if "%1" == "d" (
:d
call :clear
call :dev
goto :EOF
)
if "%1" == "test" (
:test
call :venv
nosetests -sv
goto :EOF
)
if "%1" == "venv" (
:venv
echo.%VIRTUAL_ENV% | findstr /C:"hy" 1>nul
if errorlevel 1 (
echo.You're not in a Hy virtualenv. FOR SHAME
) ELSE (
echo.We're properly in a virtualenv. Going ahead.
)
goto :EOF
)
if "%1" == "flake" (
:flake
echo.flake8 hy
flake8 hy
goto :EOF
)
if "%1" == "dev" (
:dev
call :test
call :flake
goto :EOF
)
if "%1" == "tox" (
:tox
call :venv
tox -e "py26,py27,py32,py33,flake8"
goto :EOF
)
if "%1" == "d" (
:d
call :clear
call :dev
goto :EOF
)
if "%i" == "diff" (
:diff
git diff --color
goto :EOF
)
if "%1" == "r" (
:r
call :d
call :tox
call :diff
goto :EOF
)
if "%1" == full (
call :docs
call :d
call :tox
)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python
# Copyright (c) 2012 Paul Tagliamonte <paultag@debian.org>
# Copyright (c) 2012, 2013 Paul Tagliamonte <paultag@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@ -23,12 +23,15 @@
from hy import __appname__, __version__
from setuptools import setup
import os
import sys
long_description = """Hy is a Python <--> Lisp layer. It helps
make things work nicer, and lets Python and the Hy lisp variant play
nice together. """
install_requires = []
if sys.version_info[0] == 2:
install_requires.append('argparse>=1.2.1')
if os.name == 'nt':
install_requires.append('pyreadline==2.0')
@ -36,10 +39,12 @@ setup(
name=__appname__,
version=__version__,
install_requires=install_requires,
scripts=[
"bin/hy",
"bin/hyc",
],
entry_points={
'console_scripts': [
'hy = hy.cmdline:hy_main',
'hyc = hy.cmdline:hyc_main'
]
},
packages=[
'hy',
'hy.lex',

View File

@ -408,11 +408,11 @@
(defn test-for-doodle []
"NATIVE: test for-do"
(do (do (do (do (do (do (do (do (do (setf (, x y) (, 0 0)))))))))))
(do (do (do (do (do (do (do (do (do (setv (, x y) (, 0 0)))))))))))
(foreach [- [1 2]]
(do
(setf x (+ x 1))
(setf y (+ y 1))))
(setv x (+ x 1))
(setv y (+ y 1))))
(assert (= y x 2)))
@ -597,10 +597,10 @@
(defn test-eval []
"NATIVE: test eval"
(assert (= 2 (eval (quote (+ 1 1)))))
(setf x 2)
(setv x 2)
(assert (= 4 (eval (quote (+ x 2)))))
(setf test-payload (quote (+ x 2)))
(setf x 4)
(setv test-payload (quote (+ x 2)))
(setv x 4)
(assert (= 6 (eval test-payload)))
(assert (= 9 ((eval (quote (fn [x] (+ 3 3 x)))) 3)))
(assert (= 1 (eval (quote 1))))
@ -689,9 +689,9 @@
(defn test-try-except-return []
"NATIVE: test we can return from in a try except"
(assert (= ((fn [] (try xxx (except [NameError] (+ 1 1))))) 2))
(setf foo (try xxx (except [NameError] (+ 1 1))))
(setv foo (try xxx (except [NameError] (+ 1 1))))
(assert (= foo 2))
(setf foo (try (+ 2 2) (except [NameError] (+ 1 1))))
(setv foo (try (+ 2 2) (except [NameError] (+ 1 1))))
(assert (= foo 4)))

View File

@ -3,22 +3,22 @@
(defn test-quote []
"NATIVE: test for quoting functionality"
(setf q (quote (a b c)))
(setv q (quote (a b c)))
(assert (= (len q) 3))
(assert (= q [(quote a) (quote b) (quote c)])))
(defn test-quoted-hoistable []
"NATIVE: check whether quote works on hoisted things"
(setf f (quote (if true true true)))
(setv f (quote (if true true true)))
(assert (= (car f) (quote if)))
(assert (= (cdr f) (quote (true true true)))))
(defn test-quoted-macroexpand []
"NATIVE: check that we don't expand macros in quoted expressions"
(setf q1 (quote (-> a b c)))
(setf q2 (quasiquote (-> a b c)))
(setv q1 (quote (-> a b c)))
(setv q2 (quasiquote (-> a b c)))
(assert (= q1 q2))
(assert (= (car q1) (quote ->)))
(assert (= (cdr q1) (quote (a b c)))))
@ -26,7 +26,7 @@
(defn test-quote-dicts []
"NATIVE: test quoting dicts"
(setf q (quote {foo bar baz quux}))
(setv q (quote {foo bar baz quux}))
(assert (= (len q) 4))
(assert (= (get q 0) (quote foo)))
(assert (= (get q 1) (quote bar)))
@ -37,41 +37,41 @@
(defn test-quote-expr-in-dict []
"NATIVE: test quoting nested exprs in dict"
(setf q (quote {(foo bar) 0}))
(setv q (quote {(foo bar) 0}))
(assert (= (len q) 2))
(setf qq (get q 0))
(setv qq (get q 0))
(assert (= qq (quote (foo bar)))))
(defn test-quasiquote []
"NATIVE: test that quasiquote and quote are equivalent for simple cases"
(setf q (quote (a b c)))
(setf qq (quasiquote (a b c)))
(setv q (quote (a b c)))
(setv qq (quasiquote (a b c)))
(assert (= q qq)))
(defn test-unquote []
"NATIVE: test that unquote works as expected"
(setf q (quote (unquote foo)))
(setv q (quote (unquote foo)))
(assert (= (len q) 2))
(assert (= (get q 1) (quote foo)))
(setf qq (quasiquote (a b c (unquote (+ 1 2)))))
(setv qq (quasiquote (a b c (unquote (+ 1 2)))))
(assert (= (len qq) 4))
(assert (= qq (quote (a b c 3)))))
(defn test-unquote-splice []
"NATIVE: test splicing unquotes"
(setf q (quote (c d e)))
(setf qq (quasiquote (a b (unquote-splice q) f (unquote-splice q))))
(setv q (quote (c d e)))
(setv qq (quasiquote (a b (unquote-splice q) f (unquote-splice q))))
(assert (= (len qq) 9))
(assert (= qq (quote (a b c d e f c d e)))))
(defn test-nested-quasiquote []
"NATIVE: test nested quasiquotes"
(setf qq (quasiquote (1 (quasiquote (unquote (+ 1 (unquote (+ 2 3))))) 4)))
(setf q (quote (1 (quasiquote (unquote (+ 1 5))) 4)))
(setv qq (quasiquote (1 (quasiquote (unquote (+ 1 (unquote (+ 2 3))))) 4)))
(setv q (quote (1 (quasiquote (unquote (+ 1 5))) 4)))
(assert (= (len q) 3))
(assert (= (get qq 1) (quote (quasiquote (unquote (+ 1 5))))))
(assert (= q qq)))

18
tests/resources/argparse_ex.hy Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env hy
(import sys)
(import argparse)
(setv parser (argparse.ArgumentParser))
(.add_argument parser "-i")
(.add_argument parser "-c")
(setv args (.parse_args parser))
;; using (cond) allows -i to take precedence over -c
(cond (args.i
(print (str args.i)))
(args.c
(print (str "got c"))))

View File

@ -25,13 +25,18 @@ import subprocess
import sys
def run_cmd(cmd):
def run_cmd(cmd, stdin_data=None):
p = subprocess.Popen(cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
stdout = ""
stderr = ""
if stdin_data is not None:
p.stdin.write(stdin_data.encode('ASCII'))
p.stdin.flush()
p.stdin.close()
# Read stdout and stderr otherwise if the PIPE buffer is full, we might
# wait for ever…
while p.poll() is None:
@ -41,28 +46,28 @@ def run_cmd(cmd):
def test_bin_hy():
ret = run_cmd("echo | bin/hy")
ret = run_cmd("hy", "")
assert ret[0] == 0
def test_bin_hy_stdin():
ret = run_cmd("echo \"(koan)\" | bin/hy")
ret = run_cmd("hy", '(koan)')
assert ret[0] == 0
assert "monk" in ret[1]
def test_bin_hy_cmd():
ret = run_cmd("bin/hy -c \"(koan)\"")
ret = run_cmd("hy -c \"(koan)\"")
assert ret[0] == 0
assert "monk" in ret[1]
ret = run_cmd("bin/hy -c \"(koan\"")
ret = run_cmd("hy -c \"(koan\"")
assert ret[0] == 1
assert "LexException" in ret[1]
def test_bin_hy_icmd():
ret = run_cmd("echo \"(ideas)\" | bin/hy -i \"(koan)\"")
ret = run_cmd("hy -i \"(koan)\"", "(ideas)")
assert ret[0] == 0
output = ret[1]
@ -71,16 +76,41 @@ def test_bin_hy_icmd():
def test_bin_hy_file():
ret = run_cmd("bin/hy eg/nonfree/halting-problem/halting.hy")
ret = run_cmd("hy eg/nonfree/halting-problem/halting.hy")
assert ret[0] == 0
assert "27" in ret[1]
def test_bin_hy_missing_file():
ret = run_cmd("hy foobarbaz")
assert ret[0] == 1
assert "No such file" in ret[2]
def test_bin_hy_file_with_args():
ret = run_cmd("hy tests/resources/argparse_ex.hy -h")
assert ret[0] == 0
assert "usage" in ret[1]
ret = run_cmd("hy tests/resources/argparse_ex.hy -c bar")
assert ret[0] == 0
assert "got c" in ret[1]
ret = run_cmd("hy tests/resources/argparse_ex.hy -i foo")
assert ret[0] == 0
assert "foo" in ret[1]
ret = run_cmd("hy tests/resources/argparse_ex.hy -i foo -c bar")
assert ret[0] == 0
assert "foo" in ret[1]
def test_hy2py():
# XXX Astor doesn't seem to support Python3 :(
if sys.version_info[0] == 3:
return
# and running this script this way doesn't work on Windows
if os.name == "nt":
return
i = 0
for dirpath, dirnames, filenames in os.walk("tests/native_tests"):
for f in filenames: