move submit to form

move submit to form

... to leverage html5 validation

--- src/diary/ui/signup.cljs
+++ src/diary/ui/signup.cljs
@@ -19,8 +19,10 @@
             (dom/div #js{:className "signup"}
                      (m/errors errors)
                      (dom/h1 nil "Create an Account")
-                     (dom/form #js{:onSubmit #(doto %
-                                                (.preventDefault))}
+                     (dom/form #js{:onSubmit  (o/submit
+                                               this
+                                               :user
+                                               (fn [e] `[(user/create ~e)])) }
                                (dom/ul nil
                                        (dom/li nil
                                                (dom/label #js{:htmlFor "firstNameField"}
@@ -47,10 +49,6 @@
                                                          :required true}))
                                        (dom/li nil
                                                (dom/button #js{:type "submit"
-                                                               :className "submit"
-                                                               :onClick (o/submit
-                                                                         this
-                                                                         :user
-                                                                         (fn [e] `[(user/create ~e)]))}
+                                                               :className "submit"}
                                                            "Create an Account"))))))
           ))


The old apply-contracts is the new provide-contracts using the compact syntax

--- src/fogus/me/trammel.clj
+++ src/fogus/me/trammel.clj
@@ -174,14 +174,17 @@
        ~(if (:doc mdata) (:doc mdata) "")
        ~@body)))

-(defmacro apply-contracts [& contracts]
+(defmacro provide-contracts [& contracts]
   (let [fn-names  (map first contracts)
-        contracts (for [c contracts] (if (vector? (second c)) (list* `contract c) (second c)))]
+        contracts (for [[n ds & more] contracts]
+                    (if (vector? (first more))
+                      (list* `contract n ds more)
+                      (first more)))]
     `(do
-       ~@(for [[n# c#] (zipmap fn-names contracts)]
-           (list `alter-var-root (list `var n#)
-                 (list `fn '[f c] (list `with-constraints 'f 'c)) c#))
-       nil)))
+      ~@(for [[n# c#] (zipmap fn-names contracts)]
+          (list `alter-var-root (list `var n#)
+                (list `fn '[f c] (list `with-constraints 'f 'c)) c#))
+      nil)))

 (defmacro defconstrainedrecord
   [name slots & etc]


update right away on button click

update right away on button click

--- samples/twitterbuzz/src/twitterbuzz/core.cljs
+++ samples/twitterbuzz/src/twitterbuzz/core.cljs
@@ -125,7 +125,8 @@
         (events/listen timer goog.Timer/TICK do-timer))))

 (defn do-track-button-clicked []
-  (send-event :track-clicked))
+  (do (do-timer)
+      (send-event :track-clicked)))

 (defn do-refresh-button-clicked []
   (send-event :refresh-clicked))


explicitly closing websocket before unload

fixes #164

--- support/src/figwheel/client/socket.cljs
+++ support/src/figwheel/client/socket.cljs
@@ -63,6 +63,8 @@
                                                    conj msg)))))
         (set! (.-onopen socket)  (fn [x]
                                    (reset! socket-atom socket)
+                                   (when (utils/html-env?)
+                                     (.addEventListener js/window "beforeunload" close!))
                                    (utils/log :debug "Figwheel: socket connection established")))
         (set! (.-onclose socket) (fn [x]
                                    (let [retried-count (or retried-count 0)]


update REPL header docs

update REPL header docs

--- sidecar/src/figwheel_sidecar/auto_builder.clj
+++ sidecar/src/figwheel_sidecar/auto_builder.clj
@@ -234,7 +234,7 @@
           :cljs/quit                 ;; allows you to switch REPL to another build
     Docs: (doc function-name-here)
     Exit: Control+C or :cljs/quit
- Results: Stored in vars *1, *2, *3")
+ Results: Stored in vars *1, *2, *3, *e holds last exception object")

 (defn get-build-choice [choices]
   (let [choices (set (map name choices))]


Mandate that constructor names are capitalized

--- parser/parser.clj
+++ parser/parser.clj
@@ -18,6 +18,16 @@
                 (Result name)
             (List _ range)
                 (Error  (MalformedSymbolError range))))
+
+(def char-is-upper-case? (char)
+     (and (>= char 65) (<= char 90)))
+
+(def name-of-constructor? (name)
+     (match name
+            (Cons first-letter _)
+                (char-is-upper-case? first-letter)
+            Empty
+                False))

 (typ type          (SimpleType           (list int32) range)
                    (ComplexType          (list int32) (list type) range)
@@ -166,6 +176,11 @@
                               (FunctionApplication expressions range))))
          expressions))

+(def to-constructor-or-capture (range name)
+     (match (name-of-constructor? name)
+            True  (Result (ConstructorPattern name Empty range))
+            False (Result (Capture name range))))
+
 (def sexp-to-pattern (sexp)
      (match sexp
             (List (Cons name rest) range)
@@ -180,8 +195,7 @@
                   ((pipe
                       (maybe-map  (fn (integer)
                                       (Result (IntegerPattern integer range))))
-                      (maybe-else (fn ()
-                                      (Result (Capture name range))))
+                      (maybe-else (fn () (to-constructor-or-capture range name)))
                   ) (string-to-int32 name))))

 (def sexp-to-match-pair (pair)


Refactored parser

Refactored parser

--- parser/parser.clj
+++ parser/parser.clj
@@ -15,6 +15,22 @@
 (def list-map (f list)
      (list-foldr (fn (x xs)
                      (Cons (f x) xs))
+                 Empty
+                 list))
+
+(def string-of-char (character)
+     (Cons character Empty))
+
+(def string-concat (a b)
+     (match a
+            Empty       b
+            (Cons x xs) (Cons x (string-concat xs b))))
+
+(def string-join (separator list)
+     (list-foldr (fn (x xs)
+                     (match xs
+                            Empty       x
+                            (Cons _ __) (string-concat (string-concat xs separator) x)))
                  Empty
                  list))

@@ -74,19 +90,25 @@
                          (ParseOut i)
                          ParseEnd)

+(def parse-symbol (input)
+     (match (read-while atom-character? input)
+            (Pair input Empty) (ParseOut input)
+            (Pair input name)  (ParseNext input (Symbol name))))
+
+(def parse-list (input parse-expressions)
+     (match (parse-expressions input Empty)
+            (Pair input expressions) (ParseNext input (List expressions))))
+
 (def parse-expression (input parse-expressions)
      (match input
             Empty       ParseEnd
             (Cons x xs) (match (whitespace? x)
                                True (parse-expression xs parse-expressions)
                   False (match (= x 40)
-                               True (match (parse-expressions xs Empty)
-                                           (Pair input expressions) (ParseNext input (List expressions)))
+                               True (parse-list xs parse-expressions)
                   False (match (= x 41)
                                True (ParseOut xs)
-                  False (match (read-while atom-character? input)
-                               (Pair input Empty) (ParseOut input)
-                               (Pair input name)  (ParseNext input (Symbol name))))))))
+                  False (parse-symbol input))))))

 (def parse-expressions (input expressions)
      (match (parse-expression input parse-expressions)
@@ -97,22 +119,6 @@
 (def parse (input)
      (match (parse-expressions input Empty)
             (Pair _ expressions) expressions))
-
-(def string-of-char (character)
-     (Cons character Empty))
-
-(def string-concat (a b)
-     (match a
-            Empty       b
-            (Cons x xs) (Cons x (string-concat xs b))))
-
-(def string-join (separator list)
-     (list-foldr (fn (x xs)
-                     (match xs
-                            Empty       x
-                            (Cons _ __) (string-concat (string-concat xs separator) x)))
-                 Empty
-                 list))

 (def wrap-in-brackets (string)
      (string-concat (string-of-char 40) (string-concat string (string-of-char 41))))


Formatting (I had Cursive set with "Default to Only Indent" off, which is inconsistent with other code in this file.)

--- Clojure/src/ambly/repl/jsc.clj
+++ Clojure/src/ambly/repl/jsc.clj
@@ -44,22 +44,22 @@
   [stack-line]
   (let [[function file line column]
         (rest (re-matches #"(.*)@file://(.*):([0-9]+):([0-9]+)"
-                     stack-line))]
+                stack-line))]
     (if (and function file line column)
       {:function function
        :file     file
-       :line (Long/parseLong line)
-       :column (Long/parseLong column)})))
+       :line     (Long/parseLong line)
+       :column   (Long/parseLong column)})))

 (defn process-exception
   "Process a JSC stack representation, optionally parsing it into
   stack frames if normalize? is true."
   [normalize? stack]
   (merge {:stack stack}
-         (when normalize?
-           {:frames (remove nil?
-                            (map stack-line->frame
-                                 (rest (string/split-lines stack))))})))
+    (when normalize?
+      {:frames (remove nil?
+                 (map stack-line->frame
+                   (rest (string/split-lines stack))))})))

 (defn jsc-eval
   "Evaluate a JavaScript string in the JSC REPL process."
@@ -71,9 +71,9 @@
           status (keyword (:status result))
           value (:value result)]
       {:status status
-       :value (if (= :exception status)
-                (process-exception true value)              ; TODO determine when to normalize based on REPL flag
-                value)})))
+       :value  (if (= :exception status)
+                 (process-exception true value)             ; TODO determine when to normalize based on REPL flag
+                 value)})))

 (defn load-javascript
   "Load a Closure JavaScript file into the JSC REPL process."


- fixed s.replace error with hack.  can't figure out why this happens.

--- src/isomorphic/core.cljs
+++ src/isomorphic/core.cljs
@@ -55,4 +55,5 @@
         action (or action identity)
         params (merge params query-params)
         params (assoc params :callback callback :state state)]
-    (action params)))
+    (action params)
+    nil))                                                   ; HACK - without this, secretary/core.cljs:305 throws a s.replace is not a function


Added explanatory text as per sw1nn's request.

--- src/kixi/hecuba/data.clj
+++ src/kixi/hecuba/data.clj
@@ -3,12 +3,18 @@

 ;; Some utility funcitons

-(defn parse-list [m key]
+(defn parse-list
+  "Add a json list to a map with the given key if the list exists,
+  otherwise return the map unchanged."
+  [m key]
   (if-let [items (get m key)]
     (assoc m key (mapv #(json/parse-string % keyword) items))
     m))

-(defn parse-item [m key]
+(defn parse-item
+  "Add a json object to a map with the given key if the list exists,
+  otherwise return the map unchanged."
+  [m key]
   (if-let [item (get m key)]
     (assoc m key (json/parse-string item keyword))
     m))


refactored first-truthy-fn to use a generic unchunking fn

--- src/midje/util/form_utils.clj
+++ src/midje/util/form_utils.clj
@@ -99,14 +99,18 @@
              (next vs))
       m)))

+(defn unchunk
+  "force a lazy sequence not to use size 32 chunks - we want size-1 units!"
+  [s]
+  (lazy-seq (when-let [s (seq s)]
+              (cons (first s) (unchunk (rest s))))))
+
 (defn first-truthy-fn
   "Returns the first function in a seq of functions
-  that evaluates to truthy for the given arguments"
-  [[pred & more-preds] & args]
-  (when pred
-    (if (apply pred args)
-      pred
-      (apply first-truthy-fn more-preds args))))
+  that evaluates to truthy for the given arguments - it shortcicuits,
+  only evaluating the minimum number of functions necessary to evaluate"
+  [preds & args]
+  (first (filter #(apply % args) (unchunk preds))))

 (defn translate-zipper
   "Traverses the zipper - for the first predicate that evaluates to truthy for matching a


One more test fix

One more test fix

--- test/hundred_pushups/datetime_test.cljc
+++ test/hundred_pushups/datetime_test.cljc
@@ -39,6 +39,6 @@
        (is (= [2016 01 02]
               (local-date #inst "2016-01-02T12:01:01Z" "America/Denver")))
        (is (= [1969 12 31]
-              (local-date (inst 0))))
+              (local-date (inst 0) "America/Denver")))
        (is (= [2015 12 31]
               (local-date (inst "2016-01-01T00:00:00Z") "America/Denver"))))))


more card implementation

more card implementation

--- src/node/game/cards.cljs
+++ src/node/game/cards.cljs
@@ -26,46 +26,65 @@
    "Dyson Mem Chip" {:effect (effect (gain :link 1 :memory 1))
                      :leave-play (effect (lose :link 1 :memory 1))}
    "Easy Mark" {:effect (effect (gain :credit 3))}
+   "Gila Hands Arcology" {:abilities [{:cost [:click 2] :effect (effect (gain :credit 3)) :msg "gain 3 [Credits]"}]}
+   "Government Contracts" {:abilities [{:cost [:click 2] :effect (effect (gain :credit 4)) :msg "gain 4 [Credits]"}]}
    "Green Level Clearance" {:effect (effect (gain :credit 3) (draw))}
    "GRNDL: Power Unleashed" {:effect (effect (gain :credit 5 :bad-publicity 1))}
    "Hedge Fund" {:effect (effect (gain :credit 9))}
+   "Hostile Takeover" {:effect (effect (gain :credit 7 :bad-publicity 1))}
    "Lawyer Up" {:effect (effect (draw 3) (lose :tag 2))}
    "Levy AR Lab Access"
    {:effect (effect (shuffle-into-deck :hand :discard) (draw 5) (move (first (:play-area runner)) :rfg))}
    "Lucky Find" {:effect (effect (gain :credit 9))}
    "Magnum Opus" {:abilities [{:cost [:click 1] :effect (effect (gain :credit 2)) :msg "gain 2 [Credits]"}]}
    "Medical Research Fundraiser" {:effect (effect (gain :credit 8) (gain :runner :credit 3))}
+   "Melange Mining Corp." {:abilities [{:cost [:click 3] :effect (effect (gain :credit 7)) :msg "gain 7 [Credits]"}]}
    "NBN: The World is Yours*" {:effect (effect (gain :max-hand-size 1))}
    "Neural EMP" {:req (req (:made-run register)) :effect (effect (damage :net 1))}
    "Paper Tripping" {:req (req (not (:spent-click register))) :effect (effect (lose :tag :all))}
+   "Philotic Entanglement" {:effect (effect (damage :net (count (:scored runner))))}
+   "Private Security Force"
+   {:abilities [{:req (req tagged) :cost [:click 1] :effect (effect (damage :meat 1)) :msg "do 1 meat damage"}]}
+   "Public Sympathy" {:effect (effect (gain :max-hand-size 2)) :leave-play (effect (lose :max-hand-size 2))}
    "Power Nap"
    {:effect (effect (gain :credit (+ 2 (count (filter (fn [c] (has? c :subtype "Double")) (:discard runner))))))}
    "Professional Contacts" {:abilities [{:cost [:click 1] :effect (effect (gain :credit 1) (draw))
                                          :msg "gain 1 [Credits] and draw 1 card"}]}
    "Quality Time" {:effect (effect (draw 5))}
    "Restructure" {:effect (effect (gain :credit 15))}
+   "Scorched Earth" {:req (req tagged) :effect (effect (damage :meat 4))}
+   "Successful Demonstration" {:req (req (:unsucessful-run register)) :effect (gain :credit 7)}
    "Sure Gamble" {:effect (effect (gain :credit 9))}
-   "Scorched Earth" {:req (req tagged) :effect (effect (damage :meat 4))}
-   "Successful Demonstration" {:prereq [()]}
    "Sweeps Week" {:effect (effect (gain :credit (count (:hand runner))))}
+   "Veterans Program" {:effect (effect (lose :bad-publicity 2))}
    "Witness Tampering" {:effect (effect (lose :bad-publicity 2))}

    ;; partial implementation
    "Astrolabe" {:effect (effect (gain :memory 1)) :leave-play (effect (lose :memory 1))}
+   "Bad Times" {:req (req tagged)}
    "Exile: Streethawk" {:effect (effect (gain :link 1))}
    "Grimoire" {:effect (effect (gain :memory 2)) :leave-play (effect (lose :memory 2))}
    "Desperado" {:effect (effect (gain :memory 1)) :leave-play (effect (lose :memory 1))}
    "Doppelgänger" {:effect (effect (gain :memory 1)) :leave-play (effect (lose :memory 1))}
+   "Early Bird" {:req (req (not (:spent-click register)))}
+   "Emergency Shutdown" {:req (req (some :hq (:successful-run register)))}
    "Iain Stirling: Retired Spook" {:effect (effect (gain :link 1))}
+   "Freelancer" {:req (req tagged)}
    "Kate \"Mac\" McCaffrey: Digital Tinker" {:effect (effect (gain :link 1))}
+   "Kraken" {:req (req (:stole-agenda register))}
    "Logos" {:effect (effect (gain :memory 1 :max-hand-size 1))
             :leave-play (effect (lose :memory 1 :max-hand-size 1))}
+   "Midseason Replacements" {:req (req (:stole-agenda register))}
    "Monolith" {:effect (effect (gain :memory 3)) :leave-play (effect (lose :memory 3))}
    "Nasir Meidan: Cyber Explorer" {:effect (effect (gain :link 1))}
+   "Power Shutdown" {:req (req (:made-run register))}
+   "Psychographics" {:req (req tagged)}
    "Rabbit Hole" {:effect (effect (gain :link 1)) :leave-play (effect (lose :link 1))}
    "Reina Roja: Freedom Fighter" {:effect (effect (gain :link 1))}
+   "SEA Source" {:req (req (:sucessful-run register))}
    "Spinal Modem" {:effect (effect (gain :memory 1)) :leave-play (effect (lose :memory 1))}
    "The Helpful AI" {:effect (effect (gain :link 1)) :leave-play (effect (lose :link 1))}
    "The Toolbox" {:effect (effect (gain :link 2 :memory 2))
                   :leave-play (effect (lose :link 2 :memory 2))}
+   "Three Steps Ahead" {:req (req (not (:spent-click register)))}
    })


[core] Remove extraneous refer

[core] Remove extraneous refer

--- src/braid/core.clj
+++ src/braid/core.clj
@@ -7,7 +7,7 @@
    [braid.core.modules :as modules]
    ;; all following requires are for mount:
    [braid.core.server.core]
-   [braid.core.server.email-digest :refer [email-jobs]]))
+   [braid.core.server.email-digest]))

 ;; because we often use http-kit as our http-client
 ;; including this so that SNI works


Use vis-svg-arrow more.

Use vis-svg-arrow more.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -223,9 +223,8 @@
                              cy (ch-y ch)]
                          (when (not= ay cy)
                            [(if (= :put wait-kind)
-                              ["<line x1='500' y1='" ay "' x2='600' y2='" cy]
-                              ["<line x1='600' y1='" cy "' x2='500' y2='" ay])
-                            "' stroke='#faa' stroke-width='1' marker-end='url(#triangle)'/>"
+                              (vis-svg-arrow "" 500 ay 600 cy "#faa")
+                              (vis-svg-arrow "" 600 cy 500 ay "#faa"))
                             (when ch-name
                               ["<text class='ch-name' x='540' y='" (* 0.5 (+ ay cy))
                                "'>" ch-name "</text>"])])))


Add time unit.

Add time unit.

--- src/dsbdp/main.clj
+++ src/dsbdp/main.clj
@@ -56,7 +56,7 @@
         delta-cntr (delta-counter)
         stats-fn (fn []
                    (println
-                     "time-delta:" (delta-cntr :time (System/currentTimeMillis)) ";"
+                     "time-delta:" (delta-cntr :time (System/currentTimeMillis)) "ms;"
                      "in:" (long (/ (delta-cntr :in (.value in-cntr)) 1000)) "k;"
                      "out:" (long (/ (delta-cntr :out (.value out-cntr)) 1000)) "k;"))
         out-fn (fn [_ _]


add json handler

add json handler

--- json-demo/src/json_demo/handler.clj
+++ json-demo/src/json_demo/handler.clj
@@ -1,11 +1,29 @@
 (ns json-demo.handler
   (:require [compojure.core :refer :all]
-            [compojure.route :as route]
-            [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
+            [compojure.route :refer [not-found]]
+            [ring.middleware.resource :refer [wrap-resource]]
+            [ring.middleware.params :refer [wrap-params]]
+            [ring.middleware.json
+             :refer [wrap-json-body wrap-json-response]]
+            [ring.util.response :refer [response redirect]]))
+
+(defn respond-to-json [s]
+  (println "post-parameters: " s)
+  (response {:main-character2 "Huck"
+              :main-character1 "Tom"}))

 (defroutes app-routes
-  (GET "/" [] "Hello World")
-  (route/not-found "Not Found"))
+  (POST "/a" [s] (respond-to-json s))
+
+  (GET "/" []
+       (redirect "/postjson.html"))
+
+  (not-found (str "no mathching route found\n"
+                  "Try this")))

 (def app
-  (wrap-defaults app-routes site-defaults))
+  (-> app-routes
+      (wrap-params)
+      (wrap-resource "public")
+      (wrap-json-body)
+      (wrap-json-response)))


convert any bus arguments to ugens to their :id property (in a similar fashion to buffers)

--- src/overtone/sc/ugen.clj
+++ src/overtone/sc/ugen.clj
@@ -8,7 +8,7 @@
    clojure.contrib.pprint
    overtone.sc.ugen.defaults
    [overtone util]
-   [overtone.sc buffer]
+   [overtone.sc buffer bus]
    [overtone.sc.ugen special-ops common categories]
    [clojure.contrib.types :only (deftype)]
    [clojure.contrib.generic :only (root-type)])
@@ -266,6 +266,14 @@
              (fn [args]
                (map #(if (buffer? %) (:id %) %) args))))

+(defn- bus->id
+  "Returns a function that converts any bus arguments to their :id property
+  value."
+  [ugen]
+  (update-in ugen [:args]
+             (fn [args]
+               (map #(if (bus? %) (:id %) %) args))))
+
 (defn- with-init-fn
   "Creates the final argument initialization function which is applied to
   arguments at runtime to do things like re-ordering and automatic filling in
@@ -292,6 +300,7 @@
                  n-outputer
                  floater
                  buffer->id
+                 bus->id
                  appender
                  auto-rater
                  rate-checker)))))
@@ -623,5 +632,3 @@
      ~@body))

 (load "ugen/extra")
-
-


More server compilation woes...

More server compilation woes...

--- src/polismath/server.clj
+++ src/polismath/server.clj
@@ -133,14 +133,20 @@
                  :key (full-aws-path filename)
                  :file (full-path filename)))

-
-;; This should be good enough for now... just dispatch on tag
+;; This will end up redirecting to the aws download link
+(defn get-datadump-url
+  [filename zinvite]
+  (full-url (str "datadump/results?filename=" filename "&zinvite=" zinvite)))
+
+
+;; Email notification of completion
+
 (defn hiccup-to-plain-text-dispatch
   [hiccup-or-string]
   (if (string? hiccup-or-string)
     :type/string
     (first hiccup-or-string)))
-;(ns-unmap *ns* 'hiccup-to-plain-text)
+
 (defmulti hiccup-to-plain-text
   "Converts hiccup data to plain text."
   {:arglists '([hiccup])}
@@ -312,10 +318,6 @@

 ;; Requests for checking the status of a computation

-(defn get-datadump-url
-  [filename zinvite]
-  (full-url (str "datadump/results?filename=" filename "&zinvite=" zinvite)))
-
 (defn complete-response
   [filename zinvite]
   (let [url (get-datadump-url filename zinvite)]


datamunging part3 (clojure)

datamunging part3 (clojure)

--- src/main/clojure/datamunging/datamunging0.clj
+++ src/main/clojure/datamunging/datamunging0.clj
@@ -2,28 +2,30 @@
   (:use [clojure.string :only [split]]
         clojure.test))

+(defn read-file-lines [file-name] (vec (.split (slurp file-name) "\n")))
+(defn as-int [s] (. Integer parseInt (.replace s "*" "")))
+(defn split-each-line [lines] (map #(vec (.split (.trim %) "\\s+")) lines))
+(defn find-row-with-min-diff [data-rows]
+  (apply min-key #(Math/abs (- (nth % 1) (nth % 2))) data-rows))
+
+
 (defn find-day-with-min-temperature-spread []
-  (defn file-as-string [] (slurp "/Users/dima/IdeaProjects/katas/src/main/scala/ru/katas/n4/weather.dat"))
-  (defn lines [] (drop 8 (drop-last 2 (seq (.split (file-as-string) "\n")))))
-  (defn data [] (map #(vec (.split (.trim %) "\\s+")) (lines)))
-  (defn temperatures []
-    (defn as-int [s] (. Integer parseInt (.replace s "*" "")))
-    (map #(vec [(nth % 0) (as-int (nth % 1)) (as-int (nth % 2))]) (data)))
-  (defn row-with-min-temperature-diff []
-    (apply min-key #(Math/abs (- (nth % 1) (nth % 2))) (temperatures)))
+  (defn filter-non-data-lines [lines] (drop 8 (drop-last 2 lines)))
+  (defn parse-as-data [lines] (map #(vec [(nth % 0) (as-int (nth % 1)) (as-int (nth % 2))]) (split-each-line lines)))

-  (nth (row-with-min-temperature-diff) 0)
+  (let [lines (read-file-lines "/Users/dima/IdeaProjects/katas/src/main/scala/ru/katas/n4/weather.dat")]
+    (first (find-row-with-min-diff (parse-as-data (filter-non-data-lines lines))))
+  )
 )

 (defn find-team-with-min-goal-diff []
-  (defn read-file [] (slurp "/Users/dima/IdeaProjects/katas/src/main/scala/ru/katas/n4/football.dat"))
-  (defn lines [] (vec (.split (read-file) "\n")))
-  (defn drop-header-and-footer [] (drop-last 1 (drop 5 (filter #(not (.contains % "---")) (lines)))))
-  (defn data-as-strings [] (map #(vec (.split (.trim %) "\\s+")) (drop-header-and-footer)))
-  (defn as-int [s] (Integer/parseInt s))
-  (defn data [] (map #(vec [(nth % 1) (as-int (nth % 6)) (as-int (nth % 8))])(data-as-strings)))
+  (defn filter-non-data-lines [lines] (drop-last 1 (drop 5 (filter #(not (.contains % "---")) lines))))
+  (defn parse-as-data [lines]
+    (map #(vec [(nth % 1) (as-int (nth % 6)) (as-int (nth % 8))])(split-each-line lines)))

-  (first (apply min-key #(Math/abs (- (nth % 1) (nth % 2))) (data)))
+  (let [lines (read-file-lines "/Users/dima/IdeaProjects/katas/src/main/scala/ru/katas/n4/football.dat")]
+    (first (find-row-with-min-diff (parse-as-data (filter-non-data-lines lines))))
+  )
 )

 (deftest should-find-team-with-min-goal-diff


Minor changes on tools.clj script.

Minor changes on tools.clj script.

--- tools.clj
+++ tools.clj
@@ -56,61 +56,9 @@
    :pseudo-names true
    :verbose true})

-;; (defmethod task "test"
-;;   [[_ exclude]]
-;;   (let [tests (ef/find-tests "test")
-;;         tests (if (string? exclude)
-;;                 (ef/find-tests (symbol exclude))
-;;                 tests)]
-;;     (ef/run-tests tests
-;;                   {:fail-fast? true
-;;                    :capture-output? false
-;;                    :multithread? false})
-;;     (System/exit 1)))
-
 (defmethod task "build:tests"
   [args]
   (api/build (api/inputs "src" "test") build-options))
-
-;; (defmethod task "test-cljs"
-;;   [[_ type]]
-;;   (letfn [(build [optimizations]
-;;             (api/build (api/inputs "src" "test")
-;;                        (cond->  (assoc options :optimizations optimizations)
-;;                          (= optimizations :none) (assoc :source-map true))))
-
-;;           (run-tests []
-;;             (let [{:keys [out err]} (shell/sh "node" "out/tests.js")]
-;;               (println out err)))
-
-;;           (test-once []
-;;             (build :none)
-;;             (run-tests)
-;;             (shutdown-agents))
-
-;;           (test-watch []
-;;             (println "Start watch loop...")
-;;             (try
-;;               (api/watch (api/inputs "src", "test")
-;;                          (assoc options
-;;                                 :parallel-build false
-;;                                 :watch-fn run-tests
-;;                                 :cache-analysis false
-;;                                 :optimizations :none
-;;                                 :source-map true))
-;;               (catch Exception e
-;;                 (println "ERROR:" e)
-;;                 (Thread/sleep 2000)
-;;                 (test-watch))))]
-
-;;     (case type
-;;       (nil "once") (test-once)
-;;       "watch"      (test-watch)
-;;       "build-none"     (build :none)
-;;       "build-simple"   (build :simple)
-;;       "build-advanced" (build :advanced)
-;;       (do (println "Unknown argument to test task:" type)
-;;           (System/exit 1)))))

 (defmethod task "jar"
   [args]


continue to isolate/encapsulate join internal rep

--- dada2-core/src/test/clojure/org/dada2/test_join_model.clj
+++ dada2-core/src/test/clojure/org/dada2/test_join_model.clj
@@ -62,10 +62,9 @@

 ;;--------------------------------------------------------------------------------

-(defn- lhs-upsert [old-indeces ks v join-fn joined-model]
-  (let [new-indeces (lhs-assoc old-indeces ks v)
-	[_ & rhs-indeces] old-indeces
-	joins (derive-joins v rhs-indeces ks join-fn)]
+(defn- lhs-upsert [old-indeces keys lhs join-fn joined-model]
+  (let [new-indeces (lhs-assoc old-indeces keys lhs)
+	joins (derive-joins lhs (rest new-indeces) keys join-fn)]
     [new-indeces (fn [_] (on-upserts joined-model joins))]))

 ;;; TODO


Longer wait

Longer wait

--- src/nube/app.clj
+++ src/nube/app.clj
@@ -114,12 +114,12 @@

 (defn health-check-host [host port]
   (mark-host-health (str host ":" port)
-   (loop [n 10]
+   (loop [n 15]
      (when (pos? n)
        (if (= 200 (:status @(http/get (str "http://" host ":" port "/") {:timeout 5000})))
          true
          (do
-           (Thread/sleep (* (- 10 n) 500))
+           (Thread/sleep (* (- 15 n) 500))
            (recur (dec n))))))))

 (defn health-check-instances []


Add some conditions to title-case

Add some conditions to title-case

--- src/str/core.clj
+++ src/str/core.clj
@@ -332,6 +332,8 @@
 (defn ^String title-case
   "Capitalize the first character of s and lower case the rest."
   [^String s]
+  {:pre [(string? s)]
+   :post [(string? %)]}
   (let [first-char (first s)
         start (if (upper-exists? first-char) (upper-case first-char) first-char)]
     (str start (lower-case (.substring s 1)))))


log per line

log per line

--- src/vc/guest.clj
+++ src/vc/guest.clj
@@ -17,7 +17,7 @@
   (:require
     [clj-http.client :as client])
   (:use
-    [clojure.string :only (join)]
+    [clojure.string :only (join split)]
     [slingshot.slingshot :only  [throw+]]
     [celestial.provider :only (wait-for)]
     [celestial.common :only (gen-uuid import-logging)]
@@ -93,13 +93,14 @@
   "set guest static ip"
   [hostname auth config]
   (let [uuid (gen-uuid) tmp-file (<< "/tmp/intrefaces_~{uuid}")]
+    (debug "setting up guest static ip")
     (upload-file (render-resource "static-ip.mustache" (update-in config [:names] (partial join ","))) tmp-file hostname auth)
     (guest-run hostname "/bin/cp" (<< "-v ~{tmp-file} /etc/network/interfaces") auth uuid [2 :seconds])
     (guest-run hostname "/usr/sbin/service" "networking restart" auth uuid [3 :seconds])
     (guest-run hostname "/bin/rm" (<< "-v ~{tmp-file}") auth uuid [2 :seconds])
     (guest-run hostname "echo" (<< "'kernel.hostname = ~{hostname}' | sudo tee -a /etc/sysctl.conf") auth uuid [2 :seconds])
     (guest-run hostname "sysctl" "-e -p" auth uuid [2 :seconds])
-    (debug (fetch-log hostname uuid auth))))
+    (doseq [line (split (fetch-log hostname uuid auth) #"\n")] (debug line))))

 (comment
   (set-ip "red1" {:user "ronen" :password "foobar" :sudo true}


Fixed broken test

Fixed broken test

--- kuona-core/test/kuona_core/builder_test.clj
+++ kuona-core/test/kuona_core/builder_test.clj
@@ -32,5 +32,7 @@

 (facts "about project scanning"
        (fact
-        (let [result (collect-builder-metrics ".")]
-          (:artifactId (:artifact (first result)))  =>  "kuona-core")))
+        (let [result (collect-builder-metrics "./test")]
+          (-> (first result) :artifact :groupId) => "kuona"
+          (-> (first result) :artifact :version) => "0.1"
+          (-> (first result) :artifact :artifactId)  =>  "kuona-dashboard")))


issue with type implicits

issue with type implicits

--- src/latte/core.clj
+++ src/latte/core.clj
@@ -101,6 +101,7 @@
         (if-let [res (u/fetch-implicit-type-parameters params)]
           (handle-implicit-type-parameters `definition def-name doc (:rest-params res) body
                                            (:implicit-types res)
+                                           (map first (:explicit-type-params res))
                                            (symbol (str def-name "-def"))
                                            (into [] (concat (:explicit-type-params res) (:rest-params res))))
           ;; no implicit parmeter types from here...
@@ -135,12 +136,14 @@
     (throw (ex-info "Definition kind not supported." {:def-kind def-kind}))))

 (defn ^:no-doc handle-implicit-type-parameters
-  [def-kind def-name doc params body implicit-types explicit-def-name explicit-params]
+  [def-kind def-name doc params body implicit-types implicit-types-params explicit-def-name explicit-params]
+  (println "implicit-types-params=" implicit-types-params)
+  (println "implicit-type=" implicit-types)
   (let [[def-kind-name def-kind-kw] (def-kind-infos def-kind)]
     `(do
        (~def-kind ~explicit-def-name ~(str "This is an explicit variant of [[" def-name "]].") ~explicit-params ~body)
        (alter-meta! (var ~explicit-def-name) update-in [:no-doc] (fn [_#] true))
-       ~(gen-type-parameters-defimplicit def-name def-kind-name doc explicit-def-name implicit-types params explicit-params body)
+       ~(gen-type-parameters-defimplicit def-name def-kind-name doc explicit-def-name implicit-types implicit-types-params params explicit-params body)
        (alter-meta! (var ~def-name) update-in [:arglists] (fn [_#] (list (quote ~params))))
        [:declared ~def-kind-kw (quote ~explicit-def-name) :implicit (quote ~def-name)])))

@@ -153,7 +156,7 @@

 (defn ^:no-doc gen-type-parameters-defimplicit
   "Generate the defimplicit for definitions with implicit type parameters."
-  [def-name def-kind doc explicit-def-name implicit-types real-params explicit-params body]
+  [def-name def-kind doc explicit-def-name implicit-types implicit-types-params real-params explicit-params body]
   (let [def-env-var (gensym "def-env")
         ctx-var (gensym "ctx")
         ndoc (mk-def-doc def-kind body doc)
@@ -179,7 +182,7 @@
        ~ndoc
        [~def-env-var ~ctx-var ~@defparams]
        (let [~@lt-clauses]
-         (list (var ~explicit-def-name) ~@(concat implicit-types
+         (list (var ~explicit-def-name) ~@(concat implicit-types-params
                                                   (map first defparams)))))))

 ;;{
@@ -395,6 +398,7 @@
     (if-let [res (u/fetch-implicit-type-parameters params)]
       (handle-implicit-type-parameters `defthm thm-name doc (:rest-params res) body
                                        (:implicit-types res)
+                                       (map first (:explicit-type-params res))
                                        (symbol (str thm-name "-thm"))
                                        (into [] (concat (:explicit-type-params res) (:rest-params res))))
       ;; no implicit type parameters
@@ -422,6 +426,7 @@
     (if-let [res (u/fetch-implicit-type-parameters params)]
       (handle-implicit-type-parameters `deflemma thm-name doc (:rest-params res) body
                                        (:implicit-types res)
+                                       (map first (:explicit-type-params res))
                                        (symbol (str thm-name "-lemma"))
                                        (into [] (concat (:explicit-type-params res) (:rest-params res))))
       ;; no implicit type parameters
@@ -472,6 +477,7 @@
     (if-let [res (u/fetch-implicit-type-parameters params)]
       (handle-implicit-type-parameters `defaxiom thm-name doc (:rest-params res) body
                                        (:implicit-types res)
+                                       (map first (:explicit-type-params res))
                                        (symbol (str thm-name "-ax"))
                                        (into [] (concat (:explicit-type-params res) (:rest-params res))))
       ;; no implicit type parameters


Document the runtime netty implementation choice.

--- src/riemann/transport/tcp.clj
+++ src/riemann/transport/tcp.clj
@@ -73,6 +73,9 @@
     (isSharable [] true)))

 (def netty-implementation
+  "Provide native implementation of Netty for improved performance on
+  Linux only. Provide pure-Java implementation of Netty on all other
+  platforms. See http://netty.io/wiki/native-transports.html"
   (if (.contains (. System getProperty "os.name") "Linux")
     {:event-loop-group-fn #(EpollEventLoopGroup.)
      :channel EpollServerSocketChannel}


Ensure that also the topology id is encoded/decoded correctly

--- storm-core/src/clj/backtype/storm/ui/core.clj
+++ storm-core/src/clj/backtype/storm/ui/core.clj
@@ -1016,34 +1016,40 @@
        (-> (main-page)
            ui-template))
   (GET "/topology/:id" [:as {cookies :cookies} id & m]
-       (let [include-sys? (get-include-sys? cookies)]
+       (let [include-sys? (get-include-sys? cookies)
+            id (java.net.URLDecoder/decode id)]
          (try
            (-> (topology-page id (:window m) include-sys?)
              (concat [(mk-system-toggle-button include-sys?)])
              ui-template)
            (catch Exception e (resp/redirect "/")))))
   (GET "/topology/:id/component/:component" [:as {cookies :cookies} id component & m]
-       (let [include-sys? (get-include-sys? cookies)]
-         (-> (component-page id (java.net.URLDecoder/decode component) (:window m) include-sys?)
+       (let [include-sys? (get-include-sys? cookies)
+            id (java.net.URLDecoder/decode id)
+            component (java.net.URLDecoder/decode component)]
+         (-> (component-page id component (:window m) include-sys?)
              (concat [(mk-system-toggle-button include-sys?)])
              ui-template)))
   (POST "/topology/:id/activate" [id]
     (with-nimbus nimbus
-      (let [tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
+      (let [id (java.net.URLDecoder/decode id)
+            tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
             name (.get_name tplg)]
         (.activate nimbus name)
         (log-message "Activating topology '" name "'")))
     (resp/redirect (str "/topology/" id)))
   (POST "/topology/:id/deactivate" [id]
     (with-nimbus nimbus
-      (let [tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
+      (let [id (java.net.URLDecoder/decode id)
+            tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
             name (.get_name tplg)]
         (.deactivate nimbus name)
         (log-message "Deactivating topology '" name "'")))
     (resp/redirect (str "/topology/" id)))
   (POST "/topology/:id/rebalance/:wait-time" [id wait-time]
     (with-nimbus nimbus
-      (let [tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
+      (let [id (java.net.URLDecoder/decode id)
+            tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
             name (.get_name tplg)
             options (RebalanceOptions.)]
         (.set_wait_secs options (Integer/parseInt wait-time))
@@ -1052,7 +1058,8 @@
     (resp/redirect (str "/topology/" id)))
   (POST "/topology/:id/kill/:wait-time" [id wait-time]
     (with-nimbus nimbus
-      (let [tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
+      (let [id (java.net.URLDecoder/decode id)
+            tplg (.getTopologyInfo ^Nimbus$Client nimbus id)
             name (.get_name tplg)
             options (KillOptions.)]
         (.set_wait_secs options (Integer/parseInt wait-time))


Inline helper fn

Inline helper fn

--- src/spec_tools/core.cljc
+++ src/spec_tools/core.cljc
@@ -11,8 +11,7 @@
         :cljs [[goog.date.UtcDateTime]
                [goog.date.Date]
                [clojure.test.check.generators]
-               [cljs.spec.impl.gen :as gen]])
-    [clojure.string :as str])
+               [cljs.spec.impl.gen :as gen]]))
   (:import
     #?@(:clj
         [(clojure.lang AFn IFn Var)
@@ -112,28 +111,23 @@
 (defn req [k] (->RequiredKey k))

 #?(:clj
-   (defn -map [n m env]
-     (reduce-kv
-       (fn [acc k v]
-         (let [resolve (if (impl/in-cljs? env) (partial impl/cljs-resolve env) resolve)
-               [req? kv] (if (seq? k) [(not= (resolve `opt) (resolve (first k))) (second k)] [true k])
-               k1 (if req? "req" "opt")
-               k2 (if-not (qualified-keyword? kv) "-un")
-               ak (keyword (str k1 k2))
-               [k' v'] (if (qualified-keyword? kv)
-                         [kv (if (not= kv v) v)]
-                         [(keyword (str (namespace n) "$$" (name n) "/" (name kv))) v])]
+   (defmacro map [n m]
+     (let [m (reduce-kv
+               (fn [acc k v]
+                 (let [resolve (if (impl/in-cljs? &env) (partial impl/cljs-resolve &env) resolve)
+                       [req? kv] (if (seq? k) [(not= (resolve `opt) (resolve (first k))) (second k)] [true k])
+                       k1 (if req? "req" "opt")
+                       k2 (if-not (qualified-keyword? kv) "-un")
+                       ak (keyword (str k1 k2))
+                       [k' v'] (if (qualified-keyword? kv)
+                                 [kv (if (not= kv v) v)]
+                                 [(keyword (str (namespace n) "$$" (name n) "/" (name kv))) v])]

-           (-> acc
-               (update ak (fnil conj []) k')
-               (cond-> v' (update ::defs (fnil conj []) [k' v'])))))
-       {}
-       m)))
-
-
-#?(:clj
-   (defmacro map [n m]
-     (let [m (-map n m &env)
+                   (-> acc
+                       (update ak (fnil conj []) k')
+                       (cond-> v' (update ::defs (fnil conj []) [k' v'])))))
+               {}
+               m)
            defs (::defs m)
            margs (apply concat (dissoc m ::defs))]
        `(do


Display 404 page instead of NPE stacktrace page.

Displays a 404 if no update was found for the given ID instead of
throwing a NullPointerException.

Fixes #145.

--- src/statuses/routing.clj
+++ src/statuses/routing.clj
@@ -101,18 +101,18 @@
 (defn delete-entry
   "Deletes an entry if the current user is the author of the entry"
   [id request]
-  (if (= (user request) (:author (core/get-update @db (Integer/parseInt id))))
-    (do (swap! db core/remove-update (Integer/parseInt id))
-      (resp/redirect "/statuses/updates"))
-    (resp/response (str "Delete failed as you are not " :author )))
-  )
+  (if-let [item (core/get-update @db (Integer/parseInt id))]
+    (if-not (= (user request) (:author item))
+      (resp/response (str "Delete failed as you are not " (:author item)))
+      (do (swap! db core/remove-update (Integer/parseInt id))
+          (resp/redirect "/statuses/updates")))))

 (defn page
   "Returns a listing with either the conversation of the specified item or just the item"
   [id request]
-  (let [item (core/get-update @db (Integer/parseInt id))
-        items (core/get-conversation @db (:conversation item))]
-    (list-page (if (empty? items) (list item) items) nil request (:id item))))
+  (when-let [item (core/get-update @db (Integer/parseInt id))]
+    (let [items (core/get-conversation @db (:conversation item))]
+      (list-page (if (empty? items) (list item) items) nil request (:id item)))))

 (defn conversation
   "XXX: Only kept for backwards compatibility to not break existing links to /statuses/conversation/123"
@@ -142,7 +142,7 @@
 (defn replyform
   "Returns a basic HTML form to reply to a certain post."
   [id request]
-  (let [item (core/get-update @db (Integer/parseInt id))]
+  (if-let [item (core/get-update @db (Integer/parseInt id))]
     (reply-form (:id item) (:author item) request)))


Add some index code sketches.

Add some index code sketches.

--- src/vault/index/core.clj
+++ src/vault/index/core.clj
@@ -1 +1,90 @@
-(ns vault.index.core)
+(ns vault.index.core
+  (:require
+    [vault.blob.store :as store :refer [BlobStore]]))
+
+
+(defprotocol Index
+
+  (search
+    [this pattern]
+    [this pattern attr test key]
+    "Search the index for entries with values matching the given pattern.
+    Returns an ascending sequence.")
+
+  (rsearch
+    [this pattern]
+    [this pattern attr test key]
+    "Search the index for entries with values matching the given pattern.
+    Returns a descending sequence.")
+
+  (update
+    [this record]
+    "Return an updated version of the index with information about the record."))
+
+
+(defrecord MemoryIndex [attrs index])
+
+(extend-type MemoryIndex
+  Index
+
+  (update
+    [{:keys [attrs index] :as this} record]
+    (let [key-vec (vec (map record attrs))]
+      (when (some nil? key-vec)
+        (throw (IllegalArgumentException.
+                 (str "Cannot update index with record missing required "
+                      "attributes " (pr-str attrs) " " (pr-str record)))))
+      (->>
+        (->
+          index
+          (get key-vec (hash-set))
+          (conj record))
+        (assoc index key-vec)
+        (assoc this :index)))))
+
+
+(defn memory-index
+  [attr & attrs]
+  (MemoryIndex. (vec (cons attr attrs)) (sorted-map)))
+
+
+
+#_
+{:blob      HashID      ; blob hash-id
+ :size      Long        ; blob byte length
+ :type      Keyword     ; data type
+ :stored-at DateTime}   ; time added to index
+
+#_
+(extend-type BlobIndex
+  Index
+
+  (search
+    [this prefix]
+    ()
+
+    )
+
+  BlobStore
+
+  (enumerate
+    [this opts]
+    nil)
+
+  (stat
+    [this id]
+    nil)
+
+  (put!
+    [this blob]
+
+    nil))
+
+
+
+#_
+(defn changes-by
+  [indexes pk-id]
+  (let [roots   (index/rsearch (:ref/to indexes) [pk-id :vault.entity/root])
+        updates (index/rsearch (:ref/to indexes) [pk-id :vault.entity/update])]
+    (rmerge-sort-by :time roots updates)))


this is a misleading comment

this is a misleading comment

--- src/vigil/operations.clj
+++ src/vigil/operations.clj
@@ -21,7 +21,6 @@
              (partial (comp not check/overdue?) (:sally-duration game))
              (partial check/against-team? (:team-id player)))
             sallies))
-      ;; We need to grab the game again after possibly changing it above.
       {:game (data/get-full-game-by-player-id player)
        :current-player (data/get-player player)})))


CMR-1872: Removed empty test

CMR-1872: Removed empty test

--- system-int-test/test/cmr/system_int_test/search/collection_retrieval_test.clj
+++ system-int-test/test/cmr/system_int_test/search/collection_retrieval_test.clj
@@ -1,14 +0,0 @@
-(ns cmr.system-int-test.search.collection-retrieval-test
-  "Integration test for collection retrieval with cmr-concept-id"
-  (:require [clojure.test :refer :all]
-            [cmr.umm.echo10.collection :as c]
-            [cmr.system-int-test.utils.ingest-util :as ingest]
-            [cmr.system-int-test.utils.search-util :as search]
-            [cmr.system-int-test.utils.index-util :as index]
-            [cmr.system-int-test.data2.collection :as dc]
-            [cmr.mock-echo.client.echo-util :as e]
-            [cmr.system-int-test.system :as s]
-            [cmr.system-int-test.data2.core :as d]
-            [cmr.system-int-test.utils.dev-system-util :as dev-sys-util]
-            [cmr.common.mime-types :as mt]))
-


Fix setting trial error when trial was lost on executor

--- src/cider_ci/dispatcher/sync.clj
+++ src/cider_ci/dispatcher/sync.clj
@@ -39,8 +39,8 @@
     (doseq [lost-trial-id  (difference (set in-progress-trials-of-executor-ids)
                                        (set known-trial-ids-by-executor))]
       (trials/update-trial {:id lost-trial-id
-                     :state "aborted"
-                     :error [(str "This trial was lost on executor " (:name executor))]}))))
+                            :state "aborted"
+                            :error (str "This trial was lost on executor " (:name executor))}))))

 (defn sync [executor data]
   (catcher/with-logging {}


feature(ring-analytics): exclude any param where key contains ‘password’

--- systems/ring-analytics/src/containium/systems/ring_analytics.clj
+++ systems/ring-analytics/src/containium/systems/ring_analytics.clj
@@ -114,8 +114,7 @@
     }
     :mappings {:request {:properties {"started" {:type "date"
                                                  :format "date_hour_minute_second_millis"}}
-                                     :_source {:excludes ["params.password"
-                                                          "form-params.password"]}}}
+                                     :_source {:excludes ["*.*password*"]}}}
     :content-type :smile, :create? false))


remove extra speces in log output

remove extra speces in log output

--- src/clj/clj_money/web/server.clj
+++ src/clj/clj_money/web/server.clj
@@ -240,7 +240,7 @@
     (fn [{:keys [request-method uri] :as request}]
       (if (test-fn request)
         (do
-          (log/trace "apply middleware " description " to " request-method " " uri)
+          (log/trace "apply middleware" description "to" request-method uri)
           ((wrapper-fn handler) request))
         (handler request)))))


Use database test query postgres knows

Use database test query postgres knows

--- src/clj_crud/system/database.clj
+++ src/clj_crud/system/database.clj
@@ -95,7 +95,7 @@
                      :connection-uri db-connect-string}]
            ;; Return an updated version of the component with the
            ;; run-time state assoc'd in.
-           (try (jdbc/query conn ["VALUES 1"])
+           (try (jdbc/query conn ["SELECT *"])
                 (catch Exception e
                   (debug "DB connection failed:" e (with-out-str (.printStackTrace e)))))
            (assoc component :connection conn)))


Show slider when debugging score field

Show slider when debugging score field

--- src/cljs/hacker_agent/debug.cljs
+++ src/cljs/hacker_agent/debug.cljs
@@ -56,7 +56,9 @@
             [:span {:on-click #(reset! collapse? false)
                     :style {:cursor :pointer}}
              "Object"]
-            [edit-value v])
+            (if (= k :score)
+              [slider v 0 1000]
+              [edit-value v]))
           (if (map? @v)
             [field-list v]
             (clj->js v)))]])))


Display results when all images are judged.

--- src/cljs/wrongtangular/core.cljs
+++ src/cljs/wrongtangular/core.cljs
@@ -2,6 +2,7 @@
   (:require [wrongtangular.views :as views]
             [wrongtangular.util :as util]
             [cljs.core.async :refer [>! <! chan put!] :as async]
+            [clojure.string :as string]
             [goog.events :as events]
             [goog.dom :as gdom]
             [om.core :as om :include-macros true]
@@ -162,13 +163,30 @@
             (if-let [current-id (-> app :queue peek :id)]
               (dom/div nil
                 (dom/h1 nil "Wrongtangular")
+                (dom/p nil "(to restart, run `localStorage.clear()` in the console and refresh.")
                 (om/build views/progress app)
                 (om/build views/tinder
                   {:image-set (image-set app)
                    :last-action (last-action app)
                    :direction (:direction app)}
                   {:react-key current-id}))
-              (dom/div nil "OUT OF IMAGES, YAY"))))
+              (let [approved-ids (->> (:complete app)
+                                   (filter #(= (:status %) :approved))
+                                   (map #(-> % :item :id)))
+                    rejected-ids (->> (:complete app)
+                                   (filter #(= (:status %) :rejected))
+                                   (map #(-> % :item :id)))]
+                (dom/div nil
+                  (dom/h1 nil "Processing complete!")
+                  (dom/p nil "(to start over, run `localStorage.clear()` in the console and refresh.")
+                  (dom/h2 nil "Approved ids:")
+                  (dom/textarea #js {:rows 20
+                                     :cols 60
+                                     :value (string/join ", " approved-ids)})
+                  (dom/h2 nil "Rejected ids:")
+                  (dom/textarea #js {:rows 20
+                                     :cols 60
+                                     :value (string/join ", " rejected-ids)}))))))
         om/IWillMount
         (will-mount [_]
           (setup app))


Ohai!

Ohai!

--- src/reply/main.clj
+++ src/reply/main.clj
@@ -58,6 +58,7 @@
   (set-signal-handler! "INT" handle-ctrl-c)
   (set-signal-handler! "CONT" handle-resume)

+  (println "Welcome to REPL-y!")
   (println "Clojure" (clojure-version))
   (help)
   (setup-conveniences)


Change footer.

Change footer.

--- src/htmltohiccup/views/index.clj
+++ src/htmltohiccup/views/index.clj
@@ -35,8 +35,8 @@
         [:h3 "Hiccup"]
         [:div#out_hiccup.span6 {}]]]
       [:hr]
-      [:footer [:p "© Sean Brewer 2013"]]]
-     " "
+      [:footer
+         [:p "Clojure goodness provided by " [:a {:href "http://about.me/seabre"} "seabre"]]]]
      "<!-- /container -->"
      [:script
       {:src


wait added to make safari happy

wait added to make safari happy

--- test/etaoin/api_test.clj
+++ test/etaoin/api_test.clj
@@ -165,12 +165,14 @@
   (testing "wait for text simple"
     (doto *driver*
       (refresh)
+      (wait-visible {:id :document-end})
       (click {:id :wait-button})
       (wait-has-text "-secret-"))
     (is true "text found"))
   (testing "wait for text timeout"
     (doto *driver*
       (refresh)
+      (wait-visible {:id :document-end})
       (click {:id :wait-button}))
     (try+
      (wait-has-text *driver*
@@ -186,7 +188,9 @@
                :interval 0.1
                :times 6})))))
   (testing "wait for non-existing text"
-    (refresh *driver*)
+    (doto *driver*
+      (refresh)
+      (wait-visible {:id :document-end}))
     (try+
      (wait-has-text *driver*
                     "-dunno-whatever-foo-bar-"
@@ -204,7 +208,6 @@
   (is 1)
   (testing "wait for an element has class"
     (doto *driver*
-      (refresh)
       (click {:id :wait-add-class-trigger})
       (wait-has-class {:id :wait-add-class-target} :new-one))))


Change worker interface to assume JS arrays/data

--- src/main/audio_utils/worker.cljs
+++ src/main/audio_utils/worker.cljs
@@ -1,4 +1,5 @@
-(ns audio-utils.worker)
+(ns audio-utils.worker
+  (:require [audio-utils.util :as u]))

 ;;;; General interface for audio processing nodes in web workers

@@ -63,12 +64,11 @@
                    (process-audio @next data))))]
     (set! (.-onmessage js/self)
           (fn [msg]
-            (let [name     (aget (.-data msg) "name")
-                  data     (aget (.-data msg) "data")
-                  clj-data (mapv #(into [] (array-seq %))
-                                 (array-seq data))]
+            (let [name         (aget (.-data msg) "name")
+                  data         (aget (.-data msg) "data")]
+              (js/console.log "WORKER ENTRY NODE / ONMESSAGE")
               (when (= name "worker-process-audio")
-                (process-audio node clj-data)))))
+                (process-audio node data)))))
     node))

 (defn worker-exit-node
@@ -80,23 +80,16 @@
     (connect [this destination])
     (disconnect [this])
     (process-audio [this data]
-      (let [convert? (not (array? data))]
-        (.postMessage js/self (doto #js []
-                                (aset "name" "main-process-audio")
-                                (aset "converted?" convert?)
-                                (aset "data" (cond-> data
-                                               convert?
-                                               clj->js))))))))
+      (.postMessage js/self (doto #js []
+                              (aset "name" "main-process-audio")
+                              (aset "data" data))))))

 (defn main-exit-node
   [worker data-fn]
   (set! (.-onmessage worker)
         (fn [msg]
           (let [name       (aget (.-data msg) "name")
-                converted? (aget (.-data msg) "converted?")
                 data       (aget (.-data msg) "data")]
             (when (= name "main-process-audio")
               (when data-fn
-                (data-fn (cond-> data
-                           converted?
-                           js->clj))))))))
+                (data-fn data)))))))


Increase sleep time to make test work.

Increase sleep time to make test work.


CMR-687: Added additional tests for AND support with campaign/project parameter and refactored.

--- test/cmr/system_int_test/search/granule_campaign_search_test.clj
+++ test/cmr/system_int_test/search/granule_campaign_search_test.clj
@@ -20,34 +20,25 @@
                                                        :project-refs ["PDQ" "RST"]}))]
     (index/refresh-elastic-index)

-    (testing "search by single campaign single result."
-      (let [references (search/find-refs :granule
-                                         {"campaign" "XYZ"})]
-        (is (d/refs-match? [gran2] references))))
-    (testing "search by single campaign multiple result."
-      (let [references (search/find-refs :granule
-                                         {"campaign" "ABC"})]
-        (is (d/refs-match? [gran1 gran2] references))))
-    (testing "serch by single project single result."
-      (let [references (search/find-refs :granule
-                                         {"project" "XYZ"})]
-        (is (d/refs-match? [gran2] references))))
-    (testing "search by single project multiple results."
-      (let [references (search/find-refs :granule
-                                         {"project" "ABC"})]
-        (is (d/refs-match? [gran1 gran2] references))))
-    (testing "search by multiple projects."
-      (let [references (search/find-refs :granule
-                                         {"project" ["XYZ" "PDQ"]})]
-        (is (d/refs-match? [gran2 gran3] references))))
-    (testing "search with some missing projects."
-      (let [references (search/find-refs :granule
-                                         {"project" ["ABC" "LMN"]})]
-        (is (d/refs-match? [gran1 gran2] references))))
-    (testing "search for missing project."
-      (let [references (search/find-refs :granule
-                                         {"project" "LMN"})]
-        (is (d/refs-match? [] references))))
+    (testing "search by campaign"
+      (are [campaign-sn items] (d/refs-match? items (search/find-refs :granule {:campaign campaign-sn}))
+           "XYZ" [gran2]
+           "ABC" [gran1 gran2]))
+    (testing "search by project"
+      (are [project-sn items] (d/refs-match? items (search/find-refs :granule {:project project-sn}))
+           "XYZ" [gran2]
+           "ABC" [gran1 gran2]))
+    (testing "search by multiple campaigns"
+      (are [campaign-kvs items] (d/refs-match? items (search/find-refs :granule campaign-kvs))
+           ;; tests with AND
+           {"campaign[]" ["XYZ" "PDQ"], "options[campaign][and]" "false"} [gran2 gran3]
+           {"campaign[]" ["XYZ" "ABC"], "options[campaign][and]" "true"} [gran2]
+           ;; OR is the default
+           {"campaign[]" ["XYZ" "ABC"]} [gran1 gran2]
+           ;; some missing campaigns
+           {"campaign[]" ["ABC" "LMN"]} [gran1 gran2]
+           ;; not found
+           {"campaign[]" ["LMN"]} []))

     (testing "search by campaign with aql"
       (are [items campaigns options]


Refactor common base path

Refactor common base path

--- src/storemi/js.clj
+++ src/storemi/js.clj
@@ -6,17 +6,22 @@
     [storemi.settings :refer [site-scripts]]
     [storemi.common :refer [read-resource]]))

+(def script-dir "public/js/")
+
+(defn with-base [path]
+  (str script-dir path))
+
 (def common-scripts
-  ["public/js/underscore-min.js"
-   "public/js/site.js"])
+  ["underscore-min.js"
+   "site.js"])

 (defn with-common [& scripts]
-  (concat common-scripts scripts))
+  (map with-base
+       (concat common-scripts scripts)))

 (def parser-scope
   (let [scope (js/new-safe-scope)
-        scripts
-        (with-common "public/js/parser.js")]
+        scripts (with-common "parser.js")]
     (doseq [s scripts]
       (js/eval scope (read-resource s)))))

@@ -28,8 +33,8 @@

 (def react-scope
   (let [scripts (with-common
-                  "public/js/react.min.js"
-                  "public/js/react/story-ui.react.js")
+                  "react.min.js"
+                  "react/story-ui.react.js")
         scope (js/new-scope)]
     (js/eval scope "var global = this")
     (doseq [s scripts]


Document swiss.core namespace.

Document swiss.core namespace.

--- src/swiss/core.clj
+++ src/swiss/core.clj
@@ -3,6 +3,19 @@

   The functions in this namespace are apart of the asset 'pipeline'
   process.
+
+  A swiss context is just a map with the output of each function as
+  the value of the function's name as a keyword. The prev-fn key's
+  value refers to the prev-fn that was called. The prev-fn is
+  represented as a keyword of the name of the prev-fn.
+
+  For example:
+  {:src \"file1.js\" \"console.log('hello world!');\"
+  :prev-fn :src}
+
+  The prev-fn allows us to access the result of the previous operation
+  while keeping a map of every single operation that was applied to
+  the context.

   Example usage:


fix onclick

fix onclick

--- src/om_bootstrap/pagination.cljs
+++ src/om_bootstrap/pagination.cljs
@@ -18,9 +18,9 @@
         classes {:disabled (:disabled? bs)
                  :active (:active? bs)}]
     (d/li (u/merge-props props {:class (d/class-set classes)})
-      (d/a {:href (:href bs)
-            :on-click on-click}
-        children))))
+          (d/a {:href (:href bs)
+                :on-click (:on-click bs)}
+               children))))

 (sm/defn previous :- t/Component [opts :- Page]
   (page (assoc opts :aria-label "Previous") (d/span {:aria-hidden "true"} "«")))


Split lifecycle builders out so they can be better documented and used in information model.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -465,118 +465,177 @@
     (fn [state]
       (transform/apply-fn a-fn f state))))

-(defn build-lifecycles [{:keys [onyx.core/peer-opts] :as event}]
-  (let [pub-liveness-timeout (ms->ns (arg-or-default :onyx.peer/publisher-liveness-timeout-ms peer-opts))]
-    [{:lifecycle :lifecycle/poll-recover
-      :fn poll-recover-input-function
-      :type #{:input}
-      :blockable? true}
-     {:lifecycle :lifecycle/poll-recover
-      :type #{:function}
-      :fn poll-recover-input-function
-      :blockable? true}
-     {:lifecycle :lifecycle/poll-recover
-      :type #{:output}
-      :fn poll-recover-output
-      :blockable? true}
-     {:lifecycle :lifecycle/offer-barriers
-      :type #{:input :function}
-      :fn offer-barriers
-      :blockable? true}
-     {:lifecycle :lifecycle/offer-barrier-status
-      :type #{:input :function :output}
-      :fn offer-barrier-status
-      :blockable? true}
-     {:lifecycle :lifecycle/recover-input
-      :type #{:input}
-      :fn recover-input}
-     {:lifecycle :lifecycle/recover-state
-      :type #{:windowed}
-      :fn recover-state}
-     {:lifecycle :lifecycle/recover-output
-      :type #{:output}
-      :fn recover-output}
-     {:lifecycle :lifecycle/unblock-subscribers
-      :type #{:input :function :output}
-      :fn unblock-subscribers}
-     {:lifecycle :lifecycle/next-iteration
-      :type #{:input :function :output}
-      :fn next-iteration}
-     {:lifecycle :lifecycle/input-poll-barriers
-      :type #{:input}
-      :fn input-poll-barriers}
-     {:lifecycle :lifecycle/check-publisher-heartbeats
-      :doc "Check whether upstream has timed out directly after subscriber poll. Evict if timeout has been met."
-      :type #{:input}
-      :fn (fn [state] (check-upstream-heartbeats state pub-liveness-timeout))}
-     {:lifecycle :lifecycle/seal-barriers?
-      :type #{:input :function}
-      :fn input-function-seal-barriers?}
-     {:lifecycle :lifecycle/seal-barriers?
-      :fn output-seal-barriers?
-      :type #{:output}
-      :blockable? false}
-     {:lifecycle :lifecycle/checkpoint-input
-      :fn checkpoint-input
-      :type #{:input}
-      :blockable? true}
-     {:lifecycle :lifecycle/checkpoint-state
-      :fn checkpoint-state
-      :type #{:windowed}
-      :blockable? true}
-     {:lifecycle :lifecycle/checkpoint-output
-      :fn checkpoint-output
-      :type #{:output}
-      :blockable? true}
-     {:lifecycle :lifecycle/offer-barriers
-      :fn offer-barriers
-      :type #{:input :function}
-      :blockable? true}
-     {:lifecycle :lifecycle/offer-barrier-status
-      :type #{:input :function :output}
-      :fn offer-barrier-status
-      :blockable? true}
-     {:lifecycle :lifecycle/unblock-subscribers
-      :type #{:input :function :output}
-      :fn unblock-subscribers}
-     {:lifecycle :lifecycle/before-batch
-      :type #{:input :function :output}
-      :fn (build-lifecycle-invoke-fn event :lifecycle/before-batch)}
-     {:lifecycle :lifecycle/read-batch
-      :type #{:input}
-      :fn read-batch/read-input-batch}
-     {:lifecycle :lifecycle/read-batch
-      :type #{:function :output}
-      :fn read-batch/read-function-batch}
-     {:lifecycle :lifecycle/check-publisher-heartbeats
-      :doc "Check whether upstream has timed out directly after subscriber poll. Evict if timeout has been met."
-      :type #{:function :output}
-      :fn (fn [state] (check-upstream-heartbeats state pub-liveness-timeout))}
-     {:lifecycle :lifecycle/after-read-batch
-      :type #{:input :function :output}
-      :fn (build-lifecycle-invoke-fn event :lifecycle/after-read-batch)}
-     {:lifecycle :lifecycle/apply-fn
-      :type #{:input :function :output}
-      :fn (compile-apply-fn event)}
-     {:lifecycle :lifecycle/after-apply-fn
-      :type #{:input :function :output}
-      :fn (build-lifecycle-invoke-fn event :lifecycle/after-apply-fn)}
-     {:lifecycle :lifecycle/assign-windows
-      :type #{:windowed}
-      :fn assign-windows}
-     {:lifecycle :lifecycle/prepare-batch
-      :type #{:input :function :output}
-      :fn prepare-batch}
-     {:lifecycle :lifecycle/write-batch
-      :type #{:input :function :output}
-      :fn write-batch
-      :blockable? true}
-     {:lifecycle :lifecycle/after-batch
-      :type #{:input :function :output}
-      :fn (build-lifecycle-invoke-fn event :lifecycle/after-batch)}
-     {:lifecycle :lifecycle/offer-heartbeats
-      :type #{:input :function :output}
-      :fn offer-heartbeats}]))
+(def lifecycles
+  [{:lifecycle :lifecycle/poll-recover
+    :builder (fn [_] poll-recover-input-function)
+    :type #{:input :function}
+    :doc "Poll the messenger for the first recovery barrier sent by the coordinator. Once it has received the first barrier, it advances to the next state."
+    :phase :recovery
+    :blockable? true}
+   {:lifecycle :lifecycle/poll-recover
+    :type #{:output}
+    :doc "Poll the messenger for the first recovery barrier sent by the coordinator. Once it has received the first barrier, it advances to the next state."
+    :phase :recovery
+    :builder (fn [_] poll-recover-output)
+    :blockable? true}
+   {:lifecycle :lifecycle/offer-barriers
+    :doc "Offers the next barrier to downstream tasks. Once it succeeds in offering the barrier to all downstream tasks, it advances to the next state."
+    :phase :recovery
+    :type #{:input :function}
+    :builder (fn [_] offer-barriers)
+    :blockable? true}
+   {:lifecycle :lifecycle/offer-barrier-status
+    :type #{:input :function :output}
+    :doc "Offers the peer's current status up to upstream peers. Once it succeeds in offering the status to all upstream tasks, it advances to the next state."
+    :phase :recovery
+    :builder (fn [_] offer-barrier-status)
+    :blockable? true}
+   {:lifecycle :lifecycle/recover-input
+    :doc "Reads the checkpoint from durable storage and then supplies the checkpoint to the input plugin recover! method. Advance to the next state."
+    :phase :recovery
+    :type #{:input}
+    :builder (fn [_] recover-input)}
+   {:lifecycle :lifecycle/recover-state
+    :doc "Reads the checkpoint from durable storage and then supplies the checkpoint to recover the window and trigger states. Advance to the next state."
+    :phase :recovery
+    :type #{:windowed}
+    :builder (fn [_] recover-state)}
+   {:lifecycle :lifecycle/recover-output
+    :type #{:output}
+    :phase :recovery
+    :doc "Reads the checkpoint from durable storage and then supplies the checkpoint to the output plugin recover! method. Advance to the next state."
+    :builder (fn [_] recover-output)}
+   {:lifecycle :lifecycle/unblock-subscribers
+    :type #{:input :function :output}
+    :phase :recovery
+    :doc "Unblock the messenger subscriptions, allowing messages to be read by the task. Advance to the next state."
+    :builder (fn [_] unblock-subscribers)}
+   {:lifecycle :lifecycle/next-iteration
+    :type #{:input :function :output}
+    :doc "Resets the event map to start a new interation in the processing phase. Advance to the next state."
+    :phase :processing
+    :builder (fn [_] next-iteration)}
+   {:lifecycle :lifecycle/input-poll-barriers
+    :type #{:input}
+    :doc "Poll messenger subscriptions for new barriers. Advance to the next state."
+    :phase :processing
+    :builder (fn [_] input-poll-barriers)}
+   {:lifecycle :lifecycle/check-publisher-heartbeats
+    :doc "Check whether upstream has timed out directly after subscriber poll. Evict if timeout has been met. Advance to the next state."
+    :type #{:input}
+    :phase :processing
+    :builder (fn [event]
+          (let [timeout (ms->ns (arg-or-default :onyx.peer/publisher-liveness-timeout-ms (:onyx.core/peer-opts event)))]
+            (fn [state] (check-upstream-heartbeats state timeout))))}
+   {:lifecycle :lifecycle/seal-barriers?
+    :type #{:input :function}
+    :doc "Check whether barriers have been received from all upstream sources. If all barriers have been received, advance to checkpoint states, otherwise advance to :lifecycle/before-read-batch."
+    :phase :processing
+    :builder (fn [_] input-function-seal-barriers?)}
+   {:lifecycle :lifecycle/seal-barriers?
+    :builder (fn [_] output-seal-barriers?)
+    :type #{:output}
+    :doc "Check whether barriers have been received from all upstream sources. If all barriers have been received, advance to checkpoint states, otherwise advance to :lifecycle/before-read-batch."
+    :phase :processing
+    :blockable? false}
+   {:lifecycle :lifecycle/checkpoint-input
+    :builder (fn [_] checkpoint-input)
+    :type #{:input}
+    :doc "Start checkpoint of input state. Advance to the next state."
+    :phase :processing
+    :blockable? true}
+   {:lifecycle :lifecycle/checkpoint-state
+    :builder (fn [_] checkpoint-state)
+    :type #{:windowed}
+    :doc "Start checkpoint of window and trigger states. Advance to the next state."
+    :phase :processing
+    :blockable? true}
+   {:lifecycle :lifecycle/checkpoint-output
+    :builder (fn [_] checkpoint-output)
+    :doc "Start checkpoint of output state. Advance to the next state."
+    :type #{:output}
+    :phase :processing
+    :blockable? true}
+   {:lifecycle :lifecycle/offer-barriers
+    :builder (fn [_] offer-barriers)
+    :type #{:input :function}
+    :doc "Offers the next barrier to downstream tasks. Once it succeeds in offering the barrier to all downstream tasks, it advances to the next state."
+    :phase :processing
+    :blockable? true}
+   {:lifecycle :lifecycle/offer-barrier-status
+    :type #{:input :function :output}
+    :builder (fn [_] offer-barrier-status)
+    :doc "Offers the peer's current status up to upstream peers. Once it succeeds in offering the status to all upstream tasks, it advances to the next state."
+    :phase :processing
+    :blockable? true}
+   {:lifecycle :lifecycle/unblock-subscribers
+    :doc "Unblock the messenger subscriptions, allowing messages to be read by the task. Advance to the next state."
+    :phase :processing
+    :type #{:input :function :output}
+    :builder (fn [_] unblock-subscribers)}
+   {:lifecycle :lifecycle/before-batch
+    :type #{:input :function :output}
+    :doc "Call all `:lifecycle/before-batch` fns supplied via lifecycle calls maps. Advance to the next state."
+    :phase :processing
+    :builder (fn [event] (build-lifecycle-invoke-fn event :lifecycle/before-batch))}
+   {:lifecycle :lifecycle/read-batch
+    :type #{:input}
+    :phase :processing
+    :doc "Poll input source for messages, placing these messages in `:onyx.core/batch` in the event map. Advance to the next state."
+    :builder (fn [_] read-batch/read-input-batch)}
+   {:lifecycle :lifecycle/read-batch
+    :type #{:function :output}
+    :phase :processing
+    :builder (fn [_] read-batch/read-function-batch)}
+   {:lifecycle :lifecycle/check-publisher-heartbeats
+    :doc "Check whether upstream has timed out directly after subscriber poll. Evict if timeout has been met. Advance to the next state."
+    :type #{:function :output}
+    :phase :processing
+    :builder (fn [event]
+          (let [timeout (ms->ns (arg-or-default :onyx.peer/publisher-liveness-timeout-ms (:onyx.core/peer-opts event)))]
+            (fn [state] (check-upstream-heartbeats state timeout))))}
+   {:lifecycle :lifecycle/after-read-batch
+    :type #{:input :function :output}
+    :phase :processing
+    :doc "Call all `:lifecycle/after-read-batch` fns supplied via lifecycle calls maps. Advance to the next state."
+    :builder (fn [event] (build-lifecycle-invoke-fn event :lifecycle/after-read-batch))}
+   {:lifecycle :lifecycle/apply-fn
+    :type #{:input :function :output}
+    :phase :processing
+    :doc "Call `:onyx/fn` supplied for this task on each segment in `:onyx.core/batch`, placing the results in `:onyx.core/results`. Advance to the next state."
+    :builder compile-apply-fn}
+   {:lifecycle :lifecycle/after-apply-fn
+    :type #{:input :function :output}
+    :phase :processing
+    :doc "Call all `:lifecycle/after-apply-fn` fns supplied via lifecycle calls maps. Advance to the next state."
+    :builder (fn [event] (build-lifecycle-invoke-fn event :lifecycle/after-apply-fn))}
+   {:lifecycle :lifecycle/assign-windows
+    :type #{:windowed}
+    :phase :processing
+    :doc "Update windowed aggregation states, and call any trigger functions. Advance to the next state."
+    :builder (fn [_] assign-windows)}
+   {:lifecycle :lifecycle/prepare-batch
+    :type #{:input :function :output}
+    :phase :processing
+    :doc "Prepare batch for emission to downstream tasks or output mediums. The prepare-batch method is called on any plugins. prepare-batch is useful when output mediums may reject offers of segments, where write-batch may have to retry writes multiple times. Advance if the plugin prepare-batch method returns true, otherwise idle and retry prepare-batch."
+    :blockable? true
+    :builder (fn [_] prepare-batch)}
+   {:lifecycle :lifecycle/write-batch
+    :type #{:input :function :output}
+    :doc "Write :onyx.core/results to output medium or message :onyx.core/results to downstream peers. write-batch will be called on any plugins. Advance to the next state if write-batch returns true, otherwise idle and retry write-batch."
+    :phase :processing
+    :builder (fn [_] write-batch)
+    :blockable? true}
+   {:lifecycle :lifecycle/after-batch
+    :type #{:input :function :output}
+    :doc "Call all `:lifecycle/after-batch` fns supplied via lifecycle calls maps. Advance to the next state."
+    :phase :processing
+    :builder (fn [event] (build-lifecycle-invoke-fn event :lifecycle/after-batch))}
+   {:lifecycle :lifecycle/offer-heartbeats
+    :type #{:input :function :output}
+    :doc "Offer heartbeat messages to peers if it has been `:onyx.peer/heartbeat-ms` milliseconds since the previous heartbeats were sent. Set state to :lifecycle/next-iteration to perform the next task-lifecycle iteration."
+    :phase :processing
+    :builder (fn [_] offer-heartbeats)}])

 (defn filter-task-lifecycles
   [{:keys [onyx.core/task-map onyx.core/windows onyx.core/triggers] :as event}]
@@ -584,9 +643,10 @@
                     (or (not (empty? windows))
                         (not (empty? triggers)))
                     (conj :windowed))]
-    (->> (build-lifecycles event)
+    (->> lifecycles
          (filter (fn [lifecycle]
                    (not-empty (clojure.set/intersection task-type (:type lifecycle)))))
+         (map (fn [lifecycle] (assoc lifecycle :fn ((:builder lifecycle) event))))
          (vec))))

 ;; Used in tests to detect when a task stop is called


utils/simpledb.clj: added docstrings

utils/simpledb.clj: added docstrings

--- src/org/altlaw/util/simpledb.clj
+++ src/org/altlaw/util/simpledb.clj
@@ -5,7 +5,10 @@
 (defn- keystr [x]
   (if (keyword? x) (name x) (str x)))

-(defn- make-attr-list [keyvals]
+(defn- make-attr-list
+  "Given a map of key=>value or key=>[values], return a List of
+  ItemAttribute objects."
+  [keyvals]
   (let [attrs (ArrayList.)]
     (doseq [[k v] keyvals]
       (if (coll? v)
@@ -15,7 +18,10 @@
         (.add attrs (ItemAttribute. (keystr k) (keystr v) true))))
     attrs))

-(defn- parse-attr-list [attrs]
+(defn- parse-attr-list
+  "Given a List of ItemAttribute objects, return a map of name=>value
+  and/or name=>[values]"
+  [attrs]
   (reduce (fn [m attr]
             (let [k (.getName attr), v (.getValue attr)]
               (assoc m k
@@ -51,17 +57,22 @@
     (.putAttributes item (make-attr-list keyvals))))

 (defn get-attrs
-  "Returns attributes (a map of key=>item or key=>collection) in the
-  item under the domain."
+  "Returns attributes (a map of key=>item or key=>collection).
+  Arguments may be either an Item object by itself or strings naming a
+  domain and an item."
   ([item] (parse-attr-list (.getAttributes item)))
   ([domain-name item-name]
      (let [item (get-item domain-name item-name)]
        (parse-attr-list (.getAttributes item)))))

-(defn delete-item [domain-name item-name]
+(defn delete-item
+  "Delete the item from the domain."
+  [domain-name item-name]
   (.deleteItem (get-domain domain-name) (keystr item-name)))

 (defn list-items
+  "Get the list of Item objects, optionally filtered by a Query
+  string."
   ([domain-name]
      (.getItemList (.listItems (get-domain domain-name))))
   ([domain-name query-string]
@@ -69,13 +80,17 @@
                                query-string))))

 (defn select-items
-  ([domain-name query-string]
-     (select-items domain-name query-string nil))
-  ([domain-name query-string next-token]
+  "Perform a Select operation on the domain.  Returns a map from item
+  identifiers to the maps of their attributes."
+  ([domain-name select-string]
+     (select-items domain-name select-string nil))
+  ([domain-name select-string next-token]
      (reduce (fn [m [k v]] (assoc m k (parse-attr-list v)))
              {} (.getItems (.selectItems (get-domain domain-name)
-                                         query-string next-token)))))
+                                         select-string next-token)))))

-(defn delete-where [domain-name query-string]
+(defn delete-where
+  "Deletes items from the domain matching the Query string."
+  [domain-name query-string]
   (doseq [item (list-items domain-name query-string)]
     (delete-item domain-name (.getIdentifier item))))


Use assertions to guard against nil values in min and max

Fixes #125

--- src/tick/core.cljc
+++ src/tick/core.cljc
@@ -836,13 +836,21 @@
 (defn greater [x y]
   (if (neg? (compare x y)) y x))

-(defn max [arg & args]
+(defn max
+  "Find the latest of the given arguments. Callers should ensure that no
+  argument is nil."
+  [arg & args]
+  (assert (every? some? (cons arg args)))
   (reduce #(greater %1 %2) arg args))

 (defn lesser [x y]
   (if (neg? (compare x y)) x y))

-(defn min [arg & args]
+(defn min
+  "Find the earliest of the given arguments. Callers should ensure that no
+  argument is nil."
+  [arg & args]
+  (assert (every? some? (cons arg args)))
   (reduce #(lesser %1 %2) arg args))

 (extend-type Instant


Properly resolve urls and thumbnail urls on image list endpoint.

--- src/uxbox/frontend/images.clj
+++ src/uxbox/frontend/images.clj
@@ -30,6 +30,12 @@
                           :size [300 110]
                           :quality 92
                           :format "jpg"})
+
+(def populate-thumbnails
+  #(images/populate-thumbnails % +thumbnail-options+))
+
+(def populate-urls
+  #(images/populate-urls % media/images-storage :path :url))

 ;; --- Create Collection

@@ -105,16 +111,9 @@
                            :name filename
                            :path (str path)}))

-            (populate-thumbnails [entry]
-              (images/populate-thumbnails entry +thumbnail-options+))
-
-            (populate-urls [v]
-              (images/populate-urls v storage :path :url))
-
             (create-response [entry]
               (let [loc (str "/api/library/images/" (:id entry))]
                 (http/created loc (rsp entry))))]
-
       (->> (st/save storage filename file)
            (p/mapcat persist-image-entry)
            (p/map populate-thumbnails)
@@ -148,12 +147,17 @@

 ;; --- List collections

+(s/def ::list-images
+  (s/keys :opt-un [::us/id]))
+
 (defn list-images
   [{user :identity route-params :route-params}]
-  (let [params {:collection (uuid/from-string (:id route-params))
-                :user user
-                :type :list-images}
-        thumbnail-opts +thumbnail-options+
-        populate-thumbnails-url #(images/populate-thumbnails % thumbnail-opts)]
+  (let [{:keys [id]} (us/conform ::list-images route-params)
+        params {:collection id
+                :type :list-images
+                :user user}]
     (->> (sv/query params)
-         (p/map #(http/ok (rsp (map populate-thumbnails-url %)))))))
+         (p/map (partial map populate-thumbnails))
+         (p/map (partial map populate-urls))
+         (p/map rsp)
+         (p/map http/ok))))


Pull route id keys out into a def so they can be referred to

--- src/route_ccrs/active_routes.clj
+++ src/route_ccrs/active_routes.clj
@@ -4,19 +4,22 @@

 (defquery active-routes "route_ccrs/sql/active_routes.sql")

+(def route-id-keys
+  [:contract
+   :part_no
+   :lowest_level
+   :bom_type_db
+   :routing_revision_no
+   :routing_alternative_no])
+
 (defn route-id [r]
-  (select-keys r [:contract
-                  :part_no
-                  :lowest_level
-                  :bom_type_db
-                  :routing_revision_no
-                  :routing_alternative_no]))
+  (select-keys r route-id-keys))

 (defn sorted-operations []
   (sorted-set-by
     (fn [x y]
       (compare (:operation_no x)
-               (:operation_no y))) ))
+               (:operation_no y)))))

 (defn transduce-routes
   "Transduces routing operation records into tuples of `[route-id operations]`


Clean up ns vault.data a bit.

Clean up ns vault.data a bit.

--- src/vault/data.clj
+++ src/vault/data.clj
@@ -1,7 +1,10 @@
 (ns vault.data
   "Code to handle structured data, usually represented as EDN."
-  (:require [clojure.string :as string]
-            [clojure.data.codec.base64 :as b64]))
+  (:require [clojure.data.codec.base64 :as b64])
+  (:import
+    (java.net URI)
+    (java.text SimpleDateFormat)
+    (java.util Date TimeZone UUID)))

 ;; TOTAL-ORDERING COMPARATOR
@@ -82,14 +85,14 @@

 (defn- format-utc
   "Produces an ISO-8601 formatted date-time string from the given Date."
-  [^java.util.Date date]
+  [^Date date]
   (let [date-format (doto (java.text.SimpleDateFormat.
                             "yyyy-MM-dd'T'HH:mm:ss.SSS-00:00")
-                       (.setTimeZone (java.util.TimeZone/getTimeZone "GMT")))]
+                       (.setTimeZone (TimeZone/getTimeZone "GMT")))]
     (.format date-format date)))

-(extend-type java.util.Date
+(extend-type Date
   TaggedValue
   (edn-tag [this] 'inst)
   (edn-value [this] (format-utc this)))
@@ -97,7 +100,7 @@

 ; #uuid - Universally-unique identifier string.

-(extend-type java.util.UUID
+(extend-type UUID
   TaggedValue
   (edn-tag [this] 'uuid)
   (edn-value [this] (str this)))
@@ -126,17 +129,17 @@

 ; #uri - Universal Resource Identifier string.

-(extend-type java.net.URI
+(extend-type URI
   TaggedValue
   (edn-tag [this] 'uri)
   (edn-value [this] (str this)))

-(defprint-method java.net.URI)
+(defprint-method URI)

 (defn read-uri
   "Constructs a URI from a string value."
-  ^java.net.URI
+  ^URI
   [^String uri]
-  (java.net.URI. uri))
+  (URI. uri))


CMR-3062: Added comments.

CMR-3062: Added comments.

--- umm-lib/src/cmr/umm/dif10/collection/two_d_coordinate_system.clj
+++ umm-lib/src/cmr/umm/dif10/collection/two_d_coordinate_system.clj
@@ -1,10 +1,12 @@
 (ns cmr.umm.dif10.collection.two-d-coordinate-system
+  "Contains functions for convert two d coordinate systems to and parsing from DIF10 XML."
   (:require [clojure.data.xml :as x]
             [cmr.common.xml :as cx]
             [cmr.common.util :as util]
             [cmr.umm.collection :as c]))

 (defn- xml-elem->Coordinate
+  "Returns a UMM Coordinate from a parsed Coordinate XML structure"
   [coord-elem]
   (let [min-value (cx/double-at-path coord-elem [:Minimum_Value])
         max-value (cx/double-at-path coord-elem [:Maximum_Value])
@@ -14,6 +16,7 @@
       (c/map->Coordinate value-map))))

 (defn- xml-elem->TwoDCoordinateSystem
+  "Returns a UMM TwoDCoordinateSystem from a parsed TwoDCoordinateSystem XML structure"
   [two-d-elem]
   (let [name (cx/string-at-path two-d-elem [:TwoD_Coordinate_System_Name])
         coord-1-elem (cx/element-at-path two-d-elem [:Coordinate1])
@@ -23,6 +26,7 @@
                                   :coordinate-2 (xml-elem->Coordinate coord-2-elem)})))

 (defn xml-elem->TwoDCoordinateSystems
+  "Returns UMM TwoDCoordinateSystems from a parsed Collection XML structure"
   [collection-element]
   (seq (map xml-elem->TwoDCoordinateSystem
             (cx/elements-at-path collection-element
@@ -30,6 +34,7 @@

 (defn- generate-coordinate
+  "Returns coordinate xml structure for the given coordinate"
   [coord-key coord]
   (let [{:keys [min-value max-value]} coord]
     (x/element coord-key {}
@@ -37,6 +42,7 @@
                (when max-value (x/element :Maximum_Value {} max-value)))))

 (defn generate-two-ds
+  "Returns DIF10 Spatial_Info element for the given two d coordinate systems"
   [two-d-coordinate-systems]
   (when (seq two-d-coordinate-systems)
     (x/element


Delete unnecessary view nesting

Delete unnecessary view nesting

Former-commit-id: bbaff31570e857e55e40192675a86e8a70b6544b

--- src/syng_im/components/chat.cljs
+++ src/syng_im/components/chat.cljs
@@ -184,72 +184,70 @@
    [actions-list-view navigator chat]])

 (defn toolbar [navigator chat show-actions]
-  [view {:style {:flex (if show-actions 1 0)}}
-   [view {:style {:flexDirection "column"
-                  :backgroundColor color-white
-                  :elevation       2}}
-    [view {:style {:flexDirection   "row"
-                   :height          56}}
-     (when (not show-actions)
-       [touchable-highlight {:on-press (fn []
-                                         (nav-pop navigator))
-                             :underlay-color :transparent}
-        [view {:width  56
-               :height 56}
-         [image {:source {:uri "icon_back"}
-                 :style  {:marginTop  21
-                          :marginLeft 23
-                          :width      8
-                          :height     14}}]]])
-     [view {:style {:flex 1
-                    :marginLeft (if show-actions 16 0)
-                    :alignItems "flex-start"
-                    :justifyContent "center"}}
-      [text {:style {:marginTop  -2.5
-                     :color      text1-color
-                     :fontSize   16
+  [view {:style {:flexDirection   "row"
+                 :height          56
+                 :backgroundColor color-white
+                 :elevation       2}}
+   (when (not show-actions)
+     [touchable-highlight {:on-press (fn []
+                                       (nav-pop navigator))
+                           :underlay-color :transparent}
+      [view {:width  56
+             :height 56}
+       [image {:source {:uri "icon_back"}
+               :style  {:marginTop  21
+                        :marginLeft 23
+                        :width      8
+                        :height     14}}]]])
+   [view {:style {:flex 1
+                  :marginLeft (if show-actions 16 0)
+                  :alignItems "flex-start"
+                  :justifyContent "center"}}
+    [text {:style {:marginTop  -2.5
+                   :color      text1-color
+                   :fontSize   16
+                   :fontFamily font}}
+     (or (chat :name)
+         "Chat name")]
+    (if (:group-chat chat)
+      [view {:style {:flexDirection "row"}}
+       [image {:source {:uri "icon_group"}
+               :style  {:marginTop 4
+                        :width     14
+                        :height    9}}]
+       [text {:style {:marginTop  -0.5
+                      :marginLeft 4
+                      :fontFamily font
+                      :fontSize   12
+                      :color      text2-color}}
+        (str (count (:contacts chat))
+             (if (< 1 (count (:contacts chat)))
+               " members"
+               " member")
+             ", " (count (:contacts chat)) " active")]]
+      [text {:style {:marginTop  1
+                     :color      text2-color
+                     :fontSize   12
                      :fontFamily font}}
-       (or (chat :name)
-           "Chat name")]
-      (if (:group-chat chat)
-        [view {:style {:flexDirection "row"}}
-         [image {:source {:uri "icon_group"}
-                 :style  {:marginTop 4
-                          :width     14
-                          :height    9}}]
-         [text {:style {:marginTop  -0.5
-                        :marginLeft 4
-                        :fontFamily font
-                        :fontSize   12
-                        :color      text2-color}}
-          (str (count (:contacts chat))
-               (if (< 1 (count (:contacts chat)))
-                 " members"
-                 " member")
-               ", " (count (:contacts chat)) " active")]]
-        [text {:style {:marginTop  1
-                       :color      text2-color
-                       :fontSize   12
-                       :fontFamily font}}
-         "Active a minute ago"])]
-     (if show-actions
-       [touchable-highlight {:on-press (fn []
-                                         (dispatch [:set-show-actions false]))
-                             :underlay-color :transparent}
-        [view {:style {:width  56
-                       :height 56}}
-         [image {:source {:uri "icon_up"}
-                 :style  {:marginTop  23
-                          :marginLeft 21
-                          :width      14
-                          :height     8}}]]]
-       [touchable-highlight {:on-press (fn []
-                                         (dispatch [:set-show-actions true]))
-                             :underlay-color :transparent}
-        [view {:style {:width  56
-                       :height 56}}
-         [chat-photo {}]
-         [contact-online {:online true}]]])]]])
+       "Active a minute ago"])]
+   (if show-actions
+     [touchable-highlight {:on-press (fn []
+                                       (dispatch [:set-show-actions false]))
+                           :underlay-color :transparent}
+      [view {:style {:width  56
+                     :height 56}}
+       [image {:source {:uri "icon_up"}
+               :style  {:marginTop  23
+                        :marginLeft 21
+                        :width      14
+                        :height     8}}]]]
+     [touchable-highlight {:on-press (fn []
+                                       (dispatch [:set-show-actions true]))
+                           :underlay-color :transparent}
+      [view {:style {:width  56
+                     :height 56}}
+       [chat-photo {}]
+       [contact-online {:online true}]]])])

 (defn chat [{:keys [navigator]}]
   (let [messages          (subscribe [:get-chat-messages])


Refactor service tests to be nicer

Refactor service tests to be nicer

--- test/clojure/service_test.clj
+++ test/clojure/service_test.clj
@@ -18,12 +18,19 @@

 (use-fixtures :each start-and-stop)

+(defn- block-fn [result ^CountDownLatch latch]
+  (fn [] (.await latch) result))
+
+(defn- success-fn [result]
+  (fn [] result))
+
+(defn- error-fn [e]
+  (fn [] (throw e)))
+
 (deftest submit-test
   (testing "Submit action returns CLJ future wrapping result"
     (let [latch (CountDownLatch. 1)
-          f (service/submit-action service
-                                   (fn [] (.await latch) (* 8 8))
-                                   Long/MAX_VALUE)]
+          f (service/submit-action service (block-fn 64 latch) Long/MAX_VALUE)]
       (is (= :pending (:status f)))
       (is (not (realized? f)))
       (is (= :not-done (deref f 100 :not-done)))
@@ -33,14 +40,14 @@
       (is (nil? (:error f)))))
   (testing "Submitted action can return error"
     (let [exception (IOException.)
-          f (service/submit-action service (fn [] (throw exception)) 10000)]
+          f (service/submit-action service (error-fn exception) 10000)]
       (is (= exception @f))
       (is (= exception (:error f)))
       (is (nil? (:result f)))
       (is (= :error (:status f)))))
   (testing "Submitted action can timeout"
     (let [latch (CountDownLatch. 1)
-          f (service/submit-action service (fn [] (.await latch)) 50)]
+          f (service/submit-action service (block-fn 1 latch) 50)]
       (is (= :timed-out @f))
       (is (= :timed-out (:status f)))
       (.countDown latch)
@@ -48,8 +55,8 @@
       (is (nil? (:error f)))))
   (testing "If concurrency level exhausted, action rejected"
     (let [latch (CountDownLatch. 1)
-          _ (service/submit-action service (fn [] (.await latch)) Long/MAX_VALUE)
-          f (service/submit-action service (fn [] 1) Long/MAX_VALUE)]
+          _ (service/submit-action service (block-fn 1 latch) Long/MAX_VALUE)
+          f (service/submit-action service (success-fn 1) Long/MAX_VALUE)]
       (is (= :max-concurrency-level-exceeded @f))
       (is (= :rejected (:status f)))
       (.countDown latch))))
@@ -58,9 +65,9 @@
   (testing "Testing that metrics are updated with result of action"
     (let [metrics-service (fault/service 1 100)
           latch (CountDownLatch. 1)]
-      @(service/submit-action metrics-service (fn [] 1) Long/MAX_VALUE)
-      @(service/submit-action metrics-service (fn [] (throw (IOException.))) Long/MAX_VALUE)
-      @(service/submit-action metrics-service (fn [] (.await latch)) 10)
+      @(service/submit-action metrics-service (success-fn 1) Long/MAX_VALUE)
+      @(service/submit-action metrics-service (error-fn (IOException.)) Long/MAX_VALUE)
+      @(service/submit-action metrics-service (block-fn 1 latch) 10)
       (.countDown latch)
       (is (= 1 (-> metrics-service :metrics :successes)))
       (is (= 1 (-> metrics-service :metrics :time-outs)))
@@ -70,12 +77,12 @@
     (let [metrics-service (fault/service 1 1)
           latch (CountDownLatch. 1)]
       (service/open-circuit! metrics-service)
-      @(service/submit-action metrics-service (fn [] 1) Long/MAX_VALUE)
+      @(service/submit-action metrics-service (success-fn 1) Long/MAX_VALUE)
       (is (= 1 (-> metrics-service :metrics :circuit-open)))
       (service/close-circuit! metrics-service)

-      (service/submit-action metrics-service (fn [] (.await latch)) Long/MAX_VALUE)
-      (service/submit-action metrics-service (fn [] 1) Long/MAX_VALUE)
+      (service/submit-action metrics-service (block-fn 1 latch) Long/MAX_VALUE)
+      (service/submit-action metrics-service (success-fn 1) Long/MAX_VALUE)
       (.countDown latch)
       (is (= 1 (-> metrics-service :metrics :max-concurrency-level-exceeded)))
       (service/shutdown metrics-service))))


fixed test for wgs84-indexer.

fixed test for wgs84-indexer.

--- test/forma/reproject_test.clj
+++ test/forma/reproject_test.clj
@@ -10,9 +10,13 @@
   (line-torus - 180 45 46)   => 179
   (line-torus + 10 -2 54)    => 6)

+(def ascii-map {:step 0.5
+                :corner [0 -90]
+                :travel [+ +]})
+
 (let [step 0.5
       [width] (dimensions-for-step step)
-      rain-indexer (wgs84-indexer "1000" step + + -90 0)]
+      rain-indexer (wgs84-indexer "1000" ascii-map)]
   (facts
     "This is the only one I have so far... but we need to verify at
 least one of these indices."


Undynamic requests

Undynamic requests

--- test/icecap/e2e/http_test.clj
+++ test/icecap/e2e/http_test.clj
@@ -6,8 +6,8 @@
             [manifold.deferred :refer [let-flow]]
             [taoensso.timbre :refer [info spy]]))

-(def ^:dynamic recvd-reqs)
 (def http-server)
+(def recvd-reqs)

 (defn handler
   [req]
@@ -31,7 +31,7 @@

 (defn ^:private store-reqs-fixture
   [f]
-  (binding [recvd-reqs (atom [])]
+  (with-redefs [recvd-reqs (atom [])]
     (f)))

 (use-fixtures :once icecap-fixture http-server-fixture)


Fix notify test.

Fix notify test.

--- test/onyx/log/notify_test.clj
+++ test/onyx/log/notify_test.clj
@@ -53,7 +53,8 @@
 (def rep-reactions (partial extensions/reactions read-entry))

 (def old-replica {:messaging {:onyx.messaging/impl :dummy-messenger}
-                  :pairs {a-id b-id b-id c-id c-id a-id} :peers [a-id b-id c-id]})
+                  :pairs {a-id b-id b-id c-id c-id a-id} :peers [a-id b-id c-id]
+                  :job-scheduler :onyx.job-scheduler/greedy})

 (def old-local-state {:messenger :dummy-messenger
                       :log (:log env) :id a-id})


make test work

make test work

--- test/platinator/core_test.clj
+++ test/platinator/core_test.clj
@@ -3,5 +3,5 @@
             [platinator.core :refer :all]))

 (deftest a-test
-  (testing "FIXME, I fail."
-    (is (= 0 1))))
+  (testing "Does 1 equal 1"
+    (is (= 1 1))))


Uncomment stubbed test (we support quoted strings!)

--- test/rainboots/parse_test.clj
+++ test/rainboots/parse_test.clj
@@ -89,11 +89,10 @@
     (is (= ["third" nil]
            (default-argtype-handler
              nil "third")))
-    ;; TODO probably, support quoted strings
-    #_(is (= ["fourth   fifth" nil]
+    ; quoted strings
+    (is (= ["fourth   fifth" nil]
            (default-argtype-handler
-             nil " \"fourth   fifth\"  ")))
-    )
+             nil " \"fourth   fifth\"  "))))
   ;
   (binding [*arg-types* (atom {})
             *commands* (atom {})]