Always cleanup when delete-server-data is true.

--- src/onyx/state/bookkeeper.clj
+++ src/onyx/state/bookkeeper.clj
@@ -4,71 +4,80 @@
             [onyx.log.zookeeper :as ozk]
             [onyx.static.default-vals :refer [arg-or-default]]
             [taoensso.timbre :refer [error info warn]])
-  (:import java.io.File
-           org.apache.bookkeeper.bookie.Bookie
-           org.apache.bookkeeper.conf.ServerConfiguration
-           org.apache.bookkeeper.proto.BookieServer
-           org.apache.commons.io.FileUtils
+  (:import [java.io File]
+           [org.apache.bookkeeper.bookie Bookie BookieException$InvalidCookieException]
+           [org.apache.bookkeeper.conf ServerConfiguration]
+           [org.apache.bookkeeper.proto BookieServer]
+           [org.apache.commons.io FileUtils]
            [org.apache.zookeeper KeeperException$NodeExistsException]))

 (defn cleanup-dir [dir]
   (FileUtils/deleteDirectory (File. ^String dir)))

+(defn format-bk-server
+  "Delete journal/ledger directories and removes corresponding cookie in Zookeeper"
+  [server-conf zk-conn]
+  (let [journal-dir (str (.getJournalDirName server-conf))
+        ledger-dir (str (first (.getLedgerDirNames server-conf)))
+        cookie-path (format "%s/cookies/%s"
+                            (.getZkLedgersRootPath server-conf)
+                            (Bookie/getBookieAddress server-conf))]
+    (info "Deleting Bookie cookie" cookie-path)
+    (zk/delete zk-conn cookie-path)
+    (info "Deleting Bookie dirs" journal-dir ";" ledger-dir)
+    (cleanup-dir journal-dir)
+    (cleanup-dir ledger-dir)))
+
 (defrecord BookieComponent [env-config port log]
   component/Lifecycle
   (start [component]
-    (let [onyx-id (:onyx/tenancy-id env-config)
-          ledgers-root-path (ozk/ledgers-path onyx-id)
-          ledgers-available-path (ozk/ledgers-available-path onyx-id)
-          _ (zk/create (:conn log) ledgers-root-path :persistent? true)
-          _ (zk/create (:conn log) ledgers-available-path :persistent? true)
-          base-journal-dir (arg-or-default :onyx.bookkeeper/base-journal-dir env-config)
-          base-ledger-dir (arg-or-default :onyx.bookkeeper/base-ledger-dir env-config)
-          ;; allow loopback? only if running a local quorum
-          allow-loopback? (boolean (arg-or-default :onyx.bookkeeper/local-quorum? env-config))
-          disk-usage-threshold (arg-or-default :onyx.bookkeeper/disk-usage-threshold env-config)
-          disk-usage-warn-threshold (arg-or-default :onyx.bookkeeper/disk-usage-warn-threshold env-config)
-          server-id (str onyx-id "_" port)
-          journal-dir (str base-journal-dir "/" server-id)
-          ledger-dir (str base-ledger-dir "/" server-id)
-          server-conf (doto (ServerConfiguration.)
-                        (.setZkServers (:zookeeper/address env-config))
-                        (.setZkLedgersRootPath ledgers-root-path)
-                        (.setBookiePort port)
-                        (.setJournalDirName journal-dir)
-                        (.setLedgerDirNames (into-array String [ledger-dir]))
-                        (.setAllowLoopback allow-loopback?)
-                        (.setDiskUsageThreshold disk-usage-threshold)
-                        (.setDiskUsageWarnThreshold disk-usage-warn-threshold))
-          server (try (BookieServer. server-conf)
-                      (catch Exception e
-                        (if (instance? KeeperException$NodeExistsException (.getCause e))
-                          (let [cookie-path (format "%s/cookies/%s"
-                                                    ledgers-root-path
-                                                    (Bookie/getBookieAddress server-conf))]
-                            (info "Deleting existing Bookie cookie" cookie-path)
-                            (zk/delete (:conn log) cookie-path)
-                            (BookieServer. server-conf))
-                          (throw e))))]
-      (info "Starting BookKeeper server on port" port)
-      (.start ^BookieServer server)
-      (when (:onyx.bookkeeper/delete-server-data? env-config)
-        (.addShutdownHook (Runtime/getRuntime)
-                          (Thread. (fn []
-                                     (cleanup-dir base-ledger-dir)
-                                     (cleanup-dir base-journal-dir)))))
-      (assoc component
-             :server server
-             :port port
-             :journal-dir journal-dir
-             :ledger-dir ledger-dir)))
+    (try
+      (let [onyx-id (:onyx/tenancy-id env-config)
+            ledgers-root-path (ozk/ledgers-path onyx-id)
+            ledgers-available-path (ozk/ledgers-available-path onyx-id)
+            _ (zk/create (:conn log) ledgers-root-path :persistent? true)
+            _ (zk/create (:conn log) ledgers-available-path :persistent? true)
+            base-journal-dir (arg-or-default :onyx.bookkeeper/base-journal-dir env-config)
+            base-ledger-dir (arg-or-default :onyx.bookkeeper/base-ledger-dir env-config)
+            ;; allow loopback? only if running a local quorum
+            allow-loopback? (boolean (arg-or-default :onyx.bookkeeper/local-quorum? env-config))
+            disk-usage-threshold (arg-or-default :onyx.bookkeeper/disk-usage-threshold env-config)
+            disk-usage-warn-threshold (arg-or-default :onyx.bookkeeper/disk-usage-warn-threshold env-config)
+            server-id (str onyx-id "_" port)
+            journal-dir (str base-journal-dir "/" server-id)
+            ledger-dir (str base-ledger-dir "/" server-id)
+            server-conf (doto (ServerConfiguration.)
+                          (.setZkServers (:zookeeper/address env-config))
+                          (.setZkLedgersRootPath ledgers-root-path)
+                          (.setBookiePort port)
+                          (.setJournalDirName journal-dir)
+                          (.setLedgerDirNames (into-array String [ledger-dir]))
+                          (.setAllowLoopback allow-loopback?)
+                          (.setDiskUsageThreshold disk-usage-threshold)
+                          (.setDiskUsageWarnThreshold disk-usage-warn-threshold))
+            server (BookieServer. server-conf)]
+        (info "Starting BookKeeper server on port" port)
+        (info "Creating Bookie dirs" journal-dir ";" ledger-dir)
+        (.start ^BookieServer server)
+        (assoc component
+               :server server
+               :server-conf server-conf
+               :port port))
+      (catch Exception e
+        (if (or (instance? BookieException$InvalidCookieException (.getCause e))
+                (instance? KeeperException$NodeExistsException (.getCause e)))
+          (throw (ex-info "The Bookie server failed to start because a cookie or
+                           ledger already exists for this host. Set
+                           :onyx.bookkeeper/delete-server-data? true to format
+                           the Bookie environment on startup."))
+          (throw e)))))

-  (stop [{:keys [server] :as component}]
-    (info "Stopping BookKeeper server")
+  (stop [{:keys [server server-conf] :as component}]
+    (info "Stopping BookKeeper server:")
     (.shutdown ^BookieServer server)
+    (info "Stopped BookKeeper server with exit code:" (.getExitCode server))
     (when (:onyx.bookkeeper/delete-server-data? env-config)
-      (cleanup-dir (:journal-dir component))
-      (cleanup-dir (:ledger-dir component)))
+      (format-bk-server server-conf (:conn log)))
     (assoc component :server nil :port nil :journal-dir nil :ledger-dir nil)))

 (defn started? [bookie]


use overtone.log as logfile name

use overtone.log as logfile name

--- src/overtone/config/store.clj
+++ src/overtone/config/store.clj
@@ -38,7 +38,7 @@
        :assets assets}))

 (def OVERTONE-CONFIG-FILE (str (:root OVERTONE-DIRS) "/config.clj"))
-(def OVERTONE-LOG-FILE (str (:log OVERTONE-DIRS) "/log.log"))
+(def OVERTONE-LOG-FILE (str (:log OVERTONE-DIRS) "/overtone.log"))

 (defn- ensure-dir-structure
   []


Add the ability to query a metronome for its current bpm value (by passing it a single arg :bpm). Thanks to Dave Ray for the suggestion.

--- src/overtone/music/rhythm.clj
+++ src/overtone/music/rhythm.clj
@@ -34,19 +34,25 @@
   (def m (metronome 128))
   (m)          ; => <current beat number>
   (m 200)      ; => <timestamp of beat 200>
+  (m :bpm)     ; => return the current bpm val
   (m :bpm 140) ; => set bpm to 140"
   [bpm]
   (let [start   (atom (now))
-        tick-ms (atom (beat-ms 1 bpm))]
+        tick-ms (atom (beat-ms 1 bpm))
+        cur-bpm (atom bpm)]
     (fn
       ([] (inc (long (/ (- (now) @start) @tick-ms))))
-      ([beat] (+ (* beat @tick-ms) @start))
+      ([arg] (cond
+              (number? arg) (+ (* arg @tick-ms) @start)
+              (= :bpm arg) @cur-bpm
+              :else (throw (Exception. (str "Unsupported metronome arg: " arg)))))
       ([_ bpm]
        (let [tms (beat-ms 1 bpm)
              cur-beat (long (/ (- (now) @start) @tick-ms))
              new-start (- (now) (* tms cur-beat))]
          (reset! tick-ms tms)
-         (reset! start new-start))
+         (reset! start new-start)
+         (reset! cur-bpm bpm))
        [:bpm bpm]))))

 (comment defprotocol IMetronome


Added general parsing function for note name modifiers. Not blended in yet.

--- src/overtone/music/tuning.clj
+++ src/overtone/music/tuning.clj
@@ -49,6 +49,16 @@
           octave (quot (- note initial (- (count notemap) 1 )) (count notemap))]
         (* freq (nth notemap pos) (expt (ceil (reduce max notemap)) octave))))

+(defn collapse-to-ntave [number ntave]
+    (condp > number
+             1 (recur (* number ntave) ntave)
+             ntave number
+             (recur (/ number ntave) ntave)))
+
+(defn note-set-from-generator [generator initpower finpower ntave]
+    (let [tempset (for [exponent (range initpower finpower)] (expt generator exponent))]
+        (sort (map #(collapse-to-ntave % ntave) tempset))))
+

 ;; Public Face - the tuning multimethods.

@@ -59,7 +69,9 @@
 (defmulti tunednotes
     "Multimethod that returns a function taking note keywords to note numbers.

-    A note keyword is usually of the form :[notename][pitchmodifiers][ntave], for example, :A4, :cb6 or :Bbb0, however this is entirely dependent on the kind of scale."
+    A note keyword is usually of the form :[notename][pitchmodifiers][ntave], for example, :A4, :cb6 or :Bbb0, however this is entirely dependent on the kind of scale.
+
+    TunedNotes functions should ideally return nonmatching symbols or numbers unmodified. Particularly numbers, which could be note numbers."
     list-flatten-first)

 (defmulti reversenotes
@@ -77,6 +89,7 @@

 ;;Implementation of some tuning systems.
+
 (defmethod perfn :ed [[_ divisions multiplier initial freq]]
     "Divides a multiplier-tave (e.g. 2-tave = octave, 3-tave, &c.) into divisions divisions. Maps initial to a note with frequency freq."
     (fn [note]
@@ -90,9 +103,7 @@
     (perfn (list :edo 12 69 440)))

 (defmethod tunednotes :midi [_]
-    "Returns a function that resolves notes to MIDI number format. Resolves upper and lower-case keywords
-     and strings in MIDI note format. If given an integer or nil, returns them
-     unmodified. All other inputs will raise an exception.
+    "Returns a function that resolves notes to MIDI number format. Resolves upper and lower-case keywords and strings in MIDI note format. If given a string or keyword in a different format, throws an exception. Anything else is returned unmodified.

      Usage examples:
      (note :F#7)    ;=> 102
@@ -130,28 +141,27 @@
 (defmethod tunednotes :default [_]
     (tunednotes :midi))

+(defn parsemodifiers
+    "Parses standard modifiers b, #, es, eh, ih and is for note names. Returns shifts where 1 is equivalent to a semitone."
+    [modifiers]
+    (let [matches (map first (concat (re-seq #"([ie][sh])" modifiers) (re-seq #"([b#])" modifiers)))]
+        (+
+            (- (count (filter #(= "b" %) matches)))
+            (- (count (filter #(= "es" %) matches)))
+            (* -0.5 (count (filter #(= "eh" %) matches)))
+            (* 0.5 (count (filter #(= "ih" %) matches)))
+            (count (filter #(= "is" %) matches))
+            (count (filter #(= "#" %) matches)))))

+
+;; Some other tuning systems

 (defmethod perfn :arabic [[symb initial freq]]
     (perfn (list :edo 24 initial freq)))

-
-(defn collapse-to-ntave [number ntave]
-    (condp > number
-             1 (recur (* number ntave) ntave)
-             ntave number
-             (recur (/ number ntave) ntave)))
-
-(defn- note-set-from-generator [generator initpower finpower ntave]
-    (let [tempset (for [exponent (range initpower finpower)] (expt generator exponent))]
-        (sort (map #(collapse-to-ntave % ntave) tempset))))
-
-(def qcmeantone
-    (note-set-from-generator (expt 5 1/4) -5 7 2))
-
 (defmethod perfn :qcmeantone [[symb initial freq]]
     (fn [note]
-        (perfmap note initial freq qcmeantone)))
+        (perfmap note initial freq (note-set-from-generator (expt 5 1/4) -5 7 2))))


Fix exclude_match directive

Fix exclude_match directive

--- src/cider_ci/repository/project_configuration/task_generation.clj
+++ src/cider_ci/repository/project_configuration/task_generation.clj
@@ -30,7 +30,7 @@
   (if-let [generate-spec (:generate_tasks context)]
     (let [repository (sql.repository/resolve git-ref-id)
           include-regex (-> generate-spec :include_match)
-          exclude-regex (-> generate-spec :exclude-match)
+          exclude-regex (-> generate-spec :exclude_match)
           file-list (git.repositories/ls-tree
                       repository git-ref-id include-regex exclude-regex)
           generated-tasks (->> file-list


Add tests for spitting sam/bam

Add tests for spitting sam/bam

--- test/cljam/t_io.clj
+++ test/cljam/t_io.clj
@@ -1,7 +1,14 @@
 (ns cljam.t-io
-  (:use midje.sweet)
+  (:use midje.sweet
+        [clojure.java.io :only [file]])
   (:require [cljam.io :as io])
   (:import [cljam.sam Sam SamHeader SamAlignment]))
+
+;;; Preparations
+
+(def test-sam-file "test/resources/test.sam")
+
+(def test-bam-file "test/resources/test.bam")

 (def test-sam
   (Sam. [(assoc (SamHeader.) :SQ {:SN "ref",  :LN "45"})
@@ -19,8 +26,30 @@
          (SamAlignment. "x5"   0   "ref2" 12 30 "24M"                "*" 0  0   "aaTaattaagtctacagagcaact"   "????????????????????????"   [])
          (SamAlignment. "x6"   0   "ref2" 14 30 "23M"                "*" 0  0   "Taattaagtctacagagcaacta"    "???????????????????????"    [])]))

+(def temp-dir (str (System/getProperty "java.io.tmpdir") "cljam-test"))
+
+(defn mk-temp-dir! []
+  (.mkdir (file temp-dir)))
+
+(defn rm-temp-dir! []
+  (.delete (file temp-dir)))
+
+;;; Facts
+
 (fact "about slurp-sam"
-  (io/slurp-sam "test/resources/test.sam") => test-sam)
+  (io/slurp-sam test-sam-file) => test-sam)

 (fact "about slurp-bam"
-  (io/slurp-bam "test/resources/test.bam") => test-sam)
+  (io/slurp-bam test-bam-file) => test-sam)
+
+(with-state-changes [(before :facts (mk-temp-dir!))
+                     (after  :facts (rm-temp-dir!))]
+  (fact "about spit-sam"
+    (let [temp-file (str temp-dir "/test.sam")]
+     (io/spit-sam temp-file test-sam) => nil
+     (= (slurp temp-file) (slurp test-sam-file)) => truthy))
+
+  (fact "about spit-bam"
+    (let [temp-file (str temp-dir "/test.bam")]
+     (io/spit-bam temp-file test-sam) => nil
+     (= (slurp temp-file) (slurp test-bam-file)) => truthy)))


Case determined by type of first element.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -333,7 +333,9 @@
   (let [{:keys [data trace]} (Throwable->map throwable)
         data (assoc data :original-exception (keyword (.getName (.getClass throwable))))
         t ^Throwable (ex-info (.getMessage throwable) data)]
-    (if (sequential? trace)
+    ;; First element may either be a StackTraceElement or a vector
+    ;; of 4 elements, those of which construct a STE.
+    (if (sequential? (first trace))
       (let [ste (map #(StackTraceElement.
                        (str (nth % 0))
                        (str (nth % 1))


Revert "Close go-loops on task lifecycle shutdown"

This reverts commit c6282122d88710d257a8b5b30cd8a0b83c289548.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -280,29 +280,29 @@
 (defn close-batch-resources [event]
   (merge event (l-ext/close-batch-resources* event)))

-(defn release-messages! [messenger event cleanup-ch]
+(defn release-messages! [messenger event]
   (go
    (loop []
-     (when-let [id (first (alts!! [(:release-ch messenger) cleanup-ch]))]
+     (when-let [id (<! (:release-ch messenger))]
        (p-ext/ack-message event id)
        (recur)))))

-(defn retry-messages! [messenger event cleanup-ch]
+(defn retry-messages! [messenger event]
   (go
    (loop []
-     (when-let [id (first (alts!! [(:retry-ch messenger) cleanup-ch]))]
+     (when-let [id (<! (:retry-ch messenger))]
        (p-ext/retry-message event id)
        (recur)))))

-(defn forward-completion-calls! [event completion-ch cleanup-ch]
-  (go
+(defn forward-completion-calls! [event completion-ch]
+  (try
     (loop []
-      (when-let [{:keys [id peer-id]} (first (alts!! [completion-ch cleanup-ch]))]
-        (try
-          (let [peer-link (operation/peer-link event peer-id)]
-            (extensions/internal-complete-message (:onyx.core/messenger event) event id peer-link))
-          (catch Exception e (timbre/fatal e)))
-        (recur)))))
+      (when-let [{:keys [id peer-id]} (<!! completion-ch)]
+        (let [peer-link (operation/peer-link event peer-id)]
+          (extensions/internal-complete-message (:onyx.core/messenger event) event id peer-link)
+          (recur))))
+    (catch Exception e
+      (timbre/fatal e))))

 (defn handle-exception [e restart-ch outbox-ch job-id]
   (warn e)
@@ -423,14 +423,12 @@
             (Thread/sleep 500)
             (recur @replica)))

-        (let [cleanup-ch (chan 1)
-              release-messages-ch (release-messages! messenger pipeline-data cleanup-ch)
-              retry-messages-ch (retry-messages! messenger pipeline-data cleanup-ch)
-              forward-completion-ch (forward-completion-calls! pipeline-data completion-ch cleanup-ch)
+        (let [release-messages-ch (release-messages! messenger pipeline-data)
+              retry-messages-ch (retry-messages! messenger pipeline-data)
+              forward-completion-ch (thread (forward-completion-calls! pipeline-data completion-ch))
               task-lifecycle-ch (thread (run-task-lifecycle pipeline-data seal-resp-ch kill-ch ex-f))
               listen-for-sealer-ch (listen-for-sealer job-id task-id pipeline-data seal-resp-ch outbox-ch)]
           (assoc component
-                 :cleanup-ch cleanup-ch
                  :pipeline-data pipeline-data
                  :seal-ch seal-resp-ch
                  :release-messages-ch release-messages-ch
@@ -448,11 +446,14 @@
       (l-ext/close-lifecycle-resources* event)

       (close! (:seal-ch component))
-      (close! (:cleanup-ch component))
+      (close! (:release-messages-ch component))
+      (close! (:retry-messages-ch component))
+      (close! (:forward-completion-ch component))

       ;; Ensure task operations are finished before closing peer connections
       (<!! (:task-lifecycle-ch component))
       (<!! (:listen-for-sealer-ch component))
+      (<!! (:forward-completion-ch component))
       (<!! (:release-messages-ch component))
       (<!! (:retry-messages-ch component))


Fix collision detection

Fix collision detection

--- dungeon-crawler/desktop/src-common/dungeon_crawler/utils.clj
+++ dungeon-crawler/desktop/src-common/dungeon_crawler/utils.clj
@@ -47,7 +47,7 @@
            (-> (some #(tiled-map-cell screen % tile-x tile-y) layers)
                nil?
                not))
-         (take-while identity)
+         (filter identity)
          first
          nil?
          not)))


Improved shutdown logging.

Improved shutdown logging.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -1048,6 +1048,7 @@
       (reset! (:kill-flag component) true)
       (some-> component :task-monitoring component/stop)
       (when-let [final-state (take-final-state!! component)]
+        (info (:log-prefix component) "Task received final state, shutting down task components.")
         (t/stop final-state (:scheduler-event component))
         (reset! (:task-kill-flag component) true))
       (when-let [f (:after-task-stop-fn component)]


Perf: Use new peer replica view for backpressure check

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -199,12 +199,9 @@
                (= (:message (first batch)) :done))
       (Thread/sleep (:onyx.core/drained-back-off event)))))

-(defn read-batch [task-type replica job-id pipeline event]
-  (if (and (= task-type :input)
-           ;; rename backpressuring?
-           ;; add note about how it'll be slow with big clusters
-           (common/job-backpressuring? @replica job-id))
-    (assoc event :onyx.core/batch [])
+(defn read-batch [task-type replica peer-replica-view job-id pipeline event]
+  (if (and (= task-type :input) (get (:backpressure peer-replica-view) job-id))
+    (assoc event :onyx.core/batch '())
     (let [rets (p-ext/read-batch pipeline event)]
       (handle-backoff! event)
       (merge event rets))))


fix getting discount

fix getting discount

--- src/pc/http/routes/stripe.clj
+++ src/pc/http/routes/stripe.clj
@@ -51,7 +51,7 @@
     (with-hook-accounting plan hook-json
       (let [team (team-model/find-by-plan db plan)
             invoice-fields (get-in hook-json ["data" "object"])
-            discount-fields (get-in invoice-fields "discount")
+            discount-fields (get-in invoice-fields ["discount"])
             invoice-id (d/tempid :db.part/user)]
         @(d/transact (pcd/conn) [{:db/id (d/tempid :db.part/tx)
                                   :transaction/broadcast true


Docs.

Docs.

--- clj_record/core.clj
+++ clj_record/core.clj
@@ -4,10 +4,14 @@
   (:use (clj-record meta util config callbacks)))

-(defn table-name [model-name]
+(defn table-name
+  "Retrieves table-name from model-metadata."
+  [model-name]
   (model-metadata-for model-name :table-name))

-(defn set-table-name [model-name tbl-name]
+(defn set-table-name
+  "Puts table-name into model metadata."
+  [model-name tbl-name]
   (dosync (set-model-metadata-for model-name :table-name tbl-name)))

 (defn to-conditions


Adds main namepsace as :aot for ubjerjar generation

--- clojure/project.clj
+++ clojure/project.clj
@@ -9,4 +9,5 @@
                  [ring/ring-jetty-adapter "1.2.0"]
                  [compojure "1.1.5"]]

-  :main me.perdomo.cofre.http)+  :main me.perdomo.cofre.http
+  :aot [me.perdomo.cofre.http])


removed unused ns

removed unused ns

--- integration/src/dda/pallet/dda_user_crate/app/instantiate_aws.clj
+++ integration/src/dda/pallet/dda_user_crate/app/instantiate_aws.clj
@@ -15,7 +15,6 @@
 ; limitations under the License.
 (ns dda.pallet.dda-user-crate.app.instantiate-aws
   (:require
-    [pallet.repl :as pr]
     [clojure.inspector :as inspector]
     [dda.pallet.core.app :as core-app]
     [dda.pallet.dda-user-crate.app :as app]))


Respond 404 for unknown pods or seatings

--- mtg-pairings-server/src/clj/mtg_pairings_server/service/tournament.clj
+++ mtg-pairings-server/src/clj/mtg_pairings_server/service/tournament.clj
@@ -232,28 +232,29 @@
                          :player (:dci player)})))))))

 (defn seatings [tournament-id]
-  (sql/select db/seating
-    (sql/fields :table_number)
-    (sql/with db/team
-      (sql/fields :name))
-    (sql/where {:tournament tournament-id})
-    (sql/order :team.name :ASC)))
+  (seq
+   (sql/select db/seating
+     (sql/fields :table_number)
+     (sql/with db/team
+       (sql/fields :name))
+     (sql/where {:tournament tournament-id})
+     (sql/order :team.name :ASC))))

 (defn pods [tournament-id number]
   (let [pod-rounds (map :id (sql/select db/pod-round
                               (sql/fields :id)
                               (sql/where {:tournament tournament-id})
-                              (sql/order :id)))
-        round-id (nth pod-rounds (dec number))]
-    (sql/select db/seat
-      (sql/fields :seat)
-      (sql/with db/team
-        (sql/fields [:name :team_name]))
-      (sql/with db/pod
-        (sql/fields [:number :pod])
-        (sql/where {:pod_round round-id}))
-      (sql/order :pod.number)
-      (sql/order :seat))))
+                              (sql/order :id)))]
+    (when (<= number (count pod-rounds))
+      (sql/select db/seat
+        (sql/fields :seat)
+        (sql/with db/team
+          (sql/fields [:name :team_name]))
+        (sql/with db/pod
+          (sql/fields [:number :pod])
+          (sql/where {:pod_round (nth pod-rounds (dec number))}))
+        (sql/order :pod.number)
+        (sql/order :seat)))))

 (defn latest-pods [tournament-id]
   (sql/select db/seat
@@ -280,8 +281,9 @@
       edn/read-string))

 (defn standings-for-api [tournament-id round-num hidden?]
-  (map #(select-keys % [:rank :team_name :points :omw :pgw :ogw])
-       (standings tournament-id round-num hidden?)))
+  (seq
+   (map #(select-keys % [:rank :team_name :points :omw :pgw :ogw])
+        (standings tournament-id round-num hidden?))))

 (defn ^:private get-or-add-round [tournament-id round-num playoff?]
   (if-let [old-round (sql-util/select-unique-or-nil db/round


NS style cleanup.

NS style cleanup.

--- src/degel/muxx/server.clj
+++ src/degel/muxx/server.clj
@@ -15,12 +15,11 @@
             [compojure.route :refer [resources not-found]]
             [ring.adapter.jetty :refer [run-jetty]]
             [ring.util.response :refer [redirect]]
-            [shoreleave.middleware.rpc :refer [wrap-rpc]]
+            [shoreleave.middleware.rpc :as rpc]
             [net.cgrand.enlive-html :as html]
             [compojure.handler :refer [site]]
             [cemerick.austin.repls :as austin-repls]
             [degel.cljutil.devutils :as dev]))
-

 ;;; All of the web apps we are handling.
 ;;; Call app-app to add or modify.
@@ -81,7 +80,7 @@
   (not-found "
Muxx moans: 'page not found'.
"))

-(def app (-> app-routes wrap-rpc site))
+(def app (-> app-routes rpc/wrap-rpc site))

 (defn run-servers [& {:keys [apps port]}]
   ;; [TODO] Using an atom for this is kinda grody. Is there some


Added price listings

Added price listings

--- src/portal_clj/views/base.clj
+++ src/portal_clj/views/base.clj
@@ -2,7 +2,8 @@
   (:use [hiccup.core])
   (:require [portal-clj.views.layout :as layout]
             [hiccup.form :refer [form-to]]
-            [clojure.string :as string]))
+            [clojure.string :as string])
+  (:import [price_updates Scraper]))

 (defn htmlify [text]
   (string/replace text #"\n" "<br/>"))
@@ -38,7 +39,20 @@
     [:p "SBC is a company specializing in retail sales of single board computers
      and related components. This includes the latest in flagship series such as
      the Raspberry Pi and the Parallela board."]
-    [:img {:src "/img/raspberry.jpg" :title "The all new Raspberry Pi 2"}]]
+    [:img {:src "/img/raspberry.jpg" :title "The all new Raspberry Pi 2"}]
+    [:p "Below you will find live price updates on some of our biggest products."]
+    [:div#raspberry
+     [:p (str "The latest price of the Raspberry Pi 2 is "
+              (Scraper/getRaspberryPi 1)
+              " USD")]]
+    [:div#parallella
+     [:p (str "The latest price of the Parallella board is "
+              (Scraper/getParallella 1)
+              " USD")]]
+    [:div#beagle
+     [:p (str "The latest price of the BeagleBone Black is "
+              (Scraper/getBeagleBone 1)
+              " USD")]]]
    layout/footer])

 (defn login [session msg]


CMR-3162: Fixed broken test for index sets.

--- indexer-app/test/cmr/indexer/test/data/elasticsearch.clj
+++ indexer-app/test/cmr/indexer/test/data/elasticsearch.clj
@@ -9,9 +9,7 @@
    {:name "cmr-base-index-set",
     :id 1,
     :create-reason "indexer app requires this index set",
-    :collection {:indexes [{:name "collections",
-                            :settings i/collection-setting-v1}
-                           {:name "collections-v2",
+    :collection {:indexes [{:name "collections-v2",
                             :settings i/collection-setting-v2}
                            {:name "all-collection-revisions",
                             :settings i/collection-setting-v1},]


GAWB-23: take off underline

GAWB-23: take off underline

--- src/cljs/org/broadinstitute/firecloud_ui/page/workspace/summary/attribute_editor.cljs
+++ src/cljs/org/broadinstitute/firecloud_ui/page/workspace/summary/attribute_editor.cljs
@@ -111,7 +111,7 @@
           [:div {}
            "Workspace Attributes"
            [:span {:style {:fontSize "initial" :fontWeight "initial"}}
-            [:a {:style {:marginLeft "1em"}
+            [:a {:style {:textDecoration "none" :marginLeft "1em"}
                  :href (str (config/api-url-root) "/cookie-authed/workspaces/"
                             (:namespace (:workspace-id props)) "/"
                             (:name (:workspace-id props)) "/exportAttributesTSV")


Fix typo

Fix typo

--- src/hangul_utils/core.clj
+++ src/hangul_utils/core.clj
@@ -45,7 +45,7 @@
            vec))))

 (defn construct
-  "Takes a vector of valid jamo cars and constructs a syllable char."
+  "Takes a vector of valid jamo chars and constructs a syllable char."
   [[i m f]]
   (if (and (not m) (not f))
     i


throwing-op can't actually be private

throwing-op can't actually be private

Because that means that callers have to know where it is :)

--- src/icecap/async_util.clj
+++ src/icecap/async_util.clj
@@ -1,7 +1,7 @@
 (ns icecap.async-util
   (:require [clojure.core.async :as a]))

-(defmacro ^:private throwing-op
+(defmacro throwing-op
   "Like `op`, except throws exceptions from the chan."
   [op c]
   `(let [v# (~op ~c)]


Update to new working version of cljunit

--- src/radicalzephyr/boot_junit.clj
+++ src/radicalzephyr/boot_junit.clj
@@ -2,50 +2,56 @@
   {:boot/export-tasks true}
   (:require [boot.core :as core]
             [boot.pod  :as pod]
+            [boot.util  :as util]
             [clojure.string :as str]))

 (def pod-deps
-  '[[radicalzephyr/cljunit "0.1.1-SNAPSHOT"]])
+  '[[radicalzephyr/cljunit "0.2.0-SNAPSHOT"]])

 (defn- init [fresh-pod]
   (pod/with-eval-in fresh-pod
-    (require '[cljunit.core :refer [run-test-classes
-                                    run-tests-in-packages]])))
+    (require '[cljunit.core :refer [run-tests-in-classes]])))
+
+(defn- construct-class-name [prefix path]
+  (let [path-seq (-> path
+                     (str/replace prefix "")
+                     (str/replace #"\.java$" "")
+                     (str/split #"/"))]
+    (->> path-seq
+         (remove empty?)
+         (interpose ".")
+         (apply str))))
+
+(defn- path->class-name [class-name]
+  (let [prefix (str (core/tmp-dir class-name))
+        file (core/tmp-file class-name)]
+    (construct-class-name prefix (str file))))

 (defn- path->package-name [path]
   (str/join "." (-> path
                     (str/split #"/")
                     drop-last)))

-(defn- all-packages [user-files]
+(defn- all-class-names [user-files]
   (->> user-files
-       (map core/tmp-path)
-       (map path->package-name)
-       set))
+       (core/by-ext [".java"])
+       (map path->class-name)))

 (core/deftask junit
   "Run the jUnit test runner."
-  [p paths    PATH  #{str} "The set of source paths to search for tests."
-   c classes  CLASS #{str} "The set of Java class names to run as tests."]
+  [c class-names  CLASSNAME #{str} "The set of Java class names to run tests from."
+   p packages     PACKAGE   #{str} "The set of package names to run tests from."]
   (let [worker-pods (pod/pod-pool (update-in (core/get-env) [:dependencies] into pod-deps)
                                   :init init)]
     (core/cleanup (worker-pods :shutdown))
     (core/with-pre-wrap fileset
       (let [worker-pod (worker-pods :refresh)
-            packages (or (seq (map path->package-name paths))
-                         (all-packages (core/input-files fileset)))]
-        (cond
-          (seq classes)
-          (let [result (pod/with-eval-in worker-pod
-                         (run-test-classes '~packages '~classes))]
-            (when (> (:failures result) 0)
-              (throw (ex-info "Some tests failed or errored" {}))))
-
-          (seq packages)
-          (let [result (pod/with-eval-in worker-pod
-                         (run-tests-in-packages '~packages))]
-            (when (> (:failures result) 0)
-              (throw (ex-info "Some tests failed or errored" {}))))
-
-          :else (println "No packages were tested.")))
+            all-class-names (all-class-names (core/input-files fileset))]
+        (if-let [result (pod/with-eval-in worker-pod
+                          (run-tests-in-classes '~all-class-names
+                                                :classes ~class-names
+                                                :packages ~packages))]
+          (when (> (:failures result) 0)
+            (throw (ex-info "Some tests failed or errored" {})))
+          (util/warn "Nothing was tested.")))
       fileset)))


Avoid printing; add `with-collect-logging`. Nice.

--- test/com/nomistech/clojure_the_language/reducers_rumford_test.clj
+++ test/com/nomistech/clojure_the_language/reducers_rumford_test.clj
@@ -404,25 +404,27 @@
 ;;;; ---------------------------------------------------------------------------
 ;;;; Demo of ordering

-(reduce +  0 ((comp (partial map (fn [x] (println "doing +") (+ x 10)))
-                    (partial map (fn [x] (println "doing *") (* x 10))))
-              [1 2 3]))
-;; doing *
-;; doing *
-;; doing *
-;; doing +
-;; doing +
-;; doing +
-
-(reduce +  0 ((comp (r/map (fn [x] (println "doing +") (+ x 10)))
-                    (r/map (fn [x] (println "doing *") (* x 10))))
-              [1 2 3]))
-;; doing *
-;; doing +
-;; doing *
-;; doing +
-;; doing *
-;; doing +
+(defmacro with-collect-logging [{:keys [log-name]} & body]
+  `(let [~'log-entries (agent [])
+         ~log-name (fn [~'entry]
+                     (send ~'log-entries conj ~'entry))]
+     ~@body
+     (await ~'log-entries)
+     @~'log-entries))
+
+(fact
+  (with-collect-logging {:log-name log}
+    (reduce +  0 ((comp (partial map (fn [x] (log "+") (+ x 10)))
+                        (partial map (fn [x] (log "*") (* x 10))))
+                  [1 2 3])))
+  => ["*" "*" "*" "+" "+" "+"])
+
+(fact
+  (with-collect-logging {:log-name log}
+    (reduce +  0 ((comp (r/map (fn [x] (log "+") (+ x 10)))
+                        (r/map (fn [x] (log "*") (* x 10))))
+                  [1 2 3])))
+  => ["*" "+" "*" "+" "*" "+"])

 ;;;; ---------------------------------------------------------------------------
 ;;;; Example from Rich Hickey's EuroClojure 2012 talk:


Don't leak a connection.

Don't leak a connection.

--- modules/messaging/src/test/clojure/wunderboss/messaging_tests.clj
+++ modules/messaging/src/test/clojure/wunderboss/messaging_tests.clj
@@ -391,6 +391,5 @@
 (deftest toss-when-xa-unavailable
   (is (thrown-with-msg? NullPointerException
         #"TransactionManager not found"
-        (-> default
-          (.createConnection (coerce-connection-options {:xa true}))
-          (.createSession nil)))))
+        (with-open [conn (.createConnection default (coerce-connection-options {:xa true}))]
+          (.createSession conn nil)))))


oopsy

oopsy

--- figwheel-repl/src/figwheel/repl.cljc
+++ figwheel-repl/src/figwheel/repl.cljc
@@ -226,7 +226,7 @@
      (swap! reload-promise-chain next-promise-fn))))

 (defn ^:export after-reloads [f]
-  (swap! reload-promise-chain #(.then % (f))))
+  (swap! reload-promise-chain #(.then % f)))

 ;; --------------------------------------------------------------
 ;; REPL print forwarding


:sparkles: Improve & simplify the drawing end event.

--- frontend/src/uxbox/main/ui/workspace/drawarea.cljs
+++ frontend/src/uxbox/main/ui/workspace/drawarea.cljs
@@ -22,6 +22,7 @@
    [uxbox.util.math :as mth]
    [uxbox.util.dom :as dom]
    [uxbox.util.data :refer [seek]]
+   [uxbox.util.geom.matrix :as gmt]
    [uxbox.util.geom.path :as path]
    [uxbox.util.geom.point :as gpt]
    [uxbox.util.uuid :as uuid]))
@@ -289,23 +290,17 @@
     (watch [_ state stream]
       (let [pid (get-in state [:workspace :current])
             shape (get-in state [:workspace pid :drawing])]
-        (if (::initialized? shape)
-          (let [resize-mtx (get-in state [:workspace pid :modifiers (:id shape) :resize])
-                shape (cond-> shape
-                        resize-mtx (geom/transform resize-mtx))]
-            (rx/of
-             ;; Remove the stalled modifiers
-             ;; TODO: maybe a specific event for "clear modifiers"
-             #(update-in % [:workspace pid :modifiers] dissoc (:id shape))
-
-             ;; Unselect the drawing tool
-             ;; TODO; maybe a specific event for clear draw-tool
-             dw/clear-drawing
-
+        (rx/concat
+         (rx/of dw/clear-drawing)
+         (when (::initialized? shape)
+           (let [modifier-mtx (:modifier-mtx shape)
+                 shape (if (gmt/matrix? modifier-mtx)
+                         (geom/transform shape modifier-mtx)
+                         shape)
+                 shape (dissoc shape ::initialized? :modifier-mtx)]
              ;; Add & select the cred shape to the workspace
-             (dw/add-shape (dissoc shape ::initialized?))
-             (dw/select-first-shape)))
-          (rx/of #(update-in % [:workspace pid] dissoc :drawing :drawing-tool)))))))
+             (rx/of (dw/add-shape shape)
+                    (dw/select-first-shape)))))))))

 (def close-drawing-path
   (reify


remove uselesscode

remove uselesscode

--- worker/src/worker/worker.cljs
+++ worker/src/worker/worker.cljs
@@ -23,11 +23,10 @@
    "};"
    "})(self);"
    "importScripts('" closure-base-file "','" cljs-deps-file "');"
-   "goog.require('cljs.core');"
    "goog.require('worker.worker');"

    "self.onmessage = function(e) {"
-     fn-name ".apply();"
+     "worker.worker.wrk();"
    "};"))

 (defn worker-body-min [fn-name]
@@ -55,8 +54,8 @@

 (defn do-some []
-  (let [a (worker-body-min (func-name wrk))]
-
+(println goog.basePath)
+  (let [a (worker-body (func-name wrk))]
     (println a)

     (def b (js/Blob. (clj->js [a])))


docs(viz): re-integrate docs/comments from org file

--- src/thi/ng/geom/viz/core.cljc
+++ src/thi/ng/geom/viz/core.cljc
@@ -8,6 +8,161 @@
    [thi.ng.ndarray.contours :as contours]
    [thi.ng.math.core :as m]
    [thi.ng.strf.core :as f]))
+
+;; This module currently consists of this single namespace dedicated
+;; to creating 2D (and soon 3D too) data visualizations in an output
+;; format agnostic way. To achieve that, an overall declarative and
+;; pipelined approach has been taken to create these visualizations:
+;;
+;; 1. We first define a configuration map, supplying all data points,
+;;    axis definitions, layout arguments/handlers, styling options etc.
+;; 2. This map is then transformed into a tree/scenegraph of geometric
+;;    primitives (shapes & groups) representing the visualization.
+;; 3. This tree of still pure Clojure data is then further converted into
+;;    the final output format, e.g. for SVG first into
+;;    https://github.com/weavejester/hiccup and then actual SVG/XML...
+;;
+;; The declarative nature has several benefits:
+;;
+;; - place multiple data series w/ potentially different layout methods
+;;   into same visualization
+;; - create template/preset specs (e.g. pre-styled, only inject new data
+;;   points)
+;; - easy to integrate in central state atom pattern, compatible w/
+;;   Om/Reagent based setups
+;; - support multiple output targets from the same visualization spec
+;;
+;; Apart from SVG (the only target supported at the moment), this
+;; module also aims to support OpenGL / WebGL scenegraph generation
+;; and http://thi.ng/luxor scene exports for rendering visualizations
+;; with http://luxrender.net.
+;;
+;; Visualization spec format
+;;
+;; The main configuration map should have at least the following keys,
+;; common to all supported visualization methods. Visualizations are
+;; created by taking a series of data points and mapping them from
+;; their source `:domain` into new coordinate system (`:range`).
+;; Furthermore, this target coordinate system itself can be
+;; transformed via projections, e.g. to translate from cartesian into
+;; polar coordinates (e.g. see Radar plot and other polar examples
+;; above).
+;;
+;; | *Key*     | *Value*                  | *Required* | *Description*                             |
+;; |-----------+--------------------------+------------+-------------------------------------------|
+;; | `:x-axis` | horizontal axis spec map | Y          | X-axis behavior & representation details  |
+;; | `:y-axis` | vertical axis spec map   | Y          | Y-axis behavior & representation details  |
+;; | `:grid`   | grid spec map            | N          | Optional background axis grid             |
+;; | `:data`   | vector of dataset specs  | Y          | Allows multiple datasets in visualization |
+;;
+;; The following options are only used for visualizations using
+;; `svg-plot2d-polar`:
+;;
+;; | *Key*     | *Value*                 | *Required* | *Description*                                                                        |
+;; |-----------+-------------------------+------------+--------------------------------------------------------------------------------------|
+;; | `:origin` | 2D vector, e.g. =[x y]= | Y          | Center pos of radial layout, only required for polar projection                      |
+;; | `:circle` | boolean                 | N          | true if axis & grid should be using full circles, only required for polar projection |
+;;
+;; Axis definitions (:x-axis / :y-axis)
+;;
+;; Axis specs are usually created via one of the available axis
+;; generator functions (`linear-axis`, `log-axis`, `lens-axis`). These
+;; functions too take a map w/ some of the same keys, but replace some
+;; vals with transformed data and autofill default values for others.
+;;
+;; | *Key*          | *Value*              | *Required* | *Default*                              | *Description*                                                            |
+;; |----------------+----------------------+------------+----------------------------------------+--------------------------------------------------------------------------|
+;; | `:scale`       | scale function       | Y          | nil                                    | Scale function to translate domain values into visualization coordinates |
+;; | `:domain`      | vec of domain bounds | Y          | nil                                    | Lower & upper bound of data source interval                              |
+;; | `:range`       | vec of range bounds  | Y          | nil                                    | Lower & upper bound of projected coordinates                             |
+;; | `:pos`         | number               | Y          | nil                                    | Draw position of the axis (ypos for X-axis, xpos for Y-axis)             |
+;; | `:major`       | seq of domain values | N          | nil                                    | Seq of domain positions at which to draw labeled tick marks              |
+;; | `:minor`       | seq of domain values | N          | nil                                    | Seq of domain positions at which                                         |
+;; | `:major-size`  | number               | N          | 10                                     | Length of major tick marks                                               |
+;; | `:minor-size`  | number               | N          | 5                                      | Length of minor tick marks                                               |
+;; | `:label`       | function             | N          | =(default-svg-label (value-format 2))= | Function to format & emit tick labels                                    |
+;; | `:label-dist`  | number               | N          | 10 + major-size                        | Distance of value labels from axis                                       |
+;; | `:label-style` | map                  | N          | see next section                       | Style attribute map for value labels                                     |
+;; | `:label-y`     | number               | N          | 0                                      | Vertical offset for Y-axis labels                                        |
+;; | `:attribs`     | map                  | N          | ={:stroke "black"}=                    | Axis line attribs attributes                                             |
+;; | `:visible`     | boolean              | N          | true                                   | Flag if axis will be visible in visualization                            |
+;;
+;; About tick marks
+;;
+;; The `linear-axis` & `lens-axis` interpret the given `:major` and
+;; `:minor` values as the intended step distance between ticks and
+;; generate ticks at multiples of the given value.
+;;
+;; The `log-axis` generator auto-creates ticks based on the `:base` of
+;; the logarithm.
+;;
+;; Notes for polar projection
+;;
+;; - the `:range` interval of the x-axis must be an angle interval in radians (see above example)
+;; - the `:range` interval of the y-axis must be a radius interval
+;;
+;; Same goes for `:pos` values: The `:pos` for x-axis is a radius, the
+;; `:pos` for y-axis is an angle in radians
+;;
+;; Default axis label styling
+;;
+;; For SVG export, each axis is exported as its own group (incl. tick
+;; marks & labels). By default the following label style is applied to
+;; each group, however this can be overridden for individual labels by
+;; specifying a custom `:label` function.
+;;
+;; ```
+;; {:fill        "black"
+;;  :stroke      "none"
+;;  :font-family "Arial, sans-serif"
+;;  :font-size   10
+;;  :text-anchor "middle"}
+;; ```
+;;
+;; *** Axis grid definition (:grid)
+;;
+;; *Note:* If no `:grid` spec is given in the main spec, no background
+;; *grid will be displayed...
+;;
+;; | *Key*      | *Value* | *Required* | *Default*       | *Description*                                            |
+;; |------------+---------+------------+-----------------+----------------------------------------------------------|
+;; | `:attribs` | hashmap | N          | default attribs | allows extra attributes to be injected (e.g. for SVG)    |
+;; | `:minor-x` | boolean | N          | false           | if `false` only uses major tick mark positions on X axis |
+;; | `:minor-y` | boolean | N          | false           | if `false` only uses major tick mark positions on Y axis |
+;;
+;; Dataset specs (:data)
+;;
+;; The format of these maps is largely dependent on the concrete
+;; visualization methods used, but most have the following keys in
+;; common:
+;;
+;; | *Key*       | *Required* | *Default*  | *Description*                                                  |
+;; |-------------+------------+------------+----------------------------------------------------------------|
+;; | `:layout`   | Y          | nil        | Layout function to map data points                             |
+;; | `:values`   | Y          | nil        | Data points to be mapped                                       |
+;; | `:attribs`  | N          | nil        | Styling & other attributes to attach to surrounding group node |
+;; | `:item-pos` | N          | `identity` | Function returning domain position of single data point        |
+;;
+;; The `:item-pos` key is only needed if the data items are in a
+;; non-standard format. By the default most layout functions expect
+;; the data points to be a 2-element vector `[domain-pos value]`.
+;; Using an `:item-pos` lookup fn however, data items can be supplied
+;; in other form (eg. as maps). Also see examples above...
+;;
+;; Scales
+;;
+;; Scaling functions merely provide a means to map values from a source
+;; interval (domain) to a target interval (range). The latter usually
+;; represents values in the visualization space (e.g. partial screen
+;; coordinates).
+;;
+;; These functions can be useful also outside a visualization
+;; context, but here are used in conjunction with their related axis
+;; definition functions described below. When creating visualizations,
+;; we would not usually use these scaling functions directly, but use
+;; them implicitly via our defined axis specs.
+
+;; Value transformations

 (defn value-mapper
   [scale-x scale-y] (fn [[x y]] [(scale-x x) (scale-y y)]))
@@ -45,11 +200,15 @@
        (reduce #(conj! % [:L %2]) (transient [[:M p]]))
        persistent!))

+;; Projections
+
 (defn polar-projection
   [origin]
   (let [o (vec2 origin)]
     (fn [[x y]] (m/+ o (g/as-cartesian (vec2 y x))))))

+;; Value formatting
+
 (defn value-formatter
   [prec]
   (let [fmt [(f/float prec)]]
@@ -60,6 +219,16 @@

 (defn default-svg-label
   [f] (fn [p x] (svg/text p (f x))))
+
+;; Domain analysis ops
+;;
+;; Raw values to domain point conversion
+;;
+;; Most of the visualization methods in this module expect a seq of
+;; data points in the format: `[domain-position value]`. The function
+;; `uniform-domain-points` is useful to convert a sequence of pure
+;; values (without position) into a seq of uniformly spaced data
+;; points along the full breadth of the given domain:

 (defn uniform-domain-points
   "Given a vector of domain bounds and a collection of data values
@@ -72,6 +241,8 @@
    (m/norm-range (dec (count values)))
    values))

+;; Domain bounds
+
 (def domain-bounds-x #(gu/axis-bounds 0 %))

 (def domain-bounds-y #(gu/axis-bounds 1 %))
@@ -85,14 +256,20 @@
    (completing (fn [[aa ab] [xa xb]] [(min aa xa) (max ab xb)]))
    [m/INF+ m/INF-] colls))

+;; Matrix value domain
+
 (defn value-domain-bounds
   [mat]
   (let [vals (seq mat)]
     [(reduce min vals) (reduce max vals)]))

+;; Linear scaling
+
 (defn linear-scale
   [domain range]
   (fn [x] (m/map-interval x domain range)))
+
+;; Logorithmic scaling

 (defn log
   [base]
@@ -110,11 +287,33 @@
         dr   (- (log* d2) d1l)]
     (fn [x] (m/mix* r1 r2 (/ (- (log* x) d1l) dr)))))

+;; Lens scale (dilating / bundling)
+;;
+;; The =lens-scale= defines a non-linear mapping by specifying a focal
+;; position in the domain interval, as well as a lens strength which
+;; controls the compression or expansion of the domain space around
+;; this focal point. If strength is positive, the lens is dilating. If
+;; negative, it is bundling (compressing). A strength of zero causes a
+;; normal/linear scaling behavior.
+;;
+;; The two animations below show the effect of individually adjusting
+;; the focus and lens strength:
+;;
+;; http://media.thi.ng/geom/viz/lens-focus-2.gif
+;; Focus shift, constant strength = 0.5
+;;
+;; http://media.thi.ng/geom/viz/lens-strength-4.gif
+;; Lens strength adjustment, constant focus = 0.0
+
 (defn lens-scale
   [focus strength [d1 d2] [r1 r2]]
   (let [dr (- d2 d1)
         f  (/ (- focus d1) dr)]
     (fn [x] (m/mix-lens r1 r2 (/ (- x d1) dr) f strength))))
+
+;; Axis & tick generators
+
+;; Common axis factory

 (defn axis-common*
   [{:keys [visible major-size minor-size label attribs label-style label-dist]
@@ -137,6 +336,8 @@
                        label-style)
          :label-dist  (or label-dist (+ 10 major-size))))

+;; Linear
+
 (defn lin-tick-marks
   [[d1 d2] delta]
   (let [dr (- d2 d1)
@@ -157,6 +358,8 @@
          :minor minor')
         (axis-common*))))

+;; Logarithmic
+
 (defn log-ticks-domain
   [base d1 d2]
   (let [log* (log base)] [(m/floor (log* d1)) (m/ceil (log* d2))]))
@@ -188,6 +391,19 @@
        :major (log-tick-marks-major base domain)
        :minor (log-tick-marks-minor base domain))
       (axis-common*)))
+
+;; Lens axis
+;;
+;; The lens axis is a modified `linear-axis` with two additional
+;; required attributes to control the domain space deformation in
+;; order to compress or expand the space around a given focal point
+;; and therefore introduce a non-linear arrangement. See `lens-scale`
+;; above for further details.
+;;
+;; - `:focus` - the domain value acting as lens focus
+;;   (by default the center of the domain is used)
+;; - `:strength` - the lens strength & direction
+;;   (normalized values -1.0 ... + 1.0, default = 0.5)

 (defn lens-axis
   [{:keys [domain range focus strength major minor]
@@ -207,6 +423,10 @@
          :strength strength)
         (axis-common*))))

+;; Custom shapes
+
+;; Some preset shape functions for use with scatter plots
+
 (defn svg-triangle-up
   [w]
   (let [h (* w (Math/sin m/THIRD_PI))
@@ -239,9 +459,37 @@
   [a b c d col]
   (svg/circle (gu/centroid [a b c d]) (* 0.5 (g/dist a b)) {:fill col}))

+;; Axial visualization methods
+;;
+;; This section defines the various layout/plotting methods, each with
+;; a brief description and lists of custom `:data` spec options. See
+;; the "Dataset specs" section and examples above for details about
+;; other (required) keys...
+
+;; Line plot
+;;
+;; This method simply represents the mapped values as a single
+;; line-strip (polyline). Values are automatically sorted by domain
+;; position, so can be initially unordered.
+
 (defn svg-line-plot
   [v-spec d-spec]
   (svg/line-strip (map first (process-points v-spec d-spec)) (:attribs d-spec)))
+
+;; Area plot
+;;
+;; Similar to the line plot method above, however resulting points are
+;; represented as closed polygon (and hence an `:attribs` key should
+;; be supplied w/ a `:fill` color).
+;;
+;; *Note:* When using polar coordinate mapping (via
+;; `svg-plot2d-polar`), a `:res` option should be given too in order
+;; to create an arc approximation closing the polygon along the X-axis
+;; (e.g. `:res 20`).
+;;
+;; | *Key*  | *Required* | *Default* | *Description*                                       |
+;; |--------+------------+-----------+-----------------------------------------------------|
+;; | `:res` | N          |         1 | Number of points used to close polygon along X-axis |

 (defn svg-area-plot
   [{:keys [y-axis project] :as v-spec} {:keys [res] :as d-spec}]
@@ -252,9 +500,31 @@
         points  (concat points (mapv (partial m/mix p q) (m/norm-range (or res 1))))]
     (svg/polygon (mapv project points) (:attribs d-spec))))

+;; Radar plot
+;;
+;; This plot method is intended to be only used with `svg-plot2d-polar`.
+;;
+;; | *Key*    | *Required* | *Default*   | *Description*                                        |
+;; |----------+------------+-------------+------------------------------------------------------|
+;; | `:shape` | N          | svg/polygon | Shape function receiving seq of all points & attribs |
+
 (defn svg-radar-plot
   [v-spec {:keys [shape] :or {shape svg/polygon} :as d-spec}]
   (shape (mapv first (process-points v-spec d-spec)) (:attribs d-spec)))
+
+;; Min-Max radar plot
+;;
+;; This version of the radar plot expects a min/max interval for each
+;; data item. For example a single data point of `[2 0.25 0.75]` would
+;; define a domain position at x=2 and an interval of 0.25-0.75. If no
+;; `:item-pos-*` options are supplied this 3-element vector format is
+;; assumed for each data point.
+;;
+;; | *Key*           | *Required* | *Default* | *Description*                                                    |
+;; |-----------------+------------+-----------+------------------------------------------------------------------|
+;; | `:item-pos-min` | N          | `[x min]` | Function to provide min. data point                              |
+;; | `:item-pos-max` | N          | `[x max]` | Function to provide max. data point                              |
+;; | `:shape`        | N          | svg/path  | Shape function receiving seq of outer & inner points and attribs |

 (defn svg-radar-plot-minmax
   [v-spec
@@ -271,11 +541,28 @@
                         (points->path-segments))]
     (shape max-points min-points (assoc (:attribs d-spec) :fill-rule "evenodd"))))

+;; Scatter plot
+;;
+;; | *Key*    | *Required* | *Default* | *Description*                                          |
+;; |----------+------------+-----------+--------------------------------------------------------|
+;; | `:shape` | N          | `circle`  | Function returning shape primitive for each data point |
+
 (defn svg-scatter-plot
   [v-spec {:keys [attribs shape] :as d-spec}]
   (->> (assoc d-spec :shape (or shape (fn [[p]] (svg/circle p 3))))
        (process-points v-spec)
        (apply svg/group attribs)))
+
+;; Bar plot
+;;
+;; | *Key*         | *Required* | *Default*  | *Description*                                           |
+;; |---------------+------------+------------+---------------------------------------------------------|
+;; | `:item-pos`   | N          | `identity` | Function returning domain position of single data point |
+;; | `:shape`      | N          | `line`     | Function returning shape primitive for each data point  |
+;; | `:interleave` | N          | 1          | Number of bars per domain position                      |
+;; | `:offset`     | N          | 0          | Only used for interleaved bars, index position          |
+;; | `:bar-width`  | N          | 0          | Only used for interleaved bars, width of single bar     |
+;; | `:shape`      | Y          | svg/line   | Function returning shape primitive for each data point  |

 (defn svg-bar-plot
   [{:keys [x-axis y-axis project] :or {project vec2}}
@@ -301,6 +588,22 @@
                 (shape (project [ax ay]) (project [ax base-y]) i))))))
          (apply svg/group attribs))))

+;; Heatmap
+;;
+;; | *Key*            | *Required* | *Default*    | *Description*                                      |
+;; |------------------+------------+--------------+----------------------------------------------------|
+;; | `:matrix`        | Y          | nil          | NDArray instance of data grid                      |
+;; | `:palette`       | Y          | nil          | Color list                                         |
+;; | `:palette-scale` | N          | linear-scale | Mapping function of matrix values to palette index |
+;; | `:value-domain`  | N          | [0 1]        | Domain interval of matrix values                   |
+;; | `:clamp`         | N          | false        | If true, matrix values are clamped to value domain |
+;;
+;; *Note:* If `:clamp` is not enabled, the `:value-domain` acts as
+;; filter and will not include cells with values outside the domain,
+;; resulting in holes in the visualization. On the other hand, if
+;; `:clamp` is enabled, the `:value-domain` acts as a kind of
+;; amplification or compression function.
+
 (defn svg-heatmap
   [{:keys [x-axis y-axis project]}
    {:keys [matrix value-domain clamp palette palette-scale attribs shape]
@@ -325,6 +628,25 @@
               (project [(scale-x x) (scale-y (inc y))])
               (palette (m/clamp (int (scale-v v)) 0 pmax)))))))

+;; Contour lines
+;;
+;; Given a 2D matrix (a `thi.ng.ndarray.core.NDArray` instance) of data
+;; values and a seq of thresholds, this function computes number of
+;; polygons for each threshold level.
+;;
+;; *Note:* Since the data format for this method is different to the
+;; other layouts, we're using the `:matrix` key instead of `:values` to
+;; emphasize this difference...
+;;
+;; | *Key*              | *Required* | *Default*    | *Description*                                                  |
+;; |--------------------+------------+--------------+----------------------------------------------------------------|
+;; | `:matrix`          | Y          | nil          | NDArray instance of data grid                                  |
+;; | `:levels`          | Y          | nil          | Seq of threshold values to find contours for                   |
+;; | `:palette`         | Y          | nil          | Color list                                                     |
+;; | `:palette-scale`   | N          | linear-scale | Mapping function of matrix values to palette index             |
+;; | `:value-domain`    | N          | [0 1]        | Domain interval of matrix values                               |
+;; | `:contour-attribs` | N          | nil          | Function to produce shape attribs map for each threshold level |
+
 (defn matrix-2d
   [w h values] (nd/ndarray :float32 values [h w]))

@@ -359,6 +681,14 @@
                          (contours/find-contours-2d matrix iso))))))
          (apply svg/group attribs))))

+;; Stacked intervals
+;;
+;; | *Key*         | *Required* | *Default*  | *Description*                                         |
+;; |---------------+------------+------------+-------------------------------------------------------|
+;; | `:item-range` | N          | `identity` | Function returning domain interval for each data item |
+;; | `:offset`     | N          | 0          | Y-axis offset for this data series                    |
+;; | `:shape`      | N          | `svg/line` | Function returning shape primitive for each data item |
+
 (defn overlap? [[a b] [c d]] (and (<= a d) (>= b c)))

 (defn compute-row-stacking
@@ -399,6 +729,10 @@
          (mapv shape)
          (apply svg/group attribs))))

+;; 2D Cartesian Plotting (SVG)
+
+;; SVG axis generators
+
 (defn svg-axis*
   [{:keys [major minor attribs label-style]} axis tick1-fn tick2-fn label-fn]
   (svg/group
@@ -433,6 +767,8 @@
      #(let [y (scale %)] (svg/line (vec2 pos y) (vec2 x-minor y)))
      #(label (vec2 x-label (+ (scale %) label-y)) %))))

+;; Generic plotting helpers
+
 (defn select-ticks
   [axis minor?] (if minor? (concat (:minor axis) (:major axis)) (:major axis)))

@@ -458,6 +794,10 @@
      (map (fn [spec] ((:layout spec) opts spec)) data)
      (if (:visible x-axis) (svg-x-axis-cartesian x-axis))
      (if (:visible y-axis) (svg-y-axis-cartesian y-axis)))))
+
+;; 2D Polar Plotting (SVG)
+
+;; SVG axis generators

 (defn svg-x-axis-polar
   [{:keys [x-axis project circle origin]}]
@@ -527,3 +867,59 @@
      (map (fn [spec'] ((:layout spec') spec spec')) data)
      (if (:visible x-axis) (svg-x-axis-polar spec))
      (if (:visible y-axis) (svg-y-axis-polar spec)))))
+
+;; (currently unused) date & time helpers
+
+(comment
+
+  (defn clear-day-of-week [^GregorianCalendar cal] (.set cal Calendar/DAY_OF_WEEK 1) (clear-hour cal))
+  (defn clear-month [^GregorianCalendar cal] (.set cal Calendar/MONTH 0) (clear-day-of-month cal))
+
+  (defn year [^GregorianCalendar cal] (.get cal Calendar/YEAR))
+  (defn month [^GregorianCalendar cal] (.get cal Calendar/MONTH))
+  (defn day-of-month [^GregorianCalendar cal] (.get cal Calendar/DAY_OF_MONTH))
+  (defn day-of-week [^GregorianCalendar cal] (.get cal Calendar/DAY_OF_WEEK))
+  (defn hour [^GregorianCalendar cal] (.get cal Calendar/HOUR))
+  (defn minute [^GregorianCalendar cal] (.get cal Calendar/MINUTE))
+  (defn second [^GregorianCalendar cal] (.get cal Calendar/SECOND))
+
+  (defn round-to-year
+    [epoch]
+    (let [cal (epoch->cal epoch)]
+      (doto cal
+        (.add Calendar/MONTH 6)
+        (clear-month))))
+
+  (defn round-to-month
+    [epoch]
+    (doto (epoch->cal epoch)
+      (.setTimeInMillis (long epoch))
+      (.add Calendar/DAY_OF_MONTH 16)
+      (clear-day-of-month)))
+
+  (defn round-to-week
+    [epoch]
+    (doto (epoch->cal epoch)
+      (.setTimeInMillis (long epoch))
+      (.add Calendar/DAY_OF_WEEK 4)
+      (clear-day-of-week)))
+
+  (defn round-to-day-of-month
+    [epoch]
+    (doto (epoch->cal epoch)
+      (.add Calendar/HOUR 12)
+      (clear-hour)))
+
+  (defn round-to-day-of-week
+    [epoch]
+    (doto (epoch->cal epoch)
+      (.add Calendar/HOUR 12)
+      (clear-hour)))
+
+  (defn round-to-hour
+    [epoch]
+    (doto (epoch->cal epoch)
+      (.add Calendar/MINUTE 30)
+      (clear-minute)))
+
+  )


untested cleanest error handling

untested cleanest error handling

--- src/mediakeys/hotkeys.clj
+++ src/mediakeys/hotkeys.clj
@@ -35,31 +35,31 @@
             ([key-update]
                 (swap! keys #(merge % key-update))))))

-(defn with-error! [action hotkey old-keys]
-    (put! keymaster-errors {:action action :hotkey hotkey})
-    (-> action old-keys make-keystroke))
-
-(defn register-keys [^Provider provider keys old-keys]
-    (let [return (chan)]
+(defn register-keys [^Provider provider keys]
+    (let [return (chan)
+          failed (atom false)]
         (doseq [[action hotkey] keys
-                 keystroke [(or (make-keystroke hotkey)
-                                (with-error! action hotkey old-keys))]]
-                (.register provider keystroke
-                    (proxy [HotKeyListener] []
-                        (onHotKey [event]
-                            (put! return action)))))
-        return))
+                 keystroke [(make-keystroke hotkey)]]
+                (if keystroke
+                    (.register provider keystroke
+                        (proxy [HotKeyListener] []
+                            (onHotKey [event]
+                                (put! return action))))
+                    (reset! failed true)))
+        (if @failed
+            nil
+            return)))

 (defn keypress-channel! [key-change]
     (let [old-keys (new-keys!)]
             (let [keys (new-keys! key-change)
                   provider (new-provider!)
-                  channel (register-keys provider keys old-keys)]
-                ; hmmmm, this won't save correctly with errors,
-                ; the errors will just set and set the wrong thing.
-                ; hmmmmmmmmmmmmmm
-                (save-keys! keys)
-                channel)))
+                  channel (register-keys provider keys)]
+                (if channel
+                    (do
+                        (save-keys! keys)
+                        channel)
+                    (register-keys (new-provider!) old-keys)))))

 (defcurried seed-channel! [seed channel]
     (println "yo seedding channel")


Keep TwitterClient running indefinitely.

I don't like this solution with a Thread/sleep, but at least it works in keeping
the application running instead of shutting down after 60 seconds. If anyone
knows a better solution, I'd be curious about it.

--- Clojure-Websockets/TwitterClient/src/clj/birdwatch_tc/main.clj
+++ Clojure-Websockets/TwitterClient/src/clj/birdwatch_tc/main.clj
@@ -36,4 +36,5 @@
   (pid/save (:pidfile-name conf))
   (pid/delete-on-shutdown! (:pidfile-name conf))
   (log/info "Application started, PID" (pid/current))
-  (alter-var-root #'system component/start))
+  (alter-var-root #'system component/start)
+  (Thread/sleep Long/MAX_VALUE)) ;; Without the Thread/sleep, the application stops after 60 seconds.


Version 0.2.21

Version 0.2.21

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject sbsk "0.2.21-SNAPSHOT"
+(defproject sbsk "0.2.21"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :license {:name "Eclipse Public License"


(maint) Remove JRuby 1.7 dependency conflict resolution entry

--- project.clj
+++ project.clj
@@ -56,10 +56,6 @@

                  [puppetlabs/jruby-utils "2.0.0"]
                  [puppetlabs/jruby-deps "9.1.16.0-1"]
-
-                 ;; JRuby 1.7.x and trapperkeeper (via core.async) both bring in
-                 ;; asm dependencies.  Deferring to clj-parent to resolve the version.
-                 [org.ow2.asm/asm-all]

                  [puppetlabs/trapperkeeper]
                  [puppetlabs/trapperkeeper-authorization]


Changed version to 0.1.0 for publishing

Changed version to 0.1.0 for publishing

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject dragonmark "0.1.0-SNAPSHOT"
+(defproject dragonmark "0.1.0"
   :description "Distributed CSP/core.async"
   :url "http://dragonmark.org"
   :license {:name "Eclipse Public License"


Revert "Actually pin JVM heap in CI (#1081)" (#1084)

This reverts commit c77be680e64e8262bef72c10c9500e4c13f38416.

--- project.clj
+++ project.clj
@@ -181,15 +181,15 @@
                                  ; docker reserves 4GB. here's how to customize it:
                                  ; - https://docs.travis-ci.com/user/enterprise/worker-configuration/#configuring-jobs-allowed-memory-usage
                                  ; this reserves 3GB jvm
-                                 (System/getenv "TRAVIS") (into ["-Xms3g"
-                                                                 "-Xmx3g"])
+                                 (System/getProperty "TRAVIS") (into ["-Xms3g"
+                                                                      "-Xmx3g"])
                                  ; we have 7GB RAM on Actions
                                  ; - https://docs.github.com/en/free-pro-team@latest/actions/reference/specifications-for-github-hosted-runners#supported-runners-and-hardware-resources
                                  ; docker reserves an unknown amount of RAM.
                                  ; reserving 3GB for jvm -- this might need tweaking as we learn
                                  ; more about docker on actions.
-                                 (System/getenv "GITHUB_ACTIONS") (into ["-Xms3g"
-                                                                         "-Xmx3g"]))
+                                 (System/getProperty "GITHUB_ACTIONS") (into ["-Xms3g"
+                                                                              "-Xmx3g"]))
                     :dependencies [[clj-http-fake ~clj-http-fake-version]
                                    [com.gfredericks/test.chuck ~test-chuck-version]
                                    [org.clojure/test.check ~test-check-version]


Version 2.3.4-SNAPSHOT

Version 2.3.4-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject wb-es "2.3.3"
+(defproject wb-es "2.3.4-SNAPSHOT"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :min-lein-version "2.7.0"


Version 0.2.3-SNAPSHOT

Version 0.2.3-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject wb-es "0.2.2"
+(defproject wb-es "0.2.3-SNAPSHOT"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :min-lein-version "2.7.0"


upgrade dependencies.

upgrade dependencies.

--- project.clj
+++ project.clj
@@ -7,13 +7,13 @@
                  [org.clojure/data.xml "0.0.8"]
                  [version-clj "0.1.2"]
                  [clj-aws-s3 "0.3.10" :exclusions [com.amazonaws/aws-java-sdk]]
-                 [com.amazonaws/aws-java-sdk-s3 "1.9.22"]
+                 [com.amazonaws/aws-java-sdk-s3 "1.9.23"]
                  [clj-time "0.9.0"]
                  [http-kit "2.1.19"]
                  [joda-time "2.7"]
                  [commons-codec "1.10"]
                  [commons-logging "1.2"]
-                 [potemkin "0.3.11"]]
+                 [potemkin "0.3.12"]]
   :exclusions [org.clojure/clojure joda-time]
   :profiles {:dev {:dependencies [[midje "1.6.3" :exclusions [clj-time commons-codec]]]
                    :plugins [[lein-midje "3.1.3"]]}


Belatedly update version to 0.6.0-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject http.async.client "0.5.3"
+(defproject http.async.client "0.6.0-SNAPSHOT"
   :name             "http.async.client"
   :description      "Asynchronous HTTP Client for Clojure"
   :url              "https://github.com/cch1/http.async.client"


lein-release plugin: preparing 0.86 release

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject exploud "0.86-SNAPSHOT"
+(defproject exploud "0.86"
   :description "Exploud service"
   :url "http://wikis.in.nokia.com/NokiaMusicArchitecture/Exploud"


Tweak uberjar cljsbuild config

Tweak uberjar cljsbuild config


lein-release plugin: preparing 0.58 release

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject shuppet "0.58-SNAPSHOT"
+(defproject shuppet "0.58"
   :description "Shuppet service"
   :url "http://wikis.in.nokia.com/NokiaMusicArchitecture/Shuppet"


Update to wunderboss build that works with destinations starting with / [IMMUTANT-482]

--- project.clj
+++ project.clj
@@ -82,7 +82,7 @@
                         compojure                  "1.1.8"

                         ;; org.projectodd.wunderboss  "0.1.0"
-                        org.projectodd.wunderboss  "1.x.incremental.114"
+                        org.projectodd.wunderboss  "1.x.incremental.118"
                         ;; org.projectodd.wunderboss  "0.2.0-SNAPSHOT"

                         org.immutant               :version}}


(maint) Bump to ezbake 1.1.15

(maint) Bump to ezbake 1.1.15

This commit bumps to the latest (legacy) ezbake version. This version adds a
Gemfile to the resulting package build and makes use of the packaging gem,
rather than cloning the packaging repo.

--- project.clj
+++ project.clj
@@ -125,7 +125,7 @@
                                                [puppetlabs/puppetserver ~ps-version]
                                                [puppetlabs/trapperkeeper-webserver-jetty9 ~tk-jetty-version]
                                                [org.clojure/tools.nrepl "0.2.3"]]
-                      :plugins [[puppetlabs/lein-ezbake "0.5.0"]]
+                      :plugins [[puppetlabs/lein-ezbake "1.1.15"]]
                       :name "puppetserver"}
              :uberjar {:aot [puppetlabs.trapperkeeper.main]
                        :dependencies [[puppetlabs/trapperkeeper-webserver-jetty9 ~tk-jetty-version]]}


Upgrade to 0.9.7-alpha4.

Upgrade to 0.9.7-alpha4.

--- project.clj
+++ project.clj
@@ -1,10 +1,10 @@
-(defproject workshop "0.9.7-alpha2"
+(defproject workshop "0.9.7-alpha4"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.8.0"]
                  [org.clojure/core.async "0.2.374"]
                  ^{:voom {:repo "git@github.com:onyx-platform/onyx.git" :branch "master"}}
-                 [org.onyxplatform/onyx "0.9.7-alpha2"]
+                 [org.onyxplatform/onyx "0.9.7-alpha4"]
                  [org.slf4j/slf4j-api "1.7.12"]
                  [org.slf4j/slf4j-nop "1.7.12"]]
   :profiles {:dev {:dependencies [[org.clojure/tools.namespace "0.2.10"]


(maint) Upgrade to Jetty 9.4.44 - trivial fixes and dependency bumps

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(def jetty-version "9.4.43.v20210629")
+(def jetty-version "9.4.44.v20210927")

 (defproject puppetlabs/trapperkeeper-webserver-jetty9 "4.2.2-SNAPSHOT"
   :description "A jetty9-based webserver implementation for use with the puppetlabs/trapperkeeper service framework."


Version 1.5.1

Version 1.5.1

--- project.clj
+++ project.clj
@@ -2,7 +2,7 @@
 (def ks-version "1.3.0")
 (def jetty-version "9.2.10.v20150310")

-(defproject puppetlabs/trapperkeeper-webserver-jetty9 "1.5.1-SNAPSHOT"
+(defproject puppetlabs/trapperkeeper-webserver-jetty9 "1.5.1"
   :description "A jetty9-based webserver implementation for use with the puppetlabs/trapperkeeper service framework."
   :url "https://github.com/puppetlabs/trapperkeeper-webserver-jetty9"
   :license {:name "Apache License, Version 2.0"


Factor handle-command function a bit, add comments.

--- src/mvxcvi/vault/tool.clj
+++ src/mvxcvi/vault/tool.clj
@@ -91,6 +91,19 @@

 ;; COMMAND TREE EXECUTION

+(defn- usage-banner
+  "Builds a usage banner given a command map."
+  [branch cmd]
+  (let [{:keys [usage desc commands]} cmd]
+    (str "Usage: " (string/join " " branch) " " usage "\n\n" desc
+         (when (seq commands)
+           (str "\n\n Subcommand   Description\n"
+                    " ----------   -----------\n"
+                (->> commands
+                     (map #(format " %10s   %s" (:name %) (:desc %)))
+                     (string/join "\n")))))))
+
+
 (defn- handle-command
   "Handles a sequence of arguments following a command tree structure."
   ([cmd args]
@@ -98,40 +111,40 @@

   ([cmd branch opts args]
    (if (some #{"help"} args)
+     ; Recur with :help set in opts and the "help" argument removed.
      (recur cmd branch
             (assoc opts :help true)
             (filter #(not= "help" %) args))
+
      (let [branch (conj branch (:name cmd))
            subcmds (:commands cmd)
            subcmd-names (apply hash-set (map :name subcmds))
-           usage (str "Usage: " (string/join " " branch) " " (:usage cmd)
-                      "\n\n" (:desc cmd)
-                      (when (seq subcmds)
-                        (str "\n\n Subcommand   Description\n"
-                                 " ----------   -----------\n"
-                             (->> subcmds
-                                  (map #(format " %10s   %s" (:name %) (:desc %)))
-                                  (string/join "\n")))))
-
+           usage (usage-banner branch cmd)
+
+           ; Test for a subcommand invocation in the argument list.
            [cmd-args [subcmd & subcmd-args]]
            (split-with (complement subcmd-names) args)

+           ; Parse arguments with command specs, if present.
            [cmd-opts action-args banner]
            (if-let [specs (:specs cmd)]
              (apply cli cmd-args usage (:specs cmd))
              [opts cmd-args usage])

+           ; Merge parsed opts and initialize them.
            opts (merge opts cmd-opts (when (:help opts) {:help true}))
            opts ((or (:init cmd) identity) opts)]

        ;(clojure.pprint/pprint {:branch branch, :opts opts, :action-args action-args, :subcmd subcmd, :subcmd-args subcmd-args})

        (if-let [subcmd (some #(and (= (:name %) subcmd) %) subcmds)]
+         ; Recur on selected subcommand.
          (if-not (empty? action-args)
            (throw (IllegalArgumentException.
                     (str "Unparsed arguments before command: " action-args)))
            (recur subcmd branch opts subcmd-args))

+         ; Act on given command, either to print help or execute the action.
          (cond (:help opts)
                (do (println banner)
                    (System/exit 0))


buildnumber support for jenkins

buildnumber support for jenkins

--- project.clj
+++ project.clj
@@ -1,4 +1,11 @@
-(defproject featured "0.1.0-SNAPSHOT"
+(def feature-version "0.1")
+(def build-version (or (System/getenv "BUILD_NUMBER") "HANDBUILT"))
+(def release-version (str feature-version "." build-version))
+(def project-name "featured")
+
+(defproject featured feature-version
+  :uberjar-name ~(str project-name "-" release-version "-standalone.jar")
+  :manifest {"Implementation-Version" ~release-version}
   :description "PDOK - No FME"
   :url "http://github.so.kadaster.nl/PDOK/featured"
   :license {:name "Eclipse Public License"
@@ -32,15 +39,17 @@
                  [ring/ring-json "0.3.1"]
                  [xalan/xalan "2.7.2"]]
   :plugins [[lein-environ "1.0.0"]
-            [lein-ring "0.8.13"]]
-  :ring {:handler pdok.featured.core/app}
+            [lein-ring "0.9.6" ]]
+  :ring {:handler pdok.featured.core/app
+         :uberwar-name ~(str project-name "-" release-version "-standalone.war")}
   :main ^:skip-aot pdok.featured.core
   :target-path "target/%s"
   :source-paths ["src/main/clojure"]
   :java-source-paths ["src/main/java"]
   :resource-paths ["resources" "src/main/resources"]
   :test-paths ["src/test/clojure"]
-  :aliases {"build" ["do" ["compile"] ["test"] ["uberjar"]]}
+  :aliases {"build" ["do" ["compile"] ["test"]
+                     ["ring" "uberwar"]]}
   :profiles {:uberjar {:aot :all}
              :dev {:dependencies [[javax.servlet/servlet-api "2.5"]
                                   [ring-mock "0.1.5"]]}})


Update dependencies.

Update dependencies.

--- project.clj
+++ project.clj
@@ -15,7 +15,7 @@
   :dependencies [
     [org.clojure/clojure "1.8.0-alpha5"] ; Lisp on the JVM http://clojure.org/documentation
     [org.clojure/core.match "0.2.2"] ; Erlang-esque pattern matching https://github.com/clojure/core.match
-    [defun "0.2.0-RC"] ; Erlang-esque pattern matching for Clojure functions https://github.com/killme2008/defun
+    [defun "0.2.0"] ; Erlang-esque pattern matching for Clojure functions https://github.com/killme2008/defun
     [ring/ring-devel "1.4.0"] ; Web application library https://github.com/ring-clojure/ring
     [ring/ring-core "1.4.0"] ; Web application library https://github.com/ring-clojure/ring
     [jumblerg/ring.middleware.cors "1.0.1"] ; CORS library https://github.com/jumblerg/ring.middleware.cors
@@ -25,7 +25,7 @@
     [rethinkdb "0.10.1"] ; RethinkDB client for Clojure https://github.com/apa512/clj-rethinkdb
     [prismatic/schema "1.0.1"] ; Data validation https://github.com/Prismatic/schema
     [environ "1.0.1"] ; Get environment settings from different sources https://github.com/weavejester/environ
-    [com.taoensso/timbre "4.1.1"] ; Logging https://github.com/ptaoussanis/timbre
+    [com.taoensso/timbre "4.1.2"] ; Logging https://github.com/ptaoussanis/timbre
     [raven-clj "1.3.1"] ; Clojure interface to Sentry error reporting https://github.com/sethtrain/raven-clj
     [clj-http "2.0.0"] ; HTTP client https://github.com/dakrone/clj-http
  ]
@@ -72,7 +72,7 @@
         [lein-kibit "0.1.2"] ; Static code search for non-idiomatic code https://github.com/jonase/kibit
         [lein-checkall "0.1.1"] ; Runs bikeshed, kibit and eastwood https://github.com/itang/lein-checkall
         [lein-pprint "1.1.2"] ; pretty-print the lein project map https://github.com/technomancy/leiningen/tree/master/lein-pprint
-        [lein-ancient "0.6.7"] ; Check for outdated dependencies https://github.com/xsc/lein-ancient
+        [lein-ancient "0.6.8-SNAPSHOT"] ; Check for outdated dependencies https://github.com/xsc/lein-ancient
         [lein-spell "0.1.0"] ; Catch spelling mistakes in docs and docstrings https://github.com/cldwalker/lein-spell
         [lein-deps-tree "0.1.2"] ; Print a tree of project dependencies https://github.com/the-kenny/lein-deps-tree
         [lein-cljfmt "0.3.0"] ; Code formatting https://github.com/weavejester/cljfmt
@@ -112,7 +112,7 @@
     "start!" ["with-profile" "prod" "do" "build," "init-db," "run"] ; start a server in production
     "spell!" ["spell" "-n"] ; check spelling in docs and docstrings
     "bikeshed!" ["bikeshed" "-v" "-m" "120"] ; code check with max line length warning of 120 characters
-    "ancient" ["with-profile" "dev" "do" "ancient" ":allow-qualified," "ancient" ":plugins" ":allow-qualified"] ; check for out of date dependencies
+    "ancient!" ["do" "ancient" ":allow-qualified," "ancient" ":plugins" ":allow-qualified"] ; check for out of date dependencies
   }

   ;; ----- Code check configuration -----


Bumped project version

Bumped project version


Update plugins

Update plugins

--- project.clj
+++ project.clj
@@ -7,9 +7,9 @@
   :dependencies [[clj-glob "1.0.0" :exclusions [org.clojure/clojure]]
                  [lein-npm "0.4.0" :exclusions [org.clojure/clojure]]]

-  :plugins [[jonase/eastwood "0.1.5" :exclusions [org.clojure/clojure]]
+  :plugins [[jonase/eastwood "0.2.1" :exclusions [org.clojure/clojure]]
             [lein-kibit "0.0.8" :exclusions [org.clojure/clojure]]
-            [lein-bikeshed "0.1.8" :exclusions [org.clojure/clojure]]
+            [lein-bikeshed "0.2.0" :exclusions [org.clojure/clojure]]
             [lein-ancient "0.5.5"]]

   :profiles {


Version 1.5.4-SNAPSHOT

Version 1.5.4-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject org.zalando.stups/friboo "1.5.3"
+(defproject org.zalando.stups/friboo "1.5.4-SNAPSHOT"
   :description "A utility library to write microservices in clojure."
   :url "https://github.com/zalando-stups/friboo"


add the enlive clojar and midje as a testing library

--- project.clj
+++ project.clj
@@ -3,4 +3,7 @@
   :url "https://github.com/philippkueng/watney"
   :license {:name "MIT"
             :url "http://opensource.org/licenses/MIT"}
-  :dependencies [[org.clojure/clojure "1.6.0"]])
+  :dependencies [[org.clojure/clojure "1.6.0"]
+                 [enlive "1.1.6"]]
+  :profiles {:dev {:dependencies [[midje "1.7.0" :exclusions [org.clojure/clojure]]]
+                   :plugins [[lein-midje "3.1.3"]]}})


normalize path

normalize path

--- project.clj
+++ project.clj
@@ -2,7 +2,7 @@
   :description "A schema-free database optimized for agile development."
   :url "http://github.com/mmcgrana/fleetdb"
   :source-path "src/clj"
-  :java-source-path "src/jvm/"
+  :java-source-path "src/jvm"
   :javac-fork "true"
   :aot [fleetdb.server]
   :dependencies


**NB**: Bump Nippy dependency (2.6.3->2.7.0)

--- project.clj
+++ project.clj
@@ -14,7 +14,7 @@
   [[org.clojure/clojure         "1.4.0"]
    [com.taoensso/encore         "1.15.0"]
    [com.taoensso/timbre         "3.3.1"]
-   [com.taoensso/nippy          "2.6.3"]
+   [com.taoensso/nippy          "2.7.0"]
    [org.apache.commons/commons-pool2 "2.2"]
    [commons-codec/commons-codec "1.9"]
    [org.clojure/data.json       "0.2.5"]]


Update deps.

Update deps.

--- project.clj
+++ project.clj
@@ -6,7 +6,7 @@
   :dependencies [[org.clojure/clojure "1.6.0"]
                  [com.mdrogalis/onyx "0.2.0-SNAPSHOT"]
                  [com.datomic/datomic-free "0.9.4707"]]
-  :profiles {:dev {:dependencies [[midje "1.6.2"]
+  :profiles {:dev {:dependencies [[midje "1.6.2" :exclusions [joda-time]]
                                   [org.hornetq/hornetq-core-client "2.4.0.Final"]
                                   [org.clojure/data.fressian "0.2.0"]]
                    :plugins [[lein-midje "3.1.3"]]}})


RS | #56 | Add selenium and clj-webdriver to project.clj and fix dependency issues around xml-apis

--- project.clj
+++ project.clj
@@ -15,7 +15,8 @@
                  [ring/ring-anti-forgery "1.0.0"]
                  [ring/ring-headers "0.1.2"]
                  [org.apache.httpcomponents/httpclient "4.3.5"]
-                 [com.cemerick/friend "0.2.1" :exclusions [robert/hooke]]
+                 [xml-apis "1.4.01"]
+                 [com.cemerick/friend "0.2.1" :exclusions [robert/hooke xml-apis]]
                  [de.ubercode.clostache/clostache "1.4.0"]
                  [enlive "1.1.5"]
                  [com.taoensso/tower "3.0.2"]
@@ -33,6 +34,13 @@
                                   :timeout 120000}
                    :dependencies [[midje "1.6.3"]
                                   [ring/ring-mock "0.2.0"]
+                                  [clj-webdriver "0.6.1" :exclusions [org.seleniumhq.selenium/selenium-java
+                                                                      org.seleniumhq.selenium/selenium-server
+                                                                      org.seleniumhq.selenium/selenium-remote-driver
+                                                                      xml-apis]]
+                                  [org.seleniumhq.selenium/selenium-server "2.43.0"]
+                                  [org.seleniumhq.selenium/selenium-java "2.43.0"]
+                                  [org.seleniumhq.selenium/selenium-remote-driver "2.43.0"]
                                   [http-kit.fake "0.2.1"]
                                   [javax.servlet/servlet-api "2.5"]
                                   [peridot "0.3.1"]]


(maint) Update version to 6.5.1-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(def pdb-version "6.5.0")
+(def pdb-version "6.5.1-SNAPSHOT")
 (def clj-parent-version "2.6.0")

 (defn true-in-env? [x]


Release

Release

--- project.clj
+++ project.clj
@@ -1,6 +1,6 @@
 ;; Copyright © 2015, JUXT LTD.

-(defproject yada "1.1.40"
+(defproject yada "1.1.41"
   :description "A powerful Clojure web library, full HTTP, full async"
   :url "http://github.com/juxt/yada"
   :license {:name "The MIT License"


update version number

update version number

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject domshot "0.2.0"
+(defproject domshot "0.2.1"
   :description "Take a snapshot of your dom, a domshot"
   :url "https://github.com/dillonforrest/domshot"
   :license {:name "MIT"


Bump version to 0.15.6-SNAPSHOT

Bump version to 0.15.6-SNAPSHOT

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject clojars-web "0.15.5"
+(defproject clojars-web "0.15.6-SNAPSHOT"
   :dependencies [[org.clojure/clojure "1.5.1"]
                  [org.clojure/tools.cli "0.2.1"]
                  [org.apache.maven/maven-model "3.0.4"


Version 0.1.2

Version 0.1.2

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject expound "0.1.2-SNAPSHOT"
+(defproject expound "0.1.2"
   :description "Human-optimized error messages for clojure.spec"
   :url "https://github.com/bhb/expound"
   :license {:name "Eclipse Public License"


Manually bump version

Manually bump version

It [looks like](https://travis-ci.org/lspector/Clojush/builds/98515566#L634) version 2.0.47 was deployed already somehow to Clojars

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject clojush "2.0.47-SNAPSHOT"
+(defproject clojush "2.0.48-SNAPSHOT"
   :description "The Push programming language and the PushGP genetic programming
                 system implemented in Clojure.
                 See http://hampshire.edu/lspector/push.html"


added clojure fmt plugin

added clojure fmt plugin

--- project.clj
+++ project.clj
@@ -20,7 +20,8 @@

   :plugins [[lein-cljsbuild "1.1.0"]
             [lein-npm "0.4.0"]
-            [com.cemerick/clojurescript.test "0.3.3"]]
+            [com.cemerick/clojurescript.test "0.3.3"]
+            [lein-cljfmt "0.3.0"]]

   :source-paths ["src"]


Bump dependencies including aeron

Bump dependencies including aeron

--- project.clj
+++ project.clj
@@ -13,15 +13,15 @@
                              :sign-releases false}}
   :dependencies [[org.clojure/clojure "1.7.0"]
                  [org.clojure/core.async "0.2.371"]
-                 [org.apache.curator/curator-framework "2.9.0"]
-                 [org.apache.curator/curator-test "2.9.0"]
+                 [org.apache.curator/curator-framework "2.9.1"]
+                 [org.apache.curator/curator-test "2.9.1"]
                  [clj-tuple "0.2.2"]
                  [com.stuartsierra/dependency "0.2.0"]
                  [com.stuartsierra/component "0.3.0"]
                  [com.taoensso/timbre "4.1.4"]
                  [com.taoensso/nippy "2.10.0"]
-                 [uk.co.real-logic/aeron-all "0.1.5"]
-                 [prismatic/schema "1.0.1"]
+                 [uk.co.real-logic/aeron-all "0.2"]
+                 [prismatic/schema "1.0.3"]
                  [org.apache.zookeeper/zookeeper "3.4.6"
                   :exclusions [org.slf4j/slf4j-log4j12]]
                  [org.apache.bookkeeper/bookkeeper-server "4.3.1"


fix missed merge conflict

fix missed merge conflict


0.1.3-SNAPSHOT


Release version 0.8.1.0-alpha9.

Release version 0.8.1.0-alpha9.


add ex-data from ex-info if it's there

add ex-data from ex-info if it's there

--- src/yeller_clojure_client.clj
+++ src/yeller_clojure_client.clj
@@ -95,6 +95,11 @@
     (add-environment extra)
     (add-location extra)))

+(defn add-ex-data [exception current-custom-data]
+  (if-let [data (ex-data exception)]
+    (merge {:ex-data data} current-custom-data)
+    current-custom-data))
+
 (defn report
   "reports an exception to yeller's servers.
    Optionally takes a map of extra detail. Currently supported extra detail:
@@ -113,10 +118,9 @@
        (.report client
                 exception
                 detail
-                (stringify-keys (:custom-data extra {}))))
+                (stringify-keys (add-ex-data exception (:custom-data extra {})))))
      (.report client
               exception
-              (stringify-keys (dissoc extra
-                                      :environment
-                                      :location
-                                      :url))))))
+              (stringify-keys (add-ex-data
+                                exception
+                                (:custom-data extra {})))))))


x-session: Added clear-handlers! function

--- src/overtime/xsession.clj
+++ src/overtime/xsession.clj
@@ -59,30 +59,35 @@
         (doseq [[_k f] handlers] (f (:velocity event)))))
     hdlr-key))

-(defn start [] (map set-midi-event-hdlr [:control-change :note-on] [::cc-hdlr ::note-hdlr]))
-(defn stop [] (map ot/remove-event-handler [::cc-hdlr ::note-hdlr]))
+(defn start [] (doseq [[type hdlr-key] [[:control-change ::cc-hdlr] [:note-on ::note-hdlr]]] (set-midi-event-hdlr type hdlr-key)))
+(defn stop [] (doseq [hdlr-key [::cc-hdlr ::note-hdlr]] (ot/remove-event-handler hdlr-key)))

 (defn add-handler!
-  [xs-event key f]
-  (swap! handlers-per-knob update-in [xs-event] assoc key f))
+  [knob key f]
+  (swap! handlers-per-knob assoc-in [knob key] f))

 (defn remove-handler!
-  [xs-event key]
-  (swap! handlers-per-knob update-in [xs-event] dissoc key))
+  [knob key]
+  (swap! handlers-per-knob update knob dissoc key))
+
+(defn clear-handlers!
+  [key]
+  (doseq [knob (keys @handlers-per-knob)] (remove-handler! knob key)))

 (defn dump-handlers [] (doseq [[knob-key val] @handlers-per-knob] (println knob-key "=>" (keys val))))

 (comment
   (start)
   (stop)
-  (add-handler! :1-left :foo #(println "1-left:" %))
-  (add-handler! :1-left :foo #(println "1-left other:" %))
-  (add-handler! :1-left :bar #(println "1-left bar:" %))
-  (remove-handler! :1-left :bar)
-  (add-handler! :high-left :foo #(println "high-left:" %))
-  (add-handler! :2-left :foo #(println "2-left:" %))
-  (add-handler! :mid-left :foo #(println "mid-left:" %))
-  (add-handler! :3-left :foo #(println "3-left:" %))
-  (add-handler! :volume-left :foo #(println "volume-left:" %))
-  (add-handler! :headphone-left :foo (fn [_x] (println "headphone-left")))
+  (add-handler! :1-left :instr1 #(println "1-left:" %))
+  (add-handler! :1-left :instr1 #(println "1-left other:" %))
+  (add-handler! :1-left :instr2 #(println "1-left bar:" %))
+  (remove-handler! :1-left :instr2)
+  (add-handler! :high-left :instr1 #(println "high-left:" %))
+  (add-handler! :2-left :instr1 #(println "2-left:" %))
+  (add-handler! :mid-left :instr1 #(println "mid-left:" %))
+  (add-handler! :3-left :instr1 #(println "3-left:" %))
+  (add-handler! :volume-left :instr1 #(println "volume-left:" %))
+  (add-handler! :headphone-left :instr1 (fn [_x] (println "headphone-left")))
+  (clear-handlers! :instr1)
   (dump-handlers))


Another unused import

Another unused import

--- src/wishlistd/views/wishlist.clj
+++ src/wishlistd/views/wishlist.clj
@@ -1,8 +1,7 @@
 (ns wishlistd.views.wishlist
   (:require [wishlistd.views.common :as common]
             [wishlistd.json :as response])
-  (:use noir.core
-        wishlistd.models.redis))
+  (:use wishlistd.models.redis))

 (defn main-page []
   (common/layout ""))


Fixup mail model for clojure-mail 0.1.6

Fixup mail model for clojure-mail 0.1.6

--- src/yetibot/core/models/mail.clj
+++ src/yetibot/core/models/mail.clj
@@ -7,7 +7,7 @@
     [inflections.core :refer [pluralize]]
     [yetibot.core.config :refer [get-config]]
     [clojure-mail
-     [core :refer :all]
+     [core :as mail]
      [message :as msg]]))

 (def mail-schema
@@ -23,9 +23,8 @@

 ;; TODO - move into start
 (when (configured?)
-  (def store (gen-store))
   (let [{:keys [user pass]} (:value (config))]
-    (auth! user pass)))
+    (def store (mail/store user pass))))

 (def pool (mk-pool))
 (def poll-interval (* 1000 60))
@@ -52,9 +51,9 @@
         (fmt-messages messages)))

 (defn fetch-unread-mail []
-  (let [messages (unread-messages folder)]
+  (let [messages (mail/unread-messages folder)]
     (when-not (empty? messages)
-      (mark-all-read folder)
+      (mail/mark-all-read folder)
       (fmt-you-have-mail messages))))

 (defn fetch-and-announce-unread-mail []


:construction: Implement page history query using new sql builder.

--- backend/src/uxbox/services/pages.clj
+++ backend/src/uxbox/services/pages.clj
@@ -11,6 +11,7 @@
    [uxbox.db :as db]
    [uxbox.util.spec :as us]
    [uxbox.services.core :as sv]
+   [uxbox.util.sql :as sql]
    [uxbox.util.time :as dt]
    [uxbox.util.blob :as blob]
    [uxbox.util.uuid :as uuid]))
@@ -69,42 +70,28 @@

 ;; --- Query: Page History

-;; (def ^:private page-history-sql
-;;   "select ph.*
-;;      from pages_history as ph
-;;     where ph.user_id = $1
-;;       and ph.page_id = $2
-;;       and ph.version < $3
-;;     order by ph.version desc
-;;     limit $4")
-
-;; (defn get-page-history
-;;   [{:keys [id page-id user since max pinned]
-;;     :or {since Long/MAX_VALUE max 10}}]
-;;   (let [sqlv [page-history-sql user page-id since
-;;   (let [sqlv (sql/get-page-history {:user user
-;;                                     :page id
-;;                                     :since since
-;;                                     :max max
-;;                                     :pinned pinned})]
-;;     (->> (db/fetch conn sqlv)
-;;          ;; TODO
-;;          (map decode-row))))
-
-;; (s/def ::max ::us/integer)
-;; (s/def ::pinned ::us/boolean)
-;; (s/def ::since ::us/integer)
-
-;; (s/def ::page-history
-;;   (s/keys :req-un [::us/id ::user]
-;;           :opt-un [::max ::pinned ::since]))
-
-;; (sv/defquery :page-history
-;;   {:doc "Retrieve page history."
-;;    :spec ::page-history}
-;;   [params]
-;;   (with-open [conn (db/connection)]
-;;     (get-page-history conn params)))
+(s/def ::page-id ::us/uuid)
+(s/def ::max ::us/integer)
+(s/def ::pinned ::us/boolean)
+(s/def ::since ::us/integer)
+
+(s/def ::page-history
+  (s/keys :req-un [::page-id ::user]
+          :opt-un [::max ::pinned ::since]))
+
+(sv/defquery ::page-history
+  [{:keys [page-id user since max pinned] :or {since Long/MAX_VALUE max 10}}]
+  (let [sql (-> (sql/from ["pages_history" "ph"])
+                (sql/select "ph.*")
+                (sql/where ["ph.user_id = ?" user]
+                           ["ph.page_id = ?" page-id]
+                           ["ph.version < ?" since]
+                           (when pinned
+                             ["ph.pinned = ?" true]))
+                (sql/order "ph.version desc")
+                (sql/limit max))]
+    (-> (db/query db/pool (sql/fmt sql))
+        (p/then (partial mapv decode-row)))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Mutations


poking at DSL definitions

poking at DSL definitions

--- src/push/util/general.clj
+++ src/push/util/general.clj
@@ -22,5 +22,10 @@
   [args]
   (let [stringless (if (string? (first args)) (rest args) args)]
     (if (some keyword? stringless)
-      (into '() (butlast (first (split-with (complement keyword?) (reverse stringless)))))
-      stringless)))
+      (into '()
+        (butlast
+          (first
+            (split-with (complement keyword?) (reverse stringless))
+            )))
+      stringless
+      )))