2018-01-01 16:38:33 +01:00
|
|
|
;; Copyright 2018 the authors.
|
2017-04-27 23:16:57 +02:00
|
|
|
;; This file is part of Hy, which is free software licensed under the Expat
|
|
|
|
;; license. See the LICENSE.
|
|
|
|
|
2017-03-20 20:04:00 +01:00
|
|
|
(import
|
2018-03-12 00:25:28 +01:00
|
|
|
[hy._compat [PY3 PY36 PY37]]
|
2017-05-14 17:08:27 +02:00
|
|
|
[math [isnan]]
|
2017-11-01 00:48:59 +01:00
|
|
|
[hy.contrib.hy-repr [hy-repr hy-repr-register]])
|
2017-03-20 20:04:00 +01:00
|
|
|
|
|
|
|
(defn test-hy-repr-roundtrip-from-value []
|
|
|
|
; Test that a variety of values round-trip properly.
|
|
|
|
(setv values [
|
|
|
|
None False True
|
2017-05-14 17:08:27 +02:00
|
|
|
5 5.1 '5 '5.1 Inf -Inf
|
2017-03-20 20:04:00 +01:00
|
|
|
(int 5)
|
|
|
|
1/2
|
2017-05-14 17:08:27 +02:00
|
|
|
5j 5.1j 2+1j 1.2+3.4j Inf-Infj
|
2017-03-20 20:04:00 +01:00
|
|
|
"" b""
|
|
|
|
'"" 'b""
|
|
|
|
"apple bloom" b"apple bloom" "⚘"
|
|
|
|
'"apple bloom" 'b"apple bloom" '"⚘"
|
|
|
|
"single ' quotes" b"single ' quotes"
|
|
|
|
"\"double \" quotes\"" b"\"double \" quotes\""
|
|
|
|
'mysymbol :mykeyword
|
|
|
|
[] (,) #{} (frozenset #{})
|
|
|
|
'[] '(,) '#{} '(frozenset #{})
|
|
|
|
'['[]]
|
|
|
|
'(+ 1 2)
|
|
|
|
[1 2 3] (, 1 2 3) #{1 2 3} (frozenset #{1 2 3})
|
|
|
|
'[1 2 3] '(, 1 2 3) '#{1 2 3} '(frozenset #{1 2 3})
|
2017-10-31 19:58:25 +01:00
|
|
|
{"a" 1 "b" 2 "a" 3} '{"a" 1 "b" 2 "a" 3}
|
2017-07-19 19:25:24 +02:00
|
|
|
[1 [2 3] (, 4 (, 'mysymbol :mykeyword)) {"a" b"hello"} '(f #* a #** b)]
|
|
|
|
'[1 [2 3] (, 4 (, mysymbol :mykeyword)) {"a" b"hello"} (f #* a #** b)]])
|
2017-03-20 20:04:00 +01:00
|
|
|
(for [original-val values]
|
|
|
|
(setv evaled (eval (read-str (hy-repr original-val))))
|
|
|
|
(assert (= evaled original-val))
|
2017-05-14 17:08:27 +02:00
|
|
|
(assert (is (type evaled) (type original-val))))
|
|
|
|
(assert (isnan (eval (read-str (hy-repr NaN))))))
|
2017-03-20 20:04:00 +01:00
|
|
|
|
|
|
|
(defn test-hy-repr-roundtrip-from-str []
|
|
|
|
(setv strs [
|
2017-05-14 17:08:27 +02:00
|
|
|
"'Inf"
|
|
|
|
"'-Inf"
|
|
|
|
"'NaN"
|
|
|
|
"1+2j"
|
|
|
|
"NaN+NaNj"
|
|
|
|
"'NaN+NaNj"
|
2017-03-20 20:04:00 +01:00
|
|
|
"[1 2 3]"
|
|
|
|
"'[1 2 3]"
|
|
|
|
"[1 'a 3]"
|
|
|
|
"'[1 a 3]"
|
|
|
|
"'[1 'a 3]"
|
|
|
|
"[1 '[2 3] 4]"
|
|
|
|
"'[1 [2 3] 4]"
|
|
|
|
"'[1 '[2 3] 4]"
|
|
|
|
"'[1 `[2 3] 4]"
|
|
|
|
"'[1 `[~foo ~@bar] 4]"
|
|
|
|
"'[1 `[~(+ 1 2) ~@(+ [1] [2])] 4]"
|
|
|
|
"'[1 `[~(do (print x 'y) 1)] 4]"
|
|
|
|
"{1 20}"
|
2017-10-31 19:58:25 +01:00
|
|
|
"'{1 10 1 20}"
|
2017-03-20 20:04:00 +01:00
|
|
|
"'asymbol"
|
2017-07-19 19:25:24 +02:00
|
|
|
":akeyword"
|
|
|
|
"'(f #* args #** kwargs)"])
|
2017-03-20 20:04:00 +01:00
|
|
|
(for [original-str strs]
|
|
|
|
(setv rep (hy-repr (eval (read-str original-str))))
|
|
|
|
(assert (= rep original-str))))
|
|
|
|
|
2017-10-31 19:35:46 +01:00
|
|
|
(defn test-hy-repr-no-roundtrip []
|
|
|
|
; Test one of the corner cases in which hy-repr doesn't
|
|
|
|
; round-trip: when a HyObject contains a non-HyObject, we
|
|
|
|
; promote the constituent to a HyObject.
|
|
|
|
|
|
|
|
(setv orig `[a ~5.0])
|
|
|
|
(setv reprd (hy-repr orig))
|
|
|
|
(assert (= reprd "'[a 5.0]"))
|
|
|
|
(setv result (eval (read-str reprd)))
|
|
|
|
|
|
|
|
(assert (is (type (get orig 1)) float))
|
|
|
|
(assert (is (type (get result 1)) HyFloat)))
|
|
|
|
|
2017-11-02 21:35:52 +01:00
|
|
|
(when PY3 (defn test-dict-views []
|
|
|
|
(assert (= (hy-repr (.keys {1 2})) "(dict-keys [1])"))
|
|
|
|
(assert (= (hy-repr (.values {1 2})) "(dict-values [2])"))
|
|
|
|
(assert (= (hy-repr (.items {1 2})) "(dict-items [(, 1 2)])"))))
|
|
|
|
|
2017-11-03 18:51:41 +01:00
|
|
|
(defn test-datetime []
|
|
|
|
(import [datetime :as D])
|
|
|
|
|
|
|
|
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 0))
|
|
|
|
"(datetime.datetime 2009 1 15 15 27 5)"))
|
|
|
|
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 123))
|
|
|
|
"(datetime.datetime 2009 1 15 15 27 5 123)"))
|
|
|
|
(when PY3
|
|
|
|
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 123 :tzinfo D.timezone.utc))
|
|
|
|
"(datetime.datetime 2009 1 15 15 27 5 123 :tzinfo datetime.timezone.utc)")))
|
|
|
|
(when PY36
|
|
|
|
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 :fold 1))
|
|
|
|
"(datetime.datetime 2009 1 15 15 27 5 :fold 1)"))
|
|
|
|
(assert (= (hy-repr (D.datetime 2009 1 15 15 27 5 :fold 1 :tzinfo D.timezone.utc))
|
|
|
|
"(datetime.datetime 2009 1 15 15 27 5 :tzinfo datetime.timezone.utc :fold 1)")))
|
|
|
|
|
|
|
|
(assert (= (hy-repr (D.date 2015 11 3))
|
|
|
|
"(datetime.date 2015 11 3)"))
|
|
|
|
|
|
|
|
(assert (= (hy-repr (D.time 1 2 3))
|
|
|
|
"(datetime.time 1 2 3)"))
|
|
|
|
(assert (= (hy-repr (D.time 1 2 3 4567))
|
|
|
|
"(datetime.time 1 2 3 4567)"))
|
|
|
|
(when PY36
|
|
|
|
(assert (= (hy-repr (D.time 1 2 3 4567 :fold 1 :tzinfo D.timezone.utc))
|
|
|
|
"(datetime.time 1 2 3 4567 :tzinfo datetime.timezone.utc :fold 1)"))))
|
|
|
|
|
2017-11-03 19:56:46 +01:00
|
|
|
(defn test-collections []
|
|
|
|
(import collections)
|
|
|
|
(assert (= (hy-repr (collections.defaultdict :a 8))
|
|
|
|
(if PY3
|
|
|
|
"(defaultdict None {\"a\" 8})"
|
|
|
|
"(defaultdict None {b\"a\" 8})")))
|
|
|
|
(assert (= (hy-repr (collections.defaultdict int :a 8))
|
|
|
|
(if PY3
|
|
|
|
"(defaultdict <class 'int'> {\"a\" 8})"
|
|
|
|
"(defaultdict <type 'int'> {b\"a\" 8})")))
|
|
|
|
(assert (= (hy-repr (collections.Counter [15 15 15 15]))
|
|
|
|
(if PY3
|
|
|
|
"(Counter {15 4})"
|
|
|
|
"(Counter {15 (int 4)})")))
|
|
|
|
(setv C (collections.namedtuple "Fooey" ["cd" "a_b"]))
|
|
|
|
(assert (= (hy-repr (C 11 12))
|
|
|
|
"(Fooey :cd 11 :a_b 12)")))
|
|
|
|
|
2017-03-20 20:04:00 +01:00
|
|
|
(defn test-hy-model-constructors []
|
|
|
|
(import hy)
|
|
|
|
(assert (= (hy-repr (hy.HyInteger 7)) "'7"))
|
|
|
|
(assert (= (hy-repr (hy.HyString "hello")) "'\"hello\""))
|
|
|
|
(assert (= (hy-repr (hy.HyList [1 2 3])) "'[1 2 3]"))
|
2017-10-31 19:58:25 +01:00
|
|
|
(assert (= (hy-repr (hy.HyDict [1 2 3])) "'{1 2 3}")))
|
2017-03-20 20:04:00 +01:00
|
|
|
|
|
|
|
(defn test-hy-repr-self-reference []
|
|
|
|
|
|
|
|
(setv x [1 2 3])
|
|
|
|
(setv (get x 1) x)
|
|
|
|
(assert (= (hy-repr x) "[1 [...] 3]"))
|
|
|
|
|
|
|
|
(setv x {1 2 3 [4 5] 6 7})
|
|
|
|
(setv (get x 3 1) x)
|
2018-06-07 21:18:49 +02:00
|
|
|
(assert (in (hy-repr x) (lfor
|
2017-03-20 20:04:00 +01:00
|
|
|
; The ordering of a dictionary isn't guaranteed, so we need
|
|
|
|
; to check for all possible orderings.
|
2018-06-07 21:18:49 +02:00
|
|
|
p (permutations ["1 2" "3 [4 {...}]" "6 7"])
|
|
|
|
(+ "{" (.join " " p) "}")))))
|
2017-03-20 20:04:00 +01:00
|
|
|
|
2017-11-05 20:12:38 +01:00
|
|
|
(defn test-matchobject []
|
|
|
|
(import re)
|
|
|
|
(setv mo (re.search "b+" "aaaabbbccc"))
|
|
|
|
(assert (= (hy-repr mo)
|
|
|
|
(.format
|
2018-03-12 00:25:28 +01:00
|
|
|
#[[<{} object; :span {} :match "bbb">]]
|
|
|
|
(if PY37 "re.Match" (+ (. (type mo) __module__) ".SRE_Match"))
|
2017-11-05 20:12:38 +01:00
|
|
|
(if PY3 "(, 4 7)" "(, (int 4) (int 7))")))))
|
|
|
|
|
2017-11-01 00:48:59 +01:00
|
|
|
(defn test-hy-repr-custom []
|
|
|
|
|
|
|
|
(defclass C [object])
|
|
|
|
(hy-repr-register C (fn [x] "cuddles"))
|
|
|
|
(assert (= (hy-repr (C)) "cuddles"))
|
|
|
|
|
|
|
|
(defclass Container [object]
|
|
|
|
[__init__ (fn [self value]
|
|
|
|
(setv self.value value))])
|
|
|
|
(hy-repr-register Container :placeholder "(Container ...)" (fn [x]
|
|
|
|
(+ "(Container " (hy-repr x.value) ")")))
|
|
|
|
(setv container (Container 5))
|
|
|
|
(setv container.value container)
|
|
|
|
(assert (= (hy-repr container) "(Container (Container ...))"))
|
|
|
|
(setv container.value [1 container 3])
|
|
|
|
(assert (= (hy-repr container) "(Container [1 (Container ...) 3])")))
|
2017-03-20 20:04:00 +01:00
|
|
|
|
|
|
|
(defn test-hy-repr-fallback []
|
2017-11-01 00:48:59 +01:00
|
|
|
(defclass D [object]
|
|
|
|
[__repr__ (fn [self] "cuddles")])
|
2017-03-20 20:04:00 +01:00
|
|
|
(assert (= (hy-repr (D)) "cuddles")))
|