added react keys for seat-rows

added react keys for seat-rows

--- src-cljs/kmc_booking/components.cljs
+++ src-cljs/kmc_booking/components.cljs
@@ -11,6 +11,8 @@
 	(.getAttribute el n))

+(defn- range-key [r]
+    [(first r) (last r)])

 ;;;;;

@@ -53,10 +55,18 @@
 	(into [:div] (map #(vector :div.col_num [:div {:key %} %]) range)))

+(rum/defc seat-row < rum/static [row]
+	[:div.row_num
+		[:div {:key row} row]
+		]
+	)
+
 (rum/defc seat-rows < rum/static [range class]
 	(into [:div.rows {:class class}]
-		 	[[:div.col_num [:div {:__html " "}]]
-		 	(map #(vector :div.row_num [:div %]) range)]))
+		 	[[:div.col_num {:key "spacer"} [:div {:__html " " :key 0}]]
+		 	(map
+		 		#(rum/with-props seat-row % :rum/key %)
+		 		range)]))

@@ -94,27 +104,30 @@

 	      beletage_last_cols (range 1 26)
 	      beletage_last_rows (range 21 22)
+
+	      parter-rows (range 1 14)
 		]

-		[:div.seat-plan
-			[:div#parter
-				(seat-rows (range 1 14) "left")
-				(seat-rows (range 1 14) "right")
+		[:div.seat-plan {:key "root"}
+			[:div#parter {:key "parter"}
+				(rum/with-props seat-rows parter-rows "left" :rum/key (str "left_" (range-key parter-rows)))
+				(rum/with-props seat-rows parter-rows "right" :rum/key (str "right_" (range-key parter-rows)))

 				(seat-block [:div#left_side_house.side_house] side_rows left_side_cols seats)
 				(seat-block [:div#left_house.house] house_rows left_house_cols seats)
 				(seat-block [:div#right_house.house] house_rows right_house_cols seats)
 				(seat-block [:div#right_side_house.side_house] side_rows right_side_cols seats)
 				]
-			[:div#back_house
-				(seat-rows (range 14 21) "left")
-				(seat-rows (range 14 21) "right")
-
-				(seat-block [:div#beletage] back_house_rows beletage_cols seats)]
+			[:div#back_house {:key "back_house"}
+				(rum/with-props seat-rows house_rows "left" :rum/key (str "left_" (range-key house_rows)))
+				(rum/with-props seat-rows house_rows "right" :rum/key (str "right_" (range-key house_rows)))

-			[:div#last_row
-				(seat-rows (range 21 22) "left")
-				(seat-rows (range 21 22) "right")
+				(seat-block [:div#beletage] back_house_rows beletage_cols seats)
+				]
+
+			[:div#last_row {:key "last_row"}
+				(rum/with-props seat-rows beletage_last_rows "left" :rum/key (str "left_" (range-key beletage_last_rows)))
+				(rum/with-props seat-rows beletage_last_rows "right" :rum/key (str "right_" (range-key beletage_last_rows)))

 				(seat-block [:div#beletage_last_row] beletage_last_rows beletage_last_cols seats)
 				]


Update text for static banner

Update text for static banner

--- src-cljs/frontend/experiments/no_test_intervention.cljs
+++ src-cljs/frontend/experiments/no_test_intervention.cljs
@@ -30,11 +30,12 @@
 (defn setup-docs-banner [{:keys [owner build]}]
   (when (= (ab-test-treatment) :setup-docs-banner)
     (let [content
-          [:span
-           "It looks like we couldn't infer test settings for your project. Refer to our \""
+          [:span
+           (str "We couldn't detect the settings for your project! Please make sure "
+                "you have a circle.yml configuration file in place, and check our doc about ")
            [:a (setup-docs-link-props owner)
-               "Setting your build up manually"]
-           "\" document to get started. It should only take a few minutes."]]
+               "manual build setup"]
+           "."]]
       (common/message {:type :warning
                        :content content}))))


boolean in cljs

boolean in cljs

--- resources/leiningen/new/closp/cljc/closp_schema_helper.cljc
+++ resources/leiningen/new/closp/cljc/closp_schema_helper.cljc
@@ -20,8 +20,10 @@
   (let [expected-type (get-type-of-column v)]
     (reduce (fn [valid? [key value]]
               (cond
-                (= :unique key) (and valid? (instance? Boolean value))
-                (= :null key) (and valid? (instance? Boolean value))
+                (= :unique key) (and valid? #?(:clj  (instance? Boolean value)
+                                               :cljs (= "boolean" (type value))))
+                (= :null key) (and valid? #?(:clj  (instance? Boolean value)
+                                             :cljs (= "boolean" (type value))))
                 (= :default key) (and valid? (is-correct-default-type expected-type value))
                 :else false))
             true (partition 2 (subvec v 2)))))


Added Specs for App, Dispatch Dispatch Error

--- libs/datview/src/dat/view.cljs
+++ libs/datview/src/dat/view.cljs
@@ -6,6 +6,7 @@
             [dat.reactor.dispatcher :as dispatcher]
             [dat.view.router :as router]
             [dat.view.utils :as utils]
+            [dat.spec.protocols :as protocols]
             [dat.sync.client :as dat.sync]
             [datascript.core :as d]
             [posh.core :as posh]
@@ -29,26 +30,60 @@

 (s/def ::event-id (s/and keyword? namespace))

-
 (s/def ::event (s/and vector? (s/cat :event-id  ::event-id
                                      :event-data (constantly true))))

-
+(s/def ::conn d/conn?)
+
+(s/def ::dispatcher #(satisfies? protocols/PDispatcher %))
+
+;;todo
+(s/def ::base-context map?)
+
+
+
+;;abstraction over a sente connection
+(s/def ::remote (s/and #(satisfies? protocols/PRemoteSendEvent %)
+                       #(satisfies? protocols/PRemoteEventChan %)))
+
+
+(s/def ::app (s/keys :req-un [::conn ::dispatcher ::base-context]
+                     :opt-un [::remote]))

 ;; Some wrappers for convenience

 (defn dispatch!
-  [app event]
-  (dispatcher/dispatch! (:dispatcher app) event))
+  ([app event]
+   (dispatcher/dispatch! (:dispatcher app) event))
+  ([app event level]
+   (dispatcher/dispatch! (:dispatcher app) event level)))
+
+
+(s/def ::dispatch-args (s/cat :app ::app  :event ::event :level (s/? keyword?)))
+
+
+(s/fdef dispatch :args ::dispatch-args)
+
+

 (defn dispatch-error!
   [app event]
   (dispatcher/dispatch-error! (:dispatcher app) event))

+
+(s/fdef dispatch-error! :args (s/cat :app ::app :event ::event))
+
+
+
 (defn send-tx! [app tx-forms]
   (dispatch! app [:dat.sync.client/send-remote-tx tx-forms]))
+
+
+
+
+


Make sure the entry in the paginated board response have all the needed properties like interactions and links.

--- src/oc/storage/representations/board.clj
+++ src/oc/storage/representations/board.clj
@@ -6,46 +6,41 @@
             [oc.storage.config :as config]
             [oc.storage.representations.media-types :as mt]
             [oc.storage.representations.org :as org-rep]
-            [oc.storage.resources.board :as board-res]))
+            [oc.storage.resources.board :as board-res]
+            [oc.storage.urls.board :as board-url]
+            [oc.storage.representations.entry :as entry-rep]))

 (def public-representation-props [:uuid :slug :name :access :promoted :entries :created-at :updated-at :links])
 (def representation-props (concat public-representation-props [:slack-mirror :author :authors :viewers :draft]))

-(defun url
-  ([org-slug board-slug :guard string? params :guard map?]
-    (str (url org-slug board-slug) "?start=" (:start params) "&direction=" (name (:direction params))))
-  ([org-slug board :guard map?] (url org-slug (:slug board)))
-  ([org-slug slug :guard string?]
-    (str "/orgs/" org-slug "/boards/" slug)))
+(defn- self-link
+  ([org-slug slug] (hateoas/self-link (board-url/url org-slug slug) {:accept mt/board-media-type}))

-(defn- self-link
-  ([org-slug slug] (hateoas/self-link (url org-slug slug) {:accept mt/board-media-type}))
-
-  ([org-slug slug options] (hateoas/self-link (url org-slug slug) {:accept mt/board-media-type} options)))
+  ([org-slug slug options] (hateoas/self-link (board-url/url org-slug slug) {:accept mt/board-media-type} options)))

-(defn- create-entry-link [org-slug slug] (hateoas/create-link (str (url org-slug slug) "/entries/")
+(defn- create-entry-link [org-slug slug] (hateoas/create-link (str (board-url/url org-slug slug) "/entries/")
                                                 {:content-type mt/entry-media-type
                                                  :accept mt/entry-media-type}))

-(defn- partial-update-link [org-slug slug] (hateoas/partial-update-link (url org-slug slug)
+(defn- partial-update-link [org-slug slug] (hateoas/partial-update-link (board-url/url org-slug slug)
                                               {:content-type mt/board-media-type
                                                :accept mt/board-media-type}))

 (defn- delete-link [org-slug slug]
-  (hateoas/delete-link (url org-slug slug)))
+  (hateoas/delete-link (board-url/url org-slug slug)))

 (defn- add-author-link [org-slug slug]
-  (hateoas/add-link hateoas/POST (str (url org-slug slug ) "/authors/") {:content-type mt/board-author-media-type}))
+  (hateoas/add-link hateoas/POST (str (board-url/url org-slug slug ) "/authors/") {:content-type mt/board-author-media-type}))

 (defn- add-viewer-link [org-slug slug]
-  (hateoas/add-link hateoas/POST (str (url org-slug slug ) "/viewers/") {:content-type mt/board-viewer-media-type}))
+  (hateoas/add-link hateoas/POST (str (board-url/url org-slug slug ) "/viewers/") {:content-type mt/board-viewer-media-type}))

 (defn- remove-author-link [org-slug slug user-id]
-  (hateoas/remove-link (str (url org-slug slug) "/authors/" user-id)))
+  (hateoas/remove-link (str (board-url/url org-slug slug) "/authors/" user-id)))

 (defn- remove-viewer-link [org-slug slug user-id]
-  (hateoas/remove-link (str (url org-slug slug) "/viewers/" user-id)))
+  (hateoas/remove-link (str (board-url/url org-slug slug) "/viewers/" user-id)))

 (defn- up-link [org-slug] (hateoas/up-link (org-rep/url org-slug) {:accept mt/org-media-type}))

@@ -60,12 +55,12 @@
         first-activity-date (when activity? (or (:published-at first-activity) (:created-at first-activity)))
         next? (or (= (:direction data) :previous)
                   (= (:next-count data) config/default-activity-limit))
-        next-url (when next? (url org board {:start last-activity-date :direction :before}))
+        next-url (when next? (board-url/url org board {:start last-activity-date :direction :before}))
         next-link (when next-url (hateoas/link-map "next" hateoas/GET next-url {:accept mt/board-media-type}))
         prior? (and start?
                     (or (= (:direction data) :next)
                         (= (:previous-count data) config/default-activity-limit)))
-        prior-url (when prior? (url org board {:start first-activity-date :direction :after}))
+        prior-url (when prior? (board-url/url org board {:start first-activity-date :direction :after}))
         prior-link (when prior-url (hateoas/link-map "previous" hateoas/GET prior-url {:accept mt/board-media-type}))]
     (remove nil? [next-link prior-link])))

@@ -110,6 +105,21 @@
   {:user-id user-id
    :links (if (= access-level :author) [(remove-viewer-link org-slug slug user-id)] [])})

+(defn- comments
+  "Return a sequence of just the comments for an entry."
+  [{interactions :interactions}]
+  (filter :body interactions))
+
+(defn- reactions
+  "Return a sequence of just the reactions for an entry."
+  [{interactions :interactions}]
+  (filter :reaction interactions))
+
+(defn render-entry-for-collection
+  "Create a map of the activity for use in a collection in the API"
+  [org board entry access-level user-id]
+  (entry-rep/render-entry-for-collection org board entry (comments entry) (reactions entry) access-level user-id))
+
 (defn render-board-for-collection
   "Create a map of the board for use in a collection in the REST API"
   ([org-slug board] (render-board-for-collection org-slug board 0))
@@ -123,12 +133,16 @@

 (defn render-board
   "Create a JSON representation of the board for the REST API"
-  [org-slug board access-level params]
-  (let [rep-props (if (or (= :author access-level) (= :viemer access-level))
+  [org board ctx params]
+  (let [access-level (:access-level ctx)
+        rep-props (if (or (= :author access-level) (= :viemer access-level))
                       representation-props
-                      public-representation-props)]
+                      public-representation-props)
+        fixed-entries (map #(render-entry-for-collection org board % access-level (-> ctx :user :user-id))
+                       (:entries board))]
     (json/generate-string
       (-> board
-        (board-links org-slug access-level params)
-        (select-keys rep-props))
+        (board-links (:slug org) access-level params)
+        (select-keys rep-props)
+        (assoc :entries fixed-entries))
       {:pretty config/pretty?})))


Fix a too long line

Fix a too long line

--- src/invadm/core.clj
+++ src/invadm/core.clj
@@ -105,7 +105,8 @@
   (println (json/write-str (filter (options-to-filter options) (read-all-invoices)))))

 (defn list_ [options]
-  (apply println (map pretty-print-invoice (filter (options-to-filter options) (read-all-invoices)))))
+  (apply println (map pretty-print-invoice (filter (options-to-filter options)
+                                                   (read-all-invoices)))))

 (defn -main [& args]
   (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)]


Add --gt and --lt support for filtering invoices

--- src/invadm/core.clj
+++ src/invadm/core.clj
@@ -111,7 +111,15 @@

 (defn options-to-filter [options]
   (fn [invoice]
-    (every? #(= (get options %) (get invoice (name %))) (keys options))))
+    (and
+      (if (contains? options :gt) (t/after?
+                                     (get invoice "issue-date")
+                                     (:gt options)) true)
+      (if (contains? options :lt) (t/before?
+                                     (get invoice "issue-date")
+                                     (:lt options)) true)
+      (every? #(= (get options %) (get invoice (name %)))
+              (filter #(not (or (= % :lt) (= % :gt))) (keys options))))))

 (def cli-options
   ;; TODO: add clever currency default
@@ -124,7 +132,11 @@
    ["-n" "--net NET" "Net"
     :parse-fn #(Integer/parseInt %)]
    ["-a" "--amount AMOUNT" "Total amount"
-    :parse-fn #(Float/parseFloat %)]])
+    :parse-fn #(Float/parseFloat %)]
+   [nil "--lt DATE" "List invoices with date earlier than DATE"
+    :parse-fn parse-date]
+   [nil "--gt DATE" "List invoices with date later than DATE"
+    :parse-fn parse-date]])

 (defn parse-today-default [value]
   (cond
@@ -139,7 +151,7 @@
         "  invadm create -c CURRENCY --from FROM --to TO -a AMOUNT -n NET [-i ISSUE_DATE] [-f FILENAME] ID"
         "    Create an invoice."
         ""
-        "  invadm list {-c CURRENCY, --from FROM, --to TO, -f FILENAME}"
+        "  invadm list {-c CURRENCY, --from FROM, --to TO, -f FILENAME, --lt|--gt DATE}"
         "    List invoices, filtered according to arguments."
         ""
         "  invadm data {-c CURRENCY, --from FROM, --to TO, -f FILENAME}"


post/savecontent.clj: added hadoop context configuration

--- src/org/altlaw/jobs/post/savecontent.clj
+++ src/org/altlaw/jobs/post/savecontent.clj
@@ -1,4 +1,4 @@
-(ns org.altlaw.jobs.savecontent
+(ns org.altlaw.jobs.post.savecontent
   (:require [org.altlaw.util.hadoop :as h]
             [org.altlaw.util.log :as log]
             [org.altlaw.util.context :as context]
@@ -16,6 +16,9 @@
         (log/warn "No HTML for docid " docid)
         nil)))

+(defn mapper-configure [this jobconf]
+  (context/use-hadoop-jobconf jobconf))
+
 (def mapper-map (partial h/standard-map my-map))

 (defn tool-run [this args]


Add ns to dev to ease debugging

Add ns to dev to ease debugging

--- dev/dev.clj
+++ dev/dev.clj
@@ -1,5 +1,6 @@
 (ns dev
-  (:require [clojure.edn :as edn]
+  (:require [cljeromq.core :as mq]
+            [clojure.edn :as edn]
             [clojure.java.io :as io]
             [clojure.inspector :as i]
             [clojure.string :as str]


gh-25 -> fixing terminal reporting coloring for failing tests

--- src/untangled_spec/reporters/terminal.clj
+++ src/untangled_spec/reporters/terminal.clj
@@ -56,9 +56,9 @@
                                      (str exp " != " got)))
                        nil)
                      (condp (fn [p x] (pos? (p x 0))) status
-                       :passed c/green
                        :failed c/red
                        :error  c/red
+                       :passed c/green
                        c/reset))]
     (apply color-fn strings)))


Sets a JVM ID for every waiting realtime update

using realtime_jvm_id

--- src/webapp/framework/server/systemfns.clj
+++ src/webapp/framework/server/systemfns.clj
@@ -528,12 +528,13 @@
         sql-to-create-admin-table "
 CREATE TABLE coils_realtime_log
 (
-  id serial NOT NULL,
-  record_timestamp timestamp without time zone,
-  record_table_name character varying,
-  record_id character varying,
-  record_operation character varying,
-  record_status character varying
+  id                  serial NOT NULL,
+  realtime_jvm_id     integer,
+  record_timestamp    timestamp without time zone,
+  record_table_name   character varying,
+  record_id           character varying,
+  record_operation    character varying,
+  record_status       character varying
 );
 "
   ]
@@ -825,22 +826,25 @@
 ;(sql-1 "select count(id) from table_name " [])

+(def realtime-counter (atom 0))
+(defn next-realtime-id [] (swap! realtime-counter inc))

 (def my-pool (mk-pool))
 (every 10000 (fn []
               (let [sql (str "update coils_realtime_log"
-                            "      set record_status = 'PROCESSING'"
+                            "      set record_status = 'PROCESSING',"
+                            "          realtime_jvm_id = ? "
                             "where "
                             "      id in ( SELECT "
                             "                    id"
                             "              FROM "
                             "                    coils_realtime_log"
                             "              WHERE "
-                            "                   record_status='WAIITING' LIMIT 1 ) "
+                            "                   record_status='WAITING' LIMIT 1 ) "
                     )]
                      (do
                         (println "Checking pool!" )
-                        (korma.core/exec-raw [sql []])
+                        (korma.core/exec-raw [sql [(next-realtime-id)]])
                  ))) my-pool )


Use space delimiter when comma not present on list cmd; fix devth/yetibot#182

--- src/yetibot/core/commands/collections.clj
+++ src/yetibot/core/commands/collections.clj
@@ -168,9 +168,10 @@

 ; list
 (defn list-cmd
-  "list <comma-delimited-items> # construct a list"
+  "list <comma-or-space-delimited-items> # construct a list"
   [{:keys [args]}]
-  (map s/trim (s/split args #",")))
+  (let [delimiter (if (re-find #"," args) #"," #"\s")]
+    (map s/trim (s/split args delimiter))))

 (cmd-hook #"list"
           _ list-cmd)


Drop some debug printing that was left in with the diagnostic stuff :(

--- src/foreclojure/login.clj
+++ src/foreclojure/login.clj
@@ -127,12 +127,12 @@
   (if-let [{id :_id, name :user} (fetch-one :users
                                             :where {:email email}
                                             :only [:_id :user])]
-    (let [{:keys [success] :as diagnostics} (? (try-to-email email name id))]
+    (let [{:keys [success] :as diagnostics} (try-to-email email name id)]
       (if success
         (do (session/session-put! :login-to "/login/update")
             (flash-msg "Your password has been reset! You should receive an email soon."
                        (login-url "/login/update")))
-        (do (spit (? (str name ".pwd")) (? diagnostics))
+        (do (spit (str name ".pwd") diagnostics)
             (flash-error (str "Something went wrong emailing your new password! Please contact team@4clojure.com - we'll reset it manually and look into the problem. When you do, please mention your username.")
                          "/login/reset"))))
     (flash-error "We don't know anyone with that email address!"


OO: Use a user defined palette if available

--- src/hatti/map/viewby.cljs
+++ src/hatti/map/viewby.cljs
@@ -58,15 +58,24 @@
     (f/time-based? field) (evenly-spaced-bins raw-answers 5 "date")
     (f/select-all? field) (map #(when % (s/split % #" ")) raw-answers)))

+(defn get-user-defined-palette
+  "Return the appropriate set of colors for a select_one"
+  [{:keys [children]}]
+  (when (every? :appearance children)
+    (map :appearance children)))
+
 (defn field->colors
   "Returns the appropriate set of colors given the field."
   [field]
   (cond
     ;; if too many options w/in select-one field, fall back to select-all style
-    (f/select-one? field) (if (<= (count (:children field))
-                                  (count qualitative-palette))
-                            qualitative-palette
-                            (repeat "#f30"))
+    (f/select-one? field)
+    (if-let [user-defined-palette (get-user-defined-palette field)]
+      user-defined-palette
+      (if (<= (count (:children field))
+              (count qualitative-palette))
+        qualitative-palette
+        (repeat "#f30")))
     (f/calculate? field)  qualitative-palette
     (f/numeric? field)    sequential-palette
     (f/time-based? field) sequential-palette


Fix a bug in bucket-props

Fix a bug in bucket-props

--- src/icecap/store/riak.clj
+++ src/icecap/store/riak.clj
@@ -12,7 +12,7 @@
     (retrieve [_ index]
       (thread (kv/fetch-one conn bucket index)))
     (delete! [_ index]
-      (thread (kv/delete conn bucket)))))
+      (thread (kv/delete conn bucket index)))))

 (defn bucket-props
   "Creates some bucket props suitable for an icecap bucket.
@@ -27,7 +27,7 @@
   Additionally, we know that we're never going to see key collisions,
   because the keys are long random strings.
   "
-  [& {n :n :or {:n 3}}]
+  [& {n :n :or {n 3}}]
   (let [r 1
         w (- n r)]
     {:n-val n


allow for verbose/non-verbose generative tests

--- test/cheshire/test/generative.clj
+++ test/cheshire/test/generative.clj
@@ -2,6 +2,9 @@
   (:use [cheshire.core]
         [clojure.test.generative]
         [clojure.test :only [deftest is]]))
+
+;; determines whether generative stuff is printed to stdout
+(def verbose true)

 (defn encode-equality [x]
   [x (decode (encode x))])
@@ -36,13 +39,15 @@

 (defspec map-keyword-json-encoding
   encode-equality-keys
-  [^{:tag (hash-map keyword (hash-map keyword (list int 2) 2) 2)} a]
+  [^{:tag (hash-map keyword (hash-map keyword (list int 10) 10) 10)} a]
   (is (= (first %) (last %))))

 (deftest ^{:generative true} t-generative
   ;; I want the seeds to change every time, set the number higher if
   ;; you have more than 16 CPU cores
   (let [seeds (take 16 (repeatedly #(rand-int 1024)))]
+    (when-not verbose
+      (reset! report-fn identity))
     (println "Seeds:" seeds)
     (binding [*msec* 15000
               *seeds* seeds


Four new tests: flotr-scripts-[1-4]

Four new tests: flotr-scripts-[1-4]

--- test/clj_flotr/generator_test.clj
+++ test/clj_flotr/generator_test.clj
@@ -94,3 +94,35 @@
             [:script {:type "text/javascript" :src "bbb"}]    (script nil "bbb")
             [:script {:type "text/javascript" :src "aaabbb"}] (script "aaa" "bbb"))))

+(deftest test-flotr-scripts-1
+    (testing "Test the function flotr-scripts"
+        (is (= (flotr-scripts nil "flotr/lib" false)
+               '([:script {:type "text/javascript", :src "flotr/lib/lib/prototype-1.6.0.2.js"}]
+                 [:script {:type "text/javascript", :src "flotr/lib/lib/canvas2image.js"}]
+                 [:script {:type "text/javascript", :src "flotr/lib/lib/canvastext.js"}]
+                 [:script {:type "text/javascript", :src "flotr/lib/flotr-0.2.0-alpha.js"}])))))
+
+(deftest test-flotr-scripts-2
+    (testing "Test the function flotr-scripts"
+        (is (= (flotr-scripts "http://example.com" "flotr/lib" false)
+               '([:script {:type "text/javascript", :src "http://example.com/flotr/lib/lib/prototype-1.6.0.2.js"}]
+                 [:script {:type "text/javascript", :src "http://example.com/flotr/lib/lib/canvas2image.js"}]
+                 [:script {:type "text/javascript", :src "http://example.com/flotr/lib/lib/canvastext.js"}]
+                 [:script {:type "text/javascript", :src "http://example.com/flotr/lib/flotr-0.2.0-alpha.js"}])))))
+
+(deftest test-flotr-scripts-3
+    (testing "Test the function flotr-scripts"
+        (is (= (flotr-scripts nil "flotr/lib" true)
+               '([:script {:type "text/javascript", :src "flotr/lib/lib/prototype-1.6.0.2.js"}]
+                 [:script {:type "text/javascript", :src "flotr/lib/lib/canvas2image.js"}]
+                 [:script {:type "text/javascript", :src "flotr/lib/lib/canvastext.js"}]
+                 [:script {:type "text/javascript", :src "flotr/lib/flotr.debug-0.2.0-alpha.js"}])))))
+
+(deftest test-flotr-scripts-4
+    (testing "Test the function flotr-scripts"
+        (is (= (flotr-scripts "http://example.com" "flotr/lib" true)
+               '([:script {:type "text/javascript", :src "http://example.com/flotr/lib/lib/prototype-1.6.0.2.js"}]
+                 [:script {:type "text/javascript", :src "http://example.com/flotr/lib/lib/canvas2image.js"}]
+                 [:script {:type "text/javascript", :src "http://example.com/flotr/lib/lib/canvastext.js"}]
+                 [:script {:type "text/javascript", :src "http://example.com/flotr/lib/flotr.debug-0.2.0-alpha.js"}])))))
+


write error messages from 'die' to stderr, not stdout


clean up satie example

clean up satie example

--- examples/satie.clj
+++ examples/satie.clj
@@ -1,25 +1,10 @@
 (ns examples.satie
-  (:use [overtone.live])
+  (:use [clojure.core.match :only [match]]
+        [overtone.live]
+        [overtone.inst sampled-piano])
   (:require [polynome.core :as poly]))

 ;;Erik Satie Gnossienne No. 1
-
-;;Piano samples downloaded from: http://blackhole12.newgrounds.com/news/post/92464
-(defonce piano-samples (load-samples "~/Desktop/samples/MIS_Stereo_Piano/Piano/*LOUD*"))
-
-
-(defn matching-notes
-  [note]
-  (filter #(if-let [n (match-note (:name %))]
-             (= note (:midi-note n)))
-          piano-samples))
-
-(defn sampled-piano
-  ([note] (sampled-piano note 1))
-  ([note vol]
-     (if-let [sample (first (matching-notes note))]
-       (stereo-player sample :vol (* 0.01 vol)))))
-
 (def phrase1a [:iii :v :iv# :iii :iii :ii# :iii :ii#])
 (def phrase1b [:iii :v :iv# :iii :v# :vi :v# :vi])
 (def phrase1c [:iii :v :iv# :iii :iii :ii# :i :vii- :vi- :vii- :vi- :vii- :i :vii- :vii- :vi-])
@@ -45,7 +30,7 @@
                                 phrase3
                                 phrase2
                                 phrase2
-                                 phrase1a-reprise
+                                phrase1a-reprise
                                 phrase1b-reprise
                                 phrase1a-reprise
                                 phrase1b-reprise
@@ -80,8 +65,8 @@
                                phrase1-bass                            ;;U
                                ))

-(def lh-pitches (degrees->pitches left-hand-degrees :major :Bb3))
-(def rh-pitches (degrees->pitches right-hand-degrees :major :Bb3))
+(def lh-pitches (degrees->pitches left-hand-degrees :major :Ab4))
+(def rh-pitches (degrees->pitches right-hand-degrees :major :Ab4))

 (def cur-pitch-rh (atom -1))
 (def cur-pitch-lh (atom -1))
@@ -91,11 +76,15 @@
   (reset! cur-pitch-rh -1)
   (reset! cur-pitch-lh -1))

+(defn vol-mul
+  [vol]
+  (* vol 0.002))
+
 (defn play-next-rh
   [vol]
   (let [idx (swap! cur-pitch-rh inc)
         pitch (nth (cycle rh-pitches) idx)]
-    (sampled-piano pitch vol)))
+    (sampled-piano pitch (vol-mul vol))))

 (defn play-next-lh
   [vol]
@@ -103,25 +92,16 @@
         pitch (nth (cycle lh-pitches) idx)]
     (if (sequential? pitch)
       (doseq [p pitch]
-        (sampled-piano p vol))
-      (sampled-piano pitch vol))))
+        (sampled-piano p (vol-mul vol)))
+      (sampled-piano pitch (vol-mul vol)))))

 (defonce m (poly/init "/dev/tty.usbserial-m64-0790"))

-
 (poly/on-press m (fn [x y s]
-                   (if (= 7 x)
-                     (reset-pos)
-                     (do
-                       (if (< 5 y)
-                         (play-next-rh (+ (rand-int 5) (* 12 (+ x 4))))
-                         (play-next-lh (+ (rand-int 5) (* 12 (+ x 4)))))
-                       (poly/led-on m x y)))
-
-                   (println [x y])))
-
-(poly/on-release m (fn [x y s]
-                     (poly/led-off m x y)))
+                   (match [x y]
+                          [7 _] (reset-pos)
+                          [_ 0] (play-next-lh (+ (rand-int 5) (* 12 (+ x 4))))
+                          [_ 7] (play-next-rh (+ (rand-int 5) (* 12 (+ x 4)))))))

 ;;(poly/remove-all-callbacks m)
-;;(poly/disconnect OCOC)m
+;;(poly/disconnect m)


Adds more generative tests

Adds more generative tests

--- test/expound/alpha_test.cljc
+++ test/expound/alpha_test.cljc
@@ -1253,8 +1253,8 @@
     (fn [gr spec]
       (reduce
        (fn [g d]
-           ;; If this creates a circular reference, then
-           ;; just skip it.
+         ;; If this creates a circular reference, then
+         ;; just skip it.
          (if (deps/depends? g d spec)
            g
            (deps/depend g spec d)))
@@ -1299,14 +1299,85 @@
                                     topo-sort
                                     (filter keyword?)))))

+(defn mutate-coll [x]
+  (cond
+    (map? x)
+    (into [] x)
+
+    (vector? x)
+    (into #{} x)
+
+    (set? x)
+    (reverse (into '() x))
+
+    (list? x)
+    (into {} (map vec (partition 2 x)))
+
+    :else
+    x))
+
+(defn mutate-type [x]
+  (cond
+    (number? x)
+    (str x)
+
+    (string? x)
+    (keyword x)
+
+    (keyword? x)
+    (str x)
+
+    (boolean? x)
+    (str x)
+
+    (symbol? x)
+    (str x)
+
+    (char? x)
+    (int x)
+
+    (uuid? x)
+    (str x)
+
+    :else
+    x))
+
+(defn mutate [form path]
+  (let [[head & rst] path]
+    (cond
+      (empty? path)
+      (if (coll? form)
+        (mutate-coll form)
+        (mutate-type form))
+
+      (map? form)
+      (if (empty? form)
+        (mutate-coll form)
+        (let [k (nth (keys form) (mod head (count (keys form))))]
+          (assoc form k
+                 (mutate (get form k) rst))))
+
+      (vector? form)
+      (if (empty? form)
+        (mutate-coll form)
+        (let [idx (mod head (count form))]
+          (assoc form idx
+                 (mutate (nth form idx) rst))))
+
+      (not (coll? form))
+      (mutate-type form)
+
+      :else
+      (mutate-coll form))))
+
 #?(:clj
-   (deftest clojure-spec-tests
+   (deftest real-spec-tests
      (checking
-      "for any core spec and any data, explain-str returns a string"
+      "for any real-world spec and any data, explain-str returns a string"
       ;; At 50, it might find a bug in failures for the
       ;; :ring/handler spec, but keep it plugged in, since it
       ;; takes a long time to shrink
-      25
+      50
       [spec spec-gen
        form gen/any-printable]
       (when-not (some
@@ -1315,4 +1386,44 @@
                       s/form
                       (tree-seq coll? identity)
                       (map str)))
-        (expound/expound-str spec form)))))
+        (is (string? (expound/expound-str spec form)))))))
+
+(deftest test-mutate
+  (checking
+   "mutation alters data structure"
+   50
+   [form gen/any-printable
+    mutate-path (gen/vector gen/pos-int 1 10)]
+   (is (not= form
+             (mutate form mutate-path)))))
+
+;; Missing onyx specs
+(s/def :trigger/materialize any?)
+(s/def :trigger/pre-evictor any?)
+(s/def :trigger/post-evictor any?)
+(s/def :flow/short-circuit any?)
+
+#?(:clj
+   (deftest real-spec-tests-mutated-valid-value
+     (checking
+      "for any real-world spec and any mutated valid data, explain-str returns a string"
+      ;;300 ; TODO - shrink this
+      100
+      [spec spec-gen
+       mutate-path (gen/vector gen/pos-int)]
+      (when-not (some
+                 #{"clojure.spec.alpha/fspec"}
+                 (->> spec
+                      s/form
+                      (tree-seq coll? identity)
+                      (map str)))
+        (when (contains? (s/registry) spec)
+          (try
+            (let [valid-form (first (s/exercise spec 1))
+                  invalid-form (mutate valid-form mutate-path)]
+              (is (string? (expound/expound-str spec invalid-form))))
+            (catch clojure.lang.ExceptionInfo e
+              (when (not= :no-gen (::s/failure (ex-data e)))
+                (when (not= "Couldn't satisfy such-that predicate after 100 tries." (.getMessage e))
+                  (throw e))))))))))
+


adding line and column numbers to file message

--- src/strictly_specking/error_printing.clj
+++ src/strictly_specking/error_printing.clj
@@ -5,7 +5,8 @@
    [strictly-specking.edn-string-nav :as edn-string-nav]
    [strictly-specking.context-print :as cp]
    [clojure.string :as string]
-   [clojure.pprint :as pp]))
+   [clojure.pprint :as pp]
+   [clojure.java.io :as io]))

 #_(remove-ns 'strictly-specking.error-printing)

@@ -143,6 +144,7 @@
     (if (coll? val)
       (str "\n" (indent-lines 2 formatted))
       formatted)))
+

 (defmulti error-message :strictly-specking.core/error-type)

@@ -207,12 +209,19 @@
 ;; really need to move this towards the same interface as above
 ;; if there is a file on the error we will display it in context of the file

+(defn file-line [file line column]
+  (str (let [f (io/file file)]
+         (if (.exists f)
+           (.getAbsolutePath (io/file file))
+           f))
+       (if line (str ":" line) "") (if (and line column) (str ":" column) "")))
+
 (defn pprint-in-file [file base-path key-message-map]
   (let [[k message] (first key-message-map)
         path        (conj (vec base-path) k)]
     (when-let [{:keys [line column value path loc]}
                (edn-string-nav/get-path-in-clj-file path file)]
-      (println "File:" (str file))
+      (println (file-line file line column))
       (cp/print-message-in-context-of-file file line column message)
       true)))

@@ -270,7 +279,7 @@
   (if-let [{:keys [line column value path loc]}
            (inline-missing-keys? e)]
     (do
-      (println "File:" (str (:strictly-specking.core/file-source e)))
+      (println (file-line (:strictly-specking.core/file-source e) line column))
       (-> (cp/fetch-lines (:strictly-specking.core/file-source e))
           (cp/number-lines)
           (cp/insert-message line column


Fix capture-console on node

Fix capture-console on node

--- test/cljs/reitit/frontend/test_utils.cljs
+++ test/cljs/reitit/frontend/test_utils.cljs
@@ -2,18 +2,14 @@

 (defn capture-console [f]
   (let [messages (atom [])
-        original-console js/console
+        original-console-warn js/console.warn
         log (fn [t & message]
               (swap! messages conj {:type t
                                     :message message}))
         value (try
-                (set! js/console #js {:log (partial log :log)
-                                      :warn (partial log :warn)
-                                      :info (partial log :info)
-                                      :error (partial log :error)
-                                      :debug (partial log :debug)})
+                (set! js/console.warn (partial log :warn))
                 (f)
                 (finally
-                  (set! js/console original-console)))]
+                  (set! js/console.warn original-console-warn)))]
     {:value value
      :messages @messages}))


Enable console print in record_test.

Enable console print in record_test.

--- test/cljx/active/clojure/record_test.cljx
+++ test/cljx/active/clojure/record_test.cljx
@@ -9,6 +9,9 @@
   (:require-macros [cemerick.cljs.test
                     :refer (is deftest with-test run-tests testing test-var)]
                    [active.clojure.record :refer (define-record-type)]))
+
+#+cljs
+(enable-console-print!)

 (define-record-type Pare
   (kons a b)


Removes trailing whitespace.

Removes trailing whitespace.

--- src-cljs/reagent_tutorial/core.cljs
+++ src-cljs/reagent_tutorial/core.cljs
@@ -62,7 +62,7 @@
                 :on-change #(reset! val (-> % .-target .-value))}]
        [:button {:on-click #(when-let [c (parse-contact @val)]
                               (add-contact! c)
-                              (reset! val ""))}
+                              (reset! val ""))}
         "Add"]])))

 (defn contact-list []


set capture to true between each command triggered by the keyboard

Signed-off-by: Chris Granger <5654cde260ae99bc4d30054171b8bcd902efd19a@gmail.com>

--- src/lt/objs/keyboard.cljs
+++ src/lt/objs/keyboard.cljs
@@ -117,6 +117,7 @@
     (when-let [cs (chord|mapping key char ev)]
       (doseq [c cs]
         (when-not *stop*
+          (set! *capture* true)
           (trigger c)))
       *capture*)))


Fixes tests

Fixes tests

--- test/onyx/coordinator/simulation_test.clj
+++ test/onyx/coordinator/simulation_test.clj
@@ -66,7 +66,7 @@
     (fn [coordinator sync log]
       (let [peer (extensions/create sync :peer)
             offer-ch-spy (chan 1)
-            ack-ch-spy (chan 1)
+            ack-ch-spy (chan 3)
             evict-ch-spy (chan 1)
             failure-ch-spy (chan 1)]

@@ -113,22 +113,22 @@

             (>!! (:ack-ch-head coordinator) {:path node-path})
             (let [failure (<!! failure-ch-spy)]
+              (is (= (:ch failure) :ack)))))
+
+        (testing "Acking with a peer who's state isnt :acking fails"
+          (let [peer-id (d/tempid :onyx/log)
+                task-id (d/tempid :onyx/log)
+                node-path (str (java.util.UUID/randomUUID))
+                tx [{:db/id peer-id
+                     :peer/status :idle
+                     :node/ack node-path
+                     :peer/task {:db/id task-id
+                                 :task/complete? false}}]]
+            @(d/transact (:conn log) tx)
+
+            (>!! (:ack-ch-head coordinator) {:path node-path})
+            (let [failure (<!! failure-ch-spy)]
               (is (= (:ch failure) :ack)))))))))
-
-#_(testing "Acking with a peer who's state isnt :acking fails"
-       (let [peer-id (d/tempid :onyx/log)
-             task-id (d/tempid :onyx/log)
-             node-path (str (java.util.UUID/randomUUID))
-             tx [{:db/id peer-id
-                  :peer/status :acking
-                  :node/ack node-path
-                  :peer/task {:db/id task-id
-                              :task/complete? false}}]]
-         @(d/transact (:conn log) tx)
-
-         (>!! (:ack-ch-head coordinator) {:path node-path})
-         (let [failure (<!! failure-ch-spy)]
-           (is (= (:ch failure) :ack)))))

 (deftest plan-one-job-no-peers
   (with-system


uncomment actual work

uncomment actual work

--- src/luffer/core.clj
+++ src/luffer/core.clj
@@ -116,5 +116,5 @@
   (let [batch-size  (parse-int (nth args 0))
         concurrency (parse-int (nth args 1))]
     (println (format "starting workers batch-size=%,d concurrency=%d" batch-size concurrency))
-    ;(start-workers batch-size concurrency)
+    (start-workers batch-size concurrency)
     ))


Display multiple photos in property details.

--- src-cljs/kixi/hecuba/tabs/hierarchy/property_details.cljs
+++ src-cljs/kixi/hecuba/tabs/hierarchy/property_details.cljs
@@ -159,9 +159,9 @@
             (text-area-control property_data state owner :monitoring_policy "Monitoring Policy")
             (text-area-control property_data state owner :other_notes "Other Notes")]
            [:div.col-md-2
-            (when-let [pic (:path (first (:photos property-details)))]
-              [:img.img-thumbnail.tmg-responsive
-               {:src (str "https://s3-us-west-2.amazonaws.com/get-embed-data/" pic)}])]
+            (for [pic (:photos property-details)]
+              [:p [:img.img-thumbnail.tmg-responsive
+                   {:src (str "https://s3-us-west-2.amazonaws.com/get-embed-data/" (:path pic))}]])]
            [:div.col-md-4
             (for [ti (:technology_icons property_data)]
               [:img.tmg-responsive {:src ti :width 80 :height 80}])]]])))))
@@ -208,10 +208,10 @@
          (let [id "download-status-alert"
                pending-file? (some #{"PENDING"} (map :status (:files cursor)))]
            [:div {:id "measurements-template-with-data"}
-            [:div
+            [:div
              ;; Status alert
              (alert id "alert alert-info" status owner)]
-
+
             ;; Allow to trigger download when there are no pending files
             (when-not pending-file?
               [:button {:type "button"


[#3036] Preserve columns order after transformation

--- backend/src/akvo/lumen/lib/transformation/engine.clj
+++ backend/src/akvo/lumen/lib/transformation/engine.clj
@@ -158,7 +158,11 @@
         previous-columns (into (vec (:columns data-group)) other-dgs-columns)]
     (let [{:keys [success? message columns execution-log error-data]}
           (try-apply-operation deps source-table previous-columns (assoc transformation :dataset-id dataset-id))
-          columns (vec (set/difference (set columns) (set other-dgs-columns)))]
+          columns (let [other-dgs-columns-set (set other-dgs-columns)]
+                    (reduce (fn [container column]
+                              (if (contains? other-dgs-columns-set column)
+                                container
+                                (conj container column))) [] columns))]
       (when-not success?
         (log/errorf "Failed to transform: %s, columns: %s, execution-log: %s, data: %s" message columns execution-log error-data)
         (throw (ex-info (or message "") {})))


branchings2d.clj: fixed some bugs

branchings2d.clj: fixed some bugs

--- clojure/org/gavrog/clojure/branchings2d.clj
+++ clojure/org/gavrog/clojure/branchings2d.clj
@@ -2,6 +2,22 @@
   (:use (org.gavrog.clojure
           [generators :only [make-backtracker results]]
           [delaney])))
+
+(defn- open-orbits [ds]
+  (for [i [0 1] :let [j (inc i)]
+        D (orbit-reps ds [i j])
+        :when (nil? (v ds i j D))]
+    [i D (r ds i j D) (orbit-loopless? ds [i j] D)]))
+
+(defn- sign [s]
+  (cond (empty? s) 0
+        (= 0 (first s)) (recur (rest s))
+        :else (compare (first s) 0)))
+
+(defn- good? [ds maps]
+  (let [diffs (fn [m] (for [D (elements ds), i [0 1], :let [j (inc i)]]
+                        (- (v ds i j D) (v ds i j (m D)))))]
+    (every? #(-> % diffs sign (>= 0)) maps)))

 (defn branchings
   [d-set & {:keys [face-sizes-at-least
@@ -13,23 +29,21 @@
                  curvature-at-least 0
                  try-spins [1 2 3 4 6]}}]
   (let [ds (canonical d-set)
+        maps (automorphisms ds)
         new-curvature (fn [c s v] (+ c (* (if s 2 1) (- (/ v) 1))))
-        still-good (fn [c i D r s v]
+        still-good? (fn [c i D r s v]
                      (and (<= curvature-at-least (new-curvature c s v))
                           (cond (= 0 i) (<= face-sizes-at-least (* r v))
                                 (= 1 i) (<= vertex-degrees-at-least (* r v)))))]
     (make-backtracker
-      {:root (let [orbs (for [i [0 1] :let [j (inc i)]
-                              D (orbit-reps ds [i j])]
-                          [i D (r ds i j D) (orbit-loopless? ds [i j] D)])]
-               [ds (curvature ds 1) (into #{} orbs)])
+      {:root [ds (curvature ds 1) (into #{} (open-orbits ds))]
        :extract (fn [[ds c unused]]
-                  (when (and (empty? unused) (canonical? ds))
+                  (when (and (empty? unused)
+                             (good? ds maps))
                     ds))
        :children (fn [[ds c unused]]
                    (when-let [[i D r s] (first unused)]
-                     (for [v try-spins
-                           :when (still-good c i D r s v)]
+                     (for [v try-spins :when (still-good? c i D r s v)]
                        [(spin ds i (inc i) D v)
                         (new-curvature c s v)
                         (disj unused [i D r s])])))})))


permutations.clj: introduced and implemented SpittableGenerator protocol.

--- clojure/org/gavrog/clojure/permutations.clj
+++ clojure/org/gavrog/clojure/permutations.clj
@@ -7,6 +7,10 @@
 (defn results [gen]
   (letfn [(s [gen] (when gen (lazy-seq (cons gen (s (step gen))))))]
     (filter (comp not nil?) (map result (s gen)))))
+
+(defprotocol SplittableGenerator
+  (sub-generator [_])
+  (skip [_]))

 (defprotocol Resumable
   (checkpoint [_])
@@ -43,7 +47,23 @@
                                  :branch-nr n
                                  :siblings-left (rest children)})]
                 (recur (rest todo) stack))
-              (BacktrackingGenerator. gen-children extract desc stack))))
+              (BacktrackingGenerator. gen-children extract desc stack))))
+  SplittableGenerator
+  (sub-generator [gen]
+                 (let [desc (list desc (checkpoint gen))
+                       stack (list {:node (:node (first stack))})]
+                   (BacktrackingGenerator. gen-children extract desc stack)))
+  (skip [_]
+        (let [stack
+              (when-let [stack (seq (drop-while
+                                      #(not (seq (:siblings-left %))) stack))]
+                (let [{:keys [siblings-left branch-nr]} (first stack)]
+                  (conj (rest stack)
+                        {:node (first siblings-left)
+                         :branch-nr (inc branch-nr)
+                         :siblings-left (rest siblings-left)})))]
+          (when (seq stack)
+            (BacktrackingGenerator. gen-children extract desc stack))))
   Object
   (toString [_] (str desc)))


fixed analysis to use cosmos library properly

--- src/analysis/core.clj
+++ src/analysis/core.clj
@@ -125,10 +125,10 @@
   [logs]
   (cosmos/recommended-runs (-> (for [log logs]
                                  (for [[report gen] (map #(vector %1 %2) (:reports log) (iterate inc 0))]
-                                   (for [[ord val] (seq (get report "Cosmos Data:"))]
+                                   (for [[ord val] (seq (read-string (get report "Cosmos Data")))]
                                      (struct-map cosmos/cosmos-data
                                        :ord ord
                                        :gen gen
                                        :val val))))
-                               flatten)))
-                               +                               flatten
+                               cosmos-1)))


Make the test pass

Make the test pass

--- src/caesium/magicnonce/secretbox.clj
+++ src/caesium/magicnonce/secretbox.clj
@@ -103,9 +103,11 @@
   messages will not repeat or you can't rely on encryption-time
   randomness, consider [[secrebox-nmr]].

-  [msg key])
   To decrypt, use [[decrypt]] or [[open]], depending on which argument
   order you prefer."
+  [msg key]
+  (secretbox-pfx msg (synthetic-nonce msg key) key))
+
 (defn ^:private xor!
   "Populates `out` with the XOR of matching elements in `a`, `b`.


add timeout

add timeout

--- src/clj/elephantdb/common/domain.clj
+++ src/clj/elephantdb/common/domain.clj
@@ -364,8 +364,13 @@
   "Executes body. If an exception is thrown, will retry. At most n retries
   are done. If still some exception is thrown it is bubbled upwards in
   the call chain."
-  [n & body]
+  [[n] & body]
   `(try-times* ~n (fn [] ~@body)))
+
+(defmacro with-timeout
+  [[ms] & body]
+  `(let [^java.util.concurrent.Future f# (future ~@body)]
+     (.get f# ~ms java.util.concurrent.TimeUnit/MILLISECONDS)))

 (defn transfer-shard!
   "Transfers the supplied shard (specified by `idx`) from the supplied
@@ -377,12 +382,18 @@
         remote-store (.remoteStore domain)
         remote-fs    (.getFileSystem remote-store)
         remote-path  (.shardPath remote-store idx version)
-        local-path   (.shardPath local-store idx version)]
+        local-path   (.shardPath local-store idx version)
+        timeout-ms (* 6 60 1000)]
     (if (.exists remote-fs (h/path remote-path))
       (do (log/info (format "Copying %s to %s." remote-path local-path))
-          (try-times 3
-                     (transfer/rcopy remote-fs remote-path local-path
-                                     :throttle throttle))
+          (try
+            (try-times [3]
+                       (with-timeout [timeout-ms]
+                         (transfer/rcopy remote-fs remote-path local-path
+                                         :throttle throttle)))
+            (catch Exception e
+              (log/error e)
+              (throw e)))
           (log/info (format "Copied %s to %s." remote-path local-path)))
       (do (log/info "Shard doesn't exist. Creating shard # " idx)
           (.createShard local-store idx version)))))


Refactor - create `update-ModulesSelected-with-lesson-group!` function

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -206,6 +206,12 @@
   "Return the number of modules selected by the user"
   []
   (count ModulesSelected))
+
+(defn- update-ModulesSelected-with-lesson-group!
+  [moduleCode lessonType lessonGroup lessonInfoSeq]
+  (set! ModulesSelected
+        (assoc-in ModulesSelected [moduleCode lessonType]
+                  {:label lessonGroup, :info lessonInfoSeq})))

 (def ^{:doc     "Vector containing module code strings in the order the modules
                  were added."
@@ -785,12 +791,9 @@
             $divElemSeq         (map #(:divElem %1) augLessonInfoSeq)]
         (if isActuallySelected?
             (do
-              ; Update ModulesSelected with the lesson group
-              (set! ModulesSelected
-                    (assoc-in ModulesSelected [moduleCode lessonType]
-                              {:label lessonGroup, :info lessonInfoSeq}))
-
-              ; Add to ModulesSelectedOrder
+              (update-ModulesSelected-with-lesson-group! moduleCode lessonType
+                                                         lessonGroup
+                                                         lessonInfoSeq)
               (if (module-not-in-ModulesSelectedOrder? moduleCode)
                   (do
                     (add-to-ModulesSelectedOrder! moduleCode)


`shift-lesson-to-row!` - use destructuring

Signed-off-by: Pang Yan Han <22594c345857f664c61cd411f607c4d40a9d4af9@gmail.com>

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -1242,16 +1242,13 @@

    The parameter `augTTLessonInfo` is a `TimetableLessonInfo` object augmented
    with the `:day` and `:rowNum` keys."
-  [destinationRowNum augTTLessonInfo $divElem]
-  (let [day           (:day augTTLessonInfo)
-        sourceRowNum  (:rowNum augTTLessonInfo)
-        startTime     (:startTime augTTLessonInfo)
-        endTime       (:endTime augTTLessonInfo)
-        slotsOccupied (- endTime startTime)
-        $sourceTd     (html-timetable-get-td day sourceRowNum startTime)
+  [destinationRowNum {:keys [day rowNum startTime endTime] :as augTTLessonInfo}
+   $divElem]
+  (let [slotsOccupied (- endTime startTime)
+        $sourceTd     (html-timetable-get-td day rowNum startTime)
         $destTd       (html-timetable-get-td day destinationRowNum startTime)
         ttLessonInfo  (dissoc augTTLessonInfo :day :rowNum)]
-    (.log js/console (str "day = " day ", sourceRowNum = " sourceRowNum ", destinationRowNum = " destinationRowNum))
+    (.log js/console (str "day = " day ", sourceRowNum = " rowNum ", destinationRowNum = " destinationRowNum))
     ; Transfer lesson
 to the destination
     (.append $destTd $divElem)
     ; restore the colspan of the source
@@ -1265,7 +1262,7 @@
     ; update colspan of destination
     (attr $destTd "colspan" slotsOccupied)
     ; update `Timetable` global
-    (timetable-remove-lesson! day sourceRowNum ttLessonInfo)
+    (timetable-remove-lesson! day rowNum ttLessonInfo)
     (timetable-add-lesson! day destinationRowNum ttLessonInfo $divElem)))

 (defn- shift-lessons-upwards-to-replace-empty-slots!


Revert "Ooops, still need Iterator.next"

This reverts commit dd88586b15aaf3bfce446fb6b874d4ed4fd95648.

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -176,9 +176,13 @@
                   (when (seq nodes)
                     (apply println (map #(.pretty-print %) nodes))
                     (recur (mapcat #(.-children %) nodes)))))
+  (foreach [this f]
+           (.foreach root f))
   ISeqable
   (-seq [this]
-        (seq (iterator->elems (iterator this)))))
+        (let [results #js []]
+          (.foreach this #(apush results #js [%1 %2]))
+          (seq results))))

 (deftype Node [parent parent-ix keys vals children ^:mutable lower ^:mutable upper]
   Object
@@ -354,7 +358,14 @@
                 (assert (every? #(key-lt (aget keys %) (.-lower (aget children (inc %)))) (range (count keys))))
                 (dotimes [i (count children)] (.valid! (aget children i) max-keys))))))
   (pretty-print [this]
-                (str "(" parent-ix ")" "|" (pr-str lower) " " (pr-str (vec keys)) " " (pr-str upper) "|")))
+                (str "(" parent-ix ")" "|" (pr-str lower) " " (pr-str (vec keys)) " " (pr-str upper) "|"))
+  (foreach [this f]
+           (dotimes [i (alength keys)]
+             (when (not (nil? children))
+               (.foreach (aget children i) f))
+             (f (aget keys i) (aget vals i)))
+           (when (not (nil? children))
+             (.foreach (aget children (alength keys)) f))))

 (defn tree [min-keys key-len]
   (let [node (Node. nil nil #js [] #js [] nil nil nil)
@@ -364,47 +375,20 @@
     tree))

 ;; ITERATORS
-;; On seek, point to first key greater than or equal to seek-key, or return nil if there is no such key
-;; On next, point to next key, or return nil if there is no such key
+;; .key / .val return key and val currently pointed at. key may be aliased
+;; On creation/reset, points to first key
+;; On next, either point to next key or set .-end? true.
+;; On seek, point to first key greater than or equal to seek-key, or otherwise the last key
 ;; NOTE iterators are not write-safe unless reset after writing

-(deftype Iterator [tree ^:mutable node ^:mutable ix ^:mutable end?]
+(deftype Iterator [tree ^:mutable node ^:mutable ix]
   Object
-  (reset [this key]
-         (set node (.-root tree))
-         (set ix 0)
-         (set end? (> (alength (.-keys node)) 0)))
-  (next [this]
-        (if (nil? (.-children node))
-          (let [old-node node
-                old-ix ix]
-            (set! ix (+ ix 1))
-            (loop []
-              (if (>= ix (alength (.-keys node)))
-                (if (instance? Node (.-parent node))
-                  (do
-                    (set! ix (.-parent-ix node))
-                    (set! node (.-parent node))
-                    (recur))
-                  (do
-                    (set! node old-node)
-                    (set! ix old-ix)
-                    (set! end? true)
-                    nil))
-                (do
-                  (set! end? true)
-                  nil))))
-          (do
-            (set! node (aget (.-children node) (+ ix 1)))
-            (set! ix 0)
-            (loop []
-              (if (nil? (.-children node))
-                (do
-                  (set! end? true)
-                  nil)
-                (do
-                  (set! node (aget (.-children node) 0))
-                  (recur)))))))
+  (reset [this]
+         (set! node (.-root tree))
+         (while (not (nil? (.-children node)))
+           (set! node (aget (.-children node) 0)))
+         (set! ix 0)
+         (set! end? (<= (alength (.-keys node)) 0)))
   (seek [this key]
         (let [start-node node
               start-ix ix]
@@ -604,24 +588,11 @@
                  action (gen key-len)]
                 (run-lookup-prop min-keys key-len actions action)))

-(defn gen-next [key-len]
-  (gen/make-gen
-   (fn [rnd size]
-     [[:next] nil])))
-
 (defn gen-seek [key-len]
   (gen/make-gen
    (fn [rnd size]
      (let [key (make-simple-key rnd size key-len)]
        [[:seek key] nil]))))
-
-(defn gen-movement [key-len]
-  (gen/make-gen
-   (fn [rnd size]
-     (let [key (make-simple-key rnd size key-len)]
-       (if (pprng/boolean rnd)
-         [[:next] nil]
-         [[:seek key] nil])))))

 (defn apply-to-iterator [iterator movements]
   (for [movement movements]
@@ -651,7 +622,7 @@
 (defn iterator-prop [key-len]
   (prop/for-all [min-keys gen/s-pos-int
                  actions (gen/vector (gen-action key-len))
-                 movements (gen/vector (gen-movement key-len))]
+                 movements (gen/vector (gen-seek key-len))]
                 (run-iterator-prop min-keys key-len actions movements)))

 (defn run-self-join-prop [min-keys key-len actions movements]
@@ -669,7 +640,7 @@
 (defn self-join-prop [key-len]
   (prop/for-all [min-keys gen/s-pos-int
                  actions (gen/vector (gen-action key-len))
-                 movements (gen/vector (gen-movement key-len))]
+                 movements (gen/vector (gen-seek key-len))]
                 (run-self-join-prop min-keys key-len actions movements)))

 (defn run-product-join-prop [min-keys key-len actions movements]
@@ -694,7 +665,7 @@
 (defn product-join-prop [key-len]
   (prop/for-all [min-keys gen/s-pos-int
                  actions (gen/vector (gen-action key-len))
-                 movements (gen/vector (gen-movement key-len))]
+                 movements (gen/vector (gen-seek key-len))]
                 (run-product-join-prop min-keys key-len actions movements)))

 (comment
@@ -748,7 +719,7 @@
   (time (dotimes [_ 10] (h)))

   (do
-    (def samples (gen/sample (gen/tuple gen/s-pos-int (gen/vector gen-action) (gen/vector gen-movement)) 100))
+    (def samples (gen/sample (gen/tuple gen/s-pos-int (gen/vector gen-action) (gen/vector gen-seek)) 100))
     (def trees (for [[min-keys actions _] samples]
                  (apply-to-tree (tree min-keys) actions)))
     (def benches (mapv vector trees (map #(nth % 2) samples)))


make all params to (lightning-bolt) required

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -87,7 +87,7 @@
     result))

 ;; TODO: add usage of rule-to-lexicon cache (rather than using lexicon directly)
-(defn lightning-bolt [grammar lexicon spec & [ depth index morph]]
+(defn lightning-bolt [grammar lexicon spec depth index morph]
   "Returns a lazy-sequence of all possible trees given a spec, where
 there is only one child for each parent, and that single child is the
 head of its parent. generate (above) 'decorates' each returned lightning bolt
@@ -121,7 +121,6 @@
                           (if (some fail? candidate-lexemes)
                             (throw (exception (str "some candidate lexeme was fail?=true!"))))
                           (log/debug
-                           (str "candidate head lexemes for parent phrase "
                                 (get-in parent [:rule]) ": '"
                                 (string/join "','"
                                              (map (fn [lexeme]
@@ -156,7 +155,6 @@
                               (lightning-bolt grammar lexicon
                                               (get-in parent [:head])
                                               (+ 1 depth)
-                                              index parent morph)]
                           (if (empty? phrasal-children)
                             (let [message (str "no phrasal children for parent: " (morph parent) "(rule=" (get-in parent [:rule]) ") and spec: " (strip-refs spec))]
                               (log/debug message))


improve logging

improve logging

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -146,7 +146,7 @@
             (mapcat (fn [parent]
                       (if (= false (get-in parent [:head :phrasal] false))
                         (let [candidate-lexemes (get-lex parent :head index spec)]
-                          (log/error (str "candidate lexemes for: " (get-in parent [:rule]) ":" (count candidate-lexemes)))
+                          (log/debug (str "candidate lexemes for: " (get-in parent [:rule]) ":" (count candidate-lexemes)))
                           (if (some fail? candidate-lexemes)
                             (throw (exception (str "some candidate lexeme was fail?=true!"))))
                           (log/debug
@@ -158,8 +158,8 @@
                                                   candidate-lexemes))))
                           (let [result
                                 (if (empty? candidate-lexemes)
-                                  (log/warn (str "no head lexemes found for parent: " (:rule parent) " and spec: "
-                                                 (strip-refs spec)))
+                                  (if (= false (get-in parent [:head :phrasal] true))
+                                    (log/warn (str "no head lexemes found for parent: " (:rule parent))))
                                   (over/overh parent
                                               (map copy (lazy-shuffle candidate-lexemes))
                                               morph))]
@@ -169,7 +169,10 @@
                                                            (map #(morph %1)
                                                                 result))))
                               (if (not (empty? candidate-lexemes))
-                                (log/warn (str "all candidate lexemes failed!"))))
+                                (log/warn (str "all " (count candidate-lexemes) " candidate lexeme(s):"
+                                               (string/join ","
+                                                            (map morph candidate-lexemes))
+                                               " failed for parent: " (get-in parent [:rule]) " with spec: " (strip-refs spec)))))
                             result))))
                     candidate-heads)

@@ -298,7 +301,7 @@

               ;; else, no complements could be added to this bolt: Throw an exception
               (let [log-limit 1000
-                    log-fn (fn [message] (log/error message))
+                    log-fn (fn [message] (log/warn message))
                     throw-exception-if-no-complements-found true
                     message
                     (str " add-complement to " (get-in bolt [:rule]) " at path: " path


add more logging

add more logging

--- src/babel/forest.cljc
+++ src/babel/forest.cljc
@@ -237,9 +237,10 @@
               (do
                 (log/warn (str " add-complement to " (get-in bolt [:rule]) " took " run-time " msec, but found no lexical complements for "
                                "'" (morph from-bolt) "'"
-                               ". Complements tried were:" (str " " (string/join "," (map morph (take 5 complement-candidate-lexemes))) ".. and "
-                                                                 (- (count complement-candidate-lexemes) 5) " more.")))))
-
+                               ". Desired complement spec was: " (strip-refs (get-in bolt [:comp])) ". Complements tried were:"
+                               (str " " (string/join "," (map morph (take 5 complement-candidate-lexemes))) ".. and "
+                                    (- (count complement-candidate-lexemes) 5) " more.")))))
+

             (do (log/trace (str "add-complement after adding complement: "
                                 (string/join ","


Fix typo.

Fix typo.

--- src/afterglow/fixtures/blizzard.clj
+++ src/afterglow/fixtures/blizzard.clj
@@ -39,7 +39,7 @@
   the head straight out at the audience. At this position, it takes a
   change of -214 in the tilt channel to rotate a half circle
   counterclockwise around the X axis. (In other words, it can
-  essentially only tilt clockwise from here."
+  essentially only tilt clockwise from here.)"
   {:doc/format :markdown}
   ([]
    (blade-rgbw :15-channel))


rozcestnik

rozcestnik

--- src/blogiseq/core.clj
+++ src/blogiseq/core.clj
@@ -124,9 +124,19 @@
             [:a {:href enhanced-path} [:img.thumb {:src enhanced-path :width 160}]]))
         paths)]]))

+(defn photowalls-index
+  "lame - use metadata instead"
+  [path]
+  [:div
+   [:h1 "My photowalls"]
+   "Here you can find list of my memories."
+   (map (fn [p] [:p [:a {:href (str "/photowalls/" (.getName p))} p]])
+        (.listFiles (clojure.java.io/file path)))])
+
 (compojure/defroutes
   routes
   (compojure-route/resources "/resources/photowalls/" {:root "photowalls/"}) ; all photowalls resources (photos)
+  (compojure/GET "/photowalls/index" [] (hiccup/html (site (photowalls-index "resources/photowalls"))))
   (compojure/GET "/photowalls/:name" [name] (hiccup/html (site (dir-to-photowall (str "resources/photowalls/" name)))))

   (compojure/GET "/" [] (hiccup/html (site (md/md-to-html-string (slurp "resources/index.md")))))


When metabase can't connect to its DB log DB type :cry:

--- src/metabase/db.clj
+++ src/metabase/db.clj
@@ -225,7 +225,7 @@
   (assert (binding [*allow-potentailly-unsafe-connections* true]
             (require 'metabase.driver)
             ((resolve 'metabase.driver/can-connect-with-details?) engine details))
-    "Unable to connect to Metabase DB.")
+    (format "Unable to connect to Metabase %s DB." (name engine)))
   (log/info (str "Verify Database Connection ... ✅")))

 (defn setup-db


Add boot task options

Add boot task options

--- src/boot_fmt/core.clj
+++ src/boot_fmt/core.clj
@@ -28,15 +28,20 @@
         :out
         println)))

-(defn process [file]
+(defn process [file {:keys [mode]}]
   (let [content (slurp file)
         output (transform content)]
-    (print-diff file content output)))
+    (cond
+      (= :diff mode) (print-diff file content output)
+      (= :list mode) (when (not= content output) (println "File changed:" (.getName file))))
+    {:file file
+     :changed? (not= content output)}))

-(defn process-many [files]
-  (doseq [file files]
-    (bu/info "Processing %s\n" file)
-    (process file)))
+(defn process-many [opts files]
+  (let [changes (mapv (fn [file]
+                        (bu/info "Processing %s\n" file)
+                        (process file opts))
+                      files)]))

 (defn clj-file? [f]
   (and (.exists f) (.isFile f) (not (.isHidden f))
@@ -45,13 +50,16 @@

 (bc/deftask fmt
   "Format Clojure source files"
-  [f files VAL #{str} "file(s) to format"]
-  (assert (seq files) "At least one filename needs to be provided.")
-  (bc/with-pre-wrap fileset
-    (let [files* (some->> files
-                          (map clojure.java.io/file)
-                          (mapcat (fn [f]
-                                    (if (.isDirectory f) (file-seq f) [f])))
-                          (filter clj-file?))]
-      (process-many files*)
-      fileset)))
+  [m mode MODE kw "Mode"
+   f files VAL #{str} "file(s) to format"]
+  (let [mode (or mode :list)]
+    (assert (seq files) "At least one filename needs to be provided.")
+    (assert (#{:list :diff} mode) "Invalid mode")
+    (bc/with-pre-wrap fileset
+      (let [files* (some->> files
+                            (map clojure.java.io/file)
+                            (mapcat (fn [f]
+                                      (if (.isDirectory f) (file-seq f) [f])))
+                            (filter clj-file?))]
+        (process-many {:mode mode} files*)
+        fileset))))


CMR-626: Added tests to verify that we can update collections with different formats of metadata.

--- system-int-test/test/cmr/system_int_test/ingest/collection_ingest_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/collection_ingest_test.clj
@@ -49,6 +49,17 @@
       (is (apply = (map :concept-id created-concepts)))
       (is (= (range 1 (inc n)) (map :revision-id created-concepts))))))

+(deftest update-collection-with-different-formats-test
+  (testing "update collection in different formats ..."
+    (let [collection-formats [:echo10 :dif :iso19115 :iso-smap]
+          colls (map (partial d/ingest "PROV1" (dc/collection {:entry-id "S1"
+                                                               :short-name "S1"
+                                                               :version-id "V1"
+                                                               :entry-title "ET1"
+                                                               :long-name "L4"}))
+                     (shuffle collection-formats))]
+      (is (apply = (map :concept-id colls)))
+      (is (= (range 1 (inc (count collection-formats))) (map :revision-id colls))))))

 ;; Verify ingest behaves properly if empty body is presented in the request.
 (deftest empty-collection-ingest-test
@@ -90,7 +101,7 @@
   (def coll1 (d/ingest "PROV1" (dc/collection)))
   (ingest/delete-concept coll1)
   (get-in user/system [:apps :metadata-db :db])
-)
+  )

 (deftest delete-collection-test
   (let [coll1 (d/ingest "PROV1" (dc/collection))


More UTM params just cuz

More UTM params just cuz

--- src-cljs/frontend/components/enterprise.cljs
+++ src-cljs/frontend/components/enterprise.cljs
@@ -52,7 +52,9 @@
                                      "Initial referrer" (mixpanel/get-property "$initial_referrer")
                                      "UTM medium" (mixpanel/get-property "utm_medium")
                                      "UTM source" (mixpanel/get-property "utm_source")
-                                     "UTM campaign" (mixpanel/get-property "utm_campaign")}
+                                     "UTM campaign" (mixpanel/get-property "utm_campaign")
+                                     "UTM content" (mixpanel/get-property "utm_content")
+                                     "UTM term" (mixpanel/get-property "utm_term")}
                                     (map (fn [[k v]] (gstr/format "%s: %s" k (or v "not set"))))
                                     (str/join "\n"))
                       :enterprise true})


Macros: Add notes about what to do next.

--- test/com/nomistech/clojure_the_language/macros/examples.clj
+++ test/com/nomistech/clojure_the_language/macros/examples.clj
@@ -147,5 +147,14 @@
 ;;;; ___________________________________________________________________________

 ;;;; TODO:
+
+;;;; - Don't need to talk about accidental capture, right?
+
+;;;; - Repeated evaluation
+
 ;;;; - Capture
-;;;; - ...# symbols
+;;;; - Binding to namespace-qualified names is forbidden
+;;;; - auto-gensym (...#) symbols (maybe manual gensym first)
+;;;; - Getting to function-land quickly.
+;;;;   - Changing and recompiling (but less of an issue with Workflow Reloaded)
+;;;;   - Easier to read, write and reason about


Macros: Fix typo.

Macros: Fix typo.

--- test/com/nomistech/clojure_the_language/macros/examples.clj
+++ test/com/nomistech/clojure_the_language/macros/examples.clj
@@ -14,7 +14,7 @@
 ;;;; - Macros use code as data
 ;;;;
 ;;;; - Macros allow us to arbitrarily transform code
-;;;    - Very different to macros in non-Lisps
+;;;;   - Very different to macros in non-Lisps
 ;;;;
 ;;;; - Clojure and other Lisps are homoiconic:
 ;;;;   - Code is represented by data structures, not as sequences


first commit

first commit

--- src/cljs/cljs_react_material_ui_example/core.cljs
+++ src/cljs/cljs_react_material_ui_example/core.cljs
@@ -1,7 +1,7 @@
 (ns cljs-react-material-ui-example.core
   (:require [cljsjs.material-ui]
+            [cljs-react-material-ui.core :as ui]
             [cljs-react-material-ui.icons :as ic]
-            [cljs-react-material-ui.core :as ui]
             [goog.dom :as gdom]
             [om.next :as om :refer-macros [defui]]
             [cljs-react-material-ui-example.parser :as p]
@@ -59,9 +59,9 @@
                   {:label        (if (= step-index 2) "Finish" "Next")
                    :primary      true
                    :on-touch-tap #(om/set-state! this {:step-index (+ step-index 1)
-                                                       :finished?  (>= step-index 2)})}))))))))
-
-  (def my-stepper (om/factory MyStepper {})))
+                                                       :finished?  (>= step-index 2)})})))))))))
+
+(def my-stepper (om/factory MyStepper {}))

 (defui Person
   static om/Ident


Collate also musiknoten and tactile books

--- src/catalog/vubis.clj
+++ src/catalog/vubis.clj
@@ -294,12 +294,23 @@
   braille grades. In the catalog we want one entry"
   [items]
   (let [braille-items (filter #(= (:format %) :braille) items)
-        others (remove #(= (:format %) :braille) items)]
-    (->> braille-items
-         (group-by (juxt :source :title))
-         vals
-         (map #(merge-braille-catalog-items %))
-         (concat others))))
+        musiknoten-items (filter #(= (:format %) :musiknoten) items)
+        taktile-items (filter #(= (:format %) :taktilesbuch) items)
+        others (remove #(#{:braille :musiknoten :taktilesbuch} (:format %)) items)]
+    (concat
+     (->> braille-items
+          (group-by (juxt :source :title))
+          vals
+          (map #(merge-braille-catalog-items %)))
+     (->> musiknoten-items
+          (group-by (juxt :source :title))
+          vals
+          (map #(merge-braille-catalog-items %)))
+     (->> taktile-items
+          (group-by (juxt :source :title))
+          vals
+          (map #(merge-braille-catalog-items %)))
+     others)))

 (defn order-and-group [items]
   (->>


removing metrics and moving all to require

--- src/celestial/api.clj
+++ src/celestial/api.clj
@@ -11,20 +11,17 @@

 (ns celestial.api
   (:refer-clojure :exclude [type])
-  (:use
-    [celestial.users-api :only (users quotas)]
-    [celestial.ui-api :only (public sessions)]
-    [compojure.core :only (defroutes routes)]
-    [metrics.ring.expose :only  (expose-metrics-as-json)]
-    [celestial.roles :only (roles roles-m admin)]
-    [clojure.core.strint :only (<<)]
-    [slingshot.slingshot :only  [throw+ try+]]
-    [ring.middleware.format :only [wrap-restful-format]]
-    [ring.middleware.params :only (wrap-params)]
-    [metrics.ring.instrument :only  (instrument)]
-    [swag.model :only (defmodel wrap-swag)]
-    [celestial.common :only (import-logging get! resp conflict success version wrap-errors)])
   (:require
+    [celestial.roles :refer (admin)]
+    [ring.middleware.format :refer [wrap-restful-format]]
+    [ring.middleware.params :refer (wrap-params)]
+    [metrics.ring.instrument :refer  (instrument)]
+    [swag.model :refer (defmodel wrap-swag)]
+    [celestial.common :refer (import-logging get! version wrap-errors)]
+    [compojure.core :refer (defroutes routes)]
+    [clojure.core.strint :refer (<<)]
+    [celestial.ui-api :refer (public sessions)]
+    [celestial.users-api :refer (users quotas)]
     [celestial.persistency :as p]
     [celestial.security :as sec]
     [celestial.api.systems :refer (systems environments)]
@@ -36,7 +33,7 @@
     [swag.core :refer (swagger-routes GET- POST- PUT- DELETE- defroutes- errors )]
     [compojure.handler :as handler]
     [cemerick.friend :as friend]
-    [compojure.route :as route]))
+    [compojure.route :as route]))

 (import-logging)

@@ -105,6 +102,5 @@
       (wrap-session {:cookie-name "celestial" :store (cookie-store)})
       (wrap-restful-format :formats [:json-kw :edn :yaml-kw :yaml-in-html])
       (handler/api)
-      (expose-metrics-as-json)
       (instrument)
       (error-wrap)))


solve cyclic dependency

solve cyclic dependency

--- src/ceres/curator.clj
+++ src/ceres/curator.clj
@@ -3,7 +3,6 @@
             [monger.collection :as mc]
             [monger.operators :refer :all]
             [monger.conversion :refer [from-db-object]]
-            [ceres.inspector :refer [levenshtein]]
             [clojure.string :refer [split]]
             [clojure.data.json :as json]
             [clj-time.format :as f]


decomplect `cljs.repl/eval-and-print`, now just `cljs.repl/eval-cljs`.
`cljs.repl/eval-cljs` does not handle printing, instead just returns
the value (always represented as a string).

printing in the body of REPL loop now defers to parameterized `print`.

--- src/clj/cljs/repl.clj
+++ src/clj/cljs/repl.clj
@@ -427,17 +427,19 @@
                              (set! *e e#)
                              (throw e#)))))))

-(defn- eval-and-print
+(defn- eval-cljs
+  "Given a REPL evaluation environment, an analysis environment, and a
+   form, evaluate the form and return the result. The result is always the value
+   represented as a string."
   ([repl-env env form]
-    (eval-and-print repl-env env form nil))
+    (eval-cljs repl-env env form nil))
   ([repl-env env form opts]
-    (println
-      (evaluate-form repl-env
-        (assoc env :ns (ana/get-namespace ana/*cljs-ns*))
-        "<cljs repl>"
-        form
-        (wrap-fn form)
-        opts))))
+   (evaluate-form repl-env
+     (assoc env :ns (ana/get-namespace ana/*cljs-ns*))
+     "<cljs repl>"
+     form
+     (wrap-fn form)
+     opts)))

 ;; Special REPL fns, these provide compatiblity with Clojure functions
 ;; that are not possible to reproduce given ClojureScript's compilation model
@@ -542,8 +544,8 @@
                   prompt      repl-prompt
                   flush       flush
                   read        repl-read
-                  eval        eval
-                  print       prn
+                  eval        eval-cljs
+                  print       println
                   caught      repl-caught}
              :as opts}]
   (print "To quit, type: " :cljs/quit)
@@ -587,7 +589,7 @@
              (when-let [src (:watch opts)]
                (future
                  (let [log-file (io/file (util/output-directory opts) "watch.log")]
-                   (println "Watch compilation log available at:" (str log-file))
+                   (print "Watch compilation log available at:" (str log-file))
                    (binding [*out* (FileWriter. log-file)]
                      (cljsc/watch src (dissoc opts :watch))))))
              (loop []
@@ -608,7 +610,7 @@
                                           (ana/get-namespace ana/*cljs-ns*)))]
                               (reader/read rdr nil read-error))
                             (catch Exception e
-                              (println (.getMessage e))
+                              (print (.getMessage e))
                               read-error))]
                  ;; TODO: need to catch errors here too - David
                  (cond
@@ -620,7 +622,7 @@
                      (try
                        ((get special-fns (first form)) repl-env env form opts)
                        (catch Throwable ex
-                         (println "Failed to execute special function:" (pr-str (first form)))
+                         (print "Failed to execute special function:" (pr-str (first form)))
                          (trace/print-cause-trace ex 12)))
                      ;; flush output which could include stack traces
                      (flush)
@@ -628,8 +630,9 @@
                      (recur))

                    :else
-                   (do (eval-and-print repl-env env form opts)
-                       (recur)))))))
+                   (let [value (eval repl-env env form opts)]
+                     (print value)
+                     (recur)))))))
          (-tear-down repl-env))))))

 (defn repl


switch to tools.reader in repl, use ana/no-warn macro helper in evaluate-form

--- src/clj/cljs/repl.clj
+++ src/clj/cljs/repl.clj
@@ -66,14 +66,7 @@
      (try
        (let [ast (ana/analyze env form)
              js (comp/emit-str ast)
-             wrap-js (comp/emit-str (binding [ana/*cljs-warnings*
-                                              (merge ana/*cljs-warnings*
-                                                {:undeclared false
-                                                 :redef false
-                                                 :dynamic false
-                                                 :fn-var false
-                                                 :fn-arity false})]
-                                   (ana/analyze env (wrap form))))]
+             wrap-js (comp/emit-str (ana/no-warn (ana/analyze env (wrap form))))]
          (when (= (:op ast) :ns)
            (load-dependencies repl-env (into (vals (:requires ast))
                                              (distinct (vals (:uses ast))))))
@@ -93,16 +86,11 @@
          (.printStackTrace ex)
          (println (str ex))))))

-(defn load-stream [repl-env filename stream]
-  (with-open [r (io/reader stream)]
-    (let [env (ana/empty-env)
-          pbr (clojure.lang.LineNumberingPushbackReader. r)
-          eof (Object.)]
-      (loop [r (read pbr false eof false)]
-        (let [env (assoc env :ns (ana/get-namespace ana/*cljs-ns*))]
-          (when-not (identical? eof r)
-            (evaluate-form repl-env env filename r)
-            (recur (read pbr false eof false))))))))
+(defn load-stream [repl-env filename res]
+  (let [env (ana/empty-env)]
+    (doseq [form (ana/forms-seq res)]
+      (let [env (assoc env :ns (ana/get-namespace ana/*cljs-ns*))]
+        (evaluate-form repl-env env filename form)))))

 (defn load-file
   [repl-env f]


need to pop `:testing-contexts` after `cljs.test/testing` completes

--- src/clj/cljs/test.clj
+++ src/clj/cljs/test.clj
@@ -179,27 +179,31 @@
   ([string & body]
    (if (contains? (:locals &env) 'cljs$lang$test$body)
      `(fn [env#]
-        (reduce
-          (fn [env'# thunk#]
-            (let [ret# (thunk#)]
-              (if (fn? ret#)
-                (ret# env'#)
-                env'#)))
-          (update-in env# [:testing-contexts] conj ~string)
-          [~@(map (fn [expr] `(fn [] ~expr)) body)]))
+        (update-in
+          (reduce
+            (fn [env'# thunk#]
+              (let [ret# (thunk#)]
+                (if (fn? ret#)
+                  (ret# env'#)
+                  env'#)))
+            (update-in env# [:testing-contexts] conj ~string)
+            [~@(map (fn [expr] `(fn [] ~expr)) body)])
+          [:testing-contexts] rest))
      ;; expression evaluation case
      `(let [~'cljs$lang$test$body nil]
         (:last-value
-         (reduce
-           (fn [env'# thunk#]
-             (let [ret# (thunk#)]
-               (if (fn? ret#)
-                 (ret# env'#)
-                 env'#)))
-           (update-in (assoc (cljs.test/empty-env) :return true)
-             [:testing-contexts] conj ~string)
-           (let [~'cljs$lang$test$body nil]
-             [~@(map (fn [expr] `(fn [] ~expr)) body)])))))))
+         (update-in
+           (reduce
+             (fn [env'# thunk#]
+               (let [ret# (thunk#)]
+                 (if (fn? ret#)
+                   (ret# env'#)
+                   env'#)))
+             (update-in (assoc (cljs.test/empty-env) :return true)
+               [:testing-contexts] conj ~string)
+             (let [~'cljs$lang$test$body nil]
+               [~@(map (fn [expr] `(fn [] ~expr)) body)]))
+           [:testing-contexts] rest))))))

 ;; =============================================================================
 ;; Defining Tests


scored is second key, not first...

scored is second key, not first...

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -338,7 +338,7 @@
                         (not (:facedown c)))
                  (desactivate state side c) c)
              c (if (= dest [:rig :facedown]) (assoc c :facedown true :installed true) (dissoc c :facedown))
-             c (if (and (= (first dest) [:scored]) (:has-abilities-when-stolen (card-def c)))
+             c (if (and (= (second dest) :scored) (:has-abilities-when-stolen (card-def c)))
                  (merge c {:abilities (:abilities (card-def c))}) c)
              moved-card (assoc c :zone dest :host nil :hosted nil :previous-zone (:zone c))
              moved-card (if (and (:facedown moved-card) (:installed moved-card))


Fix typo

Fix typo

--- src/cljs/netrunner/deckbuilder.cljs
+++ src/cljs/netrunner/deckbuilder.cljs
@@ -40,7 +40,7 @@
                 {:qty (:qty card) :card (get-in card [:card :title])})
         data (assoc deck :cards cards)]
     (swap! app-state assoc :decks (conj (:decks @app-state) deck))
-    (go (let [response (<! (POST "/data/decks/delete" data :json))]))))
+    (go (let [response (<! (POST "/data/decks/" data :json))]))))

 (defn handle-edit [owner]
   (let [text (-> owner (om/get-node "deck-edit") .-value)]


refactor a bit

refactor a bit

--- src/cljam/convert.clj
+++ src/cljam/convert.clj
@@ -6,30 +6,14 @@
             [cljam.util.sam-util :as sam-util]
             [com.climate.claypoole :as cp]))

-(def ^:private default-num-block 10000)
-(def ^:private default-num-write-block 1000)
+(def ^:private default-num-block 100000)
+(def ^:private default-num-write-block 10000)

-(defn- _convert!
-  [in out num-block num-write-block alignments-writer]
-  (let [num-block (or num-block default-num-block)
-        num-write-block (or num-write-block default-num-write-block)]
-    (with-open [wtr (core/writer out)]
-      (with-open [rdr (core/reader in)]
-        (let [hdr (io/read-header rdr)]
-          (io/write-header wtr hdr)
-          (io/write-refs wtr hdr)
-          (alignments-writer rdr wtr hdr num-block num-write-block))))))
-
-(defn- sam-alignments-writer [rdr wtr hdr num-block num-write-block]
+(defn- sam-write-alignments [rdr wtr hdr num-block num-write-block]
   (doseq [alns (partition-all num-block (io/read-alignments rdr {}))]
     (io/write-alignments wtr alns hdr)))

-(defn convert-bam-to-sam
-  "Read from input bam file, and write to output sam file"
-  [in out & [num-block num-write-block]]
-  (_convert! in out num-block num-write-block sam-alignments-writer))
-
-(defn- bam-alignments-writer [rdr wtr hdr num-block num-write-block]
+(defn- bam-write-alignments [rdr wtr hdr num-block num-write-block]
   (let [refs (sam-util/make-refs hdr)
         w (.writer wtr)]
     (cp/with-shutdown! [pool (cp/threadpool (cp/ncpus))]
@@ -43,16 +27,22 @@
             (doseq [e block]
               (encoder/write-encoded-alignment w e))))))))

-(defn convert-sam-to-bam
-  "Read from input sam file, and write to output bam file"
-  [in out & [num-block num-write-block]]
-  (_convert! in out num-block num-write-block bam-alignments-writer))
+(defn- _convert!
+  [rdr wtr num-block num-write-block write-alignments-fn]
+  (let [hdr (io/read-header rdr)]
+    (io/write-header wtr hdr)
+    (io/write-refs wtr hdr)
+    (write-alignments-fn rdr wtr hdr num-block num-write-block)))

 (defn convert
   "Convert file format from input file to output file by file extension"
-  [in out & [num-block num-write-block]]
-  (condp re-find out
-    #"\.sam$" (convert-bam-to-sam in out num-block num-write-block)
-    #"\.bam$" (convert-sam-to-bam in out num-block num-write-block)
-    (throw (ex-info (str "Unsupported output file format " out) {})))
+  [in out & {:keys [num-block num-write-block]
+             :or {num-block default-num-block
+                  num-write-block default-num-write-block}}]
+  (with-open [rdr (core/reader in)
+              wtr (core/writer out)]
+    (cond
+      (core/sam-writer? wtr) (_convert! rdr wtr num-block num-write-block sam-write-alignments)
+      (core/bam-writer? wtr) (_convert! rdr wtr num-block num-write-block bam-write-alignments)
+      :else (throw (ex-info (str "Unsupported output file format " out) {}))))
   nil)


Added code to start IRC bot from the core module

--- src/clouseau/core.clj
+++ src/clouseau/core.clj
@@ -46,7 +46,10 @@
 (require '[clojure.tools.cli       :as cli])
 (require '[clojure.tools.logging   :as log])

+(require '[clouseau.config         :as config])
 (require '[clouseau.server         :as server])
+(require '[clouseau.dyncfg         :as dyncfg])
+(require '[clouseau.irc-bot        :as irc-bot])

 (def default-port
     "3000")
@@ -68,6 +71,13 @@
     [port]
     (println "Starting the server at the port: " port)
     (jetty/run-jetty app {:port (read-string port)}))
+
+(defn start-bot
+    []
+    (let [config (config/load-configuration "config.ini")]
+        (config/print-configuration config)
+        (reset! dyncfg/configuration config)
+        (irc-bot/start-irc-bot (:server config))))

 (defn get-and-check-port
     "Accepts port number represented by string and throws AssertionError
@@ -99,7 +109,8 @@
           port             (options :port)]
           (if (:help options)
               (show-help all-options)
-              (start-server (get-port port)))))
+              (do (start-bot)
+                  (start-server (get-port port))))))

 ; finito


minor improvement

minor improvement

--- src/clojure_fabric/crypto_suite.clj
+++ src/clojure_fabric/crypto_suite.clj
@@ -282,7 +282,7 @@
     (.subtract curve-n s)
     s))

-(defonce key+hash-algorithm
+(defonce key+hash-algorithm-map
   {[:ecdsa :sha256] "SHA256withECDSA"})

 ;;;sign
@@ -295,9 +295,9 @@
   Returns
         Result(Object):Signature object"
   ;; https://crypto.stackexchange.com/questions/1795/how-can-i-convert-a-der-ecdsa-signature-to-asn-1
-  [^bytes digest priv-key {:keys [algorithm curve hash-algorithm]
-                           :or {algorithm :ecdsa curve :secp256r1 hash-algorithm :sha256}}]
-  (let [signer (doto (Signature/getInstance (key+hash-algorithm [algorithm hash-algorithm]))
+  [^bytes digest priv-key {:keys [algorithm curve hash-algorithm security-provider]
+                           :or {algorithm :ecdsa curve :secp256r1 hash-algorithm :sha256 security-provider BouncyCastleProvider/PROVIDER_NAME}}]
+  (let [signer (doto (Signature/getInstance ^String (key+hash-algorithm-map [algorithm hash-algorithm]) ^String security-provider)
                  (.initSign priv-key)
                  (.update digest))
         asn-encodables (.toArray (.readObject (ASN1InputStream. (.sign signer))))]


Fixed bugs in new genome_*_eq instructions.

--- src/clojush/instructions/genome.clj
+++ src/clojush/instructions/genome.clj
@@ -528,7 +528,7 @@
       (let [genome (stack-ref :genome 0 state)
             index (mod (stack-ref :integer 0 state) (count genome))]
         (->> (pop-item :integer state)
-             (pop-item :exec state)
+             (pop-item :exec)
              (pop-item :genome)
              (push-item (= (top-item :exec state)
                            (:instruction (nth genome index)))
@@ -546,7 +546,7 @@
       (let [genome (stack-ref :genome 0 state)
             index (mod (stack-ref :integer 0 state) (count genome))]
         (->> (pop-item :integer state)
-             (pop-item :exec state)
+             (pop-item :exec)
              (pop-item :genome)
              (push-item (= (top-item :exec state)
                            (:close (nth genome index)))
@@ -564,9 +564,10 @@
       (let [genome (stack-ref :genome 0 state)
             index (mod (stack-ref :integer 0 state) (count genome))]
         (->> (pop-item :integer state)
-             (pop-item :exec state)
+             (pop-item :exec)
              (pop-item :genome)
              (push-item (= (top-item :exec state)
                            (:silent (nth genome index)))
                         :boolean)))
       state)))
+


Improve sentinel detection

Improve sentinel detection

--- src/onyx/plugin/kafka.clj
+++ src/onyx/plugin/kafka.clj
@@ -167,6 +167,10 @@
      :kafka/pending-messages pending-messages
      :kafka/pending-commits pending-commits}))

+(defn all-done? [messages]
+  (empty? (remove #(= :done (:message %))
+                  messages)))
+
 (defrecord KafkaReadMessages [max-pending batch-size batch-timeout partitions done-unsupported?
                               pending-messages pending-commits drained? read-ch]
   p-ext/Pipeline
@@ -189,9 +193,10 @@
                        (filter :message)))]
       (doseq [m batch]
         (swap! pending-messages assoc (:id m) m))
-      (when (and (= 1 (count @pending-messages))
-                 (= (count batch) 1)
-                 (= (:message (first batch)) :done))
+      (when (and (all-done? (vals @pending-messages))
+                 (all-done? batch)
+                 (or (not (empty? @pending-messages))
+                     (not (empty? batch))))
         (if done-unsupported?
           (throw (UnsupportedOperationException. ":done is not supported for auto assigned kafka partitions.
                                                  (:kafka/partition must be supplied)"))


Require core.async.

Require core.async.

--- src/orbitingnews/core.clj
+++ src/orbitingnews/core.clj
@@ -7,7 +7,8 @@
             [orbitingnews.config :as config]
             [orbitingnews.twitter :as twitter]
             [hiccup.core :as dom]
-            [hiccup.page :as page])
+            [hiccup.page :as page]
+            [clojure.core.async :as async :refer :all])
   (:gen-class))

 (defn handler [req]


Include provides with resolver data

Include provides with resolver data

--- src/com/wsscode/pathom/connect.cljc
+++ src/com/wsscode/pathom/connect.cljc
@@ -290,8 +290,10 @@
   This is a low level function, for adding to your index prefer using `pc/register`."
   ([indexes sym] (add indexes sym {}))
   ([indexes sym sym-data]
-   (let [{::keys [input output] :as sym-data} (merge {::sym   sym
-                                                      ::input #{}}
+   (let [provides (normalize-io (get sym-data ::output []))
+         {::keys [input output] :as sym-data} (merge {::sym      sym
+                                                      ::input    #{}
+                                                      ::provides provides}
                                                      sym-data)]
      (let [input' (if (and (= 1 (count input))
                            (contains? (get-in indexes [::index-io #{}]) (first input)))
@@ -300,7 +302,7 @@
        (merge-indexes indexes
          (cond-> {::index-resolvers  {sym sym-data}
                   ::index-attributes (index-attributes sym-data)
-                  ::index-io         {input' (normalize-io output)}
+                  ::index-io         {input' provides}
                   ::index-oir        (reduce (fn [indexes out-attr]
                                                (cond-> indexes
                                                  (not= #{out-attr} input)


Add missing require

Add missing require

--- src/pathfinder/system.clj
+++ src/pathfinder/system.clj
@@ -1,6 +1,7 @@
 (ns pathfinder.system
   (:require [compojure.handler :as handler]
             [pathfinder.data.elasticsearch :as es]
+            [pathfinder.present :as present]
             [pathfinder.service :as service]
             [ring.adapter.jetty :as jetty]
             [ring.middleware.stacktrace :as trace]))


Remove more workarounds from #44

Remove more workarounds from #44

--- lib/shin/cljs/cljs/core.cljs
+++ lib/shin/cljs/cljs/core.cljs
@@ -222,18 +222,26 @@
     (hamt/hash o)))

 (defn get
+  "Returns the value mapped to key, not-found or nil if key not present."
   ([o k]
-   (get o k nil))
-  ([o k not-found]
-   (cond
+   (cond (nil? o) nil
      (satisfies? ILookup o)
-     ; TODO multiple arity protocols, damn
-     (let [res (-lookup o k)]
-       (if res res not-found))
+     (-lookup o k)

      (or (array? o) (string? o))
+     (when (< k (.-length o))
+       (aget o k))
+
+     :else nil))
+  ([o k not-found]
+   (cond (nil? o) not-found
+     (satisfies? ILookup o)
+     (-lookup o k not-found)
+
+     (or (array? o) (string? o))
      (if (< k (.-length o))
-       (aget o k))
+       (aget o k)
+       not-found)

      :else not-found)))

@@ -341,26 +349,47 @@
   bounds, nth throws an exception unless not-found is supplied.  nth
   also works for strings, arrays, regex Matchers and Lists, and,
   in O(n) time, for sequences."
-  [coll n]
-  (cond
-    (not (number? n))
-    (throw "index argument to nth must be a number")
-
-    (nil? coll)
-    coll
-
-    (or (array? coll) (string? coll))
-    (when (< n (.-length coll))
-      (aget coll n))
-
-    (satisfies? IIndexed coll)
-    (-nth coll n)
-
-    (satisfies? ISeq coll)
-    (linear-traversal-nth coll n)
-
-    :else
-    (throw (str "nth not supported on this type: " (pr-str coll)))))
+  ([coll n]
+   (cond
+     (not (number? n))
+     (throw (js/Error. "index argument to nth must be a number"))
+
+     (nil? coll)
+     coll
+
+     (or (array? coll) (string? coll))
+     (when (< n (.-length coll))
+       (aget coll n))
+
+     (satisfies? IIndexed coll)
+     (-nth coll n)
+
+     (satisfies? ISeq coll)
+     (linear-traversal-nth coll n)
+
+     :else
+     (throw (js/Error. (str "nth not supported on this type: "
+                            (pr-str coll))))))
+  ([coll n not-found]
+   (cond
+     (not (number? n))
+     (throw (js/Error. "index argument to nth must be a number"))
+
+     (nil? coll)
+     not-found
+
+     (or (array? coll) (string? coll))
+     (if (< n (.-length coll))
+       (aget coll n)
+       not-found)
+
+     (satisfies? IIndexed coll)
+     (-nth coll n not-found)
+
+     :else
+     (throw (js/Error. (str "nth not supported on this type "
+                            (pr-str coll)))))))
+

 (defn first
   "Returns the first item in the collection. Calls seq on its
@@ -668,9 +697,7 @@
   (-conj  [rng o]))

 (defprotocol IIndexed
-  ; FIXME multiple arity protocols
-  (-nth [coll n]))
-  ; (-nth [coll n] [coll n not-found]))
+  (-nth [coll n] [coll n not-found]))

 (defprotocol ISeqable
   (-seq [o]))
@@ -711,10 +738,7 @@
   (-next [coll]))

 (defprotocol ILookup
-  ;; FIXME multiple arity protocols
-  (-lookup [o k])
-  ; (-lookup [o k] [o k not-found])
-)
+  (-lookup [o k] [o k not-found]))

 (defprotocol ISet
   (-disjoin [coll v]))
@@ -1297,7 +1321,6 @@
       (== 1 cnt) []
       :else  (subvec coll 0 (dec cnt))))

-
   ICollection
   (-conj [coll o]
     (PersistentVector. (hamt/set (+ offset cnt) o h) offset (inc cnt)))
@@ -1326,16 +1349,20 @@
         (.apply list nil r))))

   IIndexed
-  ; TODO: multiple arity protocols
-  ; TODO: check bounds
   (-nth [coll n]
     (hamt/get (+ offset n) h))
+  (-nth [coll n not-found]
+    (hamt/tryGet not-found (+ offset n) h))

   ILookup
-  ; TODO: multiple arity protocols
-  (-lookup [coll k] (if (number? k)
-                      (-nth coll k)
-                      nil))
+  (-lookup [coll k]
+    (if (number? k)
+      (-nth coll k)
+      nil))
+  (-lookup [coll k not-found]
+    (if (number? k)
+      (-nth coll k not-found)
+      not-found))

   IAssociative
   (-assoc [coll k v]
@@ -1434,9 +1461,10 @@
   (-count [coll] (hamt/count h))

   ILookup
-  ; TODO: multiple arity protocols
   (-lookup [coll k]
     (hamt/get k h))
+  (-lookup [coll k not-found]
+    (hamt/tryGet not-found k h))

   IAssociative
   (-assoc [coll k v]