Progress bar and current time

Progress bar and current time

--- src/cljs/sonority/player.cljs
+++ src/cljs/sonority/player.cljs
@@ -4,45 +4,110 @@
             [cljs.nodejs :as nodejs]
             [clojure.string :as string]))

+
+(nodejs/enable-util-print!)
+
+
+
+; independant utility functions
+
 (defrecord File [name path])

-(def selected-piece (reagent/atom nil))

-(def should-play (reagent/atom false))

-(def current-duration (reagent/atom 0))

-(def player-ref (reagent/atom nil))
+(defonce selected-piece (reagent/atom nil))
+
+(defonce playing (reagent/atom false))
+
+(defonce current-player-time (reagent/atom 0))
+
+(defonce clock (reagent/atom (js/Date.)))
+
+(defonce player (reagent/atom nil))
+
+
+
+(defn update-player-time [] (reset! current-player-time (.-currentTime @player)))
+
+(defn player-time-updater [key ref old-state new-state]
+  (update-player-time))
+
+(defn attach-clock-player-time-updater []
+  (add-watch clock :player-time-updater player-time-updater))
+
+(defn detach-clock-player-time-updater []
+  (remove-watch clock :player-time-updater))
+
+(defn create-player [piece]
+  (let [elem (if (nil? piece) (js/Audio.) (js/Audio. piece))]
+    (do
+      (.addEventListener elem "player-timechange" #(update-player-time))
+      (if @playing (.play elem))
+      elem)))

 (defn toggle-player [key ref old-state new-state]
-  (let [player (.getElementById js/document "main-player")]
-    (if new-state
-      (.play player)
-      (.pause player))
-    true))
+  (if new-state
+    (do
+      (attach-clock-player-time-updater)
+      (.play @player))
+    (do
+      (detach-clock-player-time-updater)
+      (.pause @player))))
+  ; (swap! player (fn [player]
+  ;   (do
+  ;     (if new-state
+  ;       (.play player)
+  ;       (.pause player))
+  ;     player))))

-(add-watch should-play :player-link toggle-player)
+(defn toggle-piece [key ref old-state new-state]
+  (if (not= old-state new-state)
+    (reset! player (create-player (:path new-state)))))

 (defn select-new [piece]
   (do
-    ;(reset! should-play true)
+    ;(reset! playing true)
     (reset! selected-piece piece)))

+(defn format-time [c]
+  (let [d (int c)]
+    (if (js/isNaN c)
+      "-:-"
+      (let [h (int (/ d 60))
+            min (int (mod d 60))]
+        (str h ":" (if (< min 10) "0" "") min)))))
+
+; ui

 (defn controls []
-  [:div.controls
-    [:button {:on-click #(swap! should-play not)} (if @should-play "||" ">")]
-    [:span @current-duration]])
-
-
-(defn player [piece]
-  [:audio#main-player {:src (:path @selected-piece) :controls true :autoPlay @should-play} "No support?"])
+  (let [player-time (.-duration @player)
+        current @current-player-time]
+    [:div.controls
+      [:button {:on-click #(swap! playing not)} (if @playing "||" ">")]
+      [:progress
+        { :value (let [val (/ (if (js/isNaN current) 0 current) player-time)]
+                   (if (js/isNaN val) 0 val))}]
+      [:span (str (format-time current) "/" (format-time player-time))]]))

 (defn interface [piece]
   [:div
-    [:div [:p "Playing: " (if (empty? (:name piece)) "nothing" (:name piece) )]]
-    (player piece)
+    [:div [:p "Playing: " (if (empty? (:name piece)) "nothing" (:name piece))]]
     (controls)])

 (defn std-interface []
   (interface @selected-piece))
+
+
+; wiring watchers
+
+(reset! player (create-player nil))
+
+(defonce clock-updater
+  (js/setInterval #(reset! clock (js/Date.)) 1000))
+
+(add-watch playing :player-link toggle-player)
+
+(add-watch selected-piece :piece-link toggle-piece)
+
+(attach-clock-player-time-updater)


Added dumb browe link.

Added dumb browe link.

--- src/clojars/web/dashboard.clj
+++ src/clojars/web/dashboard.clj
@@ -34,7 +34,8 @@
      (link-to "/register" "create an account")
      " and then check out the "
      (link-to "http://wiki.github.com/ato/clojars-web/tutorial"
-              "tutorial") "."]
+              "tutorial") ". Alternatively, "
+     (link-to "/repo" "browse") " the repository."]
     [:h2 "Recently pushed jars"]
     (unordered-list (map jar-link (recent-jars)))))


simplifications

simplifications

--- src/clojure/defgraph/core.clj
+++ src/clojure/defgraph/core.clj
@@ -1,13 +1,11 @@
 (ns defgraph.core
-  (:gen-class)
-  (:refer-clojure :exclude [parents]))
+  (:gen-class))

 (def defs     (filter #(.isFile %) (.listFiles (java.io.File. "defs/runs"))))
 (def vertices (map #(.getName %) defs))
 (def yaml     (org.yaml.snakeyaml.Yaml. (ExtendedConstructor.)))
-(def extends  (fn [x] (.get (.load yaml (slurp (.getPath x))) "ddts_extends")))
-(def parents  (map extends defs))
-(def edges    (into {} (filter val (zipmap vertices parents))))
+(def extends  (map #(.get (.load yaml (slurp (.getPath %))) "ddts_extends") defs))
+(def edges    (into {} (filter val (zipmap vertices extends))))
 (def rootpath (memoize #(let [x (edges %)] (if x (conj {% x} (rootpath x)) {}))))

 (defn graph [re]


Remove nanomsg.async ns.

Remove nanomsg.async ns.

--- src/clojure/nanomsg/async.clj
+++ src/clojure/nanomsg/async.clj
@@ -1,90 +0,0 @@
-(ns nanomsg.async
-  "Core async channels on top of jnanomsg."
-  (:import (nanomsg.async IAsyncCallback))
-  (:require [nanomsg :as nn]
-            [taoensso.nippy :as nippy]
-            [clojure.core.async :as async]
-            [clojure.core.async.impl.protocols :as protocols]))
-
-(defn- put!-impl
-  [sock value handler]
-  (let [async-sock  (:px sock)
-        callback    (reify IAsyncCallback
-                      (success [_ result]
-                        (let [cb (protocols/commit handler)]
-                          (cb)))
-                      (fail [_ throwable]
-                        (let [cb (protocols/commit handler)]
-                          (cb false))))
-        data        (nippy/freeze value)]
-    (.sendBytes async-sock data callback)
-    nil))
-
-(defn- take!-impl
-  [sock handler]
-  (let [async-sock  (:px sock)
-        callback    (reify IAsyncCallback
-                      (success [_ result]
-                        (let [cb    (protocols/commit handler)
-                              data  (nippy/thaw result)]
-                          (cb data)))
-                      (fail [_ throwable]
-                        (let [cb (protocols/commit handler)]
-                          (cb nil))))]
-    (.recvBytes async-sock callback)
-    nil))
-
-(defn- close!-impl
-  [sock closed]
-  (swap! closed (fn [closed]
-                  (if-not closed
-                    (do
-                      (nn/close! sock)
-                      (not closed))
-                    closed))))
-
-
-(deftype NanomsgWriteChannel [sock closed]
-  protocols/WritePort
-  (put! [_ value fn1-handler]
-    (if @closed
-      (delay false)
-      (put!-impl sock value fn1-handler)))
-
-  protocols/Channel
-  (close! [_]
-    (close!-impl sock closed)))
-
-(deftype NanomsgReadChannel [sock closed]
-  protocols/ReadPort
-  (take! [_ fn1-handler]
-    (take!-impl sock fn1-handler))
-
-  protocols/Channel
-  (close! [_]
-    (close!-impl sock closed)))
-
-(defn chan
-  "Channel constructor. Returns a core.async compatible
-  channel that works over jnanomsg async socket interface.
-
-  Example with connect:
-    (let [c1 (channel :socktype :pull :connect \"tcp:///tmp/sock\")]
-      (println \"Hello:\" (<!! c1)))
-
-  Example with bind:
-    (let [c1 (channel :socktype :push :bind \"tcp:///tmp/sock\")]
-      (>!! c1 \"pepe\"))
-
-  At this moment, janomsg channels only has support of
-  small subset of socket types: `:push` and `:pull`."
-  [& {:keys [bind connect socktype]}]
-  {:pre [(boolean (and socktype (or bind connect)))]}
-  (let [s   (nn/socket socktype {:async true})
-        ch  (case socktype
-              :push (NanomsgWriteChannel. s (atom false))
-              :pull (NanomsgReadChannel. s (atom false)))]
-    (cond
-      bind (nn/bind! s bind)
-      connect (nn/connect! s connect))
-    ch))


Fixed simplification generalization (and reporting of best) when using downsampling.

--- src/clojush/pushgp/report.clj
+++ src/clojush/pushgp/report.clj
@@ -355,22 +355,27 @@
         err-fn (if (= total-error-method :rmse) :weighted-error :total-error)
         sorted (sort-by err-fn < population)
         ; err-fn-best (first sorted)
-        err-fn-best (loop [sorted-individuals sorted]
-                      (if (empty? (rest sorted-individuals))
-                        (first sorted-individuals)
-                        (if (and (<= (:total-error (first sorted-individuals)) error-threshold)
-                                 (> (apply + (:errors (error-function (first sorted-individuals) :train))) error-threshold)
-                                 (<= (:total-error (second sorted-individuals)) error-threshold))
-                          (recur (rest sorted-individuals))
-                          (first sorted-individuals))))
-        psr-best (problem-specific-report err-fn-best
+        err-fn-best (error-function
+                     (loop [sorted-individuals sorted]
+                       (if (empty? (rest sorted-individuals))
+                         (first sorted-individuals)
+                         (if (and (<= (:total-error (first sorted-individuals)) error-threshold)
+                                  (> (apply + (:errors (error-function (first sorted-individuals) :train))) error-threshold)
+                                  (<= (:total-error (second sorted-individuals)) error-threshold))
+                           (recur (rest sorted-individuals))
+                           (first sorted-individuals))))
+                     :train)
+        total-error-best (assoc err-fn-best
+                                :total-error
+                                (apply +' (:errors err-fn-best)))
+        psr-best (problem-specific-report total-error-best
                                           population
                                           generation
                                           error-function
                                           report-simplifications)
         best (if (= (type psr-best) clojush.individual.individual)
                psr-best
-               err-fn-best)
+               total-error-best)
         standard-deviation (fn [nums]
                              (if (<= (count nums) 1)
                                (str "Cannot find standard deviation of "
@@ -590,13 +595,22 @@
     (when visualize
       (swap! viz-data-atom update-in [:history-of-errors-of-best] conj (:errors best))
       (swap! viz-data-atom assoc :generation generation))
-    (cond (and exit-on-success
-               (or (<= (:total-error best) error-threshold)
-                   (:success best))
-                (<= (apply + (:errors (error-function best :train))) error-threshold)) [:success best]  ;; making sure solutions pass all training cases before success
-          (>= generation max-generations) [:failure best]
-          (>= @point-evaluations-count max-point-evaluations) [:failure best]
-          :else [:continue best])))
+    (cond
+      ; Succeed
+      (and exit-on-success
+           (or (<= (:total-error best) error-threshold)
+               (:success best))
+           (<= (apply + (:errors (error-function best :train))) error-threshold))
+      [:success best]  ;; making sure solutions pass all training cases before success
+      ; Fail max generations
+      (>= generation max-generations)
+      [:failure best]
+      ; Fail max point evaluations
+      (>= @point-evaluations-count max-point-evaluations)
+      [:failure best]
+      ; Continue
+      :else
+      [:continue best])))

 (defn remove-function-values [argmap]
   (into {} (filter (fn [[k v]] (not (fn? v)))


Use helper

Use helper

--- src/braid/server/routes/api/public.clj
+++ src/braid/server/routes/api/public.clj
@@ -31,10 +31,8 @@
 (defroutes api-public-routes

   (GET "/session" req
-    (if-let [user-id (get-in req [:session :user-id])]
-      (if-let [user (db/user-by-id user-id)]
-        (edn-response user)
-        {:status 401 :body "" :session nil})
+    (if-let [user (user-from-session req)]
+      (edn-response user)
       {:status 401 :body "" :session nil}))

   (PUT "/session" [email password :as req]


Use with-open to make sure gzip reader is properly closed.

--- src/clj/clj_templates/clojars_data.clj
+++ src/clj/clj_templates/clojars_data.clj
@@ -12,16 +12,17 @@

 (def edn-opts {:eof :eof})

-(defn gzip-seq [stream]
-  (let [in (-> stream
-               (GZIPInputStream.)
-               (InputStreamReader.)
-               (PushbackReader.))]
-    (take-while #(not= :eof %) (repeatedly #(edn/read edn-opts in)))))
+(defn read-gzip-edn [stream]
+  (with-open [in (-> stream
+                     (GZIPInputStream.)
+                     (InputStreamReader.)
+                     (PushbackReader.))]
+    (doall
+      (take-while #(not= :eof %) (repeatedly #(edn/read edn-opts in))))))

 (defn extract-templates-from-gzip-stream [stream]
   (filterv (fn [{:keys [artifact-id]}] (#{"lein-template" "boot-template"} artifact-id))
-           (gzip-seq stream)))
+           (read-gzip-edn stream)))

 (defn get-clojars-templates []
   (let [res @(http/get "http://clojars.org/repo/feed.clj.gz" {:as :stream})]


Fix CLJ-2619 equivalent bug in claypoole (#60)

There is a memory "leak" for thread futures because the thread bindings are kept around after the future fn runs. We reset the bindings again by the time we run the next future, so it's not a correctness issue. Unfortunately until that next future (which might not happen for a while with large thread pools) we're keeping all the bindings saved for no good reason.

--- src/clj/com/climate/claypoole/impl.clj
+++ src/clj/com/climate/claypoole/impl.clj
@@ -35,8 +35,14 @@
   (let [frame (clojure.lang.Var/cloneThreadBindingFrame)]
     (with-meta
       (fn []
-        (clojure.lang.Var/resetThreadBindingFrame frame)
-        (f))
+        (let [frame-before (clojure.lang.Var/getThreadBindingFrame)]
+          (clojure.lang.Var/resetThreadBindingFrame frame)
+          (try
+            (f)
+            (finally
+              ;; This does not matter for correctness, but prevents leaking
+              ;; data in binding frames in thread locals.
+              (clojure.lang.Var/resetThreadBindingFrame frame-before)))))
       (meta f))))

 (defn deref-future


Allow file browser widget bar to be customized

--- src/clojure/nightcode/file_browser.clj
+++ src/clojure/nightcode/file_browser.clj
@@ -71,6 +71,8 @@
   (ui/update-project-tree!)
   (finish-edits!))

+(def ^:dynamic *widgets* [:up :new-file :edit :save :cancel])
+
 (defn create-actions
   []
   {:up go-up!
@@ -80,24 +82,24 @@
    :cancel finish-edits!})

 (defn create-widgets
-  []
-  [(create-up-button)
-   (ui/button :id :new-file
-              :text (utils/get-string :new-file)
-              :listen [:action new-file!]
-              :focusable? false)
-   (ui/button :id :edit
-              :text (utils/get-string :edit)
-              :listen [:action edit-files!]
-              :focusable? false)
-   (ui/button :id :save
-              :text (utils/get-string :save)
-              :listen [:action save-edits!]
-              :focusable? false)
-   (ui/button :id :cancel
-              :text (utils/get-string :cancel)
-              :listen [:action finish-edits!]
-              :focusable? false)])
+  [actions]
+  {:up (create-up-button)
+   :new-file (ui/button :id :new-file
+                        :text (utils/get-string :new-file)
+                        :listen [:action (:new-file actions)]
+                        :focusable? false)
+   :edit (ui/button :id :edit
+                    :text (utils/get-string :edit)
+                    :listen [:action (:edit actions)]
+                    :focusable? false)
+   :save (ui/button :id :save
+                    :text (utils/get-string :save)
+                    :listen [:action (:save actions)]
+                    :focusable? false)
+   :cancel (ui/button :id :cancel
+                      :text (utils/get-string :cancel)
+                      :listen [:action (:cancel actions)]
+                      :focusable? false)})

 (defn toggle-visible!
   [view path]
@@ -107,9 +109,9 @@
                  :#new-file (not edit?)
                  :#edit (and (not edit?)
                              (->> (io/file path)
-                               .listFiles
-                               (filter #(.isFile %))
-                               seq))
+                                  .listFiles
+                                  (filter #(.isFile %))
+                                  seq))
                  :#save edit?
                  :#cancel edit?}]
     (doseq [[id should-show?] buttons]
@@ -160,11 +162,14 @@

 (defn create-card
   []
-  (doto (s/border-panel :id :file-browser
-                        :north (ui/wrap-panel :items (create-widgets))
-                        :center (s/scrollable (ui/wrap-panel :id :file-grid)))
-    shortcuts/create-hints!
-    (shortcuts/create-mappings! (create-actions))))
+  (let [actions (create-actions)
+        widgets (create-widgets actions)
+        widget-bar (ui/wrap-panel :items (map #(get widgets % %) *widgets*))]
+    (doto (s/border-panel :id :file-browser
+                          :north widget-bar
+                          :center (s/scrollable (ui/wrap-panel :id :file-grid)))
+      shortcuts/create-hints!
+      (shortcuts/create-mappings! actions))))

 (defn update-card!
   ([path]


adapt plugin to new config api

adapt plugin to new config api

--- plugin/src/leiningen/figwheel.clj
+++ plugin/src/leiningen/figwheel.clj
@@ -68,8 +68,8 @@
   [project & build-ids]
   (let [{:keys [all-builds figwheel-options]}
         (-> project
-            (fc/figwheel-ambient-config build-ids)
-            fc/prep-figwheel-config)
+            (fc/config build-ids)
+            fc/prep-config)
         errors (fc/check-config figwheel-options
                                 (fc/narrow-builds*
                                  all-builds


Fix repl refreshability of test.

Fix repl refreshability of test.

--- test/onyx/windowing/window_session_test.clj
+++ test/onyx/windowing/window_session_test.clj
@@ -144,6 +144,7 @@

     (reset! in-chan (chan (inc (count input))))
     (reset! in-buffer {})
+    (reset! test-state [])
     (reset! out-chan (chan (sliding-buffer (inc (count input)))))

     (with-test-env [test-env [3 env-config peer-config]]


Fix naming of units.

Fix naming of units.

--- src/kolmogorov_music/talk.clj
+++ src/kolmogorov_music/talk.clj
@@ -165,8 +165,8 @@
 ;;;;;;;;;;;;

 (defmethod live/play-note :default
-  [{hertz :pitch seconds :duration}]
-  (when hertz (geb/overchauffeur (midi->hz hertz) seconds)))
+  [{midi :pitch seconds :duration}]
+  (some-> midi midi->hz (geb/overchauffeur seconds)))

 (defn copyright-infringement-song
   ([skip-to]


Genericize gradient

Genericize gradient

--- frontend/components/integrations.cljs
+++ frontend/components/integrations.cljs
@@ -157,7 +157,7 @@
     (if (= integration :docker)
       (om/build docker app)
       (html [:div#integrations.generic
-             [:div.top-section
+             [:div.top-section.heroku
               [:div.line]
               [:div.hero-wrapper
                [:div.hero


update boot-cljs-test version

update boot-cljs-test version

--- src/leiningen/new/tenzing.clj
+++ src/leiningen/new/tenzing.clj
@@ -78,7 +78,7 @@

 (defn dependencies [opts]
   (cond-> []
-          (test?    opts) (conj "crisptrutski/boot-cljs-test \"0.1.0-SNAPSHOT\" :scope \"test\"")
+          (test?    opts) (conj "crisptrutski/boot-cljs-test \"0.2.0-SNAPSHOT\" :scope \"test\"")
           (om?      opts) (conj "org.omcljs/om \"0.8.6\"")
           (reagent? opts) (conj "reagent \"0.5.0\"")
           (garden?  opts) (conj "org.martinklepsch/boot-garden \"1.2.5-3\" :scope \"test\"")


Factor constants.

Factor constants.

--- test/onyx/coordinator/cluster_test.clj
+++ test/onyx/coordinator/cluster_test.clj
@@ -43,13 +43,17 @@

 (def workflow {:in {:inc :out}})

-(doseq [_ (range 10)]
+(def n-jobs 10)
+
+(def n-peers 10)
+
+(def tasks-per-job 3)
+
+(doseq [_ (range n-jobs)]
   (>!! (:planning-ch-head coordinator) {:catalog catalog :workflow workflow}))

-(doseq [_ (range 10)]
+(doseq [_ (range n-jobs)]
   (<!! offer-spy))
-
-(def n-peers 10)

 (def peers (take n-peers (repeatedly (fn [] (extensions/create sync-storage :peer)))))

@@ -82,12 +86,12 @@

 (start-peers! peers)

-(testing "All 30 tasks complete"
+(testing "All tasks complete"
   (loop []
     (let [db (:db-after (.take tx-queue))
           query '[:find (count ?task) :where [?task :task/complete? true]]
           result (ffirst (d/q query db))]
-      (when-not (= result 30)
+      (when-not (= result (* n-jobs tasks-per-job))
         (recur)))))

 (let [db (d/db (:conn log))]


should_work_now

--- src/metabase/driver/generic_sql/sync.clj
+++ src/metabase/driver/generic_sql/sync.clj
@@ -347,7 +347,7 @@
     (if (= total-non-null-count 0) 0
         (let [url-count (-> (select korma-table
                                     (aggregate (count :*) :count)
-                                    (where {(keyword field-name) [like "http%://_%.__%"]})) first :count)] ; This is how the old Django app worked. Didn't match URLs like
+                                    (where {(raw (format "CAST(\"%s\" AS TEXT)" (name field-name))) [like "http%://_%.__%"]})) first :count)] ; This is how the old Django app worked. Didn't match URLs like
           (float (/ url-count total-non-null-count))))))                                                   ; "www.zagat.com". Is this what we want?

 (defn- check-for-urls


allow control-proxies to masquerade as numbers in the ugen checker

--- src/overtone/sc/machinery/ugen/check.clj
+++ src/overtone/sc/machinery/ugen/check.clj
@@ -98,9 +98,10 @@
   true)

 (defcheck nth-input-number? [n]
-  (str "Input with index " n " must be a number or an ir ugen")
+  (str "Input with index " n " must be a number, control proxy or an ir ugen")
   (let [val (nth inputs n)]
     (or
+     (control-proxy? val)
      (number? val)
      (= :ir (:rate-name val)))))


(PDB-4807) Make command loader future noisy

--- src/puppetlabs/puppetdb/cli/services.clj
+++ src/puppetlabs/puppetdb/cli/services.clj
@@ -78,7 +78,7 @@
             [puppetlabs.puppetdb.schema :as pls :refer [defn-validated]]
             [puppetlabs.puppetdb.time :refer [ago to-seconds to-millis parse-period
                                               format-period period?]]
-            [puppetlabs.puppetdb.utils :as utils]
+            [puppetlabs.puppetdb.utils :as utils :refer [noisy-future]]
             [puppetlabs.trapperkeeper.core :refer [defservice] :as tk]
             [puppetlabs.trapperkeeper.services :refer [service-id service-context]]
             [robert.hooke :as rh]
@@ -673,8 +673,8 @@
      ;; Caller is responsible for calling future-cancel on this in the end.
      :command-chan cmd-ch
      :command-loader (when load-messages
-                       (future
-                         (load-messages cmd-ch cmd/inc-cmd-depth)))}))
+                       (noisy-future
+                        (load-messages cmd-ch cmd/inc-cmd-depth)))}))

 (defn init-write-dbs [config]
   ;; FIXME: forbid subdb settings?


(PDB-4656) Schema check the write database(s) too

--- src/puppetlabs/puppetdb/cli/services.clj
+++ src/puppetlabs/puppetdb/cli/services.clj
@@ -745,14 +745,16 @@

             (when-not (get-in config [:puppetdb :disable-update-checking])
               (maybe-check-for-updates config read-db job-pool))
+            ;; FIXME: deduplicate?  how?
             (when (pos? schema-check-interval)
-              (interspaced schema-check-interval
-                           #(check-schema-version desired-schema-version
-                                                  context
-                                                  read-db
-                                                  service
-                                                  request-shutdown)
-                           job-pool))
+              (doseq [db (cons read-db write-dbs)]
+                (interspaced schema-check-interval
+                             #(check-schema-version desired-schema-version
+                                                    context
+                                                    db
+                                                    service
+                                                    request-shutdown)
+                             job-pool)))
             (mapv (fn [cfg db]
                     (let [interval (to-millis (:gc-interval cfg))]
                       (when (pos? interval)


bump re-frame-trace version;

bump re-frame-trace version;

--- src/leiningen/new/re_frame/project.clj
+++ src/leiningen/new/re_frame/project.clj
@@ -55,7 +55,7 @@
   :profiles
   {:dev
    {:dependencies [[binaryage/devtools "0.9.4"]{{#trace?}}
-                   [day8.re-frame/trace "0.1.12"]{{/trace?}}{{#cider?}}
+                   [day8.re-frame/trace "0.1.14"]{{/trace?}}{{#cider?}}
                    [figwheel-sidecar "0.5.13"]
                    [com.cemerick/piggieback "0.2.2"]{{/cider?}}{{#re-frisk?}}
                    [re-frisk "0.5.3"]{{/re-frisk?}}]


Add year-month-day format for invoice table

--- frontend/datetime.cljs
+++ frontend/datetime.cljs
@@ -90,6 +90,12 @@
 (def calendar-date
   (partial format-date calendar-date-format))

+(def year-month-day-date-format
+  (goog.i18n.DateTimeFormat. "yyyy/MM/dd"))
+
+(def year-month-day-date
+  (partial format-date year-month-day-date-format))
+
 (defn date-in-ms [date]
   (let [[y m d] (map js/parseInt (.split (name date) #"-"))]
     (.getTime (js/Date. (js/Date.UTC y (dec m) (dec d) 0 0 0)))))


Minor fixes on colorpalette.

Minor fixes on colorpalette.

--- src/uxbox/ui/workspace/colorpalette.cljs
+++ src/uxbox/ui/workspace/colorpalette.cljs
@@ -44,7 +44,7 @@
   (let [local (:rum/local own)
         flags (rum/react wb/flags-l)
         collections-by-id (rum/react collections-by-id-l)
-        collections (vals collections-by-id)
+        collections (sort-by :name (vals collections-by-id))
         collection (if-let [collid (:selected @local)]
                      (get collections-by-id collid)
                      (first collections))
@@ -55,7 +55,7 @@
        [:div.color-palette
         [:div.color-palette-actions
          [:select.input-select {:on-change select-collection}
-          (for [collection (vals collections-by-id)]
+          (for [collection collections]
             [:option {:key (str (:id collection))
                       :value (pr-str (:id collection))}
              (:name collection)])]


Remove old notes in wonderdome.core ns.

Remove old notes in wonderdome.core ns.

--- src/org/playasophy/wonderdome/core.clj
+++ src/org/playasophy/wonderdome/core.clj
@@ -2,34 +2,21 @@
   (:require
     [com.stuartsierra.component :as component]))

-;; Modes have some state, probably stored in an atom.
-;; Displays are protocol objects which can be read(?) and written to, but still side effecting?
-;; Loop reads in events, calls mode update.

-;; There also needs to be some concept of pixel layout.
-;; Does it make sense for a mode to be written for multiple layouts? Probably not.
-;; All layouts may address pixels linearly, but individual layouts should have
-;; more appropriate addressing. For example, square grids are best addressed
-;; using (x, y) coordinates, while a geodesic grid... uh, TBD. (strut, index)?
-
-;; A display can map a pixel index to various properties:
-;; SquareGrid: x, y
-;; Geodesic3V: strut, index, azimuth, elevation
-
-
+#_
 (def wonderdome-state
-  "Complete representation of the current wonderdome state."
-  (atom {:state :running
-         :last-autocycle 1234567890
-         :playlist [:colorcycle
-                    :sweep
-                    :twinkle
-                    :marqee]
-         :modes {:colorcycle {:speed 0.1
-                              :density 2.6
-                              :offset 0.3208}
-                 :sweep {:offset "..."}}
-         :event-handlers []}))
+  "Example representation of the current wonderdome state."
+  {:state :running
+   :last-autocycle #inst "2014-07-07T11:03:42Z"
+   :playlist [:colorcycle  ; queue is probably better
+              :sweep
+              :twinkle
+              :marqee]
+   :modes {:colorcycle {:speed 0.1
+                        :density 2.6
+                        :offset 0.3208}
+           :sweep {:offset "..."}}
+   :event-handlers []})

 (defn initialize


Added Sparkling dependency

Added Sparkling dependency

--- cljx/plongeur-clj/project.clj
+++ cljx/plongeur-clj/project.clj
@@ -19,7 +19,7 @@
                  [com.rpl/specter "0.10.0"]

                  [ring "1.4.0"]
-                 [ring/ring-defaults "0.2.0"]
+                 [ring/ring-defaults "0.2.0" :exclusions [[javax.servlet/*]]]
                  [compojure "1.5.0"]
                  [clojurewerkz/route-one "1.2.0"]
                  [http-kit "2.1.18"]
@@ -28,6 +28,8 @@
                  [com.taoensso/timbre "4.3.1"]

                  [environ "1.0.2"]
+
+                 [gorillalabs/sparkling "1.2.5"]

                  ;[t6/from-scala "0.2.1"]
                  ;[org.scala-lang/scala-library "2.11.6"]
@@ -38,6 +40,9 @@
   :plugins [[lein-environ "1.0.2"]]

   :profiles {:uberjar {:aot :all}
+
+             :provided {:dependencies [[org.apache.spark/spark-core_2.10 "1.6.1"]]}
+
              :dev     {:source-paths ["dev"]
                        :repl-options {:port 8666}
                        :dependencies [[org.clojure/tools.namespace "0.2.11"]


attack

attack

--- clojure/src/dnd/keyboard.cljs
+++ clojure/src/dnd/keyboard.cljs
@@ -20,6 +20,7 @@
     "RIGHT" (emit "move"  term level character  1  0)
     "g"     (emit "get"   term level character)
     "d"     (emit "drop"  term level character)
+    "a"     (emit "attack" term level character)
     "i"     (emit "inventory" term character)
     "ESCAPE" (.exit js/process)
     "default"))


CMR-2896 pr comments

CMR-2896 pr comments

--- access-control-app/int_test/cmr/access_control/int_test/permission_check_test.clj
+++ access-control-app/int_test/cmr/access_control/int_test/permission_check_test.clj
@@ -38,7 +38,22 @@

 (deftest invalid-params-test
   (let [target-required-err "One of [concept_id], [system_object], [target_group_id], or [provider] and [target] are required."
-        user-required-err "One of parameters [user_type] or [user_id] are required."]
+        user-required-err "One of parameters [user_type] or [user_id] are required."
+        system-target-err (str "Parameter [system_object] must be one of: [\"SYSTEM_AUDIT_REPORT\" "
+                               "\"METRIC_DATA_POINT_SAMPLE\" \"SYSTEM_INITIALIZER\" \"ARCHIVE_RECORD\" "
+                               "\"ERROR_MESSAGE\" \"TOKEN\" \"TOKEN_REVOCATION\" \"EXTENDED_SERVICE_ACTIVATION\" "
+                               "\"ORDER_AND_ORDER_ITEMS\" \"PROVIDER\" \"TAG_GROUP\" \"TAXONOMY\" "
+                               "\"TAXONOMY_ENTRY\" \"USER_CONTEXT\" \"USER\" \"GROUP\" \"ANY_ACL\" "
+                               "\"EVENT_NOTIFICATION\" \"EXTENDED_SERVICE\" \"SYSTEM_OPTION_DEFINITION\" "
+                               "\"SYSTEM_OPTION_DEFINITION_DEPRECATION\" \"INGEST_MANAGEMENT_ACL\" \"SYSTEM_CALENDAR_EVENT\"]")
+        prov-target-err (str "Parameter [target] must be one of: [\"AUDIT_REPORT\" "
+                             "\"OPTION_ASSIGNMENT\" \"OPTION_DEFINITION\" \"OPTION_DEFINITION_DEPRECATION\" "
+                             "\"DATASET_INFORMATION\" \"PROVIDER_HOLDINGS\" \"EXTENDED_SERVICE\" \"PROVIDER_ORDER\" "
+                             "\"PROVIDER_ORDER_RESUBMISSION\" \"PROVIDER_ORDER_ACCEPTANCE\" \"PROVIDER_ORDER_REJECTION\" "
+                             "\"PROVIDER_ORDER_CLOSURE\" \"PROVIDER_ORDER_TRACKING_ID\" \"PROVIDER_INFORMATION\" "
+                             "\"PROVIDER_CONTEXT\" \"AUTHENTICATOR_DEFINITION\" \"PROVIDER_POLICIES\" \"USER\" "
+                             "\"GROUP\" \"PROVIDER_OBJECT_ACL\" \"CATALOG_ITEM_ACL\" \"INGEST_MANAGEMENT_ACL\" "
+                             "\"DATA_QUALITY_SUMMARY_DEFINITION\" \"DATA_QUALITY_SUMMARY_ASSIGNMENT\" \"PROVIDER_CALENDAR_EVENT\"]")]
     (are [params errors]
       (= {:status 400 :body {:errors errors} :content-type :json}
          (ac/get-permissions (u/conn-context) params {:token "mock-echo-system-token" :raw? true}))
@@ -48,19 +63,17 @@
       {:user_id "foobar"} [target-required-err]
       ;; Provider target and provider not both present
       {:user_id "foobar" :target "PROVIDER_HOLDINGS"} [target-required-err]
+      {:user_id "foobar" :provider "PROV1"} [target-required-err prov-target-err]
       {:concept_id "C12345-ABC2" :system_object "GROUP" :user_id "bat"} [target-required-err]
       {:concept_id "C1200000-PROV1" :user_type "GROUP" :user_id "foo"} [user-required-err]
       {:not_a_valid_param "foo"} ["Parameter [not_a_valid_param] was not recognized."]
       {:user_id "foo" :concept_id ["XXXXX"]} ["Concept-id [XXXXX] is not valid."]
-      {:user_id "foo" :target_group_id ["C1200000-PROV1"]} ["Target group id [C1200000-PROV1] is not valid."]))
-  (are [params re]
-    (some #(re-find re %)
-          (:errors (:body (ac/get-permissions (u/conn-context) params {:token "mock-echo-system-token" :raw? true}))))
-    {:user_id "foo" :system_object "GROUPE"} #"Parameter \[system_object\] must be one of: .*GROUP.*"
-    {:user_id "foo" :system_object "group"} #"Parameter \[system_object\] must be one of: .*GROUP.*"
-    {:user_id "foo" :provider "PROV1" :target "PROVIDER_HOLDINGZ"} #"Parameter \[target\] must be one of: .*PROVIDER_HOLDINGS.*"
-    ;; More than one kind of target is specified
-    {:user_id "foo" :provider "PROV1" :target ["PROVIDER_HOLDINGS" "AUDIT_REPORT"]} #"Parameter \[target\] must be one of: .*PROVIDER_HOLDINGS.*"))
+      {:user_id "foo" :target_group_id ["C1200000-PROV1"]} ["Target group id [C1200000-PROV1] is not valid."]
+      {:user_id "foo" :system_object "GROUPE"} [system-target-err]
+      {:user_id "foo" :system_object "group"} [system-target-err]
+      {:user_id "foo" :provider "PROV1" :target "PROVIDER_HOLDINGZ"} [prov-target-err]
+      ;; More than one kind of target is specified
+      {:user_id "foo" :provider "PROV1" :target ["PROVIDER_HOLDINGS" "AUDIT_REPORT"]} [prov-target-err])))

 (defn get-permissions
   "Helper to get permissions with the current context and the specified username string or user type keyword and concept ids."


add space for readable error message (#797)

directory name /foo/bazz and the word "specified" was concatenated

```
package in /foo/bazzspecified entries but they were all missing
```

--- src/main/shadow/build/npm.clj
+++ src/main/shadow/build/npm.clj
@@ -184,7 +184,7 @@
     (when (and (seq entries)
                (not entry-file))
       (throw (ex-info
-               (str "package in " package-dir "specified entries but they were all missing")
+               (str "package in " package-dir " specified entries but they were all missing")
                {:tag ::missing-entries
                 :entries entries
                 :package-dir package-dir})))


Reformating code

Reformating code

--- src/tabular/grafter/tabular/common.clj
+++ src/tabular/grafter/tabular/common.clj
@@ -166,7 +166,9 @@
   serialising datasets into various different formats."
   (fn [destination dataset opts]
     (when-not (dataset? dataset)
-      (throw (IllegalArgumentException. (str "Could not write dataset to" destination " as " (class dataset) " is not a valid Dataset.  This error usually occurs if you try and generate tabular data from a graft"))))
+      (throw (IllegalArgumentException.
+              (str "Could not write dataset to" destination " as " (class dataset)
+                   " is not a valid Dataset.  This error usually occurs if you try and generate tabular data from a graft"))))
     (format-or-type destination opts)))

 (defmethod write-dataset* ::default [destination dataset {:keys [format] :as opts}]


Update and simplify geometry example

Update and simplify geometry example

--- examples/geometry/project.clj
+++ examples/geometry/project.clj
@@ -1,31 +1,29 @@
 (defproject geometry-reagent "0.5.0"
-  :dependencies [[org.clojure/clojure "1.6.0"]
-                 [org.clojure/clojurescript "0.0-2816"]
+  :dependencies [[org.clojure/clojure "1.7.0"]
+                 [org.clojure/clojurescript "0.0-3308"]
                  [reagent "0.5.0"]
-                 [figwheel "0.2.3-SNAPSHOT"]]
+                 [figwheel "0.3.7"]]

-  :plugins [[lein-cljsbuild "1.0.4"]
-            [lein-figwheel "0.2.3-SNAPSHOT"]]
+  :plugins [[lein-cljsbuild "1.0.6"]
+            [lein-figwheel "0.3.7"]]

   :hooks [leiningen.cljsbuild]

   :profiles {:dev {:cljsbuild
-                   {:builds {:client {:source-paths ["devsrc"]
-                                      :compiler
-                                      {:main geometry.dev
-                                       :optimizations :none
-                                       :source-map true
-                                       :source-map-timestamp true}}}}}
+                   {:builds {:client
+                             {:figwheel {:on-jsload "geometry.core/run"}
+                              :compiler {:main "geometry.core"
+                                         :optimizations :none}}}}}

              :prod {:cljsbuild
-                    {:builds {:client {:compiler
-                                       {:optimizations :advanced
-                                        :elide-asserts true
-                                        :pretty-print false}}}}}}
+                    {:builds {:client
+                              {:compiler {:optimizations :advanced
+                                          :elide-asserts true
+                                          :pretty-print false}}}}}}

   :figwheel {:repl false}

-  :cljsbuild {:builds {:client {:source-paths ["src"]
-                                :compiler
-                                {:output-dir "target/client"
-                                 :output-to "target/client.js"}}}})
+  :cljsbuild {:builds {:client
+                       {:source-paths ["src"]
+                        :compiler {:output-dir "target/client"
+                                   :output-to "target/client.js"}}}})


extend iam tests and fix typo

extend iam tests and fix typo

--- test/crucible/resources/aws/iam_test.clj
+++ test/crucible/resources/aws/iam_test.clj
@@ -4,11 +4,11 @@
             [crucible.resources.aws.iam :as iam]))

 (deftest test-example-iam-role
-  (testing ""
+  (testing "with singular actions and resources"
     (is (= (encode-resource
             {}
             (iam/role :assume-role-policy-document
-                      (iam/assume-role-policy-document [{:service "ec2.amazonaws.com"}])
+                      (iam/assume-role-policy-document {:service "ec2.amazonaws.com"})
                       :path "/"
                       :policies [(iam/policy "root"
                                              (iam/statement :actions "*"
@@ -20,9 +20,36 @@
              {"Version" "2012-10-17"
               "Statement"
               [{"Effect" "Allow",
-                "Principal" [{"Service" "ec2.amazonaws.com"}]
+                "Principal" {"Service" "ec2.amazonaws.com"}
                 "Action" ["sts:AssumeRole"]}]}
              "Policies"
              [{"Version" "2012-10-17"
                "Statement"
-               [{"Effect" "Allow" "Action" "*" "Resource" "*"}]}]}}))))
+               [{"Effect" "Allow" "Action" "*" "Resource" "*"}]}]}})))
+
+  (testing "with multiple actions and resources"
+    (is (= (encode-resource
+            {}
+            (iam/role :assume-role-policy-document
+                      (iam/assume-role-policy-document {:service "ec2.amazonaws.com"})
+                      :path "/"
+                      :policies [(iam/policy "root"
+                                             (iam/statement :actions ["s3:PutObject"
+                                                                      "s3:GetObject"]
+                                                            :resources ["arn:aws:s3:::mybucket/mykey"]))]))
+           {"Type" "AWS::IAM::Role"
+            "Properties"
+            {"Path" "/"
+             "AssumeRolePolicyDocument"
+             {"Version" "2012-10-17"
+              "Statement"
+              [{"Effect" "Allow",
+                "Principal" {"Service" "ec2.amazonaws.com"}
+                "Action" ["sts:AssumeRole"]}]}
+             "Policies"
+             [{"Version" "2012-10-17"
+               "Statement"
+               [{"Effect" "Allow"
+                 "Action" ["s3:PutObject"
+                           "s3:GetObject"]
+                 "Resource" ["arn:aws:s3:::mybucket/mykey"]}]}]}}))))


change "il" to "lo" and "i" to "gli" and vice versa depending on the subsequent word

--- src/babel/italiano/morphology.cljc
+++ src/babel/italiano/morphology.cljc
@@ -973,11 +973,30 @@
               ]
           (cond

+           (and (= a "gli")
+                (string? (get-in b '(:italiano)))
+                (not (or (re-find #"^[aeiou]" (get-in b '(:italiano)))
+                         (re-find #"^s[t]" (get-in b '(:italiano))))))
+           (trim (str "i " b))
+
            (and (= a "i")
                 (string? (get-in b '(:italiano)))
-                (re-find #"^[aeiou]" (get-in b '(:italiano))))
+                (or (re-find #"^[aeiou]" (get-in b '(:italiano)))
+                    (re-find #"^s[t]" (get-in b '(:italiano)))))
            (trim (str "gli " b))

+           (and (= a "il")
+                (string? b)
+                (or (re-find #"^[aeiou]" b)
+                    (re-find #"^s[t]" b)))
+           (trim (str "lo " b))
+
+           (and (= a "lo")
+                (string? b)
+                (not (or (re-find #"^[aeiou]" b)
+                         (re-find #"^s[t]" b))))
+           (trim (str "il " b))
+
            ;; TODO: cleanup & remove.
            (and false ;; going to throw out this logic: will use :initial and rule schemata instead.
                 (= :verb (get-in a '(:cat)))


Fix import syntax

Fix import syntax

--- test/caesium/crypto/secretbox_test.clj
+++ test/caesium/crypto/secretbox_test.clj
@@ -1,9 +1,8 @@
 (ns caesium.crypto.secretbox-test
-  (:require
-   [caesium.crypto.secretbox :as s]
-   [caesium.util :as u]
-   [caesium.vectors :as v]
-   [clojure.test :refer :all]))
+  (:require [caesium.crypto.secretbox :as s]
+            [caesium.util :as u]
+            [caesium.vectors :as v]
+            [clojure.test :refer [deftest is are testing]]))

 (deftest const-tests
   (is (= 32 s/keybytes))


Test for function send-error-response

Test for function send-error-response

--- test/emender_jenkins/rest_api_test.clj
+++ test/emender_jenkins/rest_api_test.clj
@@ -953,3 +953,17 @@
                      :headers {"Content-Type" "application/json"}
                      :body    "{\"response\":{\"deep\":{\"structure\":\"ok\"}}}\n"})))))

+(deftest test-send-error-response
+    "Check the function emender-jenkins.rest-api/send-error-response."
+    (testing "the function emender-jenkins.rest-api/send-error-response."
+        (let [request       {:configuration {:jenkins {:currently-building-view "Building"
+                                                      :jenkins-url "http://10.20.30.40:8080/"}}}]
+             (is (= (send-error-response {:response :error} request :ok)
+                    {:status  200
+                     :headers {"Content-Type" "application/json"}
+                     :body    "{\"response\":\"error\"}"}))
+             (is (= (send-error-response {:response {:deep {:structure :error}}} request :ok)
+                    {:status  200
+                     :headers {"Content-Type" "application/json"}
+                     :body    "{\"response\":{\"deep\":{\"structure\":\"error\"}}}"})))))
+


Had wrong url for API

Had wrong url for API

--- src/structural_typing/doc.clj
+++ src/structural_typing/doc.clj
@@ -2,4 +2,4 @@
   "Functions that jump to online documentation."
   (:require such.doc))

-(such.doc/api-url! "https://github.com/marick/structural-typing/")
+(such.doc/api-url! "http://marick.github.io/structural-typing/")


move toggle system stats button to bottom of page and only show on topology and component pages

--- src/clj/backtype/storm/ui/core.clj
+++ src/clj/backtype/storm/ui/core.clj
@@ -28,7 +28,12 @@
        (map #(.get_stats ^TaskSummary %))
        (filter not-nil?)))

-(defn ui-template [body include-sys?]
+(defn mk-system-toggle-button [include-sys?]
+  [:p [:input {:type "button"
+             :value (str (if include-sys? "Hide" "Show") " System Stats")
+             :onclick "toggleSys()"}]])
+
+(defn ui-template [body]
   (html
    [:head
     [:title "Storm UI"]
@@ -78,9 +83,6 @@
 }"]
    [:body
     [:h1 (link-to "/" "Storm UI")]
-    [:p [:input {:type "button"
-                 :value (str (if include-sys? "Hide" "Show") " System Stats")
-                 :onclick "toggleSys()"}]]
     (seq body)
     ]))

@@ -709,18 +711,20 @@
 (defroutes main-routes
   (GET "/" [:as {cookies :cookies}]
        (-> (main-page)
-           (ui-template (get-include-sys? cookies))))
+           ui-template))
   (GET "/topology/:id" [:as {cookies :cookies} id & m]
        (let [include-sys? (get-include-sys? cookies)]
          (-> (topology-page id (:window m) include-sys?)
-                            (ui-template include-sys?))))
+             (concat [(mk-system-toggle-button include-sys?)])
+             ui-template)))
   (GET "/topology/:id/component/:component" [:as {cookies :cookies} id component & m]
        (let [include-sys? (get-include-sys? cookies)]
          (-> (component-page id component (:window m) include-sys?)
-             (ui-template include-sys?))))
+             (concat [(mk-system-toggle-button include-sys?)])
+             ui-template)))
   (GET "/topology/:id/task/:task" [:as {cookies :cookies} id task & m]
        (-> (task-page id (Integer/parseInt task) (:window m))
-           (ui-template (get-include-sys? cookies))))
+           ui-template))
   (route/resources "/")
   (route/not-found "Page not found"))


other criteria trumps relvancy

other criteria trumps relvancy

--- src/clj/cljspazzer/http/artist.clj
+++ src/clj/cljspazzer/http/artist.clj
@@ -19,6 +19,6 @@

 (defn artist-image [artist]
-  (let [goog-result (:url (last (sort-by :width (filter (fn [r] (<= (Integer/parseInt (:width r)) 1024)) (images/goog-artist-images artist)))))]
+  (let [goog-result (:url (first (images/goog-artist-images artist)))]
     {:status 302
      :headers {"Location" goog-result}}))


kryoMultiGet functions across machines.

kryoMultiGet functions across machines.

--- src/clj/elephantdb/keyval/core.clj
+++ src/clj/elephantdb/keyval/core.clj
@@ -16,7 +16,7 @@
            [elephantdb.common.database Database]
            [elephantdb.common.domain Domain]
            [elephantdb.generated DomainNotFoundException
-            DomainNotLoadedException HostsDownException WrongHostException]
+            DomainNotLoadedException WrongHostException]
            [elephantdb.generated.keyval ElephantDB$Client
             ElephantDB$Iface ElephantDB$Processor])
   (:gen-class))
@@ -64,7 +64,10 @@
   [^ElephantDB$Iface service database domain-name error-suffix key-seq]
   (try (let [^Domain dom (db/domain-get database domain-name)
              serializer  (.serializer dom)
-             key-seq     (map #(.serialize serializer %) key-seq)]
+             key-seq     (map (fn [x]
+                                (ByteBuffer/wrap
+                                 (.serialize serializer x)))
+                              key-seq)]
          (.directKryoMultiGet service domain-name key-seq))
        (catch TException e
          (log/error e "Thrift exception on " error-suffix)) ;; try next host
@@ -94,14 +97,11 @@
                                             suffix
                                             key-seq)
                       (with-kv-connection hostname port remote-service
-                        (let [^Domain dom (db/domain-get database domain-name)
-                              serializer  (.serializer dom)
-                              key-seq     (map #(.serialize serializer %) key-seq)]
-                          (try-kryo-multi-get remote-service
-                                              database
-                                              domain-name
-                                              suffix
-                                              key-seq))))]
+                        (try-kryo-multi-get remote-service
+                                            database
+                                            domain-name
+                                            suffix
+                                            key-seq)))]
       (map (fn [m v] (assoc m :value v))
            indexed-keys
            vals))))
@@ -180,11 +180,16 @@
       (thrift/assert-domain database domain-name)
       (try (let [^Domain dom (db/domain-get database domain-name)
                  serializer (.serializer dom)
-                 key-seq    (map #(.deserialize serializer %) keys)]
+                 key-seq    (map (fn [^ByteBuffer x]
+                                   (let [ret (byte-array (.remaining x))]
+                                     (.get x ret)
+                                     (.deserialize serializer ret)))
+                                 keys)]
              (if-let [val-seq (direct-multiget database domain-name key-seq)]
                (doall (map thrift/mk-value val-seq))
                (throw (thrift/domain-not-loaded-ex))))
-           (catch RuntimeException _
+           (catch RuntimeException e
+             (log/error e "Thrown by directKryoMultiGet.")
              (throw (thrift/wrong-host-ex)))))

     (directMultiGet [_ domain-name keys]
@@ -201,8 +206,7 @@
         (multi-get get-fn
                    database
                    domain-name
-                   (map (fn [^ByteBuffer x]
-                          (.array x))
+                   (map (fn [^ByteBuffer x] (.array x))
                         key-seq))))

     (multiGetInt [this domain-name key-seq]


Decouple out/err printing from command cycle

--- src/clj/reply/eval_modes/nrepl.clj
+++ src/clj/reply/eval_modes/nrepl.clj
@@ -42,8 +42,6 @@
                 {:op "stdin" :stdin (str input-result "\n")
                  :id (nrepl.misc/uuid)})))
           (when value ((:value options print) value))
-          (when out ((:out options print) out))
-          (when err ((:err options print) err))
           (flush)
           (when (and ns (not (:session options)))
             (reset! current-ns ns)))))
@@ -124,7 +122,14 @@
                         ns)))
           options (if (:color options)
                     (merge options nrepl.cmdline/colored-output)
-                    options)]
+                    options)
+          session-sender (nrepl/client-session client :session session)
+          responses (session-sender {:op :eval :code ""})]
+      (future
+        (doseq [{:keys [out err] :as resp} responses]
+          (when err (print err))
+          (when out (print out))
+          (flush)))
       (execute-with-client
                client
                options


S E V E N

S E V E N

--- src/clj/think/image/image_impl.clj
+++ src/clj/think/image/image_impl.clj
@@ -1,4 +1,4 @@
-7(ns think.image.image-impl
+(ns think.image.image-impl
   (:require [think.image.protocols :as ip]
             [mikera.image.core :as imagez]
             [think.image.pixel :as pixel]


add borders to svg

add borders to svg

--- src/cljs/ceres_analytics/core.cljs
+++ src/cljs/ceres_analytics/core.cljs
@@ -47,6 +47,21 @@
       remove))

+(defn draw-border
+  "Draw dark borders around visible field"
+  [state]
+  (let [{:keys [svg width height]} @state]
+    (.. svg
+        (append "rect")
+        (attr {:x 0
+               :y 0
+               :width width
+               :height height})
+        (style {:stroke "#000000"
+                :fill "none"
+                :stroke-width 5}))))
+
+
 (defn update-graph
   "Updates nodes and links in graph"
   [state]
@@ -57,6 +72,7 @@
         node (.. svg
                  (selectAll "g.node")
                  (data (:nodes data)))]
+    (draw-border state)
     (.. link enter (append "line")
         (attr {:class "link"})
         (style {:stroke-width 1 :stroke "#aaa"}))
@@ -162,8 +178,8 @@
   (init-graph state)
   (go
     (let [{:keys [ws-channel error]} (<! (ws-ch "ws://localhost:8091/data/ws"))
-          broadcaster (rand-nth (keys broadcasters))
-          random-day (rand-int 31)]
+          broadcaster 2834511 #_(rand-nth (keys broadcasters))
+          random-day 24 #_(rand-int 31)]
       (swap! state assoc-in [:ws-channel] ws-channel)
       (swap! state assoc-in [:day] random-day)
       (>! ws-channel {:topic :user-tree :data {:broadcaster broadcaster :day random-day}})


recreate index option

recreate index option

--- src/clojure/zensols/dataset/db.clj
+++ src/clojure/zensols/dataset/db.clj
@@ -422,9 +422,9 @@
   ([id instance class-label]
    (put-instance id instance class-label nil))
   ([id instance class-label set-type]
-   (log/infof "loading instance (%s): %s => <%s>"
+   (log/debugf "loading instance (%s): %s => <%s>"
                id class-label (zs/trunc instance))
-   (log/debugf "instance: %s" instance)
+   (log/tracef "instance: %s" instance)
    (use-connection
      (with-context [instance-context]
        (let [doc (merge {class-label-key class-label instance-key instance}
@@ -437,10 +437,12 @@

 (defn instances-load
   "Parse and load the dataset in the DB."
-  []
-  (use-connection
-    (with-context [instance-context]
-      (es/recreate-index)
+  [& {:keys [recreate-index]
+      :or {recreate-index true}}]
+  (use-connection
+    (with-context [instance-context]
+      (if recreate-index
+        (es/recreate-index))
       ;; Elasticsearch queues inserts so avoid the user having to invoke
       ;; `divide-by-preset` since all records might not clear by the time
       ;; they're indexed and added to the stats index


Updated code to use the common oracle lib function to check oracle health.

--- src/cmr/ingest/services/ingest.clj
+++ src/cmr/ingest/services/ingest.clj
@@ -1,6 +1,7 @@
 (ns cmr.ingest.services.ingest
   (:require [clj-time.core :as t]
             [cmr.common.time-keeper :as tk]
+            [cmr.oracle.connection :as conn]
             [cmr.transmit.metadata-db :as mdb]
             [cmr.transmit.echo.rest :as rest]
             [cmr.ingest.data.indexer :as indexer]
@@ -72,20 +73,10 @@
     (indexer/delete-concept-from-index context concept-id revision-id)
     {:concept-id concept-id, :revision-id revision-id}))

-(deftracefn get-db-health
-  "Get the health status of db, we do this by getting provider acl hashes out of db."
-  [context]
-  (try
-    (pah/get-provider-id-acl-hashes context)
-    {:ok? true}
-    (catch Exception e
-      {:ok? false
-       :problem (.getMessage e)})))
-
 (deftracefn health
   "Returns the health state of the app."
   [context]
-  (let [db-health (get-db-health context)
+  (let [db-health (conn/health (pah/context->db context))
         echo-rest-health (rest/health context)
         metadata-db-health (mdb/get-metadata-db-health context)
         indexer-health (indexer/get-indexer-health context)


CMR-1227: Added test for handling extra whitespace in science keywords

--- system-int-test/test/cmr/system_int_test/search/collection_facets_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/collection_facets_search_test.clj
@@ -965,3 +965,126 @@
                                     (filter #(= "archive_centers" (:field %))))]
     (is (= expected-archive-centers actual-archive-centers))))

+(deftest leading-and-trailing-whitespace-facets-test
+  (grant-permissions)
+  (let [sk1-leading-ws (dc/science-keyword {:category "  Cat1"
+                                            :topic " Topic1"
+                                            :term " Term1"
+                                            :variable-level-1 "   Level1-1"
+                                            :variable-level-2 " Level1-2"
+                                            :variable-level-3 " Level1-3"
+                                            :detailed-variable " Detail1"})
+
+        sk1-trailing-ws (dc/science-keyword {:category "Cat1   "
+                                             :topic "Topic1 "
+                                             :term "Term1 "
+                                             :variable-level-1 "Level1-1     "
+                                             :variable-level-2 "Level1-2 "
+                                             :variable-level-3 "Level1-3 "
+                                             :detailed-variable "Detail1 "})
+
+        sk1-leading-and-trailing-ws (dc/science-keyword {:category "    Cat1 "
+                                                         :topic " Topic1 "
+                                                         :term " Term1 "
+                                                         :variable-level-1 " Level1-1 "
+                                                         :variable-level-2 " Level1-2 "
+                                                         :variable-level-3 " Level1-3    "
+                                                         :detailed-variable "  Detail1 "})
+
+        coll1 (make-coll 1 "PROV1"
+                         (projects "proj1" "PROJ2")
+                         (platforms "A" 2 2 1)
+                         (twod-coords "Alpha")
+                         (science-keywords sk1 sk4 sk5)
+                         (processing-level-id "PL1")
+                         {:organizations [(dc/org :archive-center "Larc")
+                                          (dc/org :processing-center "Larc")]})
+        coll2 (make-coll 2 "PROV2"
+                         (projects "proj3" "PROJ2")
+                         (platforms "B" 2 2 1)
+                         (science-keywords sk1 sk2 sk3)
+                         (processing-level-id "pl1")
+                         {:organizations [(dc/org :archive-center "GSFC")
+                                          (dc/org :processing-center "Proc")]})
+        coll3 (make-coll 3 "PROV2"
+                         (science-keywords sk1-leading-ws))
+
+        coll4 (make-coll 4 "PROV2"
+                         (science-keywords sk1-trailing-ws))
+
+        coll5 (make-coll 5 "PROV2"
+                         (science-keywords sk1-leading-and-trailing-ws))]
+
+    (index/wait-until-indexed)
+
+    (testing "retreving all facets in refs formats"
+      (let [expected-facets [{:field "data_center",
+                              :value-counts [["GSFC" 1] ["Larc" 1] ["Proc" 1]]}
+                             {:field "archive_center",
+                              :value-counts [["GSFC" 1] ["Larc" 1]]}
+                             {:field "project",
+                              :value-counts [["PROJ2" 2] ["proj1" 1] ["proj3" 1]]}
+                             {:field "platform",
+                              :value-counts
+                              [["A-p0" 1] ["A-p1" 1] ["B-p0" 1] ["B-p1" 1]]}
+                             {:field "instrument",
+                              :value-counts
+                              [["A-p0-i0" 1]
+                               ["A-p0-i1" 1]
+                               ["A-p1-i0" 1]
+                               ["A-p1-i1" 1]
+                               ["B-p0-i0" 1]
+                               ["B-p0-i1" 1]
+                               ["B-p1-i0" 1]
+                               ["B-p1-i1" 1]]}
+                             {:field "sensor",
+                              :value-counts
+                              [["A-p0-i0-s0" 1]
+                               ["A-p0-i1-s0" 1]
+                               ["A-p1-i0-s0" 1]
+                               ["A-p1-i1-s0" 1]
+                               ["B-p0-i0-s0" 1]
+                               ["B-p0-i1-s0" 1]
+                               ["B-p1-i0-s0" 1]
+                               ["B-p1-i1-s0" 1]]}
+                             {:field "two_d_coordinate_system_name",
+                              :value-counts [["Alpha" 1]]}
+                             {:field "processing_level_id",
+                              :value-counts [["PL1" 1] ["pl1" 1]]}
+                             {:field "category",
+                              :value-counts
+                              [["CAT1" 4]
+                               ["HURRICANE" 2]
+                               ["TORNADO" 1]]}
+                             {:field "topic",
+                              :value-counts
+                              [["POPULAR" 2]
+                               ["TOPIC1" 4]
+                               ["COOL" 1]]}
+                             {:field "term",
+                              :value-counts
+                              [["EXTREME" 2]
+                               ["TERM1" 4]
+                               ["TERM4" 1]
+                               ["UNIVERSAL" 1]]}
+                             {:field "variable_level_1",
+                              :value-counts
+                              [["LEVEL1-1" 4]
+                               ["LEVEL2-1" 1]
+                               ["UNIVERSAL" 1]]}
+                             {:field "variable_level_2",
+                              :value-counts
+                              [["LEVEL1-2" 4]
+                               ["LEVEL2-2" 1]]}
+                             {:field "variable_level_3",
+                              :value-counts
+                              [["LEVEL1-3" 4]
+                               ["LEVEL2-3" 1]]}
+                             {:field "detailed_variable",
+                              :value-counts
+                              [["DETAIL1" 4]
+                               ["UNIVERSAL" 1]]}]]
+
+        (is (= expected-facets
+               (:facets (search/find-refs :collection {:include-facets true}))))))))
+


Canonicalize both paths. (for #73)

Canonicalize both paths. (for #73)

--- sidecar/src/figwheel_sidecar/config.clj
+++ sidecar/src/figwheel_sidecar/config.clj
@@ -17,7 +17,7 @@
 (defn relativize-resource-paths
   "Relativize to the local root just in case we have an absolute path"
   [resource-paths]
-  (mapv #(string/replace-first (norm-path %)
+  (mapv #(string/replace-first (norm-path (.getCanonicalPath (io/file %)))
                                (str (norm-path (.getCanonicalPath (io/file ".")))
                                     "/") "") resource-paths))


delete upload when cancelled

delete upload when cancelled

--- src/frontend/server-interface.cljs
+++ src/frontend/server-interface.cljs
@@ -138,13 +138,18 @@
   (fn [socket-id]
     (println "Received umute-user signal for" socket-id)
     (swap! app-state/app-state assoc :users (merge (:users @app-state/app-state)
-                                         {socket-id (merge (get (:users @app-state/app-state) socket-id)
-                                                                {"muted" false})}))))
+                                                   {socket-id (merge (get (:users @app-state/app-state) socket-id)
+                                                                     {"muted" false})}))))

 (.on app-state/socket "upload-cancelled"
   (fn [id]
-    (swap! app-state/app-state assoc :current-uploads-info
-      (dissoc (:current-uploads-info @app-state/app-state) id))))
+    (let [current-uploads-info (:current-uploads-info @app-state/app-state)
+          uploads (:uploads @app-state/app-state)
+          client-id (.-clientid (get current-uploads-info id))]
+    (swap! app-state/app-state
+           merge
+           {:current-uploads-info (dissoc current-uploads-info id)
+            :uploads (dissoc uploads client-id)}))))

 (.on app-state/socket "track-order-change"
   (fn [track-order]


Add some type hints to suppress reflection warnings

--- src/main/clojure/cascade/asset.clj
+++ src/main/clojure/cascade/asset.clj
@@ -16,6 +16,7 @@
   #^{:doc "Asset management"}
   cascade.asset
   (:import
+    (java.io InputStream OutputStream)
     (java.net URL URLConnection)
     (javax.servlet ServletContext)
     (javax.servlet.http HttpServletRequest HttpServletResponse))
@@ -139,11 +140,11 @@
         ; TODO: Should we just ignore bad requests, let the container send a 404?
         _ (fail-if (nil? application-version) "Invalid %s asset URL." domain-name)
         _ (fail-unless (= application-version (read-config :application-version)) "Incorrect application version.")
-        asset-url (url-provider asset-path)
+        #^URL asset-url (url-provider asset-path)
         _ (fail-if (nil? asset-url) "Could not locate %s asset %s." domain-name asset-path)
         mime-type (get-mime-type asset-path)]
-    (with-open [output-stream (open-output-stream-for-asset response asset-url mime-type)]
-      (with-open [input-stream (.openStream asset-url)]
+    (with-open [#^OutputStream output-stream (open-output-stream-for-asset response asset-url mime-type)]
+      (with-open [#^InputStream input-stream (.openStream asset-url)]
         (copy input-stream output-stream)
         (.flush output-stream))))
   ; If we got this far, we copied the contents (or failed, throwing an exception)


Format controller.matrices data logging, using datetime.

This is rudimentary logging; a better logging treatment is intended.

--- src/mtrx9/controllers/matrices.clj
+++ src/mtrx9/controllers/matrices.clj
@@ -4,6 +4,7 @@
         [aleph.http :only (wrap-aleph-handler)]
         [aleph.formats :only (encode-json->string)])
   (:require [ring.util.response :as ring]
+            [clj-time.core :as time]
             [mtrx9.views.matrices :as view]))

 (def id-chars  "0123456789SLATF-")
@@ -25,7 +26,7 @@
   (ring/redirect (str "/matrices/" (rand-matrix-id))))

 (defn update [id streams]
-  (println "U:" id streams)
+  (println (str "[" (str (time/now)) "] " id  " <- " streams))
   (enqueue (named-channel id nil) (encode-json->string {:streams streams}))
   {:status 204})


moving limbo to be subscriber-specific

moving limbo to be subscriber-specific

--- libs/axiom-cljs/src/axiom_cljs/core.cljs
+++ libs/axiom-cljs/src/axiom_cljs/core.cljs
@@ -72,22 +72,29 @@
 (defn wrap-feed-forward [host]
   (let [{:keys [pub sub]} host
         ps (pubsub :name)
-        limbo (atom #{})
         project #(dissoc % :readers)]
     (-> host
         (assoc :pub (fn [ev]
                       ((:pub ps) ev)
-                      (pub ev)
-                      (swap! limbo conj (project ev))))
+                      (pub ev)))
         (assoc :sub (fn [disp f]
-                      ((:sub ps) disp f)
-                      (let [f (fn [ev]
-                                (let [pev (project ev)]
-                                  (cond (contains? @limbo pev)
-                                        (swap! limbo disj pev)
-                                        :else
-                                        (f ev))))]
-                        (sub disp f)))))))
+                      ;; Limbo stores events that were feed-forwarded internally
+                      ;; but were not yet received from the server.
+                      ;; It is local to a subscriber
+                      (let [limbo (atom #{})]
+                        ;; Called upon publication by the client
+                        (let [f' (fn [ev]
+                                   (swap! limbo conj (project ev))
+                                   (f ev))]
+                          ((:sub ps) disp f'))
+                        ;; Called upon receiving event from the server
+                        (let [f' (fn [ev]
+                                  (let [pev (project ev)]
+                                    (cond (contains? @limbo pev)
+                                          (swap! limbo disj pev)
+                                          :else
+                                          (f ev))))]
+                          (sub disp f'))))))))

 (defn wrap-atomic-updates [host]
   (let [sub (:sub host)]


[Add] test make-double-jarray

[Add] test make-double-jarray

--- test/clj_elm/core_test.clj
+++ test/clj_elm/core_test.clj
@@ -75,7 +75,12 @@
         [0.5 0.5 0.5]]))

 (facts "test-make-double-jarray"
-  (fact "(make-double-jarray array2h)"))
+  (fact "(make-double-jarray array2h)"
+    (let [m (make-double-jarray [[1.0 2.0 3.0] [4.0 5.0 6.0] [7.0 8.0 9.0]])]
+      (for [x [0 1 2]
+            y [0 1 2]]
+        (.get m x y))
+      => [1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0])))

 (defn roundn [^Double x ^Integer n]
   (-> (BigDecimal. x)


More on atoms.

More on atoms.

--- test/com/nomistech/clojure_the_language/intro_to_state.clj
+++ test/com/nomistech/clojure_the_language/intro_to_state.clj
@@ -87,18 +87,22 @@
 ;;;; Illustration of multiple threads competing to update an atom.
 ;;;;
 ;;;; - Each thread uses `swap!` with a function that runs for a long time.
+;;;;   (I'm calling the function a "swap function".)
 ;;;;
 ;;;; - Clojure allows each thread to be optimistic.
-;;;;   - So multiple swap operations run concurrently.
+;;;;   - So multiple swap functions run concurrently.
 ;;;;
-;;;; - When a swap operation finishes:
+;;;; - When a swap function finishes:
 ;;;;   - If the current value of the atom is the same as the value when the
-;;;;     operation started
+;;;;     function started
 ;;;;     then
 ;;;;         the new value is swapped in
 ;;;;     else
-;;;;         the swap operation is retried
-;;;;         (using the current value as input to the swap operation).
+;;;;         the swap function is retried
+;;;;         (using the current value as input to the swap function).
+;;;;
+;;;; - An agent (another kind or reference) is used to keep track of how
+;;;;   many times the swap function is called.

 (def atom-to-demo-competing-updates (atom 0))


Rework query tests to use a live DB. Fixes #35.

--- test/datomish/test/query.cljc
+++ test/datomish/test/query.cljc
@@ -1,19 +1,32 @@
 (ns datomish.test.query
+  #?(:cljs
+     (:require-macros
+      [datomish.pair-chan :refer [go-pair <?]]
+      [datomish.node-tempfile-macros :refer [with-tempfile]]
+      [cljs.core.async.macros :as a :refer [go]]))
   (:require
+     [datomish.query.cc :as cc]
      [datomish.query.context :as context]
      [datomish.query.source :as source]
      [datomish.query.transforms :as transforms]
      [datomish.query :as query]
+     [datomish.db :as db]
      [datomish.schema :as schema]
+     [datomish.transact :as transact]
+     [datomish.api :as d]
      #?@(:clj
-           [
-          [honeysql.core :as sql :refer [param]]
-          [clojure.test :as t :refer [is are deftest testing]]])
+           [[datomish.pair-chan :refer [go-pair <?]]
+            [datomish.jdbc-sqlite]
+            [datomish.test-macros :refer [deftest-db]]
+            [honeysql.core :as sql :refer [param]]
+            [tempfile.core :refer [tempfile with-tempfile]]
+            [clojure.test :as t :refer [is are deftest testing]]])
      #?@(:cljs
-           [
-          [honeysql.core :as sql :refer-macros [param]]
-          [cljs.test :as t :refer-macros [is are deftest testing]]])
-     )
+           [[datomish.promise-sqlite]
+            [datomish.test-macros :refer-macros [deftest-db]]
+            [honeysql.core :as sql :refer-macros [param]]
+            [datomish.node-tempfile :refer [tempfile]]
+            [cljs.test :as t :refer-macros [is are deftest testing]]]))
   #?(:clj
        (:import [clojure.lang ExceptionInfo])))

@@ -29,305 +42,404 @@
        (fgensym s (dec (swap! counter inc)))))))

 (def simple-schema
-  {:db/txInstant {:db/ident :db/txInstant
-                  :db/valueType :long
-                  :db/cardinality :db.cardinality/one}
-   :foo/int {:db/ident :foo/int
-             :db/valueType :db.type/integer
-             :db/cardinality :db.cardinality/one}
-   :foo/str {:db/ident :foo/str
-             :db/valueType :db.type/string
-             :db/cardinality :db.cardinality/many}})
-
-(defn mock-source [db schema]
-  (source/map->DatomsSource
-    {:table :datoms
-     :fulltext-table :fulltext_values
-     :fulltext-view :all_datoms
-     :columns [:e :a :v :tx :added]
-     :attribute-transform transforms/attribute-transform-string
-     :constant-transform transforms/constant-transform-default
-     :table-alias (comp (make-predictable-gensym) name)
-     :schema (schema/map->Schema
-               {:schema schema
-                :rschema nil})
-     :make-constraints nil}))
-
-(defn- expand [find schema]
-  (let [context (context/->Context (mock-source nil schema) nil nil)
+  [{:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :db/txInstant
+    :db/valueType :db.type/long
+    :db/cardinality :db.cardinality/one}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :foo/bar
+    :db/valueType :db.type/string
+    :db/cardinality :db.cardinality/many}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :foo/int
+    :db/valueType :db.type/long
+    :db/cardinality :db.cardinality/one}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :foo/str
+    :db/valueType :db.type/string
+    :db/cardinality :db.cardinality/many}])
+
+(def page-schema
+  [{:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :page/loves
+    :db/valueType :db.type/ref
+    :db/cardinality :db.cardinality/many}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :page/likes
+    :db/valueType :db.type/ref
+    :db/cardinality :db.cardinality/many}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :page/url
+    :db/valueType :db.type/string
+    :db/unique :db.unique/identity
+    :db/cardinality :db.cardinality/one}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :page/title
+    :db/valueType :db.type/string
+    :db/cardinality :db.cardinality/one}
+   {:db/id (d/id-literal :db.part/user)
+    :db.install/_attribute :db.part/db
+    :db/ident :page/starred
+    :db/valueType :db.type/boolean
+    :db/cardinality :db.cardinality/one}])
+
+(def schema-with-page
+  (concat
+    simple-schema
+    page-schema))
+
+(defn mock-source [db]
+  (assoc (datomish.db/datoms-source db)
+         :table-alias (comp (make-predictable-gensym) name)))
+
+(defn conn->context [conn]
+  (context/->Context (mock-source (d/db conn)) nil nil))
+
+(defn- expand [find conn]
+  (let [context (conn->context conn)
         parsed (query/parse find)]
     (query/find->sql-clause context parsed)))

-(defn- populate [find schema]
-  (let [context (context/->Context (mock-source nil schema) nil nil)
+(defn- populate [find conn]
+  (let [context (conn->context conn)
         parsed (query/parse find)]
     (query/find-into-context context parsed)))

-(deftest test-type-extraction
+(defn <initialize-with-schema [conn schema]
+  (go-pair
+    (let [tx (<? (d/<transact! conn schema))]
+      (let [idents (map :db/ident schema)
+            db (d/db conn)]
+        (into {}
+          (map (fn [ident]
+                 [ident (d/entid db ident)])
+               idents))))))
+
+(deftest-db test-type-extraction conn
+  ;; We expect to be able to look up the default types.
+  (is (integer? (d/entid (d/db conn) :db.type/ref)))
+  (is (integer? (d/entid (d/db conn) :db.type/long)))
+
+  ;; Add our own schema.
+  (<? (<initialize-with-schema conn simple-schema))
   (testing "Variable entity."
-    (is (= (:known-types (:cc (populate '[:find ?e ?v :in $ :where [?e :foo/int ?v]] simple-schema)))
-           {'?v :db.type/integer
+    (is (= (->
+             (populate '[:find ?e ?v :in $ :where [?e :foo/int ?v]] conn)
+             :cc :known-types)
+           {'?v :db.type/long
             '?e :db.type/ref})))
+
   (testing "Numeric entid."
-    (is (= (:known-types (:cc (populate '[:find ?v :in $ :where [6 :foo/int ?v]] simple-schema)))
-           {'?v :db.type/integer})))
+    (is (= (->
+             (populate '[:find ?v :in $ :where [6 :foo/int ?v]] conn)
+             :cc :known-types)
+           {'?v :db.type/long})))
+
   (testing "Keyword entity."
-    (is (= (:known-types (:cc (populate '[:find ?v :in $ :where [:my/thing :foo/int ?v]] simple-schema)))
-           {'?v :db.type/integer}))))
-
-(deftest test-value-constant-constraint-descends-into-not-and-or
-  (testing "Elision of types inside a join."
-    (is (= '{:select ([:datoms0.e :e]
-                      [:datoms0.v :v]),
-             :modifiers [:distinct],
-             :from [[:datoms datoms0]],
-             :where (:and
-                       [:= :datoms0.a "foo/int"]
-                       [:not
-                        [:exists
-                         {:select [1],
-                          :from [[:all_datoms all_datoms1]],
-                          :where (:and
-                                    [:= :all_datoms1.e 15]
-                                    [:= :datoms0.v :all_datoms1.v])}]])}
-           (expand
-             '[:find ?e ?v :in $ :where
-               [?e :foo/int ?v]
-               (not [15 ?a ?v])]
-             simple-schema))))
-
-  (testing "Type collisions inside :not."
-    (is (thrown-with-msg?
-          ExceptionInfo #"\?v already has type :db\.type\/integer"
-          (expand
-            '[:find ?e ?v :in $ :where
-              [?e :foo/int ?v]
-              (not [15 :foo/str ?v])]
-            simple-schema))))
-  (testing "Type collisions inside :or"
-    (is (thrown-with-msg?
-          ExceptionInfo #"\?v already has type :db\.type\/integer"
-          (expand
-            '[:find ?e ?v :in $ :where
-              [?e :foo/int ?v]
-              (or
-                [15 :foo/str ?v]
-                [10 :foo/int ?v])]
-            simple-schema)))))
-
-(deftest test-type-collision
+    (is (= (->
+             (populate '[:find ?v :in $ :where [:my/thing :foo/int ?v]] conn)
+             :cc :known-types)
+           {'?v :db.type/long}))))
+
+(deftest-db test-value-constant-constraint-descends-into-not-and-or conn
+  (let [attrs (<? (<initialize-with-schema conn simple-schema))]
+    (testing "Elision of types inside a join."
+      (is (= {:select '([:datoms0.e :e]
+                        [:datoms0.v :v]),
+               :modifiers [:distinct],
+               :from [[:datoms 'datoms0]],
+               :where (list :and
+                         [:= :datoms0.a (:foo/int attrs)]
+                         [:not
+                          [:exists
+                           {:select [1],
+                            :from [[:all_datoms 'all_datoms1]],
+                            :where (list :and
+                                      [:= :all_datoms1.e 15]
+                                      [:= :datoms0.v :all_datoms1.v])}]])}
+             (expand
+               '[:find ?e ?v :in $ :where
+                 [?e :foo/int ?v]
+                 (not [15 ?a ?v])]
+               conn))))
+
+    (testing "Type collisions inside :not."
+      (is (thrown-with-msg?
+            ExceptionInfo #"v already has type :db.type.long"
+            (expand
+              '[:find ?e ?v :in $ :where
+                [?e :foo/int ?v]
+                (not [15 :foo/str ?v])]
+              conn))))
+
+    (testing "Type collisions inside :or"
+      (is (thrown-with-msg?
+            ExceptionInfo #"v already has type :db.type.long"
+            (expand
+              '[:find ?e ?v :in $ :where
+                [?e :foo/int ?v]
+                (or
+                  [15 :foo/str ?v]
+                  [10 :foo/int ?v])]
+              conn))))))
+
+(deftest-db test-type-collision conn
+  (<? (<initialize-with-schema conn simple-schema))
   (let [find '[:find ?e ?v :in $
                :where
                [?e :foo/int ?v]
                [?x :foo/str ?v]]]
      (is (thrown-with-msg?
-           ExceptionInfo #"\?v already has type :db\.type\/integer"
-           (populate find simple-schema)))))
-
-(deftest test-value-constant-constraint
+           ExceptionInfo #"v already has type :db.type.long"
+           (populate find conn)))))
+
+(deftest-db test-value-constant-constraint conn
+  (<? (<initialize-with-schema conn simple-schema))
   (is (= {:select '([:all_datoms0.e :foo]),
           :modifiers [:distinct],
           :from '[[:all_datoms all_datoms0]],
           :where (list :and
                        (list :or
                              [:= :all_datoms0.value_type_tag 0]
+                             ;; In CLJS, this can also be an `instant`.
+                             #?@(:cljs [[:= :all_datoms0.value_type_tag 4]])
                              [:= :all_datoms0.value_type_tag 5])
                        [:= :all_datoms0.v 99])}
          (expand
            '[:find ?foo :in $ :where
              [?foo _ 99]]
-           simple-schema))))
-
-(deftest test-value-constant-constraint-elided-using-schema
-  (testing "There's no need to produce value_type_tag constraints when the attribute is specified."
-    (is
-      (= '{:select ([:datoms1.v :timestampMicros] [:datoms0.e :page]),
-           :modifiers [:distinct],
-           :from [[:datoms datoms0]
-                  [:datoms datoms1]],
-           :where (:and
-                     ;; We don't need a type check on the range of page/starred...
-                     [:= :datoms0.a "page/starred"]
+           conn))))
+
+(deftest-db test-value-constant-constraint-elided-using-schema conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (testing "Our attributes were interned."
+      (is (integer? (d/entid (d/db conn) :foo/str)))
+      (is (integer? (d/entid (d/db conn) :page/starred))))
+
+    (testing "There's no need to produce value_type_tag constraints when the attribute is specified."
+      (is
+        (= {:select '([:datoms1.v :timestampMicros] [:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from [[:datoms 'datoms0]
+                   [:datoms 'datoms1]],
+            :where (list :and
+                       ;; We don't need a type check on the range of page/starred...
+                       [:= :datoms0.a (:page/starred attrs)]
+                       [:= :datoms0.v 1]
+                       [:= :datoms1.a (:db/txInstant attrs)]
+                       [:not
+                        [:exists
+                         {:select [1],
+                          :from [[:datoms 'datoms2]],
+                          :where (list :and
+                                    [:= :datoms2.a (:foo/bar attrs)]
+                                    [:= :datoms0.e :datoms2.e])}]]
+                       [:= :datoms0.tx :datoms1.e])}
+           (expand
+             '[:find ?timestampMicros ?page :in $ ?latest :where
+               [?page :page/starred true ?t]
+               [?t :db/txInstant ?timestampMicros]
+               (not [?page :foo/bar _])]
+
+             conn))))))
+
+(deftest-db test-basic-join conn
+  ;; Note that we use a schema without :page/starred, so we
+  ;; don't know what type it is.
+  (let [attrs (<? (<initialize-with-schema conn simple-schema))]
+    (is (= {:select '([:datoms1.v :timestampMicros] [:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from '([:datoms datoms0]
+                    [:datoms datoms1]),
+            :where (list
+                     :and
+                     ;; Note that :page/starred is literal, because
+                     ;; it's not present in the interned schema.
+                     [:= :datoms0.a :page/starred]
+                     [:= :datoms0.value_type_tag 1]   ; boolean
                      [:= :datoms0.v 1]
-                     [:= :datoms1.a "db/txInstant"]
+                     [:= :datoms1.a (:db/txInstant attrs)]
+                     [:not
+                      (list :and (list :> :datoms0.tx (sql/param :latest)))]
+                     [:= :datoms0.tx :datoms1.e])}
+           (expand
+             '[:find ?timestampMicros ?page :in $ ?latest :where
+               [?page :page/starred true ?t]
+               [?t :db/txInstant ?timestampMicros]
+               (not [(> ?t ?latest)])]
+             conn)))))
+
+(deftest-db test-pattern-not-join conn
+  (let [attrs (<? (<initialize-with-schema conn simple-schema))]
+    (is (= {:select '([:datoms1.v :timestampMicros] [:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from [[:datoms 'datoms0]
+                   [:datoms 'datoms1]],
+            :where (list
+                     :and
+                     ;; Note that :page/starred is literal, because
+                     ;; it's not present in the interned schema.
+                     [:= :datoms0.a :page/starred]
+                     [:= :datoms0.value_type_tag 1]   ; boolean
+                     [:= :datoms0.v 1]
+                     [:= :datoms1.a (:db/txInstant attrs)]
                      [:not
                       [:exists
                        {:select [1],
-                        :from [[:datoms datoms2]],
-                        :where (:and
-                                  [:= :datoms2.a "foo/bar"]
+                        :from [[:datoms 'datoms2]],
+                        :where (list :and
+                                  [:= :datoms2.a (:foo/bar attrs)]
                                   [:= :datoms0.e :datoms2.e])}]]
                      [:= :datoms0.tx :datoms1.e])}
-         (expand
-           '[:find ?timestampMicros ?page :in $ ?latest :where
-             [?page :page/starred true ?t]
-             [?t :db/txInstant ?timestampMicros]
-             (not [?page :foo/bar _])]
-
-           (merge
-             simple-schema
-             {:page/starred {:db/valueType :db.type/boolean
-                             :db/ident :page/starred
-                             :db/cardinality :db.cardinality/one}}))))))
-
-(deftest test-basic-join
-  (is (= {:select '([:datoms1.v :timestampMicros] [:datoms0.e :page]),
-          :modifiers [:distinct],
-          :from '[[:datoms datoms0]
-                  [:datoms datoms1]],
-          :where (list
-                   :and
-                   [:= :datoms0.a "page/starred"]
-                   [:= :datoms0.value_type_tag 1]   ; boolean
-                   [:= :datoms0.v 1]
-                   [:= :datoms1.a "db/txInstant"]
-                   [:not
-                    (list :and (list :> :datoms0.tx (sql/param :latest)))]
-                   [:= :datoms0.tx :datoms1.e])}
-         (expand
-           '[:find ?timestampMicros ?page :in $ ?latest :where
-             [?page :page/starred true ?t]
-             [?t :db/txInstant ?timestampMicros]
-             (not [(> ?t ?latest)])]
-           simple-schema))))
-
-(deftest test-pattern-not-join
-  (is (= '{:select ([:datoms1.v :timestampMicros] [:datoms0.e :page]),
-           :modifiers [:distinct],
-           :from [[:datoms datoms0]
-                  [:datoms datoms1]],
-           :where (:and
-                     [:= :datoms0.a "page/starred"]
-                     [:= :datoms0.value_type_tag 1]   ; boolean
-                     [:= :datoms0.v 1]
-                     [:= :datoms1.a "db/txInstant"]
-                     [:not
-                      [:exists
-                       {:select [1],
-                        :from [[:datoms datoms2]],
-                        :where (:and
-                                  [:= :datoms2.a "foo/bar"]
-                                  [:= :datoms0.e :datoms2.e])}]]
-                     [:= :datoms0.tx :datoms1.e])}
-         (expand
-           '[:find ?timestampMicros ?page :in $ ?latest :where
-             [?page :page/starred true ?t]
-             [?t :db/txInstant ?timestampMicros]
-             (not [?page :foo/bar _])]
-           simple-schema))))
+           (expand
+             '[:find ?timestampMicros ?page :in $ ?latest :where
+               [?page :page/starred true ?t]
+               [?t :db/txInstant ?timestampMicros]
+               (not [?page :foo/bar _])]
+             conn)))))

 ;; Note that clause ordering is not directly correlated to the output: cross-bindings end up
 ;; at the front. The SQL engine will do its own analysis. See `clauses/expand-where-from-bindings`.
-(deftest test-not-clause-ordering-preserved
-  (is (= {:select '([:datoms1.v :timestampMicros] [:datoms0.e :page]),
-          :modifiers [:distinct],
-          :from '[[:datoms datoms0]
-                  [:datoms datoms1]],
-          :where (list
-                   :and
-                   [:= :datoms0.a "page/starred"]
-                   [:= :datoms0.value_type_tag 1]   ; boolean
-                   [:= :datoms0.v 1]
-                   [:not
-                    (list :and (list :> :datoms0.tx (sql/param :latest)))]
-                   [:= :datoms1.a "db/txInstant"]
-                   [:= :datoms0.tx :datoms1.e]
-                   )}
-         (expand
-           '[:find ?timestampMicros ?page :in $ ?latest :where
-             [?page :page/starred true ?t]
-             (not [(> ?t ?latest)])
-             [?t :db/txInstant ?timestampMicros]]
-           simple-schema))))
-
-(deftest test-pattern-not-join-ordering-preserved
-  (is (= '{:select ([:datoms2.v :timestampMicros] [:datoms0.e :page]),
-           :modifiers [:distinct],
-           :from [[:datoms datoms0]
-                  [:datoms datoms2]],
-           :where (:and
-                     [:= :datoms0.a "page/starred"]
-                     [:= :datoms0.value_type_tag 1]   ; boolean
+(deftest-db test-not-clause-ordering-preserved conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (is (= {:select '([:datoms1.v :timestampMicros] [:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from '[[:datoms datoms0]
+                    [:datoms datoms1]],
+            :where (list
+                     :and
+                     ;; We don't need a value tag constraint -- we know the range of the attribute.
+                     [:= :datoms0.a (:page/starred attrs)]
                      [:= :datoms0.v 1]
                      [:not
-                      [:exists
-                       {:select [1],
-                        :from [[:datoms datoms1]],
-                        :where (:and
-                                  [:= :datoms1.a "foo/bar"]
-                                  [:= :datoms0.e :datoms1.e])}]]
-                     [:= :datoms2.a "db/txInstant"]
-                     [:= :datoms0.tx :datoms2.e]
+                      (list :and (list :> :datoms0.tx (sql/param :latest)))]
+                     [:= :datoms1.a (:db/txInstant attrs)]
+                     [:= :datoms0.tx :datoms1.e]
                      )}
-         (expand
-           '[:find ?timestampMicros ?page :in $ ?latest :where
-             [?page :page/starred true ?t]
-             (not [?page :foo/bar _])
-             [?t :db/txInstant ?timestampMicros]]
-           simple-schema))))
-
-(deftest test-single-or
-  (is (= '{:select ([:datoms0.e :page]),
-           :modifiers [:distinct],
-           :from ([:datoms datoms0] [:datoms datoms1] [:datoms datoms2]),
-           :where (:and
-                     [:= :datoms0.a "page/url"]
-                     [:= :datoms0.value_type_tag 10]
-                     [:= :datoms0.v "http://example.com/"]
-                     [:= :datoms1.a "page/title"]
-                     [:= :datoms2.a "page/loves"]
-                     [:= :datoms0.e :datoms1.e]
-                     [:= :datoms0.e :datoms2.v])}
-         (expand
-           '[:find ?page :in $ ?latest :where
-             [?page :page/url "http://example.com/"]
-             [?page :page/title ?title]
-             (or
-               [?entity :page/loves ?page])]
-           simple-schema))))
-
-(deftest test-simple-or
-  (is (= '{:select ([:datoms0.e :page]),
-           :modifiers [:distinct],
-           :from ([:datoms datoms0] [:datoms datoms1] [:datoms datoms2]),
-           :where (:and
-                     [:= :datoms0.a "page/url"]
-                     [:= :datoms0.value_type_tag 10]
-                     [:= :datoms0.v "http://example.com/"]
-                     [:= :datoms1.a "page/title"]
-                     (:or
-                        [:= :datoms2.a "page/likes"]
-                        [:= :datoms2.a "page/loves"])
-                     [:= :datoms0.e :datoms1.e]
-                     [:= :datoms0.e :datoms2.v])}
-         (expand
-           '[:find ?page :in $ ?latest :where
-             [?page :page/url "http://example.com/"]
-             [?page :page/title ?title]
-             (or
-               [?entity :page/likes ?page]
-               [?entity :page/loves ?page])]
-           simple-schema))))
-
-(deftest test-tag-projection
-  (is (= '{:select ([:datoms0.e :page]
-                    [:datoms1.v :thing]
-                    [:datoms1.value_type_tag :_thing_type_tag]),
-           :modifiers [:distinct],
-           :from ([:datoms datoms0]
-                  [:datoms datoms1]),
-           :where (:and
-                     [:= :datoms0.a "page/url"]
-                     [:= :datoms0.value_type_tag 10]
-                     [:= :datoms0.v "http://example.com/"]
-                     (:or
-                        [:= :datoms1.a "page/likes"]
-                        [:= :datoms1.a "page/loves"])
-                     [:= :datoms0.e :datoms1.e])}
-         (expand
-           '[:find ?page ?thing :in $ ?latest :where
-             [?page :page/url "http://example.com/"]
-             (or
-               [?page :page/likes ?thing]
-               [?page :page/loves ?thing])]
-           simple-schema))))
+           (expand
+             '[:find ?timestampMicros ?page :in $ ?latest :where
+               [?page :page/starred true ?t]
+               (not [(> ?t ?latest)])
+               [?t :db/txInstant ?timestampMicros]]
+             conn)))))
+
+(deftest-db test-pattern-not-join-ordering-preserved conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (is (= {:select '([:datoms2.v :timestampMicros] [:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from [[:datoms 'datoms0]
+                   [:datoms 'datoms2]],
+            :where (list :and
+                     ;; We don't need a value tag constraint -- we know the range of the attribute.
+                      [:= :datoms0.a (:page/starred attrs)]
+                      [:= :datoms0.v 1]
+                      [:not
+                       [:exists
+                        {:select [1],
+                         :from [[:datoms 'datoms1]],
+                         :where (list :and
+                                   [:= :datoms1.a (:foo/bar attrs)]
+                                   [:= :datoms0.e :datoms1.e])}]]
+                      [:= :datoms2.a (:db/txInstant attrs)]
+                      [:= :datoms0.tx :datoms2.e])}
+           (expand
+             '[:find ?timestampMicros ?page :in $ ?latest :where
+               [?page :page/starred true ?t]
+               (not [?page :foo/bar _])
+               [?t :db/txInstant ?timestampMicros]]
+             conn)))))
+
+(deftest-db test-single-or conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (is (= {:select '([:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from '([:datoms datoms0] [:datoms datoms1] [:datoms datoms2]),
+            :where (list :and
+                      [:= :datoms0.a (:page/url attrs)]
+                      [:= :datoms0.v "http://example.com/"]
+                      [:= :datoms1.a (:page/title attrs)]
+                      [:= :datoms2.a (:page/loves attrs)]
+                      [:= :datoms0.e :datoms1.e]
+                      [:= :datoms0.e :datoms2.v])}
+           (expand
+             '[:find ?page :in $ ?latest :where
+               [?page :page/url "http://example.com/"]
+               [?page :page/title ?title]
+               (or
+                 [?entity :page/loves ?page])]
+             conn)))))
+
+(deftest-db test-simple-or conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (is (= {:select '([:datoms0.e :page]),
+            :modifiers [:distinct],
+            :from '([:datoms datoms0] [:datoms datoms1] [:datoms datoms2]),
+            :where (list :and
+                      [:= :datoms0.a (:page/url attrs)]
+                      [:= :datoms0.v "http://example.com/"]
+                      [:= :datoms1.a (:page/title attrs)]
+                      (list :or
+                         [:= :datoms2.a (:page/likes attrs)]
+                         [:= :datoms2.a (:page/loves attrs)])
+                      [:= :datoms0.e :datoms1.e]
+                      [:= :datoms0.e :datoms2.v])}
+           (expand
+             '[:find ?page :in $ ?latest :where
+               [?page :page/url "http://example.com/"]
+               [?page :page/title ?title]
+               (or
+                 [?entity :page/likes ?page]
+                 [?entity :page/loves ?page])]
+             conn)))))
+
+(defn tag-clauses [column input]
+  (let [codes (cc/->tag-codes input)]
+    (if (= 1 (count codes))
+      [:= column (first codes)]
+      (cons :or (map (fn [tag]
+                       [:= column tag])
+                     codes)))))
+
+(deftest-db test-url-tag conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (is (= {:select '([:all_datoms0.e :page]
+                      [:datoms1.v :thing]),
+            :modifiers [:distinct],
+            :from '([:all_datoms all_datoms0]
+                    [:datoms datoms1]),
+            :where (list
+                     :and
+                     (tag-clauses :all_datoms0.value_type_tag "http://example.com/")
+                     [:= :all_datoms0.v "http://example.com/"]
+                     (list
+                       :or
+                       [:= :datoms1.a (:page/likes attrs)]
+                       [:= :datoms1.a (:page/loves attrs)])
+                     [:= :all_datoms0.e :datoms1.e])}
+           (expand
+             '[:find ?page ?thing :in $ ?latest :where
+               [?page _ "http://example.com/"]
+               (or
+                 [?page :page/likes ?thing]
+                 [?page :page/loves ?thing])]
+             conn)))))
+
+(deftest-db test-tag-projection conn
+  (let [attrs (<? (<initialize-with-schema conn schema-with-page))]
+    (is (= {:select '([:all_datoms0.e :page]
+                      [:all_datoms0.v :thing]
+                      [:all_datoms0.value_type_tag :_thing_type_tag]),
+            :modifiers [:distinct],
+            :from '([:all_datoms all_datoms0])}
+           (expand
+             '[:find ?page ?thing :in $ :where
+               [?page _ ?thing]]
+             conn)))))