Provide bin scripts for both Windows and *nix
Summary: This update does away with the scripts in bin and changes setup.py to use entry_points in cmdline.py for the scripts 'hy' and 'hyc'. This fixes installing and running on Windows. The tests are updated to run the 'hy' script produced by setup.py and not from bin/hy. This is more correct and makes the tox tests run on both Window and *nix. For running hy or nosetests directly in the source tree, you do have to run 'python setup.py develop' first. But since tox runs and builds dists, all tox tests pass on all platforms. Also, since there is no built-in readline on Windows, the setup.py only on Windows requires 'pyreadline' as a replacement. Switched from optparse to argparse in cmdline.py Instead of trying to manually separate args meant for hy from args meant for a hy script, this switches from optparse to argparse for the CLI. argparse automatically peels out args meant for hy and leaves the rest, including the user hy script in options.args. This fixes the issue @paultag found running "hy foo" where foo is not a real file. Also added a test that makes sure trying to run a non-existent script exits instead of dropping the user into the REPL. Added argparse as setup.py resource (and removed from tox.ini) as well as removed uses of deprecated setf
This commit is contained in:
parent
9cf3ee4b43
commit
df7bb1d29a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*swp
|
*swp
|
||||||
*hy*egg*
|
*hy*egg*
|
||||||
|
*pyreadline*egg*
|
||||||
.tox
|
.tox
|
||||||
*pycache*
|
*pycache*
|
||||||
dist
|
dist
|
||||||
|
@ -8,7 +8,7 @@ python:
|
|||||||
# command to install dependencies
|
# command to install dependencies
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt --use-mirrors
|
- 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 == '2.7' ]]; then pip install astor --use-mirrors; fi
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi
|
||||||
- python setup.py -q install
|
- python setup.py -q install
|
||||||
|
1
AUTHORS
1
AUTHORS
@ -14,4 +14,5 @@
|
|||||||
* Thomas Ballinger <thomasballinger@gmail.com>
|
* Thomas Ballinger <thomasballinger@gmail.com>
|
||||||
* Morten Linderud <mcfoxax@gmail.com>
|
* Morten Linderud <mcfoxax@gmail.com>
|
||||||
* Guillermo Vayá <guivaya@gmail.com>
|
* Guillermo Vayá <guivaya@gmail.com>
|
||||||
|
* Bob Tolbert <bob@tolbert.org>
|
||||||
* Ralph Möritz <ralph.moeritz@outlook.com>
|
* Ralph Möritz <ralph.moeritz@outlook.com>
|
||||||
|
8
bin/hy
8
bin/hy
@ -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))
|
|
6
bin/hyc
6
bin/hyc
@ -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))
|
|
@ -24,7 +24,7 @@
|
|||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
# DEALINGS IN THE SOFTWARE.
|
# DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
import optparse
|
import argparse
|
||||||
import code
|
import code
|
||||||
import ast
|
import ast
|
||||||
import sys
|
import sys
|
||||||
@ -198,26 +198,40 @@ def run_icommand(source):
|
|||||||
return run_repl(hr)
|
return run_repl(hr)
|
||||||
|
|
||||||
|
|
||||||
USAGE = "usage: %prog [-h | -i cmd | -c cmd | file | -]"
|
USAGE = "%(prog)s [-h | -i cmd | -c cmd | file | -] [arg] ..."
|
||||||
VERSION = "%prog " + hy.__version__
|
VERSION = "%(prog)s " + hy.__version__
|
||||||
EPILOG = """ file program read from script
|
EPILOG = """ file program read from script
|
||||||
- program read from stdin
|
- program read from stdin
|
||||||
|
[arg] ... arguments passed to program in sys.argv[1:]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def cmdline_handler(scriptname, argv):
|
def cmdline_handler(scriptname, argv):
|
||||||
parser = optparse.OptionParser(usage=USAGE, version=VERSION)
|
parser = argparse.ArgumentParser(
|
||||||
parser.add_option(
|
prog="hy",
|
||||||
"-c", dest="command", metavar="COMMAND",
|
usage=USAGE,
|
||||||
help="program passed in as string")
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
parser.add_option(
|
epilog=EPILOG)
|
||||||
"-i", dest="icommand", metavar="ICOMMAND",
|
parser.add_argument("-c", dest="command",
|
||||||
help="program passed in as string, then stay in repl")
|
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.add_argument("-v", action="version", version=VERSION)
|
||||||
parser.format_epilog = lambda self: EPILOG
|
|
||||||
|
|
||||||
(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:
|
if options.command:
|
||||||
# User did "hy -c ..."
|
# User did "hy -c ..."
|
||||||
@ -227,14 +241,25 @@ def cmdline_handler(scriptname, argv):
|
|||||||
# User did "hy -i ..."
|
# User did "hy -i ..."
|
||||||
return run_icommand(options.icommand)
|
return run_icommand(options.icommand)
|
||||||
|
|
||||||
if args:
|
if options.args:
|
||||||
if args[0] == "-":
|
if options.args[0] == "-":
|
||||||
# Read the program from stdin
|
# Read the program from stdin
|
||||||
return run_command(sys.stdin.read())
|
return run_command(sys.stdin.read())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# User did "hy <filename>"
|
# User did "hy <filename>"
|
||||||
return run_file(args[0])
|
return run_file(options.args[0])
|
||||||
|
|
||||||
# User did NOTHING!
|
# User did NOTHING!
|
||||||
return run_repl()
|
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])
|
||||||
|
116
make.bat
Normal file
116
make.bat
Normal 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
|
||||||
|
)
|
15
setup.py
15
setup.py
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/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
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
# copy of this software and associated documentation files (the "Software"),
|
# copy of this software and associated documentation files (the "Software"),
|
||||||
@ -23,12 +23,15 @@
|
|||||||
from hy import __appname__, __version__
|
from hy import __appname__, __version__
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
long_description = """Hy is a Python <--> Lisp layer. It helps
|
long_description = """Hy is a Python <--> Lisp layer. It helps
|
||||||
make things work nicer, and lets Python and the Hy lisp variant play
|
make things work nicer, and lets Python and the Hy lisp variant play
|
||||||
nice together. """
|
nice together. """
|
||||||
|
|
||||||
install_requires = []
|
install_requires = []
|
||||||
|
if sys.version_info[0] == 2:
|
||||||
|
install_requires.append('argparse>=1.2.1')
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
install_requires.append('pyreadline==2.0')
|
install_requires.append('pyreadline==2.0')
|
||||||
|
|
||||||
@ -36,10 +39,12 @@ setup(
|
|||||||
name=__appname__,
|
name=__appname__,
|
||||||
version=__version__,
|
version=__version__,
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
scripts=[
|
entry_points={
|
||||||
"bin/hy",
|
'console_scripts': [
|
||||||
"bin/hyc",
|
'hy = hy.cmdline:hy_main',
|
||||||
],
|
'hyc = hy.cmdline:hyc_main'
|
||||||
|
]
|
||||||
|
},
|
||||||
packages=[
|
packages=[
|
||||||
'hy',
|
'hy',
|
||||||
'hy.lex',
|
'hy.lex',
|
||||||
|
18
tests/resources/argparse_ex.hy
Executable file
18
tests/resources/argparse_ex.hy
Executable 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"))))
|
@ -25,13 +25,18 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def run_cmd(cmd):
|
def run_cmd(cmd, stdin_data=None):
|
||||||
p = subprocess.Popen(cmd,
|
p = subprocess.Popen(cmd,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
shell=True)
|
shell=True)
|
||||||
stdout = ""
|
stdout = ""
|
||||||
stderr = ""
|
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
|
# Read stdout and stderr otherwise if the PIPE buffer is full, we might
|
||||||
# wait for ever…
|
# wait for ever…
|
||||||
while p.poll() is None:
|
while p.poll() is None:
|
||||||
@ -41,28 +46,28 @@ def run_cmd(cmd):
|
|||||||
|
|
||||||
|
|
||||||
def test_bin_hy():
|
def test_bin_hy():
|
||||||
ret = run_cmd("echo | bin/hy")
|
ret = run_cmd("hy", "")
|
||||||
assert ret[0] == 0
|
assert ret[0] == 0
|
||||||
|
|
||||||
|
|
||||||
def test_bin_hy_stdin():
|
def test_bin_hy_stdin():
|
||||||
ret = run_cmd("echo \"(koan)\" | bin/hy")
|
ret = run_cmd("hy", '(koan)')
|
||||||
assert ret[0] == 0
|
assert ret[0] == 0
|
||||||
assert "monk" in ret[1]
|
assert "monk" in ret[1]
|
||||||
|
|
||||||
|
|
||||||
def test_bin_hy_cmd():
|
def test_bin_hy_cmd():
|
||||||
ret = run_cmd("bin/hy -c \"(koan)\"")
|
ret = run_cmd("hy -c \"(koan)\"")
|
||||||
assert ret[0] == 0
|
assert ret[0] == 0
|
||||||
assert "monk" in ret[1]
|
assert "monk" in ret[1]
|
||||||
|
|
||||||
ret = run_cmd("bin/hy -c \"(koan\"")
|
ret = run_cmd("hy -c \"(koan\"")
|
||||||
assert ret[0] == 1
|
assert ret[0] == 1
|
||||||
assert "LexException" in ret[1]
|
assert "LexException" in ret[1]
|
||||||
|
|
||||||
|
|
||||||
def test_bin_hy_icmd():
|
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
|
assert ret[0] == 0
|
||||||
output = ret[1]
|
output = ret[1]
|
||||||
|
|
||||||
@ -71,16 +76,41 @@ def test_bin_hy_icmd():
|
|||||||
|
|
||||||
|
|
||||||
def test_bin_hy_file():
|
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 ret[0] == 0
|
||||||
assert "27" in ret[1]
|
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():
|
def test_hy2py():
|
||||||
# XXX Astor doesn't seem to support Python3 :(
|
# XXX Astor doesn't seem to support Python3 :(
|
||||||
if sys.version_info[0] == 3:
|
if sys.version_info[0] == 3:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# and running this script this way doesn't work on Windows
|
||||||
|
if os.name == "nt":
|
||||||
|
return
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for dirpath, dirnames, filenames in os.walk("tests/native_tests"):
|
for dirpath, dirnames, filenames in os.walk("tests/native_tests"):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
|
Loading…
Reference in New Issue
Block a user