Merge pull request #1360 from gilch/model-repr

proper reprs for Hy models
This commit is contained in:
Ryan Gonzalez 2017-09-18 08:45:28 -05:00 committed by GitHub
commit db210929d0
7 changed files with 509 additions and 144 deletions

View File

@ -22,12 +22,18 @@ Example:
.. code-block:: hy .. code-block:: hy
=> (import [hy.contrib.walk [walk]]) => (import [hy.contrib.walk [walk]])
=> (setv a '(a b c d e f)) => (setv a '(a b c d e f))
=> (walk ord identity a) => (walk ord identity a)
(97 98 99 100 101 102) HyExpression([
=> (walk ord first a) 97,
97 98,
99,
100,
101,
102])
=> (walk ord first a)
97
postwalk postwalk
--------- ---------
@ -41,25 +47,73 @@ each sub-form, uses ``f`` 's return value in place of the original.
.. code-block:: hy .. code-block:: hy
=> (import [hy.contrib.walk [postwalk]]) => (import [hy.contrib.walk [postwalk]])
=> (def trail '([1 2 3] [4 [5 6 [7]]])) => (def trail '([1 2 3] [4 [5 6 [7]]]))
=> (defn walking [x] => (defn walking [x]
(print "Walking:" x) ... (print "Walking:" x :sep "\n")
x ) ... x)
=> (postwalk walking trail) => (postwalk walking trail)
Walking: 1 Walking:
Walking: 2 1
Walking: 3 Walking:
Walking: (1 2 3) 2
Walking: 4 Walking:
Walking: 5 3
Walking: 6 Walking:
Walking: 7 HyExpression([
Walking: (7) HyInteger(1),
Walking: (5 6 [7]) HyInteger(2),
Walking: (4 [5 6 [7]]) HyInteger(3)])
Walking: ([1 2 3] [4 [5 6 [7]]]) Walking:
([1 2 3] [4 [5 6 [7]]]) 4
Walking:
5
Walking:
6
Walking:
7
Walking:
HyExpression([
HyInteger(7)])
Walking:
HyExpression([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])
Walking:
HyExpression([
HyInteger(4),
HyList([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])])
Walking:
HyExpression([
HyList([
HyInteger(1),
HyInteger(2),
HyInteger(3)]),
HyList([
HyInteger(4),
HyList([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])])])
HyExpression([
HyList([
HyInteger(1),
HyInteger(2),
HyInteger(3)]),
HyList([
HyInteger(4),
HyList([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])])])
prewalk prewalk
-------- --------
@ -73,22 +127,70 @@ each sub-form, uses ``f`` 's return value in place of the original.
.. code-block:: hy .. code-block:: hy
=> (import [hy.contrib.walk [prewalk]]) => (import [hy.contrib.walk [prewalk]])
=> (def trail '([1 2 3] [4 [5 6 [7]]])) => (def trail '([1 2 3] [4 [5 6 [7]]]))
=> (defn walking [x] => (defn walking [x]
(print "Walking:" x) ... (print "Walking:" x :sep "\n")
x ) ... x)
=> (prewalk walking trail) => (prewalk walking trail)
Walking: ([1 2 3] [4 [5 6 [7]]]) Walking:
Walking: [1 2 3] HyExpression([
Walking: 1 HyList([
Walking: 2 HyInteger(1),
Walking: 3 HyInteger(2),
Walking: [4 [5 6 [7]]] HyInteger(3)]),
Walking: 4 HyList([
Walking: [5 6 [7]] HyInteger(4),
Walking: 5 HyList([
Walking: 6 HyInteger(5),
Walking: [7] HyInteger(6),
Walking: 7 HyList([
([1 2 3] [4 [5 6 [7]]]) HyInteger(7)])])])])
Walking:
HyList([
HyInteger(1),
HyInteger(2),
HyInteger(3)])
Walking:
1
Walking:
2
Walking:
3
Walking:
HyList([
HyInteger(4),
HyList([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])])
Walking:
4
Walking:
HyList([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])
Walking:
5
Walking:
6
Walking:
HyList([
HyInteger(7)])
Walking:
7
HyExpression([
HyList([
HyInteger(1),
HyInteger(2),
HyInteger(3)]),
HyList([
HyInteger(4),
HyList([
HyInteger(5),
HyInteger(6),
HyList([
HyInteger(7)])])])])

View File

@ -890,7 +890,7 @@ doto
.. code-block:: clj .. code-block:: clj
=> (doto [] (.append 1) (.append 2) .reverse) => (doto [] (.append 1) (.append 2) .reverse)
[2 1] [2, 1]
.. code-block:: clj .. code-block:: clj
@ -899,7 +899,7 @@ doto
=> (.append collection 2) => (.append collection 2)
=> (.reverse collection) => (.reverse collection)
=> collection => collection
[2 1] [2, 1]
eval-and-compile eval-and-compile
@ -1383,9 +1383,10 @@ alternatively be written using the apostrophe (``'``) symbol.
.. code-block:: clj .. code-block:: clj
=> (setv x '(print "Hello World")) => (setv x '(print "Hello World"))
; variable x is set to expression & not evaluated => x ; varible x is set to unevaluated expression
=> x HyExpression([
(u'print' u'Hello World') HySymbol('print'),
HyString('Hello World')])
=> (eval x) => (eval x)
Hello World Hello World
@ -1694,12 +1695,17 @@ is aliased to the tilde (``~``) symbol.
.. code-block:: clj .. code-block:: clj
(def name "Cuddles") => (setv nickname "Cuddles")
(quasiquote (= name (unquote name))) => (quasiquote (= nickname (unquote nickname)))
;=> (u'=' u'name' u'Cuddles') HyExpression([
HySymbol('='),
`(= name ~name) HySymbol('nickname'),
;=> (u'=' u'name' u'Cuddles') 'Cuddles'])
=> `(= nickname ~nickname)
HyExpression([
HySymbol('='),
HySymbol('nickname'),
'Cuddles'])
unquote-splice unquote-splice
@ -1715,15 +1721,25 @@ into the form. ``unquote-splice`` is aliased to the ``~@`` syntax.
.. code-block:: clj .. code-block:: clj
(def nums [1 2 3 4]) => (setv nums [1 2 3 4])
(quasiquote (+ (unquote-splice nums))) => (quasiquote (+ (unquote-splice nums)))
;=> ('+' 1 2 3 4) HyExpression([
HySymbol('+'),
`(+ ~@nums) 1,
;=> ('+' 1 2 3 4) 2,
3,
`[1 2 ~@(if (< (nth nums 0) 0) nums)] 4])
;=> ('+' 1 2) => `(+ ~@nums)
HyExpression([
HySymbol('+'),
1,
2,
3,
4])
=> `[1 2 ~@(if (neg? (first nums)) nums)]
HyList([
HyInteger(1),
HyInteger(2)])
Here, the last example evaluates to ``('+' 1 2)``, since the condition Here, the last example evaluates to ``('+' 1 2)``, since the condition
``(< (nth nums 0) 0)`` is ``False``, which makes this ``if`` expression ``(< (nth nums 0) 0)`` is ``False``, which makes this ``if`` expression

View File

@ -618,17 +618,29 @@ arguments. If the argument list only has one element, return it.
.. code-block:: hy .. code-block:: hy
=> (list* 1 2 3 4) => (list* 1 2 3 4)
(1 2 3 . 4) <HyCons (
HyInteger(1)
=> (list* 1 2 3 [4]) HyInteger(2)
[1, 2, 3, 4] HyInteger(3)
. HyInteger(4))>
=> (list* 1) => (list* 1 2 3 [4])
1 [HyInteger(1), HyInteger(2), HyInteger(3), 4]
=> (list* 1)
=> (cons? (list* 1 2 3 4)) 1
True => (cons? (list* 1 2 3 4))
True
=> (list* 1 10 2 20 '{})
HyDict([
HyInteger(1), HyInteger(10),
HyInteger(2), HyInteger(20)])
=> (list* 1 10 2 20 {})
<HyCons (
HyInteger(1)
HyInteger(10)
HyInteger(2)
HyInteger(20)
. HyDict())>
.. _macroexpand-fn: .. _macroexpand-fn:
@ -643,11 +655,23 @@ Returns the full macro expansion of *form*.
.. code-block:: hy .. code-block:: hy
=> (macroexpand '(-> (a b) (x y))) => (macroexpand '(-> (a b) (x y)))
(u'x' (u'a' u'b') u'y') HyExpression([
HySymbol('x'),
=> (macroexpand '(-> (a b) (-> (c d) (e f)))) HyExpression([
(u'e' (u'c' (u'a' u'b') u'd') u'f') HySymbol('a'),
HySymbol('b')]),
HySymbol('y')])
=> (macroexpand '(-> (a b) (-> (c d) (e f))))
HyExpression([
HySymbol('e'),
HyExpression([
HySymbol('c'),
HyExpression([
HySymbol('a'),
HySymbol('b')]),
HySymbol('d')]),
HySymbol('f')])
.. _macroexpand-1-fn: .. _macroexpand-1-fn:
@ -662,8 +686,18 @@ Returns the single step macro expansion of *form*.
.. code-block:: hy .. code-block:: hy
=> (macroexpand-1 '(-> (a b) (-> (c d) (e f)))) => (macroexpand-1 '(-> (a b) (-> (c d) (e f))))
(u'_>' (u'a' u'b') (u'c' u'd') (u'e' u'f')) HyExpression([
HySymbol('_>'),
HyExpression([
HySymbol('a'),
HySymbol('b')]),
HyExpression([
HySymbol('c'),
HySymbol('d')]),
HyExpression([
HySymbol('e'),
HySymbol('f')])])
.. _merge-with-fn: .. _merge-with-fn:
@ -839,26 +873,26 @@ Chunks *coll* into *n*-tuples (pairs by default).
.. code-block:: hy .. code-block:: hy
=> (list (partition (range 10))) ; n=2 => (list (partition (range 10))) ; n=2
[(, 0 1) (, 2 3) (, 4 5) (, 6 7) (, 8 9)] [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
The *step* defaults to *n*, but can be more to skip elements, or less for a sliding window with overlap. The *step* defaults to *n*, but can be more to skip elements, or less for a sliding window with overlap.
.. code-block:: hy .. code-block:: hy
=> (list (partition (range 10) 2 3)) => (list (partition (range 10) 2 3))
[(, 0 1) (, 3 4) (, 6 7)] [(0, 1), (3, 4), (6, 7)]
=> (list (partition (range 5) 2 1)) => (list (partition (range 5) 2 1))
[(, 0 1) (, 1 2) (, 2 3) (, 3 4)]) [(0, 1), (1, 2), (2, 3), (3, 4)]
The remainder, if any, is not included unless a *fillvalue* is specified. The remainder, if any, is not included unless a *fillvalue* is specified.
.. code-block:: hy .. code-block:: hy
=> (list (partition (range 10) 3)) => (list (partition (range 10) 3))
[(, 0 1 2) (, 3 4 5) (, 6 7 8)] [(0, 1, 2), (3, 4, 5), (6, 7, 8)]
=> (list (partition (range 10) 3 :fillvalue "x")) => (list (partition (range 10) 3 :fillvalue "x"))
[(, 0 1 2) (, 3 4 5) (, 6 7 8) (, 9 "x" "x")] [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 'x', 'x')]
.. _pos?-fn: .. _pos?-fn:
@ -1220,36 +1254,43 @@ if *from-file* ends before a complete expression can be parsed.
.. code-block:: hy .. code-block:: hy
=> (read) => (read)
(+ 2 2) (+ 2 2)
('+' 2 2) HyExpression([
=> (eval (read)) HySymbol('+'),
(+ 2 2) HyInteger(2),
4 HyInteger(2)])
=> (eval (read))
(+ 2 2)
4
=> (import io)
=> (setv buffer (io.StringIO "(+ 2 2)\n(- 2 1)"))
=> (eval (read :from_file buffer))
4
=> (eval (read :from_file buffer))
1
=> (import io) => (with [f (open "example.hy" "w")]
=> (def buffer (io.StringIO "(+ 2 2)\n(- 2 1)")) ... (.write f "(print 'hello)\n(print \"hyfriends!\")"))
=> (eval (read :from_file buffer)) 35
4 => (with [f (open "example.hy")]
=> (eval (read :from_file buffer)) ... (try (while True
1 ... (setv exp (read f))
... (print "OHY" exp)
=> ; assuming "example.hy" contains: ... (eval exp))
=> ; (print "hello") ... (except [e EOFError]
=> ; (print "hyfriends!") ... (print "EOF!"))))
=> (with [f (open "example.hy")] OHY HyExpression([
... (try HySymbol('print'),
... (while True HyExpression([
... (setv exp (read f)) HySymbol('quote'),
... (print "OHY" exp) HySymbol('hello')])])
... (eval exp)) hello
... (except [e EOFError] OHY HyExpression([
... (print "EOF!")))) HySymbol('print'),
OHY ('print' 'hello') HyString('hyfriends!')])
hello hyfriends!
OHY ('print' 'hyfriends!') EOF!
hyfriends!
EOF!
read-str read-str
-------- --------
@ -1261,11 +1302,12 @@ string:
.. code-block:: hy .. code-block:: hy
=> (read-str "(print 1)") => (read-str "(print 1)")
(u'print' 1L) HyExpression([
=> (eval (read-str "(print 1)")) HySymbol('print'),
1 HyInteger(1)])
=> => (eval (read-str "(print 1)"))
1
.. _remove-fn: .. _remove-fn:
@ -1409,3 +1451,4 @@ are available. Some of their names have been changed:
- ``dropwhile`` has been changed to ``drop-while`` - ``dropwhile`` has been changed to ``drop-while``
- ``filterfalse`` has been changed to ``remove`` - ``filterfalse`` has been changed to ``remove``

View File

@ -39,6 +39,15 @@ Compound Models
Parenthesized and bracketed lists are parsed as compound models by the Parenthesized and bracketed lists are parsed as compound models by the
Hy parser. Hy parser.
Hy uses pretty-printing reprs for its compound models by default.
If this is causing issues,
it can be turned off globally by setting ``hy.models.PRETTY`` to ``False``,
or temporarily by using the ``hy.models.pretty`` context manager.
Hy also attempts to color pretty reprs using ``clint.textui.colored``.
This module has a flag to disable coloring,
and a method ``clean`` to strip colored strings of their color tags.
.. _hylist: .. _hylist:
HyList HyList

View File

@ -66,7 +66,7 @@
(or (is t HyKeyword) (and (is t str-type) (.startswith x HyKeyword.PREFIX))) (or (is t HyKeyword) (and (is t str-type) (.startswith x HyKeyword.PREFIX)))
(cut x 1) (cut x 1)
(in t [str-type HyString bytes-type HyBytes]) (do (in t [str-type HyString bytes-type HyBytes]) (do
(setv r (.lstrip (repr x) "ub")) (setv r (.lstrip (base-repr x) "ub"))
(+ (if (in t [bytes-type HyBytes]) "b" "") (if (.startswith "\"" r) (+ (if (in t [bytes-type HyBytes]) "b" "") (if (.startswith "\"" r)
; If Python's built-in repr produced a double-quoted string, use ; If Python's built-in repr produced a double-quoted string, use
; that. ; that.
@ -75,9 +75,9 @@
; convert it. ; convert it.
(+ "\"" (.replace (cut r 1 -1) "\"" "\\\"") "\"")))) (+ "\"" (.replace (cut r 1 -1) "\"" "\\\"") "\""))))
(and (not PY3) (is t int)) (and (not PY3) (is t int))
(.format "(int {})" (repr x)) (.format "(int {})" (base-repr x))
(and (not PY3) (in t [long_type HyInteger])) (and (not PY3) (in t [long_type HyInteger]))
(.rstrip (repr x) "L") (.rstrip (base-repr x) "L")
(and (in t [float HyFloat]) (isnan x)) (and (in t [float HyFloat]) (isnan x))
"NaN" "NaN"
(and (in t [float HyFloat]) (= x Inf)) (and (in t [float HyFloat]) (= x Inf))
@ -85,9 +85,18 @@
(and (in t [float HyFloat]) (= x -Inf)) (and (in t [float HyFloat]) (= x -Inf))
"-Inf" "-Inf"
(in t [complex HyComplex]) (in t [complex HyComplex])
(.replace (.replace (.strip (repr x) "()") "inf" "Inf") "nan" "NaN") (.replace (.replace (.strip (base-repr x) "()") "inf" "Inf") "nan" "NaN")
(is t fraction) (is t fraction)
(.format "{}/{}" (f x.numerator q) (f x.denominator q)) (.format "{}/{}" (f x.numerator q) (f x.denominator q))
; else ; else
(repr x)))) (base-repr x))))
(f obj False)) (f obj False))
(defn base-repr [x]
(unless (instance? HyObject x)
(return (repr x)))
; Call (.repr x) using the first class of x that doesn't inherit from
; HyObject.
(.__repr__
(next (genexpr t [t (. (type x) __mro__)] (not (issubclass t HyObject))))
x))

View File

@ -3,9 +3,28 @@
# license. See the LICENSE. # license. See the LICENSE.
from __future__ import unicode_literals from __future__ import unicode_literals
from contextlib import contextmanager
from math import isnan, isinf from math import isnan, isinf
from hy._compat import PY3, str_type, bytes_type, long_type, string_types from hy._compat import PY3, str_type, bytes_type, long_type, string_types
from fractions import Fraction from fractions import Fraction
from clint.textui import colored
PRETTY = True
@contextmanager
def pretty(pretty=True):
"""
Context manager to temporarily enable
or disable pretty-printing of Hy model reprs.
"""
global PRETTY
old, PRETTY = PRETTY, pretty
try:
yield
finally:
PRETTY = old
class HyObject(object): class HyObject(object):
@ -25,6 +44,9 @@ class HyObject(object):
return self return self
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, super(HyObject, self).__repr__())
_wrappers = {} _wrappers = {}
@ -59,6 +81,10 @@ def replace_hy_obj(obj, other):
% type(obj)) % type(obj))
def repr_indent(obj):
return repr(obj).replace("\n", "\n ")
class HyString(HyObject, str_type): class HyString(HyObject, str_type):
""" """
Generic Hy String object. Helpful to store string literals from Hy Generic Hy String object. Helpful to store string literals from Hy
@ -109,6 +135,9 @@ class HyKeyword(HyObject, str_type):
obj = str_type.__new__(cls, value) obj = str_type.__new__(cls, value)
return obj return obj
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self[1:]))
def strip_digit_separators(number): def strip_digit_separators(number):
# Don't strip a _ or , if it's the first character, as _42 and # Don't strip a _ or , if it's the first character, as _42 and
@ -217,8 +246,22 @@ class HyList(HyObject, list):
return ret return ret
color = staticmethod(colored.cyan)
def __repr__(self): def __repr__(self):
return "[%s]" % (" ".join([repr(x) for x in self])) return str(self) if PRETTY else super(HyList, self).__repr__()
def __str__(self):
with pretty():
c = self.color
if self:
return ("{}{}\n {}{}").format(
c(self.__class__.__name__),
c("(["),
(c(",") + "\n ").join([repr_indent(e) for e in self]),
c("])"))
else:
return '' + c(self.__class__.__name__ + "()")
_wrappers[list] = lambda l: HyList(wrap_value(x) for x in l) _wrappers[list] = lambda l: HyList(wrap_value(x) for x in l)
_wrappers[tuple] = lambda t: HyList(wrap_value(x) for x in t) _wrappers[tuple] = lambda t: HyList(wrap_value(x) for x in t)
@ -229,8 +272,24 @@ class HyDict(HyList):
HyDict (just a representation of a dict) HyDict (just a representation of a dict)
""" """
def __repr__(self): def __str__(self):
return "{%s}" % (" ".join([repr(x) for x in self])) with pretty():
g = colored.green
if self:
pairs = []
for k, v in zip(self[::2],self[1::2]):
k, v = repr_indent(k), repr_indent(v)
pairs.append(
("{0}{c}\n {1}\n "
if '\n' in k+v
else "{0}{c} {1}").format(k, v, c=g(',')))
if len(self) % 2 == 1:
pairs.append("{} {}\n".format(
repr_indent(self[-1]), g("# odd")))
return "{}\n {}{}".format(
g("HyDict(["), ("{c}\n ".format(c=g(',')).join(pairs)), g("])"))
else:
return '' + g("HyDict()")
def keys(self): def keys(self):
return self[0::2] return self[0::2]
@ -248,9 +307,7 @@ class HyExpression(HyList):
""" """
Hy S-Expression. Basically just a list. Hy S-Expression. Basically just a list.
""" """
color = staticmethod(colored.yellow)
def __repr__(self):
return "(%s)" % (" ".join([repr(x) for x in self]))
_wrappers[HyExpression] = lambda e: HyExpression(wrap_value(x) for x in e) _wrappers[HyExpression] = lambda e: HyExpression(wrap_value(x) for x in e)
_wrappers[Fraction] = lambda e: HyExpression( _wrappers[Fraction] = lambda e: HyExpression(
@ -261,9 +318,7 @@ class HySet(HyList):
""" """
Hy set (just a representation of a set) Hy set (just a representation of a set)
""" """
color = staticmethod(colored.red)
def __repr__(self):
return "#{%s}" % (" ".join([repr(x) for x in self]))
_wrappers[set] = lambda s: HySet(wrap_value(x) for x in s) _wrappers[set] = lambda s: HySet(wrap_value(x) for x in s)
@ -339,10 +394,24 @@ class HyCons(HyObject):
HyObject.replace(self, other) HyObject.replace(self, other)
def __repr__(self): def __repr__(self):
if isinstance(self.cdr, self.__class__): if PRETTY:
return "(%s %s)" % (repr(self.car), repr(self.cdr)[1:-1]) return str(self)
else: else:
return "(%s . %s)" % (repr(self.car), repr(self.cdr)) return "HyCons({}, {})".format(
repr(self.car), repr(self.cdr))
def __str__(self):
with pretty():
c = colored.yellow
lines = ['' + c("<HyCons (")]
while True:
lines.append(" " + repr_indent(self.car))
if not isinstance(self.cdr, HyCons):
break
self = self.cdr
lines.append("{} {}{}".format(
c("."), repr_indent(self.cdr), c(")>")))
return '\n'.join(lines)
def __eq__(self, other): def __eq__(self, other):
return ( return (

View File

@ -3,9 +3,12 @@
# license. See the LICENSE. # license. See the LICENSE.
import copy import copy
import hy
from clint.textui.colored import clean
from hy._compat import long_type, str_type from hy._compat import long_type, str_type
from hy.models import (wrap_value, replace_hy_obj, HyString, HyInteger, HyList, from hy.models import (wrap_value, replace_hy_obj, HyString, HyInteger, HyList,
HyDict, HySet, HyExpression, HyCons, HyComplex, HyFloat) HyDict, HySet, HyExpression, HyCons, HyComplex, HyFloat,
pretty)
def test_wrap_long_type(): def test_wrap_long_type():
@ -140,3 +143,117 @@ def test_number_model_copy():
c = HyComplex(42j) c = HyComplex(42j)
assert (c == copy.copy(c)) assert (c == copy.copy(c))
assert (c == copy.deepcopy(c)) assert (c == copy.deepcopy(c))
PRETTY_STRINGS = {
k % ('[1.0] {1.0} (1.0) #{1.0} (0.0 1.0 . 2.0)',):
v.format("""
HyList([
HyFloat(1.0)]),
HyDict([
HyFloat(1.0) # odd
]),
HyExpression([
HyFloat(1.0)]),
HySet([
HyFloat(1.0)]),
<HyCons (
HyFloat(0.0)
HyFloat(1.0)
. HyFloat(2.0))>""")
for k, v in {'[%s]': 'HyList([{}])',
'#{%s}': 'HySet([{}])'}.items()}
PRETTY_STRINGS.update({
'{[1.0] {1.0} (1.0) #{1.0} (0.0 1.0 . 2.0)}':
"""HyDict([
HyList([
HyFloat(1.0)]),
HyDict([
HyFloat(1.0) # odd
])
,
HyExpression([
HyFloat(1.0)]),
HySet([
HyFloat(1.0)])
,
<HyCons (
HyFloat(0.0)
HyFloat(1.0)
. HyFloat(2.0))> # odd
])"""
,
'([1.0] {1.0} (1.0) #{1.0} (0.0 1.0 . 2.0) . 3.0)':
"""<HyCons (
HyList([
HyFloat(1.0)])
HyDict([
HyFloat(1.0) # odd
])
HyExpression([
HyFloat(1.0)])
HySet([
HyFloat(1.0)])
<HyCons (
HyFloat(0.0)
HyFloat(1.0)
. HyFloat(2.0))>
. HyFloat(3.0))>"""
,
'[1.0 1j [] {} () #{}]':
"""HyList([
HyFloat(1.0),
HyComplex(1j),
HyList(),
HyDict(),
HyExpression(),
HySet()])"""
,
'{{1j 2j} {1j 2j [][1j]} {[1j][] 1j 2j} {[1j][1j]}}':
"""HyDict([
HyDict([
HyComplex(1j), HyComplex(2j)]),
HyDict([
HyComplex(1j), HyComplex(2j),
HyList(),
HyList([
HyComplex(1j)])
])
,
HyDict([
HyList([
HyComplex(1j)]),
HyList()
,
HyComplex(1j), HyComplex(2j)]),
HyDict([
HyList([
HyComplex(1j)]),
HyList([
HyComplex(1j)])
])
])"""})
def test_compound_model_repr():
HY_LIST_MODELS = (HyExpression, HyDict, HySet, HyList)
with pretty(False):
assert eval(repr(HyCons(1, 2))).__class__ is HyCons
assert eval(repr(HyCons(1, 2))) == HyCons(1, 2)
for model in HY_LIST_MODELS:
assert eval(repr(model())).__class__ is model
assert eval(repr(model([1, 2]))) == model([1, 2])
assert eval(repr(model([1, 2, 3]))) == model([1, 2, 3])
for k, v in PRETTY_STRINGS.items():
# `str` should be pretty, even under `pretty(False)`.
assert clean(str(hy.read_str(k))) == v
for k in PRETTY_STRINGS.keys():
assert eval(repr(hy.read_str(k))) == hy.read_str(k)
with pretty(True):
for model in HY_LIST_MODELS:
assert eval(clean(repr(model()))).__class__ is model
assert eval(clean(repr(model([1, 2])))) == model([1, 2])
assert eval(clean(repr(model([1, 2, 3])))) == model([1, 2, 3])
for k, v in PRETTY_STRINGS.items():
assert clean(repr(hy.read_str(k))) == v