From 7fe997e9f7a1049c63957ca3c9dd52f8f656c3be Mon Sep 17 00:00:00 2001 From: schuster-rainer Date: Sat, 1 Mar 2014 00:23:49 +0100 Subject: [PATCH 01/35] Added name and keyword functions to core --- hy/core/language.hy | 33 ++++++++++++++++++++++++++++++--- hy/models/keyword.py | 5 +++-- tests/native_tests/language.hy | 26 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/hy/core/language.hy b/hy/core/language.hy index 19e8486..21c7808 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -25,7 +25,8 @@ (import [hy._compat [long-type]]) ; long for python2, int for python3 -(import [hy.models.cons [HyCons]]) +(import [hy.models.cons [HyCons]] + [hy.models.keyword [HyKeyword KEYWORD_PREFIX]]) (defn _numeric-check [x] @@ -351,10 +352,36 @@ (import functools) (map (functools.partial (fn [f args] (apply f args)) func) (apply zip lists)))) +(defn hyify [text] + "Convert text to match hy identifier" + (.replace (string text) "_" "-")) + +(defn keyword [value] + "Create a keyword from the given value. Strings numbers and even objects + with the __name__ magic will work" + (if (and (string? value) (value.startswith KEYWORD_PREFIX)) + (hyify value) + (if (string? value) + (HyKeyword (+ ":" (hyify value))) + (try + (hyify (.__name__ value)) + (catch [] (HyKeyword (+ ":" (string value)))))))) + +(defn name [value] + "Convert the given value to a string. Keyword special character will be stripped. + String will be used as is. Even objects with the __name__ magic will work" + (if (and (string? value) (value.startswith KEYWORD_PREFIX)) + (hyify (slice value 2)) + (if (string? value) + (hyify value) + (try + (hyify (. value __name__)) + (catch [] (string value)))))) + (def *exports* '[calling-module-name coll? cons cons? cycle dec distinct disassemble drop drop-while empty? even? every? first filter flatten float? gensym identity inc instance? integer - integer? integer-char? iterable? iterate iterator? - list* macroexpand macroexpand-1 neg? nil? none? nth + integer? integer-char? iterable? iterate iterator? keyword + list* macroexpand macroexpand-1 name neg? nil? none? nth numeric? odd? pos? remove repeat repeatedly rest second some string string? take take-nth take-while zero? zipwith]) diff --git a/hy/models/keyword.py b/hy/models/keyword.py index 6d25633..a3d778b 100644 --- a/hy/models/keyword.py +++ b/hy/models/keyword.py @@ -22,6 +22,7 @@ from __future__ import unicode_literals from hy.models import HyObject from hy._compat import str_type +KEYWORD_PREFIX = "\uFDD0" class HyKeyword(HyObject, str_type): """Generic Hy Keyword object. It's either a ``str`` or a ``unicode``, @@ -29,8 +30,8 @@ class HyKeyword(HyObject, str_type): """ def __new__(cls, value): - if not value.startswith("\uFDD0"): - value = "\uFDD0" + value + if not value.startswith(KEYWORD_PREFIX): + value = KEYWORD_PREFIX + value obj = str_type.__new__(cls, value) return obj diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 5e6f6c7..dc91da0 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -988,3 +988,29 @@ "NATIVE: test keyword quoting magic" (assert (= :foo "\ufdd0:foo")) (assert (= `:foo "\ufdd0:foo"))) + +(defn test-keyword-creation [] + "NATIVE: Test keyword creation" + (assert (= (keyword "foo") :foo)) + (assert (= (keyword "foo_bar") :foo-bar)) + (assert (= (keyword `foo) :foo)) + (assert (= (keyword `foo-bar) :foo-bar)) + (assert (= (keyword 'foo) :foo)) + (assert (= (keyword 'foo-bar) :foo-bar)) + (assert (= (keyword 1) :1)) + (assert (= (keyword 1.0) :1.0)) + (assert (= (keyword :foo_bar) :foo-bar))) + +(defn test-name-conversion [] + "NATIVE: Test name conversion" + (assert (= (name "foo") "foo")) + (assert (= (name "foo_bar") "foo-bar")) + (assert (= (name `foo) "foo")) + (assert (= (name `foo_bar) "foo-bar")) + (assert (= (name 'foo) "foo")) + (assert (= (name 'foo_bar) "foo-bar")) + (assert (= (name 1) "1")) + (assert (= (name 1.0) "1.0")) + (assert (= (name :foo) "foo")) + (assert (= (name :foo_bar) "foo-bar")) + (assert (= (name test-name-conversion) "test-name-conversion"))) From a49047b7a3b77e267ec9d148c2ee6ac39cbabf7f Mon Sep 17 00:00:00 2001 From: schuster-rainer Date: Sat, 1 Mar 2014 00:23:49 +0100 Subject: [PATCH 02/35] Added name and keyword functions to core --- hy/core/language.hy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hy/core/language.hy b/hy/core/language.hy index 21c7808..c65bcbe 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -26,7 +26,7 @@ (import [hy._compat [long-type]]) ; long for python2, int for python3 (import [hy.models.cons [HyCons]] - [hy.models.keyword [HyKeyword KEYWORD_PREFIX]]) + [hy.models.keyword [HyKeyword *keyword-prefix*]]) (defn _numeric-check [x] @@ -359,7 +359,7 @@ (defn keyword [value] "Create a keyword from the given value. Strings numbers and even objects with the __name__ magic will work" - (if (and (string? value) (value.startswith KEYWORD_PREFIX)) + (if (and (string? value) (value.startswith *keyword-prefix*)) (hyify value) (if (string? value) (HyKeyword (+ ":" (hyify value))) @@ -370,7 +370,7 @@ (defn name [value] "Convert the given value to a string. Keyword special character will be stripped. String will be used as is. Even objects with the __name__ magic will work" - (if (and (string? value) (value.startswith KEYWORD_PREFIX)) + (if (and (string? value) (value.startswith *keyword-prefix*)) (hyify (slice value 2)) (if (string? value) (hyify value) From c1b83c0265cacfbf1a3f2865c960b485fba28cbd Mon Sep 17 00:00:00 2001 From: schuster-rainer Date: Sat, 1 Mar 2014 01:00:46 +0100 Subject: [PATCH 03/35] Fixed flake8 blank line issue --- hy/models/keyword.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hy/models/keyword.py b/hy/models/keyword.py index a3d778b..32b2306 100644 --- a/hy/models/keyword.py +++ b/hy/models/keyword.py @@ -22,8 +22,10 @@ from __future__ import unicode_literals from hy.models import HyObject from hy._compat import str_type + KEYWORD_PREFIX = "\uFDD0" + class HyKeyword(HyObject, str_type): """Generic Hy Keyword object. It's either a ``str`` or a ``unicode``, depending on the Python version. From ecc664337d25fdc0cefdf7a51eaa54ce5288a653 Mon Sep 17 00:00:00 2001 From: han semaj Date: Sat, 23 Aug 2014 23:35:31 +1200 Subject: [PATCH 04/35] Make nth return default value when out of bounds --- docs/language/core.rst | 21 ++++++++++++++------- hy/core/language.hy | 9 ++++----- tests/native_tests/core.hy | 11 +++++++++-- tests/native_tests/language.hy | 2 ++ 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index f18eedf..a05979e 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -534,9 +534,9 @@ nth Usage: ``(nth coll n)`` -Return the `nth` item in a collection, counting from 0. Unlike -``get``, ``nth`` works on both iterators and iterables. Raises ``IndexError`` -if the `n` is outside the range of ``coll`` or ``ValueError`` if it's negative. +Return the `nth` item in a collection, counting from 0. Return ``nil`` +if out of bounds (unless specified otherwise). Raise ``ValueError`` if +``n`` is negative. .. code-block:: hy @@ -546,14 +546,21 @@ if the `n` is outside the range of ``coll`` or ``ValueError`` if it's negative. => (nth [1 2 4 7] 3) 7 - => (nth [1 2 4 7] 5) - Traceback (most recent call last): - ... - IndexError: 5 + => (nil? (nth [1 2 4 7] 5)) + True + + => (nth [1 2 4 7] 5 "default") + 'default' => (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2)) 5 + => (nth [1 2 4 7] -1) + Traceback (most recent call last): + ... + ValueError: Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize. + + .. _numeric?-fn: numeric? diff --git a/hy/core/language.hy b/hy/core/language.hy index cb04eea..bc5587a 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -270,11 +270,10 @@ (import numbers) (instance? numbers.Number x)) -(defn nth [coll index] - "Return nth item in collection or sequence, counting from 0" - (try - (next (drop index coll)) - (catch [e StopIteration] (raise (IndexError index))))) +(defn nth [coll n &optional [default nil]] + "Return nth item in collection or sequence, counting from 0. + Return nil if out of bounds unless specified otherwise." + (next (drop n coll) default)) (defn odd? [n] "Return true if n is an odd number" diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index a4042b6..2f858ce 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -30,6 +30,9 @@ (defn assert-equal [x y] (assert (= x y))) +(defn assert-nil [x] + (assert (is x nil))) + (defn test-coll? [] "NATIVE: testing coll?" (assert-true (coll? [1 2 3])) @@ -390,13 +393,17 @@ "NATIVE: testing the nth function" (assert-equal 2 (nth [1 2 4 7] 1)) (assert-equal 7 (nth [1 2 4 7] 3)) - (try (do (nth [1 2 4 7] 5) (assert False)) - (catch [e [IndexError]] nil)) + (assert-nil (nth [1 2 4 7] 5)) + (assert-equal (nth [1 2 4 7] 5 "some default value") + "some default value") ; with default specified (try (do (nth [1 2 4 7] -1) (assert False)) (catch [e [ValueError]] nil)) ;; now for iterators (assert-equal 2 (nth (iter [1 2 4 7]) 1)) (assert-equal 7 (nth (iter [1 2 4 7]) 3)) + (assert-nil (nth (iter [1 2 4 7]) 5)) + (assert-equal (nth (iter [1 2 4 7]) 5 "some default value") + "some default value") ; with default specified (try (do (nth (iter [1 2 4 7]) -1) (assert False)) (catch [e [ValueError]] nil)) (assert-equal 5 (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index cc104fa..7f3ba54 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -495,9 +495,11 @@ (setv output (list (gen))) (assert (= [1] output))) + (defn test-first [] "NATIVE: test firsty things" (assert (= (first [1 2 3 4 5]) 1)) + (assert (is (first []) nil)) (assert (= (car [1 2 3 4 5]) 1))) From c8985a898b2f0a242cce22717eb4069c7270a0a3 Mon Sep 17 00:00:00 2001 From: han semaj Date: Tue, 26 Aug 2014 21:38:52 +1200 Subject: [PATCH 05/35] Shadow '+' to handle string/list concatenation --- hy/core/shadow.hy | 9 ++++++--- tests/__init__.py | 1 + tests/native_tests/shadow.hy | 19 +++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/hy/core/shadow.hy b/hy/core/shadow.hy index f59f0ca..e68c4ec 100644 --- a/hy/core/shadow.hy +++ b/hy/core/shadow.hy @@ -26,9 +26,12 @@ (defn + [&rest args] "Shadow + operator for when we need to import / map it against something" - (if (= (len args) 0) - 0 - (sum args))) ; shortcut here. + (let [[count (len args)]] + (if (zero? count) + (raise (TypeError "Need at least 1 argument to add/concatenate")) + (if (= count 1) + (get args 0) + (reduce operator.add args))))) (defn - [&rest args] diff --git a/tests/__init__.py b/tests/__init__.py index 56ab9fc..eb292ac 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -12,6 +12,7 @@ from .native_tests.when import * # noqa from .native_tests.with_decorator import * # noqa from .native_tests.core import * # noqa from .native_tests.reader_macros import * # noqa +from .native_tests.shadow import * # noqa from .native_tests.with_test import * # noqa from .native_tests.contrib.anaphoric import * # noqa from .native_tests.contrib.loop import * # noqa diff --git a/tests/native_tests/shadow.hy b/tests/native_tests/shadow.hy index 362ac50..54bf81e 100644 --- a/tests/native_tests/shadow.hy +++ b/tests/native_tests/shadow.hy @@ -1,11 +1,22 @@ - - (defn test-shadow-addition [] "NATIVE: test shadow addition" (let [[x +]] - (assert (= (x) 0)) + (assert (try + (x) + (catch [TypeError] True) + (else (throw AssertionError)))) (assert (= (x 1 2 3 4) 10)) - (assert (= (x 1 2 3 4 5) 15)))) + (assert (= (x 1 2 3 4 5) 15)) + ; with strings + (assert (= (x "a") + "a")) + (assert (= (x "a" "b" "c") + "abc")) + ; with lists + (assert (= (x ["a"]) + ["a"])) + (assert (= (x ["a"] ["b"] ["c"]) + ["a" "b" "c"])))) (defn test-shadow-subtraction [] From 325f873f1e0f4e50bcfeded98f11f4bc226e02f4 Mon Sep 17 00:00:00 2001 From: Foxboron Date: Tue, 2 Sep 2014 22:26:47 +0200 Subject: [PATCH 06/35] Fixed (read) docs as mentioned inn #641 --- docs/language/core.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index f18eedf..59d6a5b 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -907,7 +907,7 @@ Return an iterator of `x`, `fn(x)`, `fn(fn(x))`. read ---- -Usage: ``(read [from-file eof])`` +Usage: ``(read &optional [from-file eof])`` Reads the next hy expression from `from-file` (defaults to `sys.stdin`), and can take a single byte as EOF (defaults to an empty string). From 6ca47df34c8c67f3164c62e7b55ad0c18e8cb9b8 Mon Sep 17 00:00:00 2001 From: han semaj Date: Wed, 3 Sep 2014 20:53:28 +1200 Subject: [PATCH 07/35] Include optional arg in docs (nth) --- docs/language/core.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index a05979e..e5eb774 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -532,11 +532,11 @@ Return True if x is None. nth --- -Usage: ``(nth coll n)`` +Usage: ``(nth coll n &optional [default nil])`` -Return the `nth` item in a collection, counting from 0. Return ``nil`` -if out of bounds (unless specified otherwise). Raise ``ValueError`` if -``n`` is negative. +Return the `nth` item in a collection, counting from 0. Return the +default value, ``nil``, if out of bounds (unless specified otherwise). +Raise ``ValueError`` if ``n`` is negative. .. code-block:: hy From 66e3cdcb99d8ac85bd6ec472b715b7c45f71ca85 Mon Sep 17 00:00:00 2001 From: Foxboron Date: Thu, 4 Sep 2014 00:04:05 +0200 Subject: [PATCH 08/35] Rename slots to attribute/attr --- hy/compiler.py | 4 ++-- tests/native_tests/defclass.hy | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index 7d275c3..610d643 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -2003,12 +2003,12 @@ class HyASTCompiler(object): except TypeError: raise HyTypeError( expression, - "Wrong argument type for defclass slots definition.") + "Wrong argument type for defclass attributes definition.") for b in body_expression: if len(b) != 2: raise HyTypeError( expression, - "Wrong number of argument in defclass slot.") + "Wrong number of argument in defclass attribute.") body += self._compile_assign(b[0], b[1], b.start_line, b.start_column) body += body.expr_as_stmt() diff --git a/tests/native_tests/defclass.hy b/tests/native_tests/defclass.hy index c1ebe5b..f303c4c 100644 --- a/tests/native_tests/defclass.hy +++ b/tests/native_tests/defclass.hy @@ -20,16 +20,16 @@ (assert (not (isinstance (A) D)))) -(defn test-defclass-slots [] - "NATIVE: test defclass slots" +(defn test-defclass-attrs [] + "NATIVE: test defclass attributes" (defclass A [] [[x 42]]) (assert (= A.x 42)) (assert (= (getattr (A) "x") 42))) -(defn test-defclass-slots-fn [] - "NATIVE: test defclass slots with fn" +(defn test-defclass-attrs-fn [] + "NATIVE: test defclass attributes with fn" (defclass B [] [[x 42] [y (fn [self value] @@ -52,7 +52,7 @@ (defn test-defclass-no-fn-leak [] - "NATIVE: test defclass slots with fn" + "NATIVE: test defclass attributes with fn" (defclass A [] [[x (fn [] 1)]]) (try From 99db02668b08f950d8cffe0a710618e0e6a1a39e Mon Sep 17 00:00:00 2001 From: han semaj Date: Thu, 4 Sep 2014 21:29:38 +1200 Subject: [PATCH 09/35] Fix 'some' (first logical true value or nil) --- docs/language/core.rst | 18 +++++++++++------- hy/core/language.hy | 8 ++++---- tests/native_tests/core.hy | 13 ++++++++++--- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index 4aa2f53..59af6bc 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -654,21 +654,25 @@ some Usage: ``(some pred coll)`` -Return True if ``(pred x)`` is logical true for any ``x`` in ``coll``, otherwise False. Return False if ``coll`` is empty. +Return the first logical true value of ``(pred x)`` for any ``x`` in +``coll``, otherwise ``nil``. Return ``nil`` if ``coll`` is empty. .. code-block:: hy => (some even? [2 4 6]) True - => (some even? [1 3 5]) - False - - => (some even? [1 3 6]) + => (nil? (some even? [1 3 5])) True - => (some even? []) - False + => (nil? (some identity [0 "" []])) + True + + => (some identity [0 "non-empty-string" []]) + 'non-empty-string' + + => (nil? (some even? [])) + True .. _string?-fn: diff --git a/hy/core/language.hy b/hy/core/language.hy index bc5587a..e81d8cd 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -26,7 +26,7 @@ (import itertools) (import functools) (import collections) -(import sys) +(import sys) (import [hy._compat [long-type]]) ; long for python2, int for python3 (import [hy.models.cons [HyCons]]) (import [hy.lex [LexException PrematureEndOfInput tokenize]]) @@ -299,8 +299,8 @@ (nth coll 1)) (defn some [pred coll] - "Return true if (pred x) is logical true for any x in coll, else false" - (any (map pred coll))) + "Return the first logical true value of (pred x) for any x in coll, else nil" + (first (filter nil (map pred coll)))) (defn string [x] "Cast x as current string implementation" @@ -347,7 +347,7 @@ (setv buff (+ buff inn)) (try (def parsed (first (tokenize buff))) - (except [e [LexException PrematureEndOfInput IndexError]]) + (except [e [LexException PrematureEndOfInput IndexError]]) (else (if parsed (break))))) parsed) diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index 2f858ce..3e390a6 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -474,9 +474,16 @@ (defn test-some [] "NATIVE: testing the some function" (assert-true (some even? [2 4 6])) - (assert-false (some even? [1 3 5])) - (assert-true (some even? [1 3 6])) - (assert-false (some even? []))) + (assert-nil (some even? [1 3 5])) + (assert-true (some even? [1 2 3])) + (assert-nil (some even? [])) + ; 0, "" (empty string) and [] (empty list) are all logical false + (assert-nil (some identity [0 "" []])) + ; non-empty string is logical true + (assert-equal (some identity [0 "this string is non-empty" []]) + "this string is non-empty") + ; nil if collection is empty + (assert-nil (some even? []))) (defn test-string? [] "NATIVE: testing string?" From 3f01ed5014c8761a9e894f0845bd3634e26e18ff Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 16 Jul 2014 15:34:24 +0200 Subject: [PATCH 10/35] Add a `Botsbuildbots` function A tribute to Portal 2, this function will return an infinite list of the contents of the AUTHORS file on GitHub master (assuming requests is installed). Except, the macro does this, the function never gets called, it is purely there for tribute reasons. Signed-off-by: Gergely Nagy --- hy/core/language.hy | 5 ++++- hy/core/macros.hy | 12 ++++++++++++ requirements-travis.txt | 2 ++ tests/native_tests/native_macros.hy | 3 +++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/hy/core/language.hy b/hy/core/language.hy index e81d8cd..91cd990 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -352,7 +352,10 @@ parsed) -(def *exports* '[butlast calling-module-name coll? cons cons? cycle +(defun Botsbuildbots () (Botsbuildbots)) + +(def *exports* '[Botsbuildbots + butlast calling-module-name coll? cons cons? cycle dec distinct disassemble drop drop-while empty? even? every? first filter filterfalse flatten float? gensym identity inc input instance? integer integer? integer-char? interleave diff --git a/hy/core/macros.hy b/hy/core/macros.hy index c6071ba..58ac4b5 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -198,3 +198,15 @@ (.append ret `(setv ~name ~main))) ret)) + +(defmacro Botsbuildbots [] + "Build bots, repeatedly.^W^W^WPrint the AUTHORS, forever." + `(try + (do + (import [requests]) + + (let [[r (requests.get + "https://raw.githubusercontent.com/hylang/hy/master/AUTHORS")]] + (repeat r.text))) + (catch [e ImportError] + (repeat "Botsbuildbots requires `requests' to function.")))) diff --git a/requirements-travis.txt b/requirements-travis.txt index 80be0ce..9216e4f 100644 --- a/requirements-travis.txt +++ b/requirements-travis.txt @@ -1,3 +1,5 @@ +# for Botsbuildbots +requests # code quality flake8 coverage diff --git a/tests/native_tests/native_macros.hy b/tests/native_tests/native_macros.hy index fb2879c..408ca6c 100644 --- a/tests/native_tests/native_macros.hy +++ b/tests/native_tests/native_macros.hy @@ -214,3 +214,6 @@ (assert (= (tda-a1) :bazinga)) (assert (= (tda-a2) :bazinga)) (assert (= tda-main tda-a1 tda-a2))) + +(defn test-botsbuildbots [] + (assert (> (len (first (Botsbuildbots))) 50))) From 4a4bfd8699c2a0205c3ff3f1202b2c4170815632 Mon Sep 17 00:00:00 2001 From: Abhishek Lekshmanan Date: Fri, 5 Sep 2014 18:27:20 +0530 Subject: [PATCH 11/35] fix @kirbyfan64's name in AUTHORS --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 42f89c1..41514fe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -42,7 +42,7 @@ * Halit Alptekin * Richard Parsons * han semaj -* kirbyfan64 +* Ryan Gonzalez * Brendan Curran-Johnson * Ivan Kozik * Allison Kaptur From e3646bb8742e467bf19dcda0d4e2e4d873f15c06 Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Sat, 6 Sep 2014 08:48:53 -0400 Subject: [PATCH 12/35] add @microamp --- docs/coreteam.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/coreteam.rst b/docs/coreteam.rst index 982df9d..7800b25 100644 --- a/docs/coreteam.rst +++ b/docs/coreteam.rst @@ -13,3 +13,4 @@ * `Bob Tolbert `_ * `Berker Peksag `_ * `Clinton N. Dreisbach `_ +* `han semaj `_ From 2d60aa678153de5b67e161cfb6a87f7d5bab4557 Mon Sep 17 00:00:00 2001 From: Foxboron Date: Mon, 8 Sep 2014 14:56:04 +0200 Subject: [PATCH 13/35] added new mail --- .mailmap | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.mailmap b/.mailmap index 678f585..e5d76d6 100644 --- a/.mailmap +++ b/.mailmap @@ -2,11 +2,10 @@ Paul R. Tagliamonte Paul Tagliamonte Paul R. Tagliamonte Paul Tagliamonte Paul R. Tagliamonte Paul Tagliamonte Paul R. Tagliamonte Paul Tagliamonte -Morten Linderud Foxboron -Morten Linderud +Morten Linderud Foxboron James King agentultra James King J Kenneth King Abhishek L Bob Tolbert Bob Tolbert Guillermo Vaya Guillermo Vaya -Gergely Nagy Gergely Nagy \ No newline at end of file +Gergely Nagy Gergely Nagy From 89dec9ef4487ef541438840be4682848afc145fa Mon Sep 17 00:00:00 2001 From: Foxboron Date: Mon, 8 Sep 2014 16:57:52 +0200 Subject: [PATCH 14/35] Fixed example to be streamlined --- docs/contrib/multi.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/contrib/multi.rst b/docs/contrib/multi.rst index dc4bf64..91d8cfa 100644 --- a/docs/contrib/multi.rst +++ b/docs/contrib/multi.rst @@ -11,13 +11,13 @@ args and/or kwargs. Inspired by clojures take on `defn`. => (require hy.contrib.multi) => (defmulti fun - ... ([a] a) + ... ([a] "a") ... ([a b] "a b") ... ([a b c] "a b c")) - => (fun 1 2 3) - 'a b c' - => (fun a b) - "a b" => (fun 1) - 1 + "a" + => (fun 1 2) + "a b" + => (fun 1 2 3) + "a b c" From 4d2aad1b0f4a85ee3e000f84f3f698db1e87a902 Mon Sep 17 00:00:00 2001 From: Ian Denhardt Date: Sun, 21 Sep 2014 11:36:40 -0400 Subject: [PATCH 15/35] Call _wrap_value recursively on HyExpressions. Without this, cases like: (defmacro foo [] `(~0)) (foo) throw exceptions, because the embedded zero is not a HyObject. --- hy/macros.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hy/macros.py b/hy/macros.py index 937e7b8..57fcea6 100644 --- a/hy/macros.py +++ b/hy/macros.py @@ -117,6 +117,7 @@ _wrappers = { list: lambda l: HyList(_wrap_value(x) for x in l), tuple: lambda t: HyList(_wrap_value(x) for x in t), type(None): lambda foo: HySymbol("None"), + HyExpression: lambda e: HyExpression(_wrap_value(x) for x in e), } if sys.version_info[0] < 3: # do not add long on python3 From ca255a86af6782bbadef59a7039eb7fae6964be3 Mon Sep 17 00:00:00 2001 From: Ian Denhardt Date: Sun, 21 Sep 2014 11:40:23 -0400 Subject: [PATCH 16/35] Add @zenhack --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 41514fe..f26151b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,3 +48,4 @@ * Allison Kaptur * Matthew Wampler-Doty * Tianon Gravi +* Ian Denhardt From 3503ed902728b5cfaa58d7b6fc028310a3e7b3b4 Mon Sep 17 00:00:00 2001 From: Ian Denhardt Date: Sun, 21 Sep 2014 12:08:14 -0400 Subject: [PATCH 17/35] Add tests for _wrap_value --- tests/macros/test_wrap_value.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/macros/test_wrap_value.py diff --git a/tests/macros/test_wrap_value.py b/tests/macros/test_wrap_value.py new file mode 100644 index 0000000..0a6e7d5 --- /dev/null +++ b/tests/macros/test_wrap_value.py @@ -0,0 +1,28 @@ +from hy._compat import long_type +from hy.models.integer import HyInteger +from hy.models.list import HyList +from hy.models.expression import HyExpression + +from hy.macros import _wrap_value + + +def test_wrap_long_type(): + """ Test conversion of integers.""" + wrapped = _wrap_value(long_type(0)) + assert type(wrapped) == HyInteger + + +def test_wrap_tuple(): + """ Test conversion of tuples.""" + wrapped = _wrap_value((HyInteger(0),)) + assert type(wrapped) == HyList + assert type(wrapped[0]) == HyInteger + assert wrapped == HyList([HyInteger(0)]) + + +def test_wrap_nested_expr(): + """ Test conversion of HyExpressions with embedded non-HyObjects.""" + wrapped = _wrap_value(HyExpression([long_type(0)])) + assert type(wrapped) == HyExpression + assert type(wrapped[0]) == HyInteger + assert wrapped == HyExpression([HyInteger(0)]) From 8ba547c4cf66e71058fe5be91be8cebf6be75438 Mon Sep 17 00:00:00 2001 From: Alexander Artemenko Date: Tue, 30 Sep 2014 22:07:34 +0400 Subject: [PATCH 18/35] Added command-line utility which takes current NEWS changelog and reformats it in debian style. --- reformat-changelog | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100755 reformat-changelog diff --git a/reformat-changelog b/reformat-changelog new file mode 100755 index 0000000..2c74480 --- /dev/null +++ b/reformat-changelog @@ -0,0 +1,66 @@ +#!/usr/bin/env hy + +(import re) +(import pdb) +(import codecs) + +(setv *maintainer-line* + " -- Alexander Artemenko Thu, 30 Sep 2014 13:06:09 +0400") + +(defun read-lines-from-file [filename] + (let [[f (codecs.open filename "r" "utf-8")]] + (fn [] (let [[line (.readline f) ]] + line)))) + + +(defun get-version-number [line] + (let [[match (re.search r"Changes from.*(\d+\.\d+\.\d+)$" line)]] + (if match + (let [[version (.group match (int 1))] + [numbered (list (map int (.split version "."))) ] + [explicit-mapping {"0.9.12" "0.10.0" + "0.8.2" "0.9.0"}]] + (assoc numbered 2 (+ (get numbered 2) 1)) + (.get explicit-mapping + version + (.join "." (map str numbered))))))) + + +(defun read-version-content [reader] + (setv line (reader)) + (setv content []) + (while (and line (not (get-version-number line))) + (.append content (.strip line)) + (setv line (reader))) + [content line]) + + +(defun read-versions-from-file [filename] + (let [[reader (read-lines-from-file filename)]] + (read-versions-rec (reader) + reader))) + +(defun read-versions-rec [line reader] + (if line + (let [[version (get-version-number line)] + [[content next-line] (read-version-content reader)]] + + (+ [{"from" version + "content" content}] + (read-versions-rec next-line reader))) + [])) + +(defun format-deb-version [version] + (setv result [(.format "hy ({}) unstable; urgency=low" + (get version "from"))]) + (for [line (get version "content")] + (.append result (+ " " line))) + (.append result *maintainer-line*) + (.append result "") + (.join "\n" result)) + + +(defmain [&rest args] + (let ((versions (read-versions-from-file "NEWS"))) + (for [version versions] + (print (.encode (format-deb-version version) "utf-8"))))) From 76d7e3479a23d37bcf34940763d107bba1a4ab4b Mon Sep 17 00:00:00 2001 From: bismigalis Date: Tue, 14 Jan 2014 09:30:36 +0200 Subject: [PATCH 19/35] Added merge-with --- docs/language/core.rst | 18 ++++++++++++++++++ hy/core/language.hy | 18 +++++++++++++++++- tests/native_tests/language.hy | 21 ++++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index 59af6bc..703bdf4 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -449,6 +449,24 @@ Returns the single step macro expansion of form. => (macroexpand-1 '(-> (a b) (-> (c d) (e f)))) (u'_>' (u'a' u'b') (u'c' u'd') (u'e' u'f')) + +.. _merge-with-fn: + +merge-with +---------- + +.. versionadded:: 0.10.0 + +Usage: ``(merge-with f &rest maps) + +Returns a map that consist of the rest of the maps joined onto first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter). + +.. code-block:: clojure + + => (merge-with (fn [x y] (+ x y)) {"a" 10 "b" 20} {"a" 1 "c" 30}) + {u'a': 11L, u'c': 30L, u'b': 20L} + + .. _neg?-fn: neg? diff --git a/hy/core/language.hy b/hy/core/language.hy index 91cd990..749fa9e 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -253,6 +253,22 @@ (setv name (calling-module-name)) (hy.macros.macroexpand-1 form name)) +(defn merge-with [f &rest maps] + "Returns a map that consists of the rest of the maps joined onto + the first. If a key occurs in more than one map, the mapping(s) + from the latter (left-to-right) will be combined with the mapping in + the result by calling (f val-in-result val-in-latter)." + (if (any maps) + (let [[merge-entry (fn [m e] + (let [[k (get e 0)] [v (get e 1)]] + (if (in k m) + (assoc m k (f (get m k) v)) + (assoc m k v))) + m)] + [merge2 (fn [m1 m2] + (reduce merge-entry (.items m2) (or m1 {})))]] + (reduce merge2 maps)))) + (defn neg? [n] "Return true if n is < 0" (_numeric-check n) @@ -360,7 +376,7 @@ every? first filter filterfalse flatten float? gensym identity inc input instance? integer integer? integer-char? interleave interpose iterable? iterate iterator? keyword? list* - macroexpand macroexpand-1 map neg? nil? none? nth + macroexpand macroexpand-1 map merge-with neg? nil? none? nth numeric? odd? pos? range read remove repeat repeatedly rest reduce second some string string? take take-nth take-while zero? zip zip_longest zipwith]) diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 7f3ba54..895249f 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -1,6 +1,7 @@ (import [tests.resources [kwtest function-with-a-dash]] [os.path [exists isdir isfile]] - [sys :as systest]) + [sys :as systest] + [operator [or_]]) (import sys) (import [hy._compat [PY33 PY34]]) @@ -985,6 +986,24 @@ (assert (= (macroexpand-1 '(-> (a b) (-> (c d) (e f)))) '(-> (a b) (c d) (e f))))) +(defn test-merge-with [] + "NATIVE: test merge-with" + (assert (= (merge-with + {} {}) nil)) + (assert (= (merge-with + {"a" 10 "b" 20} {}) {"a" 10 "b" 20})) + (assert (= (merge-with + {} {"a" 10 "b" 20}) {"a" 10 "b" 20})) + (assert (= (merge-with + {"a" 10 "b" 20} {"a" 1 "c" 30}) + {"a" 11 "b" 20 "c" 30})) + (assert (= (merge-with + + {:a 1 :b 2} + {:a 9 :b 98 :c 0} + {:a 10 :b 100 :c 10} + {:a 5} + {:c 5 :d 42}) + {:d 42 :c 15 :a 25 :b 200})) + (assert (= (merge-with or_ + {"a" (set [1 2 3]) "b" (set [4 5 6])} + {"a" (set [2 3 7 8]) "c" (set [1 2 3])}) + {"a" (set [1 2 3 7 8]) "c" (set [1 2 3]) "b" (set [4 5 6])}))) (defn test-calling-module-name [] "NATIVE: Test the calling-module-name function" From 0041d508e8cc863fbbc07f19727aa71cd3cad3b0 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 6 Oct 2014 13:37:51 -0600 Subject: [PATCH 20/35] Add initial .dockerignore file This avoids adding ".git" to the Docker image, which speeds up the initial "uploading context" phase and helps slim the image a small amount (since ".git" of Hy itself isn't necessary for using Hy). --- .dockerignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6b8710a --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.git From 377c3ec5ee7ae688ce0dd7a1e32db731d183ab31 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Thu, 9 Oct 2014 02:58:42 +0300 Subject: [PATCH 21/35] Update versionadded directive for merge-with. --- docs/language/core.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index 703bdf4..2a594ba 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -455,11 +455,14 @@ Returns the single step macro expansion of form. merge-with ---------- -.. versionadded:: 0.10.0 +.. versionadded:: 0.10.1 Usage: ``(merge-with f &rest maps) -Returns a map that consist of the rest of the maps joined onto first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter). +Returns a map that consist of the rest of the maps joined onto first. +If a key occurs in more than one map, the mapping(s) from the latter +(left-to-right) will be combined with the mapping in the result by +calling ``(f val-in-result val-in-latter)``. .. code-block:: clojure From 78131a9d122f68ee996608c26167c4ff224cd52c Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Thu, 9 Oct 2014 03:00:08 +0300 Subject: [PATCH 22/35] Add @bismigalis to AUTHORS. --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 41514fe..9518075 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,3 +48,4 @@ * Allison Kaptur * Matthew Wampler-Doty * Tianon Gravi +* Ruslan Prokopiev From 0a8fc0ebb71906ffd3980a201a44558263699566 Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Fri, 10 Oct 2014 09:45:07 -0400 Subject: [PATCH 23/35] Add in NEWS for 0.10.1 --- NEWS | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/NEWS b/NEWS index ed5c534..2cc4709 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,49 @@ +Changes from 0.10.0 + + This release took some time (sorry, all my fault) but it's got a bunch of + really nice feature. We hope you enjoy hacking with Hy as much as we enjoy + hacking on Hy. + + In other news, we're Dockerized as an official library image! + https://registry.hub.docker.com/_/hylang/> + + $ docker run -it --rm hylang + hy 0.10.0 using CPython(default) 3.4.1 on Linux + => ((lambda [] (print "Hello, World!"))) + Hello, World! + + - Hy Society + + [ Language Changes ] + * Implement raise :from, Python 3 only. + * defmain macro + * name & keyword functions added to core + * (read) added to core + * shadow added to core + * New functions interleave interpose zip_longest added to core + * nth returns default value when out of bounds + * merge-with added + * doto macro added + * keyword? to findout keywords + * setv no longer allows "." in names + + [Internals ] + * Builtins reimplemented in terms of python stdlib + * gensyms (defmacro/g!) handles non-string types better + + [Tools] + * Added hy2py to installed scripts + + [ Misc. Fixes ] + * Symbols like true, false, none can't be assigned + * Set sys.argv default to [''] like Python does + * REPL displays the the python version and platform at startup + * Dockerfile added for https://registry.hub.docker.com/_/hylang/ + + [ Contrib changes ] + * Fix ap-first and ap-last for failure conditions + + Changes from 0.9.12 0.10.0 - the "oh man I'm late for PyCon" release From ecc003b43433e5b46511157598e4857a761007bf Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Fri, 10 Oct 2014 09:45:23 -0400 Subject: [PATCH 24/35] 0.10.1 --- hy/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hy/version.py b/hy/version.py index 23a31bc..d1f5edb 100644 --- a/hy/version.py +++ b/hy/version.py @@ -20,4 +20,4 @@ __appname__ = "hy" -__version__ = "0.10.0" +__version__ = "0.10.1" From 75adfb93d6716306c9ad75165e1db13055f9158c Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Fri, 10 Oct 2014 09:52:44 -0400 Subject: [PATCH 25/35] Damnit @tianon --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2cc4709..423cc7d 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,7 @@ Changes from 0.10.0 This release took some time (sorry, all my fault) but it's got a bunch of - really nice feature. We hope you enjoy hacking with Hy as much as we enjoy + really nice features. We hope you enjoy hacking with Hy as much as we enjoy hacking on Hy. In other news, we're Dockerized as an official library image! From f5f4384722520fe519e0c3a76599c18ec639ea12 Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Fri, 10 Oct 2014 09:53:33 -0400 Subject: [PATCH 26/35] Another typo. Don't be a release manager in the morning --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 423cc7d..08e6b98 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,7 @@ Changes from 0.10.0 hacking on Hy. In other news, we're Dockerized as an official library image! - https://registry.hub.docker.com/_/hylang/> + $ docker run -it --rm hylang hy 0.10.0 using CPython(default) 3.4.1 on Linux From d01b6bbacc931eef0bcc303563c3058b233a728c Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Sat, 1 Nov 2014 15:00:41 -0500 Subject: [PATCH 27/35] Fix Python 3 re-raising --- hy/_compat.py | 5 +++++ hy/compiler.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hy/_compat.py b/hy/_compat.py index 096282a..80d8f80 100644 --- a/hy/_compat.py +++ b/hy/_compat.py @@ -52,3 +52,8 @@ if PY3: long_type = int else: long_type = long # NOQA + +if PY3: + exec('def raise_empty(t, *args): raise t(*args) from None') +else: + def raise_empty(t, *args): raise t(*args) diff --git a/hy/compiler.py b/hy/compiler.py index 610d643..4c7af9c 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -38,7 +38,7 @@ from hy.models.cons import HyCons from hy.errors import HyCompileError, HyTypeError import hy.macros -from hy._compat import str_type, long_type, PY27, PY33, PY3, PY34 +from hy._compat import str_type, long_type, PY27, PY33, PY3, PY34, raise_empty from hy.macros import require, macroexpand, reader_macroexpand import hy.importer @@ -429,7 +429,7 @@ class HyASTCompiler(object): except HyTypeError as e: raise except Exception as e: - raise HyCompileError(e, sys.exc_info()[2]) + raise_empty(HyCompileError, e, sys.exc_info()[2]) raise HyCompileError(Exception("Unknown type: `%s'" % _type)) From a6d9a963b5ecf01efd0d444d3661758d30f117e5 Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Sat, 1 Nov 2014 16:07:39 -0500 Subject: [PATCH 28/35] Fix flake8 errors --- hy/_compat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hy/_compat.py b/hy/_compat.py index 80d8f80..af710f2 100644 --- a/hy/_compat.py +++ b/hy/_compat.py @@ -56,4 +56,5 @@ else: if PY3: exec('def raise_empty(t, *args): raise t(*args) from None') else: - def raise_empty(t, *args): raise t(*args) + def raise_empty(t, *args): + raise t(*args) From c88e75251cd60be7e7adfff2263dba12196dfc3d Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Wed, 5 Nov 2014 21:01:10 -0600 Subject: [PATCH 29/35] Fix Travis failures --- .travis.yml | 8 +------- Makefile | 50 +++++++++++++++++++++++++++++++++++++++++++++-- tests/test_bin.py | 5 ++++- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0009569..9e51591 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,15 +8,9 @@ python: - "3.4" cache: - $HOME/.pip-cache -# command to install dependencies -install: - - pip install -r requirements-travis.txt --download-cache $HOME/.pip-cache - - pip install coveralls --download-cache $HOME/.pip-cache - - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi # needs for running tests - - pip install --allow-all-external -e . # command to run tests script: make travis -after_success: coveralls +after_success: make coveralls notifications: email: - paultag@gmail.com diff --git a/Makefile b/Makefile index e1f3ea9..374a48f 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,21 @@ +pypy_url=http://buildbot.pypy.org/nightly/trunk/pypy-c-jit-latest-linux64.tar.bz2 +pip_url=https://bootstrap.pypa.io/get-pip.py +python=python +pip=pip +coveralls=coveralls +nose=nosetests +pcache=$(HOME)/.pip-cache + +ifeq (PyPy 2.4,$(findstring PyPy 2.4,$(shell python -V 2>&1 | tail -1))) + bad_pypy=1 + python=./pypy + pip=./pip + coveralls=./coveralls + nose=./nosetests +else + bad_pypy= +endif + all: @echo "No default step. Use setup.py" @echo "" @@ -53,14 +71,42 @@ diff: r: d tox diff -travis: - nosetests -s --with-coverage --cover-package hy +python: +ifeq ($(bad_pypy),1) + # Due to stupid PyPy 2.4 bugs, a custom version needs to be downloaded + curl $(pypy_url) -o pypy.tbz2 + tar xf pypy.tbz2 + ln -sf `pwd`/pypy-*/bin/pypy $(python) + curl $(pip_url) | $(python) + ln -sf `pwd`/pypy-*/bin/pip $(pip) + sudo $(pip) install nose + ln -sf `pwd`/pypy-*/bin/nosetests $(nose) +endif +ifeq (Python 2.6,$(findstring Python 2.6,$(shell python -V 2>&1))) + $(pip) install unittest2 +endif + $(pip) install -r requirements-travis.txt --download-cache $(pcache) + $(pip) install coveralls --download-cache $(pcache) + $(pip) install --allow-all-external -e . +ifeq ($(bad_pypy),1) + ln -sf `pwd`/pypy-*/bin/coveralls $(coveralls) +endif + +travis: python +ifeq ($(bad_pypy),1) + HY_DIR=`pwd`/pypy-*/bin $(nose) -s --with-coverage --cover-package hy +else + $(nose) -s --with-coverage --cover-package hy +endif ifeq (PyPy,$(findstring PyPy,$(shell python -V 2>&1 | tail -1))) @echo "skipping flake8 on pypy" else flake8 hy bin tests endif +coveralls: + $(coveralls) + clean: @find . -name "*.pyc" -exec rm {} \; @find -name __pycache__ -delete diff --git a/tests/test_bin.py b/tests/test_bin.py index 16383e4..e8a0fc8 100644 --- a/tests/test_bin.py +++ b/tests/test_bin.py @@ -26,8 +26,11 @@ import subprocess from hy._compat import PY3 +hy_dir = os.environ.get('HY_DIR', '') + + def run_cmd(cmd, stdin_data=None): - p = subprocess.Popen(cmd, + p = subprocess.Popen(os.path.join(hy_dir, cmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, From 96410f506e8dbc8e215bdf790d2853d95b6fe81a Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 10 Sep 2014 10:55:11 -0600 Subject: [PATCH 30/35] Add a dedicated `lisp-if-not` / `lif-not` macro This is in parallel to `if` / `if-not` (so not without precedent). :) --- docs/language/api.rst | 18 +++++++++++++++--- hy/core/macros.hy | 4 ++++ tests/native_tests/native_macros.hy | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/docs/language/api.rst b/docs/language/api.rst index 9097910..72d5b6b 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -818,14 +818,18 @@ any numeric type, empty sequence and empty dictionary are considered `False`. Everything else is considered `True`. -lisp-if / lif -------------- +lisp-if / lif and lisp-if-not / lif-not +--------------------------------------- .. versionadded:: 0.10.0 +.. versionadded:: 0.10.2 + lisp-if-not / lif-not + For those that prefer a more lisp-y if clause, we have lisp-if, or lif. This *only* considers None/nil as false! All other values of python -"falseiness" are considered true. +"falseiness" are considered true. Conversely, we have lisp-if-not or lif-not, +in parallel to if / if-not, which reverses the comparison. .. code-block:: clj @@ -840,12 +844,20 @@ For those that prefer a more lisp-y if clause, we have lisp-if, or lif. This "false" => (lisp-if None "true" "false") "false" + => (lisp-if-not nil "true" "false") + "true" + => (lisp-if-not None "true" "false") + "true" + => (lisp-if-not False "true" "false") + "false" ; And, same thing => (lif True "true" "false") "true" => (lif nil "true" "false") "false" + => (lif-not None "true" "false") + "true" import diff --git a/hy/core/macros.hy b/hy/core/macros.hy index 58ac4b5..38a45ee 100644 --- a/hy/core/macros.hy +++ b/hy/core/macros.hy @@ -153,6 +153,10 @@ "Like `if`, but anything that is not None/nil is considered true." `(if (is-not ~test nil) ~@branches)) +(defmacro-alias [lisp-if-not lif-not] [test &rest branches] + "Like `if-not`, but anything that is not None/nil is considered true." + `(if (is ~test nil) ~@branches)) + (defmacro when [test &rest body] "Execute `body` when `test` is true" diff --git a/tests/native_tests/native_macros.hy b/tests/native_tests/native_macros.hy index 408ca6c..0768b3c 100644 --- a/tests/native_tests/native_macros.hy +++ b/tests/native_tests/native_macros.hy @@ -206,6 +206,24 @@ (assert (= (lif nil "true" "false") "false")) (assert (= (lif 0 "true" "false") "true"))) +(defn test-lisp-if-not [] + "test that lisp-if-not works as expected" + ; nil is false + (assert (= (lisp-if-not None "false" "true") "false")) + (assert (= (lisp-if-not nil "false" "true") "false")) + + ; But everything else is True! Even falsey things. + (assert (= (lisp-if-not True "false" "true") "true")) + (assert (= (lisp-if-not False "false" "true") "true")) + (assert (= (lisp-if-not 0 "false" "true") "true")) + (assert (= (lisp-if-not "some-string" "false" "true") "true")) + (assert (= (lisp-if-not "" "false" "true") "true")) + (assert (= (lisp-if-not (+ 1 2 3) "false" "true") "true")) + + ; Just to be sure, test the alias lif-not + (assert (= (lif-not nil "false" "true") "false")) + (assert (= (lif-not 0 "false" "true") "true"))) + (defn test-defn-alias [] (defn-alias [tda-main tda-a1 tda-a2] [] :bazinga) From c9362d39c1be54f8290006db00fe71d824ff091c Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Thu, 13 Nov 2014 17:49:17 -0600 Subject: [PATCH 31/35] Fix #684 --- hy/compiler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hy/compiler.py b/hy/compiler.py index 4c7af9c..7c7925e 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1268,7 +1268,8 @@ class HyASTCompiler(object): def compile_decorate_expression(self, expr): expr.pop(0) # with-decorator fn = self.compile(expr.pop(-1)) - if not fn.stmts or not isinstance(fn.stmts[-1], ast.FunctionDef): + if not fn.stmts or not (isinstance(fn.stmts[-1], ast.FunctionDef) or + isinstance(fn.stmts[-1], ast.ClassDef)): raise HyTypeError(expr, "Decorated a non-function") decorators, ret = self._compile_collect(expr) fn.stmts[-1].decorator_list = decorators From c7e4d4cd6e0b68daa030ff474ac500a7a8bd6c92 Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez Date: Fri, 14 Nov 2014 14:21:16 -0600 Subject: [PATCH 32/35] Add tests --- tests/native_tests/with_decorator.hy | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/native_tests/with_decorator.hy b/tests/native_tests/with_decorator.hy index dc6ad6e..867c63a 100644 --- a/tests/native_tests/with_decorator.hy +++ b/tests/native_tests/with_decorator.hy @@ -7,6 +7,15 @@ (* 2 2))) +(defn bardec [cls] + (setv cls.my_attr 123)) + +(with-decorator bardec + (defclass cls [] + [[my_attr 456]])) + + (defn test-decorators [] "NATIVE: test decorators." - (assert (= (tfunction) 2))) + (assert (= (tfunction) 2)) + (assert (= cls.my_attr 123))) From dcf29d3d2a147fe66a199712149f7b58fd7fef04 Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Sat, 15 Nov 2014 07:47:55 -0500 Subject: [PATCH 33/35] Fix the test decorator to return the class. --- tests/native_tests/with_decorator.hy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/native_tests/with_decorator.hy b/tests/native_tests/with_decorator.hy index 867c63a..d82214d 100644 --- a/tests/native_tests/with_decorator.hy +++ b/tests/native_tests/with_decorator.hy @@ -8,7 +8,8 @@ (defn bardec [cls] - (setv cls.my_attr 123)) + (setv cls.my_attr 123) + cls) (with-decorator bardec (defclass cls [] From bb8b93dbdea195aa6a7efc931951d1bf93c29e31 Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Sat, 15 Nov 2014 07:52:20 -0500 Subject: [PATCH 34/35] Move reformat-changelog into scripts. --- reformat-changelog => scripts/reformat-changelog | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename reformat-changelog => scripts/reformat-changelog (100%) diff --git a/reformat-changelog b/scripts/reformat-changelog similarity index 100% rename from reformat-changelog rename to scripts/reformat-changelog From b8f5fbc43baaca94596617fd389665987191099b Mon Sep 17 00:00:00 2001 From: Paul Tagliamonte Date: Sat, 15 Nov 2014 07:54:01 -0500 Subject: [PATCH 35/35] Add in Alexander Artemenko to authors. --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index fabec9a..c596a53 100644 --- a/AUTHORS +++ b/AUTHORS @@ -50,3 +50,4 @@ * Tianon Gravi * Ian Denhardt * Ruslan Prokopiev +* Alexander Artemenko