Expose read, read_str, and eval in Python

- Expose `read`, `read_str`, and `eval` in Python
- Add string evaluation example to interop section of docs
- Add test for `eval`
- Explain `eof` keyword argument in `read` docstring
This commit is contained in:
Jordan Danford 2017-08-05 17:29:15 -07:00
parent b6dceb0aa3
commit c67b8bccb9
5 changed files with 41 additions and 2 deletions

4
NEWS
View File

@ -27,6 +27,10 @@ Changes from 0.13.0
* `exec` now works under Python 2 * `exec` now works under Python 2
* No TypeError from multi-arity defn returning values evaluating to None * No TypeError from multi-arity defn returning values evaluating to None
[ Misc. Improvements ]
* `read`, `read_str`, and `eval` are exposed and documented as top-level
functions in the `hy` module
Changes from 0.12.1 Changes from 0.12.1
[ Language Changes ] [ Language Changes ]

View File

@ -131,5 +131,17 @@ argument::
test() test()
bar bar
Evaluating strings of Hy code from Python
-----------------------------------------
Evaluating a string (or ``file`` object) containing a Hy expression requires
two separate steps. First, use the ``read_str`` function (or ``read`` for a
``file`` object) to turn the expression into a Hy model::
>>> import hy
>>> expr = hy.read_str("(- (/ (+ 1 3 88) 2) 8)")
Then, use the ``eval`` function to evaluate it::
>>> hy.eval(expr)
38.0

View File

@ -10,3 +10,7 @@ from hy.models import HyExpression, HyInteger, HyKeyword, HyComplex, HyString, H
import hy.importer # NOQA import hy.importer # NOQA
# we import for side-effects. # we import for side-effects.
from hy.core.language import read, read_str # NOQA
from hy.importer import hy_eval as eval # NOQA

View File

@ -426,8 +426,8 @@
(defn read [&optional [from-file sys.stdin] (defn read [&optional [from-file sys.stdin]
[eof ""]] [eof ""]]
"Read from input and returns a tokenized string. "Read from input and returns a tokenized string. Can take a given input buffer
Can take a given input buffer to read from" to read from, and a single byte as EOF (defaults to an empty string)"
(setv buff "") (setv buff "")
(while True (while True
(setv inn (string (.readline from-file))) (setv inn (string (.readline from-file)))

View File

@ -2,12 +2,14 @@
# This file is part of Hy, which is free software licensed under the Expat # This file is part of Hy, which is free software licensed under the Expat
# license. See the LICENSE. # license. See the LICENSE.
import hy
from hy.importer import (import_file_to_module, import_buffer_to_ast, from hy.importer import (import_file_to_module, import_buffer_to_ast,
MetaLoader, get_bytecode_path) MetaLoader, get_bytecode_path)
from hy.errors import HyTypeError from hy.errors import HyTypeError
import os import os
import ast import ast
import tempfile import tempfile
from fractions import Fraction
def test_basics(): def test_basics():
@ -64,3 +66,20 @@ def test_import_autocompiles():
os.remove(f.name) os.remove(f.name)
os.remove(get_bytecode_path(f.name)) os.remove(get_bytecode_path(f.name))
def test_eval():
def eval_str(s):
return hy.eval(hy.read_str(s))
assert eval_str('[1 2 3]') == [1, 2, 3]
assert eval_str('{"dog" "bark" "cat" "meow"}') == {
'dog': 'bark', 'cat': 'meow'}
assert eval_str('(, 1 2 3)') == (1, 2, 3)
assert eval_str('#{3 1 2}') == {1, 2, 3}
assert eval_str('1/2') == Fraction(1, 2)
assert eval_str('(.strip " fooooo ")') == 'fooooo'
assert eval_str(
'(if True "this is if true" "this is if false")') == "this is if true"
assert eval_str('(list-comp (pow num 2) (num (range 100)) (= (% num 2) 1))') == [
pow(num, 2) for num in range(100) if num % 2 == 1]