Fix #1243: read raises EOFError on false inputs (#1244)

* Fix #1243: `read` raises EOFError on false inputs

* Fix crash when trying to `eval` false values
This commit is contained in:
Kodi Arfer 2017-03-06 08:51:25 -08:00 committed by Ryan Gonzalez
parent 8b6a45e43a
commit 5f00921dea
4 changed files with 42 additions and 16 deletions

2
NEWS
View File

@ -15,6 +15,8 @@ Changes from 0.12.1
* Shadowed comparison operators now use `and` instead of `&` * Shadowed comparison operators now use `and` instead of `&`
for chained comparisons for chained comparisons
* partition no longer prematurely exhausts input iterators * partition no longer prematurely exhausts input iterators
* read and read-str no longer raise an error when the input
parses to a false value (e.g., the empty string)
Changes from 0.12.0 Changes from 0.12.0

View File

@ -24,9 +24,9 @@
# 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.
from hy.models import (HyExpression, HyKeyword, HyInteger, HyComplex, HyString, from hy.models import (HyObject, HyExpression, HyKeyword, HyInteger, HyComplex,
HyBytes, HySymbol, HyFloat, HyList, HySet, HyDict, HyString, HyBytes, HySymbol, HyFloat, HyList, HySet,
HyCons) HyDict, HyCons)
from hy.errors import HyCompileError, HyTypeError from hy.errors import HyCompileError, HyTypeError
from hy.lex.parser import hy_symbol_mangle from hy.lex.parser import hy_symbol_mangle
@ -2689,7 +2689,10 @@ def hy_compile(tree, module_name, root=ast.Module, get_expr=False):
body = [] body = []
expr = None expr = None
if tree: if not (isinstance(tree, HyObject) or type(tree) is list):
raise HyCompileError("tree must be a HyObject or a list")
if isinstance(tree, HyObject) or tree:
compiler = HyASTCompiler(module_name) compiler = HyASTCompiler(module_name)
result = compiler.compile(tree) result = compiler.compile(tree)
expr = result.force_expr expr = result.force_expr
@ -2697,10 +2700,9 @@ def hy_compile(tree, module_name, root=ast.Module, get_expr=False):
if not get_expr: if not get_expr:
result += result.expr_as_stmt() result += result.expr_as_stmt()
if isinstance(tree, list): # We need to test that the type is *exactly* `list` because we don't
spoof_tree = tree[0] # want to do `tree[0]` on HyList or such.
else: spoof_tree = tree[0] if type(tree) is list else tree
spoof_tree = tree
body = compiler.imports_as_stmts(spoof_tree) + result.stmts body = compiler.imports_as_stmts(spoof_tree) + result.stmts
ret = root(body=body) ret = root(body=body)

View File

@ -435,17 +435,17 @@
[eof ""]] [eof ""]]
"Read from input and returns a tokenized string. "Read from input and returns a tokenized string.
Can take a given input buffer to read from" Can take a given input buffer to read from"
(def buff "") (setv buff "")
(while True (while True
(def inn (str (.readline from-file))) (setv inn (string (.readline from-file)))
(if (= inn eof) (if (= inn eof)
(raise (EOFError "Reached end of file" ))) (raise (EOFError "Reached end of file")))
(setv buff (+ buff inn)) (+= buff inn)
(try (try
(def parsed (first (tokenize buff))) (setv parsed (first (tokenize buff)))
(except [e [PrematureEndOfInput IndexError]]) (except [e [PrematureEndOfInput IndexError]])
(else (if parsed (break))))) (else (break))))
parsed) parsed)
(defn read-str [input] (defn read-str [input]
"Reads and tokenizes first line of input" "Reads and tokenizes first line of input"

View File

@ -1055,6 +1055,19 @@
(assert (= None (eval (quote (print "")))))) (assert (= None (eval (quote (print ""))))))
(defn test-eval-false []
(assert (is (eval 'False) False))
(assert (is (eval 'None) None))
(assert (= (eval '0) 0))
(assert (= (eval '"") ""))
(assert (= (eval 'b"") b""))
(assert (= (eval ':) :))
(assert (= (eval '[]) []))
(assert (= (eval '(,)) (,)))
(assert (= (eval '{}) {}))
(assert (= (eval '#{}) #{})))
(defn test-eval-globals [] (defn test-eval-globals []
"NATIVE: test eval with explicit global dict" "NATIVE: test eval with explicit global dict"
(assert (= 'bar (eval (quote foo) {'foo 'bar}))) (assert (= 'bar (eval (quote foo) {'foo 'bar})))
@ -1383,7 +1396,16 @@
(defn test-read-str [] (defn test-read-str []
"NATIVE: test read-str" "NATIVE: test read-str"
(assert (= (read-str "(print 1)") '(print 1)))) (assert (= (read-str "(print 1)") '(print 1)))
(assert (is (type (read-str "(print 1)")) (type '(print 1))))
; Watch out for false values: https://github.com/hylang/hy/issues/1243
(assert (= (read-str "\"\"") '""))
(assert (is (type (read-str "\"\"")) (type '"")))
(assert (= (read-str "[]") '[]))
(assert (is (type (read-str "[]")) (type '[])))
(assert (= (read-str "0") '0))
(assert (is (type (read-str "0")) (type '0))))
(defn test-keyword-creation [] (defn test-keyword-creation []
"NATIVE: Test keyword creation" "NATIVE: Test keyword creation"