Fix: def is app global, let is scoped

Fix: def is app global, let is scoped

Also, using ^:dynamic didn't seem to affect
the scope of function defined variable:
it stayed global.

This version seems to work

--- src/cljs/repodoc/core.cljs
+++ src/cljs/repodoc/core.cljs
@@ -78,13 +78,11 @@
   "Creates closure based database
   of the map given as data"
   [data]
-  (def db (atom data))
-  {:update (fn [key val]
-              (println @db db key val)
-              (swap! db #(assoc % key val)))
-   :query (fn [key]
-             (println @db db key)
-             (get @db key))})
+  (let [cdb (atom data)]
+           {:update (fn [key val]
+                  (swap! cdb #(assoc % key val)))
+            :query (fn [key]
+                 (get @cdb key))}))

 ;; Handlers


long time no commit, got visible working

--- src/cljs/unfolds/core.cljs
+++ src/cljs/unfolds/core.cljs
@@ -4,6 +4,7 @@
             [om.dom :as dom :include-macros true]
             [cljs.core.async :refer [put! chan <!]]))

+;; TODO: Move this else where, just data.
 (def basic-list
   "come get give go keep let make put seem take be do have say see
   send may will about across after against among at before between by
@@ -87,19 +88,45 @@
   public rough sad safe secret short shut simple slow small soft solid
   special strange thin white wrong")

-(defonce app-state (atom {:items ["foo"
-                                  "Basic English is an English-based controlled language created by linguist and philosopher Charles Kay Ogden as an international auxiliary language, and as an aid for teaching English as a second language. Basic English is, in essence, a simplified subset of regular English. It was presented in Ogden's book Basic English: A General Introduction with Rules and Grammar (1930).
-
-Ogden's Basic, and the concept of a simplified English, gained its greatest publicity just after the Allied victory in World War II as a means for world peace. Although Basic English was not built into a program, similar simplifications have been devised for various international uses. Ogden's associate I. A. Richards promoted its use in schools in China.[1] More recently, it has influenced the creation of Voice of America's Special English for news broadcasting, and Simplified English, another English-based controlled language designed to write technical manuals."
-                                  #_"Foobar [[foo|blitz]] lolophone hoptigoff."]}))
+;; TODO: Move this too.
+;; Old with link "Foobar [[foo|blitz]] lolophone hoptigoff."
+
+(defonce app-state (atom {:search "Foobar"
+                          :word-map {"Ogden" [0]}
+                          :visible [0]
+                          :items [[0 "Basic English is an English-based controlled language created by linguist and philosopher Charles Kay Ogden as an international auxiliary language, and as an aid for teaching English as a second language. Basic English is, in essence, a simplified subset of regular English. It was presented in Ogden's book Basic English: A General Introduction with Rules and Grammar (1930).
+
+Ogden's Basic, and the concept of a simplified English, gained its greatest publicity just after the Allied victory in World War II as a means for world peace. Although Basic English was not built into a program, similar simplifications have been devised for various international uses. Ogden's associate I. A. Richards promoted its use in schools in China. More recently, it has influenced the creation of Voice of America's Special English for news broadcasting, and Simplified English, another English-based controlled language designed to write technical manuals."]
+                                  [1 "Foo"]
+                                  [2 "Hello there"]]}))
+
+;; before items looked like this
+;; :items [{:id "foo" :text "bar"}] ;; dammit!
+
+(def id-atom (atom 0))
+(swap! id-atom inc) ;; first item
+(swap! id-atom inc) ;; second item

 (defn add-item [app owner]
-  (let [new-item (-> (om/get-node owner "new-item")
-                     .-value)]
+  (let [new-item-text (-> (om/get-node owner "new-item")
+                     .-value)
+        new-item {:id (swap! id-atom inc) :text new-item-text}]
     (when new-item
       (om/transact! app :items #(conj % new-item)))))
-
-(defn handle-change [e owner {:keys [text]}]
+;; Do this when adding
+;;(str (naive-key-extractor item) ", ")
+
+(defn search [app owner]
+  (let [search (-> (om/get-node owner "search")
+                   .-value)]
+    (when search
+      (om/transact! app :search (fn [] search)))))
+
+;; also filter views?
+
+;; TODO: when adding note, add/merge words-item to word-map
+
+(defn handle-item-change [e owner {:keys [text]}]
   (let [value (.. e -target -value)
         count (count value)]
     (om/set-state! owner :count count)
@@ -107,6 +134,11 @@
       (om/set-state! owner :text text)
       (om/set-state! owner :text value))))

+;; This doesn't change the actual thing
+(defn handle-search-change [e owner {:keys [text]}]
+  (let [value (.. e -target -value)]
+    (om/set-state! owner :text text)))
+
 (def link-re #"\[\[([a-z]+)\|([a-z]+)\]\]")
 (defn link [href str] (dom/a #js {:href href} str))
 (defn link? [s] (if (re-find link-re s) true false))
@@ -119,16 +151,16 @@
     (link (get-href x) (get-title x))
     (str " " x " ")))

-(defn prepare-item [s] (vec (map str-or-link (split-words s))))
+;;(defn prepare-item [s] (vec (map str-or-link (split-words s))))

 ;; td-idf, 1-gram
 ;; now with basic-list! (or not, does that help here - more like remove those?)
 ;; and go to lower-case?
 ;; should also have id in it
-#_(defn naive-key-extractor [str]
+(defn naive-key-extractor [str]
     (vec (map first
               (filter #(= (second %) 1)
-                      (frequencies (split-words str))))))
+                      (frequencies (split-words (:text str)))))))

 (defn make-word-map [str id]
   (zipmap (map first
@@ -137,15 +169,23 @@
 ;; then merge
 ;; should be elsewhere?

-(defn item-view [item owner]
+#_(defn item-view [item owner]
   (reify
     om/IRender
     (render [this]
       (dom/li nil
               (apply dom/div nil
-                     (str item)
+                     (str (:text item))
                      (str (naive-key-extractor item) ", ")
                      #_(prepare-item item))))))
+
+(defn visible-item-view [item owner]
+  (reify
+    om/IRender
+    (render [this]
+      (dom/li nil
+              (apply dom/div nil
+                     (str (second item)))))))

 (defn app-view [app owner]
   (reify
@@ -153,15 +193,23 @@
     (render-state [this state]
       (dom/div nil
                #_(dom/h1 nil (str (:text app) " " (:count state)))
+               (dom/p nil
+                      (str "Search: ")
+                      (dom/input #js {:value (:search state)
+                                      :type "text"
+                                      :ref "search"
+                                      :onChange #(handle-search-change % owner state)})
+                      (dom/button #js {:onClick #(search app owner)} "Search"))
                (dom/textarea #js
                               {:value (:text state)
                                :ref "new-item"
                                :rows "12" :cols "80"
-                               :onChange #(handle-change % owner state)})
-               (dom/button #js
-                            {:onClick #(add-item app owner)} "Add item")
+                               :onChange #(handle-item-change % owner state)})
+               (dom/button #js {:onClick #(add-item app owner)} "Add item")
                (apply dom/ul nil
-                      (om/build-all item-view (:items app)))))))
+                      (om/build-all visible-item-view
+                                    ;; into vec?
+                                    (filter (fn [[i _]] (contains? (:visible app) i)) (:items app))))))))

 (defn main []
   (om/root app-view


search results link to item

search results link to item

--- src/cljs/unfolds/core.cljs
+++ src/cljs/unfolds/core.cljs
@@ -87,7 +87,13 @@
         new-item [(swap! id-atom inc) new-item-text]]
     (when new-item
       (om/transact! app :word-map #(merge-with union % (make-word-map new-item)))
-      (om/transact! app :items #(conj % new-item)))))
+      (om/transact! app :items #(conj % new-item))
+      ;; TODO: transact to server
+      ;; XXX: Why doesn't it update the url field? Manually?
+      (secretary/dispatch! (str "#/notes/" (first new-item)))
+      #_(put! comm-alt {:tag :notes
+                        :value {:id (first new-item)}}))))
+;; show item

 (defn search [app owner]
   (let [search (-> (om/get-node owner "search")
@@ -114,13 +120,15 @@
               (filter #(= (second %) 1)
                       (frequencies (split-words (:text str)))))))

+;; TODO: Link to view item, just do preview
+;; TODO: Change name of fn
 (defn visible-item-view [item owner]
   (reify
     om/IRender
     (render [this]
       (dom/li nil
-              (apply dom/div nil
-                     (str (second item)))))))
+              (dom/p nil (second item) " "
+                     (link (str "#/notes/" (first item)) "link"))))))

 ;; TODO: with links
 (defn item-view [app owner]
@@ -195,13 +203,17 @@
                         (apply dom/ul nil
                                (om/build-all visible-item-view
                                              (filter (fn [[i _]] (in? (:visible app) i))
-                                                     (:items app)))))
+                                                     (:items app))))
+                        (dom/p nil "Indexed words: "
+                               (str (map first (:word-map @app-state))))
+                        )

                ;; View
                (om/build item-view app)

                ;; Add
                (dom/div #js {:style (hidden (-> app :hidden :add))}
+                        (dom/p nil (str "" (:count state) "/1000"))
                         (dom/textarea #js
                                       {:value (:text state)
                                        :ref "new-item"


Updated entry id documentation based on GCMD feedback.

--- src/cmr/umm/collection.clj
+++ src/cmr/umm/collection.clj
@@ -10,8 +10,7 @@

 (defrecord UmmCollection
   [
-   ;; A combination of shortname and version id
-   ;; TODO how do we combine them? I've emailed Katie for clarification.
+   ;; A combination of shortname and version id with an underscore.
    entry-id

    ;; The dataset-id in ECHO10


Support requests that include the name of an attachment

--- src/io/aviso/twixt/ring.clj
+++ src/io/aviso/twixt/ring.clj
@@ -14,21 +14,29 @@
       .getTime))

 (defn- asset->ring-response
-  [asset]
-  (cond->
-    ;; First the standard stuff ...
-    (-> asset
-        :content
-        io/input-stream
-        r/response
-        (r/header "Content-Length" (:size asset))
-        ;; Because any change to the content will create a new checksum and a new URL, a change to the content
-        ;; is really an entirely new resource. The current resource is therefore immutable and can have a far-future expires
-        ;; header.
-        (r/header "Expires" far-future)
-        (r/content-type (:content-type asset)))
-    ;; The optional extras ...
-    (:compressed asset) (r/header "Content-Encoding" "gzip")))
+  [asset attachment-name]
+  (let [content-source (if (some? attachment-name)
+                         (get-in asset [:attachments attachment-name])
+                         asset)]
+    ;; content-source may be nil if the URL includes an attachment but the attachment doesn't exist.
+    (if content-source
+      ;; First the standard stuff ...
+      (cond->
+        (->
+          content-source
+          :content
+          io/input-stream
+          r/response
+          (r/header "Content-Length" (:size content-source))
+          ;; Because any change to the content will create a new checksum and a new URL, a change to the content
+          ;; is really an entirely new resource. The current resource is therefore immutable and can have a far-future expires
+          ;; header.
+          (r/header "Expires" far-future)
+          (r/content-type (:content-type content-source)))
+
+        ;; The optional extras ...
+        ;; :compressed will never be true for an attachment (that may change in the future).
+        (:compressed content-source) (r/header "Content-Encoding" "gzip")))))

 (defn- match? [^String path-prefix ^String path]
@@ -37,18 +45,27 @@
     (not (or (= path path-prefix)
              (.endsWith path "/")))))

+(defn- split-asset-path-and-attachment-name
+  [path]
+  (let [atx (.indexOf path "@")]
+    (if (< atx 0)
+      [path nil]
+      [(.substring path 0 atx)
+       (.substring path (inc atx))])))
+
 (defn- parse-path
-  "Parses the complete request path into a checksum, compressed-flag, and asset path."
+  "Parses the complete request path into a checksum, compressed-flag, asset path and (optional) attachment name."
   [^String path-prefix ^String path]
   (let [suffix (.substring path (.length path-prefix))
         slashx (.indexOf suffix "/")
         full-checksum (.substring suffix 0 slashx)
         compressed? (.startsWith full-checksum "z")
         checksum (if compressed? (.substring full-checksum 1) full-checksum)
-        asset-path (.substring suffix (inc slashx))]
+        [asset-path attachment-name] (-> suffix (.substring (inc slashx)) split-asset-path-and-attachment-name)]
     [checksum
      compressed?
-     asset-path]))
+     asset-path
+     attachment-name]))

 (defn- asset->redirect-response
   [status path-prefix asset]
@@ -59,25 +76,28 @@
 (def ^:private asset->301-response (partial asset->redirect-response 301))

 (defn- create-asset-response
-  [path-prefix requested-checksum asset]
+  [path-prefix requested-checksum asset attachment-name]
   (cond
     (nil? asset) nil
-    (= requested-checksum (:checksum asset)) (asset->ring-response asset)
+    (= requested-checksum (:checksum asset)) (asset->ring-response asset attachment-name)
     :else (asset->301-response path-prefix asset)))

 (defn twixt-handler
   "A Ring request handler that identifies requests targetted for Twixt assets.  Returns a Ring response map
-  if the request is for an existing asset, otherwise returns nil.
+   if the request is for an existing asset, otherwise returns nil.

-  Asset URLs always include the intended asset's checksum; if the actual asset checksum does not match, then
-  a 301 (moved permanently) response is sent with the correct asset URL."
+   The path may indicate an attachment to the asset (such as the source.map for a compiled JavaScript file).
+   The attachment is indicated as a suffix: the `@` symbol and the name of the attachment.
+
+   Asset URLs always include the intended asset's checksum; if the actual asset checksum does not match, then
+   a 301 (moved permanently) response is sent with the correct asset URL."
   [request]
   (let [path-prefix (-> request :twixt :path-prefix)
         path (:uri request)]
     (when (match? path-prefix path)
       (t/track
         #(format "Handling asset request `%s'" path)
-        (let [[requested-checksum compressed? asset-path] (parse-path path-prefix path)
+        (let [[requested-checksum compressed? asset-path attachment-name] (parse-path path-prefix path)
               context (:twixt request)
               ;; When actually servicing an asset request, we have to trust the data in the URL
               ;; that determines whether to server the normal or gzip'ed resource.
@@ -85,7 +105,8 @@
               asset-pipeline (:asset-pipeline context)]
           (create-asset-response path-prefix
                                  requested-checksum
-                                 (asset-pipeline asset-path context')))))))
+                                 (asset-pipeline asset-path context')
+                                 attachment-name))))))

 ;;; It's really difficult to start with a path, convert it to a resource, and figure out if it is a folder
 ;;; or a file on the classpath. Instead, we just assume that anything that doesn't look like a path that


free-seats should be synchronized, make it an atom

--- clojure/day3.clj
+++ clojure/day3.clj
@@ -26,7 +26,7 @@
 ; barber <serviced>
 (def barber (agent 0))
 ; seats <free>
-(def free-seats (agent 3))
+(def free-seats (atom 3))

 (defn any-seat-occupied? []
   (< @free-seats 3))
@@ -40,7 +40,7 @@
 (defn cut-hair [serviced]
   (if (any-seat-occupied?)
     (do
-      (send free-seats free-seat)
+      (swap! free-seats free-seat)
       (Thread/sleep 20)
       (inc serviced))
     serviced))
@@ -61,7 +61,7 @@
     (if @continue-running
       (let [time (+ 10 (rand-int 20))]
         (Thread/sleep time)
-        (send free-seats try-occupy)
+        (swap! free-seats try-occupy)
         (recur)))))

 (future (move-to-chair))


Small cleanups and re-org

Small cleanups and re-org

--- src/core/clj/virt/core.clj
+++ src/core/clj/virt/core.clj
@@ -19,23 +19,51 @@
 (def apps
   {:chat {:link "/chat"}})

+
 (declare channels threads messages)
+
+(defn geoFromText [lon lat]
+  (str "ST_GeographyFromText('SRID=4326;POINT(" lon " " lat ")')"))
+
+(defn get-channels [lon lat]
+  (korma/select channels
+    (korma/where
+      (korma/raw (str "ST_DWithin(location," (geoFromText lon lat) ",200)")))))
+
+(defn add-channel [channel-name lon lat]
+  (korma/insert channels
+    (korma/values
+      {:name channel-name
+       :location (korma/raw (geoFromText lon lat))})))
+
+(defn get-threads [channel-id]
+  (korma/select threads
+    (korma/where {:channel_id channel-id})))
+
+(defn add-chat-thread [channel-id thread-descr]
+  (korma/insert threads
+    (korma/values {:channel_id channel-id
+                   :description thread-descr})))
+
+(defn get-messages [channel-id thread-id]
+  (korma/select messages
+    (korma/where {:channel_id channel-id
+                  :thread_id thread-id})))
+
+(defn add-msg [channel-id thread-id msg]
+  (korma/insert messages
+    (korma/values {:channel_id channel-id
+                   :thread_id thread-id
+                   :message msg})))
+

 (defn edn-response [body]
   {:status 200
    :headers {"Content-Type" "application/edn"}
    :body (pr-str body)})

-(defn geoFromText [lon lat]
-  (str "ST_GeographyFromText('SRID=4326;POINT(" lon " " lat ")')"))
-
 (defn apps-handler [request]
   (edn-response apps))
-
-(defn get-channels [lon lat]
-  (korma/select channels
-    (korma/where
-      (korma/raw (str "ST_DWithin(location," (geoFromText lon lat) ",200)")))))

 (defn channels-handler [request]
   (edn-response
@@ -44,21 +72,11 @@
           lat (Double/parseDouble (:lat params))]
       (get-channels lon lat))))

-(defn new-channel [channel-name lon lat]
-  (korma/insert channels
-    (korma/values
-      {:name channel-name
-       :location (korma/raw (geoFromText lon lat))})))
-
 (defn new-channel-handler [request]
   (edn-response
     (let [body (read-string (slurp (:body request)))
           geolocation (:geolocation body)]
-      (new-channel (:channel-name body) (:lon geolocation) (:lat geolocation)))))
-
-(defn get-threads [channel-id]
-  (korma/select threads
-    (korma/where {:channel_id channel-id})))
+      (add-channel (:channel-name body) (:lon geolocation) (:lat geolocation)))))

 (defn chat-threads-handler [request]
   (edn-response
@@ -66,22 +84,12 @@
           channel-id (Integer/parseInt (:channel-id params))]
       (get-threads channel-id))))

-(defn new-chat-thread [channel-id thread-descr]
-  (korma/insert threads
-    (korma/values {:channel_id channel-id
-                   :description thread-descr})))
-
 (defn new-chat-thread-handler [request]
   (edn-response
     (let [params (:route-params request)
           channel-id (Integer/parseInt (:channel-id params))
           body (read-string (slurp (:body request)))]
-      (new-chat-thread channel-id (:thread-descr body)))))
-
-(defn get-messages [channel-id thread-id]
-  (korma/select messages
-    (korma/where {:channel_id channel-id
-                  :thread_id thread-id})))
+      (add-chat-thread channel-id (:thread-descr body)))))

 (defn chat-messages-handler [request]
   (edn-response
@@ -89,12 +97,6 @@
           channel-id (Integer/parseInt (:channel-id params))
           thread-id (Integer/parseInt (:thread-id params))]
       (get-messages channel-id thread-id))))
-
-(defn add-msg [channel-id thread-id msg]
-  (korma/insert messages
-    (korma/values {:channel_id channel-id
-                   :thread_id thread-id
-                   :message msg})))

 (defn chat-thread-ws-handler [ch request]
   (let [params (:route-params request)
@@ -138,7 +140,6 @@
                                    :password "postgres"}))

   (korma/defentity channels
-    (korma/table :channels)
     (korma/transform
       (fn [c] (-> c
                   (assoc :app :chat)
@@ -146,13 +147,11 @@
                   (clojure.set/rename-keys {:id :channel-id})))))

   (korma/defentity threads
-    (korma/table :threads)
     (korma/transform
       (fn [t] (clojure.set/rename-keys t {:id :thread-id
                                           :channel_id :channel-id}))))

   (korma/defentity messages
-    (korma/table :messages)
     (korma/transform
       (fn [m] (-> m
                   (clojure.set/rename-keys {:id :message-id


use a plus icon

use a plus icon

--- src-cljs/frontend/components/plan.cljs
+++ src-cljs/frontend/components/plan.cljs
@@ -375,7 +375,7 @@
               [:span "Add payment"]]
              (when (plan-model/trial-over? plan)
                [:a.vein.make {:on-click #(cast! :extend-trial-clicked)}
-                (common/icon :credit)
+                (common/icon :plus)
                 [:span "Extend trial"]]))
             (list
              [:a.vein.make {:href (urls/plan-submenu-path doc "info")}


insights: keep recent-builds when reloading projects

--- src-cljs/frontend/controllers/api.cljs
+++ src-cljs/frontend/controllers/api.cljs
@@ -107,16 +107,28 @@

 (defmethod api-event [:projects :success]
-  [target message status {:keys [resp]} {:keys [navigation-point] :as state}]
-  ;; for the insights screen, we go on to get recent builds from the
-  ;; default_branch of each project
-  (when (= navigation-point :build-insights)
-    (let [api-ch (get-in state [:comms :api])
-          project-build-ids (map project-build-id resp)]
-      (api/get-projects-builds project-build-ids api-ch)))
-  (->> resp
-       (map (fn [project] (update project :scopes #(set (map keyword %)))))
-       (assoc-in state state/projects-path)))
+  [target message status {:keys [resp]} {:keys [navigation-point] :as current-state}]
+  (cond->> resp
+    true (map (fn [project] (update project :scopes #(set (map keyword %)))))
+    ;; For the insights screen:
+    ;;   1. copy old recent_builds so page doesn't empty out.
+    ;;   2. we go on to update recent_builds default_branch of each project
+    (= navigation-point :build-insights)
+    ((fn [resp]
+       (let [old-projects (get-in current-state state/projects-path)
+             api-ch (get-in current-state [:comms :api])
+             project-build-ids (map project-build-id resp)
+             updated-projects (map (fn [{:keys [vcs_url] :as project}]
+                                     (let [target-build-id (project-build-id project)]
+                                       (if-let [{:keys [recent_builds]} (->> old-projects
+                                                                             (filter #(= target-build-id (project-build-id %)))
+                                                                             first)]
+                                         (assoc project :recent_builds recent_builds)
+                                         project)))
+                                   resp)]
+         (api/get-projects-builds project-build-ids api-ch)
+         updated-projects)))
+      true (assoc-in current-state state/projects-path)))

 (defmethod api-event [:me :success]
   [target message status args state]


Improve styles.

Improve styles.

--- src/garden/puzzle-view.clj
+++ src/garden/puzzle-view.clj
@@ -101,7 +101,9 @@
             {:font-size "30px"
              :margin "10px 0px"}]

-        [:.invitation {:font-size "20px"}]
+        [:.invitation
+            {:font-size "20px"
+             :margin-bottom "5px"}]

         [:.choices


Changed live indicies to a single line

Changed live indicies to a single line

--- src/hphelper/live/view.clj
+++ src/hphelper/live/view.clj
@@ -65,7 +65,7 @@
             ]
            [:body
             [:div
-             (html-print-indicies-table (:indicies game) 3)
+             (html-print-indicies-table (:indicies game) 13)
              ]
             [:div
              (map (fn [n] [:div n])


commenting out obscured route

commenting out obscured route

--- src/jasons_game/routes.clj
+++ src/jasons_game/routes.clj
@@ -4,7 +4,7 @@
             [compojure.route :as route]))

 (defroutes app-routes
-  (GET "/" [] "This is Jason's game")
+;  (GET "/" [] "This is Jason's game")
   (route/resources "/")
   (route/not-found "Not Found"))


util/hadoop.clj: fix errors when counter gets non-string argument

Automatically convert any passed args to strings.

--- src/org/altlaw/util/hadoop.clj
+++ src/org/altlaw/util/hadoop.clj
@@ -21,9 +21,9 @@

 (defn counter
   ([counter-name]
-     (.incrCounter *reporter* "Custom counters" counter-name 1))
+     (.incrCounter *reporter* "Custom counters" (str counter-name) 1))
   ([group counter-name]
-     (.incrCounter *reporter* group counter-name 1)))
+     (.incrCounter *reporter* (str group) (str counter-name) 1)))

 (defn default-jobconf [this]
   (let [conf (.getConf this)


add pm-osc pseudo-ugen

add pm-osc pseudo-ugen

--- src/overtone/sc/ugen/extra.clj
+++ src/overtone/sc/ugen/extra.clj
@@ -34,3 +34,17 @@
           positions (splay-pan n center spread)
           pans (pan2 in-array positions level)]
       (map + (parallel-seqs pans)))))
+
+(defn pm-osc
+  "Phase modulation sine oscillator pair. Defaults to :ar"
+  [car-freq mod-freq pm-index mod-phase]
+  (with-ugens
+    (sin-osc:ar car-freq (* pm-index (sin-osc:ar mod-freq mod-phase)))))
+
+(defn pm-osc:kr
+  "Phase modulation sine oscillator pair at :kr"
+  [car-freq mod-freq pm-index mod-phase]
+  (with-ugens
+    (sin-osc:kr car-freq (* pm-index (sin-osc:kr mod-freq mod-phase)))))
+
+(def pm-osc:ar pm-osc)


Remove trailing parens (except on melody/chord definitions).

--- src/overtunes/songs/before.clj
+++ src/overtunes/songs/before.clj
@@ -1,7 +1,6 @@
 (ns overtunes.songs.before
   (:use [overtone.live])
-  (:use [overtunes.instruments.organ-cornet])
-)
+  (:use [overtunes.instruments.organ-cornet]))

 (def melody
   [:C3 :Bb3 :Eb3 :G3 :Eb3]
@@ -58,54 +57,40 @@
 (defn play-note [tone instrument duration]
   (let [
     seconds (/ duration 1000)
-    frequency (midi->hz (note tone))
-  ]
-    (instrument frequency seconds)
-  )
-)
+    frequency (midi->hz (note tone))]
+    (instrument frequency seconds)))

 (defn play-chord [tones instrument duration]
   (if (not (empty? tones))
     (let [
       root (first tones)
       bass [(- root 12) (- root 24)]
-      with-bass (concat bass tones)
-    ]
-      (mix (map (fn [tone] (play-note tone instrument duration)) with-bass))
-    )
-  )
-)
+      with-bass (concat bass tones)]
+      (mix (map (fn [tone] (play-note tone instrument duration)) with-bass)))))

 (defn play-progression [progression metro start]
   (let [
     beats-per-chord 4
-    duration (* beats-per-chord (beat-length metro))
-  ]
+    duration (* beats-per-chord (beat-length metro))]
     (if (not (empty? progression)) ( do
       (at (metro start) (play-chord (first progression) organ-cornet duration))
-      (play-progression (rest progression) metro (+ start beats-per-chord))
-    ))
-  )
-)
+      (play-progression (rest progression) metro (+ start beats-per-chord))))))

 (defn play-melody [melody metro start]
   (let [
     beats-per-note 2
-    duration (* beats-per-note (beat-length metro))
-  ]
+    duration (* beats-per-note (beat-length metro))]
     (if (not (empty? melody)) ( do
       (at (metro start) (play-note (first melody) organ-cornet duration))
-      (play-melody (rest melody) metro (+ start beats-per-note))
-    ))
-  )
-)
+      (play-melody (rest melody) metro (+ start beats-per-note))))))

 (defn n-times [n items] (flatten (repeat n items)))

 (defn play [chords metro] ( do
   (play-melody (n-times (/ (count chords) 2.5) melody) metro (metro))
-  (play-progression (concat chords finish) metro (metro))
-))
+  (play-progression (concat chords finish) metro (metro))))

-(defn full-version [] (play (concat start middle start middle variation) (metronome 60)))
+(defn full-version []
+  (play (concat start middle start middle variation) (metronome 60)))
+
 (defn short-version [] (play variation (metronome 200)))


Removed the trailing parens on chord and melody definitions - not so sure about this one, but I get the feeling that trailing parens make Clojure hackers' eyes bleed.

--- src/overtunes/songs/before.clj
+++ src/overtunes/songs/before.clj
@@ -3,8 +3,7 @@
   (:use [overtunes.instruments.organ-cornet]))

 (def melody
-  [:C3 :Bb3 :Eb3 :G3 :Eb3]
-)
+  [:C3 :Bb3 :Eb3 :G3 :Eb3])

 (def start [
   (chord :Eb3 :major)
@@ -14,8 +13,7 @@
   (chord :Eb3 :major)
   (chord :Eb3 :major)
   (chord :C3  :minor7)
-  (chord :C3  :minor7)
-])
+  (chord :C3  :minor7)])

 (def middle [
   (chord :G3  :minor)
@@ -25,8 +23,7 @@
   (chord :Eb4 :major)
   (chord :Eb4 :major)
   (chord :Bb3 :major)
-  (chord :Bb3 :major)
-])
+  (chord :Bb3 :major)])

 (def variation [
   (chord :G3  :minor)
@@ -44,13 +41,11 @@
   (chord :Eb4 :major)
   (chord :Eb4 :major)
   (chord :Bb3 :major)
-  (chord :Bb3 :major)
-])
+  (chord :Bb3 :major)])

 (def finish [
   (chord :Eb4 :major)
-  (chord :Eb4 :major)
-])
+  (chord :Eb4 :major)])

 (defn beat-length [metro] (- (metro 1) (metro 0)))


Fix indentation.

Fix indentation.

--- src/oc/storage/api/orgs.clj
+++ src/oc/storage/api/orgs.clj
@@ -28,11 +28,11 @@
 ;; ----- Utility functions -----

 (defn- user-from-context [ctx]
-    (or (:user ctx)
-        (let [id-token (get-in (:request ctx) [:params "id-token"])
-              decoded-token (jwt/decode-id-token id-token config/passphrase)]
-          {:user-id (get-in decoded-token [:claims :user_id])
-           :teams [(get-in decoded-token [:claims :team_id])]})))
+  (or (:user ctx)
+      (let [id-token (get-in (:request ctx) [:params "id-token"])
+            decoded-token (jwt/decode-id-token id-token config/passphrase)]
+        {:user-id (get-in decoded-token [:claims :user_id])
+         :teams [(get-in decoded-token [:claims :team_id])]})))

 (defn- board-with-access-level
   "


Log event debug messages on a separate thread to ensure logging doesn't interfere with event handling latency

--- src/overtone/libs/event.clj
+++ src/overtone/libs/event.clj
@@ -7,6 +7,12 @@

 (defonce handler-pool (handlers/mk-handler-pool "Overtone Event Handlers"))
 (defonce event-debug* (atom false))
+
+(defn- log-event
+  "Log event on separate thread to ensure logging doesn't interfere with
+  event handling latency"
+  [msg & args]
+  (future (apply log/debug msg args)))

 (defn on-event
   "Asynchronously runs handler whenever events of event-type are
@@ -28,7 +34,7 @@
   Handlers can return :overtone/remove-handler to be removed from the
   handler list after execution."
   [event-type handler key]
-  (log/debug "Registering async event handler:: " event-type key)
+  (log-event "Registering async event handler:: " event-type key)
   (handlers/add-handler! handler-pool event-type key handler ))

 (defn on-sync-event
@@ -51,19 +57,19 @@
   Handlers can return :overtone/remove-handler to be removed from the
   handler list after execution."
   [event-type handler key]
-  (log/debug "Registering sync event handler:: " event-type key)
+  (log-event "Registering sync event handler:: " event-type key)
   (handlers/add-sync-handler! handler-pool event-type key handler))

 (defn oneshot-event
   ""
   [event-type handler key]
-  (log/debug "Registering async self-removing event handler:: " event-type key)
+  (log-event "Registering async self-removing event handler:: " event-type key)
   (handlers/add-one-shot-handler! handler-pool event-type key handler))

 (defn oneshot-sync-event
   ""
   [event-type handler key]
-  (log/debug "Registering sync self-removing event handler:: " event-type key)
+  (log-event "Registering sync self-removing event handler:: " event-type key)
   (handlers/add-one-shot-sync-handler! handler-pool event-type key handler))

 (defn remove-handler
@@ -81,11 +87,6 @@
   [key]
   (handlers/remove-handler! handler-pool key))

-(defn remove-event-handlers
-  "Remove all handlers for events of type event-type."
-  [event-type]
-  (handlers/remove-event-handlers! handler-pool event-type))
-
 (defn remove-all-handlers
   "Remove all handlers."
   []
@@ -101,7 +102,7 @@
   (event ::my-event)
   (event ::filter-sweep-done :instrument :phat-bass)"
   [event-type & args]
-  (log/debug "event: " event-type " " args)
+  (log-event "event: " event-type " " args)
   (when @event-debug*
     (println "event: " event-type " " args "\n"))
   (binding [overtone.libs.handlers/*log-fn* log/error]
@@ -117,7 +118,7 @@
   new threads which generate events, these will revert back to the
   default behaviour of event (i.e. not forced sync). See event."
   [event-type & args]
-  (log/debug "sync-event: " event-type " " args)
+  (log-event "sync-event: " event-type " " args)
   (when @event-debug*
     (println "sync-event: " event-type " " args "\n"))
   (binding [overtone.libs.handlers/*log-fn* log/error]


tiny docstring clarification

tiny docstring clarification

--- src/overtone/libs/event.clj
+++ src/overtone/libs/event.clj
@@ -94,9 +94,9 @@

   Takes an event-type (name of the event), a handler fn and a key (to
-  refer back to this handler in the future). The handler accept a single
-  event argument, which is a map containing the :event-type property and
-  any other properties specified when it was fired.
+  refer back to this handler in the future). The handler must accept a
+  single event argument, which is a map containing the :event-type
+  property and any other properties specified when it was fired.

   (on-event \"/tr\" handler ::status-check )
   (on-event :midi-note-down (fn [event]


Bolt with whitespace in name can be viewed in ui

--- storm-core/src/clj/backtype/storm/ui/core.clj
+++ storm-core/src/clj/backtype/storm/ui/core.clj
@@ -1024,7 +1024,7 @@
            (catch Exception e (resp/redirect "/")))))
   (GET "/topology/:id/component/:component" [:as {cookies :cookies} id component & m]
        (let [include-sys? (get-include-sys? cookies)]
-         (-> (component-page id component (:window m) include-sys?)
+         (-> (component-page id (java.net.URLDecoder/decode component) (:window m) include-sys?)
              (concat [(mk-system-toggle-button include-sys?)])
              ui-template)))
   (POST "/topology/:id/activate" [id]


fixed typo

fixed typo

--- kanbanik-statistics/src/main/clojure/org/kanbanik/statistics.clj
+++ kanbanik-statistics/src/main/clojure/org/kanbanik/statistics.clj
@@ -40,6 +40,9 @@
          vals)
   )
 )
+
+
+

 (defn group-by-timeframe [stream timeframe]
   "Gets a vector of task related events sorted by time and groups them according to given time frame.
@@ -88,6 +91,8 @@
   )
 )

+
+
 (defn generate-report [descriptor tasks]
 "
 The tasks are one timeframe output from the reduce-tasks
@@ -104,7 +109,7 @@
   (loop [res [] desc descriptor]
     (if (= (count desc) 0)
       res
-      (let [filtered-tasks (apoply-filter (:filter (first desc)) tasks) function (:function (first desc))]
+      (let [filtered-tasks (apply-filter (:filter (first desc)) tasks) function (:function (first desc))]
            (if (:children (first desc))
              (recur (conj res (apply-function function filtered-tasks) (generate-report (:children (first desc)) filtered-tasks)) (rest desc))
              (recur (conj res (apply-function function filtered-tasks)) (rest desc))


use (reflexive-to-infinitive) within (present)

--- src/babel/espanol/morphology/verbs.clj
+++ src/babel/espanol/morphology/verbs.clj
@@ -301,7 +301,7 @@
 (defn present [word & [ {usted :usted
                          vosotros :vosotros
                          ustedes :ustedes}]]
-  (let [infinitive (get-in word '(:espanol))
+  (let [infinitive (reflexive-to-infinitive (get-in word '(:espanol)))
         ar-type (try (re-find #"ar$" infinitive)
                      (catch Exception e
                        (throw (Exception. (str "Can't regex-find on non-string: " infinitive " from word: " word)))))


Prevent adding same folder and file to workspace #775 #1588 #1217

--- src/lt/objs/workspace.cljs
+++ src/lt/objs/workspace.cljs
@@ -207,16 +207,18 @@
 (behavior ::add-file!
                   :triggers #{:add.file!}
                   :reaction (fn [this f]
-                              (add! this :files f)
-                              (object/raise this :add f)
-                              (object/raise this :updated)))
+                              (when-not (some #{f} (:files (-> @this)))
+                                (add! this :files f)
+                                (object/raise this :add f)
+                                (object/raise this :updated))))

 (behavior ::add-folder!
                   :triggers #{:add.folder!}
                   :reaction (fn [this f]
-                              (add! this :folders f)
-                              (object/raise this :add f)
-                              (object/raise this :updated)))
+                              (when-not (some #{f} (:folders (-> @this)))
+                                (add! this :folders f)
+                                (object/raise this :add f)
+                                (object/raise this :updated))))

 (behavior ::remove-file!
                   :triggers #{:remove.file!}


CLJS-1384: cljs.js/eval-str doc that :ns returned upon success

--- src/main/cljs/cljs/js.cljs
+++ src/main/cljs/cljs/js.cljs
@@ -728,8 +728,9 @@

   cb (function)
     callback, will be invoked with a map. If succesful the map will contain
-    a :value key with the result of evaluation. If unsuccessful will contain
-    a :error key with an ex-info instance describing the cause of failure."
+    a :value key with the result of evaluation and :ns the current namespace.
+    If unsuccessful will contain a :error key with an ex-info instance describing
+    the cause of failure."
   ([state source cb]
    (eval-str state source nil cb))
   ([state source name cb]
@@ -847,6 +848,20 @@
       (println ret)))

   (cljs/eval-str st
+    "(ns foo.bar (:require-macros [bootstrap-test.macros :refer [foo]]))\n(foo 4 4)"
+    'foo.bar
+    {:verbose true
+     :source-map true
+     :eval node-eval
+     :load node-load}
+    (fn [{:keys [error] :as res}]
+      (if error
+        (do
+          (println "Error:" error)
+          (println (.. error -cause -stack)))
+        (println "Result:" res))))
+
+  (cljs/compile-str st
     "(ns foo.bar (:require-macros [bootstrap-test.macros :refer [foo]]))\n(foo 4 4)"
     'foo.bar
     {:verbose true


change card layout

change card layout

--- src/cljs/offcourse/views/components/course_card.cljs
+++ src/cljs/offcourse/views/components/course_card.cljs
@@ -17,8 +17,8 @@
                   [:meta (Meta :curator curator
                                :learners 123
                                :forks 23)]
-                  [:list (TodoList course-id checkpoints handlers)]
-                  [:tags (Tags tags)]]]
+                  [:tags (Tags tags)]
+                  [:list (TodoList course-id checkpoints handlers)]]]
     (d/section {:key course-id
                 :className (css/classes "card" highlighted)
                 :onClick #(go-to-course course-id %1)}


added normalize method -> fill optional data about mount resources (assure consistency)

--- src/cljs/swarmpit/component/service/form_mounts.cljs
+++ src/cljs/swarmpit/component/service/form_mounts.cljs
@@ -17,6 +17,26 @@
     (routes/path-for-backend :volumes)
     {:on-success (fn [response]
                    (reset! volumes response))}))
+
+(defn- normalize-volume
+  "Associate volumes with optional data (driver, labels)"
+  [volume]
+  (let [volume-data (first
+                      (filter #(= (:host volume)
+                                  (:volumeName %)) @volumes))]
+    (-> volume
+        (assoc-in [:volumeOptions :labels] (:labels volume-data))
+        (assoc-in [:volumeOptions :driver :name] (:driver volume-data))
+        (assoc-in [:volumeOptions :driver :options] (:options volume-data)))))
+
+(defn normalize
+  "Associate mounts with optional data required for consistency"
+  []
+  (->> (state/get-value cursor)
+       (map (fn [mount] (if (= "volume" (:type mount))
+                          (normalize-volume mount)
+                          mount)))
+       (into [])))

 (def headers [{:name  "Type"
                :width "15%"}


Build K-smoother for group clustering; fixes #77

--- src/polismath/conversation.clj
+++ src/polismath/conversation.clj
@@ -73,7 +73,8 @@
                           :max-k 12
                           :group-iters 10
                           :max-ptpts 80000
-                          :max-cmts 800}
+                          :max-cmts 800
+                          :group-k-buffer 4}
                     opts))

    :zid         (plmb/fnk [conv votes]
@@ -230,11 +231,32 @@
                     [k (silhouette bucket-dists clsts)])
                   group-clusterings)))

-      ; Here we just pick the best K value, based on silhouette
+      ; This smooths changes in cluster counts (K-vals) by remembering what the last K was, and only changing
+      ; after (:group-k-buffer opts') many times on a new K value
+      :group-k-smoother
+            (plmb/fnk
+              [conv group-clusterings group-clusterings-silhouettes opts']
+              (let [{:keys [last-k last-k-count smoothed-k] :or {last-k-count 0}}
+                      (:group-k-smoother conv)
+                    count-buffer (:group-k-buffer opts')
+                                 ; Find best K value for current data, given silhouette
+                    this-k       (apply max-key group-clusterings-silhouettes (keys group-clusterings))
+                                 ; If this and last K values are the same, increment counter
+                    same         (if last-k (= this-k last-k) false)
+                    this-k-count (if same (+ last-k-count 1) 1)
+                                 ; if seen > buffer many times, switch, OW, take last smoothed
+                    smoothed-k   (if (>= this-k-count count-buffer)
+                                   this-k
+                                   (if smoothed-k smoothed-k this-k))]
+                {:last-k       this-k
+                 :last-k-count this-k-count
+                 :smoothed-k   smoothed-k}))
+
+      ; Pick the cluster corresponding to smoothed K value from group-k-smoother
       :group-clusters
-            (plmb/fnk [group-clusterings group-clusterings-silhouettes]
+            (plmb/fnk [group-clusterings group-k-smoother]
               (get group-clusterings
-                (apply max-key group-clusterings-silhouettes (keys group-clusterings))))
+                (:smoothed-k group-k-smoother)))

       :bid-to-pid (plmb/fnk [base-clusters]
                     (greedy


Make sure to update bounds of autocomplete on update

--- src/cljs/travel_site/utils/inputs.cljs
+++ src/cljs/travel_site/utils/inputs.cljs
@@ -35,18 +35,29 @@
              :value (edit-key parent-state)
              :type "text" }))))

-
 ;; Generic component for using google places autocomplete input
 ;; Same API as the editable-input component above
 (defn address-autocomplete-input [[parent-state {:keys [className edit-key placeholder-text coords-key center]}] owner]
   {:pre [(some? parent-state)]}
   (reify
+    om/IInitState
+    (init-state [_]
+      {:autocomplete nil})
+
+    om/IDidUpdate
+    (did-update [_ [_ {:keys [center]}] _]
+      (let [[_ {:keys [new-center]}] (om/get-props owner)]
+        (if-not (= center new-center)
+          (.setBounds (:autocomplete (om/get-state owner)) (js/google.maps.LatLngBounds. center center)))))
+
     om/IDidMount
     (did-mount [_]
       (let [address-input (om/get-node owner)]
         (let [autocomplete (js/google.maps.places.Autocomplete.
                              address-input
                              #js  {:bounds  (if (some? center) (js/google.maps.LatLngBounds. center center))})]
+
+          (om/set-state! owner :autocomplete autocomplete)
           (.addListener
             autocomplete
             "place_changed"
@@ -56,6 +67,7 @@
                   (om/transact! parent-state coords-key (fn [_] {:lat (.lat (.. place -geometry -location))
                                                                  :lng (.lng (.. place -geometry -location))}))))
               (om/transact! parent-state edit-key (fn [_] (.-value address-input))))))))
+
     om/IRenderState
     (render-state [_ _]
       (om/build editable-input [parent-state {:className className


Fixed test

Fixed test

--- test/cloverage_jenkins_reporter/core_test.clj
+++ test/cloverage_jenkins_reporter/core_test.clj
@@ -44,7 +44,7 @@
 ;

 (deftest test-main-existence
-    "Check that the clouseau.core/-main definition exists."
-    (testing "if the clouseau.core/-main definition exists."
-        (is (callable? 'clouseau.core/-main))))
+    "Check that the cloverage-jenkins-reporter.core/-main definition exists."
+    (testing "if the cloverage-jenkins-reporter.core/-main definition exists."
+        (is (callable? 'cloverage-jenkins-reporter.core/-main))))


Avoid unnecessary object creation

Avoid unnecessary object creation

And fix check for input/textarea

--- src/reagent/impl/template.cljs
+++ src/reagent/impl/template.cljs
@@ -118,26 +118,27 @@

 (defn input-component? [x]
   (let [DOM (.' js/React :DOM)]
-    (or (identical? x (.' DOM :input))
+    (or (= x "input")
+        (= x "textarea")
+        (identical? x (.' DOM :input))
         (identical? x (.' DOM :textarea)))))

 ;;; Wrapping of native components

-(declare convert-args)
+(declare make-element)

 (defn wrapped-render [this comp id-class input-setup]
   (let [inprops (.' this :props)
         argv (.' inprops :argv)
         props (nth argv 1 nil)
         hasprops (or (nil? props) (map? props))
-        jsprops (convert-props (if hasprops props) id-class)
-        jsargs (convert-args argv comp jsprops
-                             (if hasprops 2 1)
-                             (inc (.' inprops :level)))]
+        jsprops (convert-props (if hasprops props) id-class)]
     (when-not (nil? input-setup)
       (input-setup this jsprops))
-    (.apply (.' js/React :createElement) nil jsargs)))
+    (make-element argv comp jsprops
+                  (if hasprops 2 1)
+                  (inc (.' inprops :level)))))

 (defn wrapped-should-update [c nextprops nextstate]
   (or util/*always-update*
@@ -191,14 +192,13 @@

 (defn as-class [tag]
   (if (hiccup-tag? tag)
-    (cached-wrapper tag)
-    (do
-      (let [cached-class (util/cached-react-class tag)]
-        (if-not (nil? cached-class)
-          cached-class
-          (if (.' js/React isValidElement tag)
-            (util/cache-react-class tag (wrap-component tag nil nil))
-            (fn-to-class tag)))))))
+    (cached-wrapper tag)
+    (let [cached-class (util/cached-react-class tag)]
+      (if-not (nil? cached-class)
+        cached-class
+        (if (.' js/React isValidElement tag)
+          (util/cache-react-class tag (wrap-component tag nil nil))
+          (fn-to-class tag))))))

 (defn get-key [x]
   (when (map? x) (get x :key)))
@@ -253,12 +253,14 @@
       (aset a i (as-component (aget a i) level')))
     a))

-(defn convert-args [argv comp jsprops first-child level]
+(defn make-element [argv comp jsprops first-child level]
   (if (== (count argv) (inc first-child))
     ;; Optimize common case of one child
-    #js[comp jsprops (as-component (nth argv first-child) level)]
-    (reduce-kv (fn [a k v]
-                 (when (>= k first-child)
-                   (.push a (as-component v level)))
-                 a)
-               #js[comp jsprops] argv)))
+    (.' js/React createElement comp jsprops
+        (as-component (nth argv first-child) level))
+    (.apply (.' js/React :createElement) nil
+            (reduce-kv (fn [a k v]
+                         (when (>= k first-child)
+                           (.push a (as-component v level)))
+                         a)
+                       #js[comp jsprops] argv))))


(PDB-3298) Preserve types in factset-map result

Don't coerce all the factset values to string, so that tests can detect
unexpected type changes.

Change some tests to use factset-map instead of their own string
coercions, and sprinkle around some non-string values.

--- test/puppetlabs/puppetdb/scf/storage_test.clj
+++ test/puppetlabs/puppetdb/scf/storage_test.clj
@@ -56,23 +56,32 @@
     (testing "creates new row for non-existing producer"
       (is (= 2 (ensure-producer prod2))))))

-(defn-validated factset-map :- {s/Str s/Str}
-  "Return all facts and their values for a given certname as a map"
-  [certname :- String]
-  (let [result (jdbc/query
-                ["SELECT fp.path as name,
-                    COALESCE(f.value_string,
-                             cast(f.value_integer as text),
-                             cast(f.value_boolean as text),
-                             cast(f.value_float as text),
-                             '') as value
-                    FROM factsets fs
-                    INNER JOIN facts as f on fs.id = f.factset_id
-                    INNER JOIN fact_paths as fp on f.fact_path_id = fp.id
-                    WHERE fp.depth = 0 AND fs.certname = ?"
-                 certname])]
-    (zipmap (map :name result)
-            (map :value result))))
+(defn factset-map
+  "Returns a map of fact names to values for certname."
+  [certname]
+  (jdbc/call-with-query-rows
+   [(str "select fp.path,"
+         "       f.value_type_id,"
+         "       f.value,"
+         "       f.value_string,"
+         "       f.value_integer,"
+         "       f.value_float,"
+         "       f.value_boolean"
+         "  from factsets fs"
+         "  inner join facts as f on fs.id = f.factset_id"
+         "  inner join fact_paths as fp on f.fact_path_id = fp.id"
+         "  where fp.depth = 0 and fs.certname = ?")
+    certname]
+   {:as-arrays? true}
+   (fn [[col-names & rows]]
+     (doall
+      (into {} (for [[path type-id v vstr vint vfloat vbool] rows]
+                 (case type-id
+                   0 [path vstr]
+                   1 [path vint]
+                   2 [path vfloat]
+                   3 [path vbool]
+                   (4 5) [path (sutils/parse-db-json v)])))))))

 (deftest-db large-fact-update
   (testing "updating lots of facts"
@@ -142,7 +151,11 @@
                  "fqdn" "myhost.mydomain.com"
                  "hostname" "myhost"
                  "kernel" "Linux"
-                 "operatingsystem" "Debian"}
+                 "operatingsystem" "Debian"
+                 "excitement?" true
+                 "version" 1
+                 "temperature" 273.16
+                 "binary" [0 1]}
           producer "bar.com"]
       (add-certname! certname)

@@ -157,26 +170,9 @@
                    :environment nil
                    :producer_timestamp previous-time
                    :producer producer})
+
       (testing "should have entries for each fact"
-        (is (= (query-to-vec
-                "SELECT fp.path as name,
-                        COALESCE(f.value_string,
-                                 cast(f.value_integer as text),
-                                 cast(f.value_boolean as text),
-                                 cast(f.value_float as text),
-                                 '') as value,
-                        fs.certname
-                 FROM factsets fs
-                   INNER JOIN facts as f on fs.id = f.factset_id
-                   INNER JOIN fact_paths as fp on f.fact_path_id = fp.id
-                 WHERE fp.depth = 0
-                 ORDER BY name")
-               [{:certname certname :name "domain" :value "mydomain.com"}
-                {:certname certname :name "fqdn" :value "myhost.mydomain.com"}
-                {:certname certname :name "hostname" :value "myhost"}
-                {:certname certname :name "kernel" :value "Linux"}
-                {:certname certname :name "operatingsystem" :value "Debian"}]))
-
+        (is (= facts (factset-map certname)))
         (is (jdbc/with-db-transaction []
               (timestamp-of-newest-record :factsets  "some_certname")))
         (is (= facts (factset-map "some_certname"))))
@@ -197,7 +193,7 @@
                            "fqdn" "myhost.mynewdomain.com"
                            "hostname" "myhost"
                            "kernel" "Linux"
-                           "uptime_seconds" "3600"}]
+                           "uptime_seconds" 3600}]
             (replace-facts! {:certname certname
                              :values new-facts
                              :environment "DEV"
@@ -205,30 +201,14 @@
                              :timestamp reference-time
                              :producer producer})
             (testing "should have only the new facts"
-              (is (= (query-to-vec
-                      "SELECT fp.path as name,
-                              COALESCE(f.value_string,
-                                       cast(f.value_integer as text),
-                                       cast(f.value_boolean as text),
-                                       cast(f.value_float as text),
-                                       '') as value
-                       FROM factsets fs
-                         INNER JOIN facts as f on fs.id = f.factset_id
-                         INNER JOIN fact_paths as fp on f.fact_path_id = fp.id
-                       WHERE fp.depth = 0
-                       ORDER BY name")
-                     [{:name "domain" :value "mynewdomain.com"}
-                      {:name "fqdn" :value "myhost.mynewdomain.com"}
-                      {:name "hostname" :value "myhost"}
-                      {:name "kernel" :value "Linux"}
-                      {:name "uptime_seconds" :value "3600"}])))
+              (is (= new-facts (factset-map certname))))
             (testing "producer_timestamp should store current time"
               (is (= (query-to-vec "SELECT producer_timestamp FROM factsets")
                      [{:producer_timestamp (to-timestamp reference-time)}])))
             (testing "should update existing keys"
               (is (some #{{:timestamp (to-timestamp reference-time)
                            :environment_id 1
-                           :hash "cf56e1d01b3517d26f875855da4459ce19f8cd18"
+                           :hash "1a4b10a865b8c7b435ec0fe06968fdc62337f57f"
                            :producer_timestamp (to-timestamp reference-time)
                            :producer_id 1}}
                         ;; Again we grab the pertinent non-id bits


Modified hunt-and-kill to accommodate core.async

--- src/snergly/algorithms.cljc
+++ src/snergly/algorithms.cljc
@@ -191,15 +191,13 @@
 (s/defn maze-hunt-and-kill [grid :- g/Grid result-chan report-partial-steps?]
   (go-loop [grid (assoc grid :algorithm-name "hunt-and-kill")
             current-coord (g/random-coord grid)]
-    (go
       (when (and report-partial-steps? (g/changed? grid))
-        (async/>! result-chan grid)))
+        (async/>! result-chan grid))
     (let [[new-grid next-coord] (hunt-and-kill-step (g/begin-step grid) current-coord)]
       (if-not next-coord
         (do
           (async/>! result-chan new-grid)
-          (async/close! result-chan)
-          )
+          (async/close! result-chan))
         (recur new-grid next-coord)))))

 (s/defn maze-recursive-backtrack :- g/Grid [grid :- g/Grid result-chan report-partial-steps?]


removed unused require

removed unused require

--- main/src/dda/pallet/dda_serverspec_crate/infra.clj
+++ main/src/dda/pallet/dda_serverspec_crate/infra.clj
@@ -20,7 +20,6 @@
    [schema.core :as s]
    [pallet.api :as api]
    [pallet.actions :as actions]
-   [pallet.crate :as crate]
    [dda.pallet.core.infra :as core-infra]
    [dda.pallet.dda-serverspec-crate.infra.fact.package :as package-fact]
    [dda.pallet.dda-serverspec-crate.infra.fact.netstat :as netstat-fact]


Cleaned up the net-ns example in the comment

--- src/net_ns/client/core.clj
+++ src/net_ns/client/core.clj
@@ -4,11 +4,13 @@

 (comment
   (net-ns
-    :register [some-func :to ["host1" "192.168.2.2" :as this-func]
-                             ["host3"]
-                             ["host4" :as some-function]]
-    :expose [:to ["host1]
-                 ["host2" :only some-func))
+    (:register [some-func :to ["host1" "192.168.2.2" :as this-func]
+                              ["host3"]
+                              ["host4" :as some-function]])
+    (:expose [:to ["host1]
+                  ["host2" :only some-func]])
+    (:require [some-other-func :as this-cool-func]
+              [one-more-func :as omf :from "host1"])))
 (comment (expose function & to-lists))

 (defn registerfn-str
@@ -20,6 +22,7 @@
 ; ns-map -> map of all the ns mappings
 ; ns-publics -> all public interns for the ns
 ; ns-interns -> all interns for the ns
+; ns-resolve -> resolves the symbol the given namespace, nil if not resolved

 (defn map-replace-str
   "Perform a bunch of replaces on a string, using a map {'match-word' 'new-word'"


add ::buffer-info type to buffer-info and also add multimethod for determining a buffer's size. Perhaps buffer-info and buffer should be unified?

--- src/overtone/sc/buffer.clj
+++ src/overtone/sc/buffer.clj
@@ -101,6 +101,11 @@
 (defmulti buffer-id type)
 (defmethod buffer-id java.lang.Integer [id] id)
 (defmethod buffer-id ::buffer [buf] (:id buf))
+(defmethod buffer-id ::buffer-info [buf-info] (:id buf-info))
+
+(defmulti buffer-size type)
+(defmethod buffer-size ::buffer [buf] (:size buf))
+(defmethod buffer-size ::buffer-info [buf-info] (:n-frames buf-info))

 (defn buffer-data
   "Get the floating point data for a buffer on the internal server."
@@ -109,15 +114,18 @@
         snd-buf (.getSndBufAsFloatArray @sc-world* buf-id)]
     snd-buf))

-(defn buffer-info [buf]
-
+(defn buffer-info
+  [buf]
   (let [mesg-p (recv "/b_info")
-        _   (snd "/b_query" (buffer-id buf))
+        buf-id (buffer-id buf)
+        _   (snd "/b_query" buf-id)
         msg (await-promise! mesg-p)
         [buf-id n-frames n-channels rate] (:args msg)]
-    {:n-frames n-frames
-     :n-channels n-channels
-     :rate rate}))
+    (with-meta     {:n-frames n-frames
+                    :n-channels n-channels
+                    :rate rate
+                    :id buf-id}
+      {:type ::buffer-info})))

 (defn sample-info [s]
   (buffer-info (:buf s)))


Fixed failing test for clusters dropping/splitting in kmeans

--- src/polismath/clusters.clj
+++ src/polismath/clusters.clj
@@ -69,11 +69,11 @@
     ; Reduces a "blank" set of clusters w/ centers into clusters that have elements
     (reduce add-to-closest (cleared-clusters clusters))
     vals
+    ; Filter out clusters that don't have any members (should maybe log on verbose?)
+    (filter #(> (count (:members %)) 0))
     ; Apply mean to get updated centers
     (map #(-> (assoc % :center (mean (:positions %)))
-            (dissoc :positions)))
-    ; Filter out clusters that don't have any members (should maybe log on verbose?)
-    (filter #(> (count (:members %)) 0))))
+            (dissoc :positions)))))

 (defnp recenter-clusters


Add one test

Add one test

--- src/test/discuss/tests.cljs
+++ src/test/discuss/tests.cljs
@@ -8,7 +8,7 @@

 (enable-console-print!)

-#_(doo-tests 'discuss.components.clipboard-test
-           'discuss.references.lib-test
-           'discuss.utils.common-test
+(doo-tests ;;'discuss.components.clipboard-test
+ ;;'discuss.references.lib-test
+ ;;'discuss.utils.common-test
            'discuss.translations-test)


a little reorganization

a little reorganization

--- sidecar/src/figwheel_sidecar/components/cljs_autobuild.clj
+++ sidecar/src/figwheel_sidecar/components/cljs_autobuild.clj
@@ -78,11 +78,6 @@
      libs
      (not-empty (mapv :file foreign-libs)))))

-(defn build-handler [{:keys [figwheel-server build-config] :as watcher}
-                     cljs-build-fn
-                     files]
-  (cljs-build-fn (assoc watcher :changed-files (map str files))))
-
 (defrecord CLJSAutobuild [build-config figwheel-server]
   component/Lifecycle
   (start [this]
@@ -96,15 +91,27 @@
         #_(clean-cljs-build* (:build-options build-config))
         ;; initial build only needs the injection and the
         ;; start and end messages
-        ((-> cljs-build
-             injection/build-hook
-             figwheel-start-and-end-messages) this)
+
         (let [log-writer (or (:log-writer this)
                              (:log-writer figwheel-server)
                              (io/writer "figwheel_server.log" :append true))
               cljs-build-fn (or (:cljs-build-fn this)
                                 (:cljs-build-fn figwheel-server)
-                                figwheel-build)]
+                                ;; if no figwheel server
+                                ;; default build should be standard
+                                ;; cljs build
+                                (if figwheel-server
+                                  figwheel-build
+                                  (figwheel-start-and-end-messages cljs-build)))]
+          ;; build once before watching
+          ;; tiny experience tweak
+          ;; first build shouldn't send notifications
+          ((if (= cljs-build-fn figwheel-build)
+            (-> cljs-build
+                injection/build-hook
+                figwheel-start-and-end-messages)
+            cljs-build-fn) this)
+
           (assoc this
                  :file-watcher
                  (watching/watch! (source-paths-that-affect-build build-config)
@@ -113,7 +120,9 @@
                              (fn []
                                (binding [*out* log-writer
                                          *err* log-writer]
-                                 (build-handler this cljs-build-fn files)))))))))
+                                 (cljs-build-fn
+                                  (assoc this
+                                         :changed-files (map str files)))))))))))
       this))
   (stop [this]
     (when (:file-watcher this)


added in automatic union initialization

added in automatic union initialization

--- src/untangled/client/core.cljs
+++ src/untangled/client/core.cljs
@@ -8,10 +8,11 @@
     [untangled.dom :as udom]
     [om.next.protocols :as omp]
     [untangled.client.impl.util :as util]
-    [untangled.client.impl.om-plumbing :as plumbing])
+    [untangled.client.impl.om-plumbing :as plumbing]
+    [clojure.set :as set])
   (:import goog.Uri))

-(declare map->Application)
+(declare map->Application merge-alternate-union-elements!)

 (defn new-untangled-client
   "Entrypoint for creating a new untangled client. Instantiates an Application with default values, unless
@@ -55,7 +56,25 @@
                                                                                :global-error-callback network-error-callback))}))

 (defprotocol InitialAppState
-  (initial-state [clz params] "Get the initial state when params are passed. params will be nil when called internally, "))
+  (initial-state [clz params] "Get the initial state to be used for this component in app state. You are responsible for composing these together."))
+
+(defn get-initial-state [clz params]
+  (let [state (initial-state clz params)
+        q (om/get-query clz)
+        to-one? (map? state)
+        to-many? (vector? state)
+        union? (map? q)
+        keys-of-interest (fn [s] (set/difference (set s) #{:union/default}))
+        ]
+    (if union?
+      (cond
+        to-one? (let [default-key (get state :union/default)]
+                  (assert (set/subset? (keys-of-interest state) (keys-of-interest q)) (str "Initial state for " clz " contains keys that are not in the query"))
+                  (assert default-key (str "Initial state for " clz " does not indicate which state is the :union/default."))
+                  )
+        to-many? (do)
+        :else (log/warn (str "Union on " clz " has a strange initial state")))
+      state)))

 (defprotocol UntangledApplication
   (mount [this root-component target-dom-id] "Start/replace the webapp on the given DOM ID or DOM Node.")
@@ -73,7 +92,9 @@
         (do
           (when (and (or (= Atom (type initial-state)) (seq initial-state)) (implements? InitialAppState root-component))
             (log/warn "You supplied an initial state AND a root component with a constructor. Using InitialAppState!"))
-          (app/initialize this state root-component dom-id-or-node reconciler-options)))))
+          (let [app (app/initialize this state root-component dom-id-or-node reconciler-options)]
+            (merge-alternate-union-elements! app root-component)
+            app)))))

   (reset-state! [this new-state] (reset! (om/app-state reconciler) new-state))

@@ -151,11 +172,9 @@
    If the target is a vector element then that element must already exist in the vector.
   "
   [state ident & named-parameters]
-  (js/console.log "integrating" named-parameters)
   (let [already-has-ident-at-path? (fn [data-path] (boolean (seq (filter #(= % ident) (get-in @state data-path)))))
         actions (partition 2 named-parameters)]
     (doseq [[command data-path] actions]
-      (js/console.log :cmd command :dp data-path)
       (case command
         :prepend (when-not (already-has-ident-at-path? data-path)
                    (assert (vector? (get-in @state data-path)) (str "Path " data-path " for prepend must target an app-state vector."))
@@ -216,3 +235,27 @@
     (omp/queue! reconciler data-path-keys)
     @state))

+(defn- merge-alternate-union-elements! [app root-component]
+  (letfn [(walk-ast
+            ([ast visitor]
+             (walk-ast ast visitor nil))
+            ([ast visitor last-join-component]
+             (visitor ast last-join-component)
+             (when (:children ast)
+               (let [join-component (if (= :join (:type ast))
+                                      (:component ast)
+                                      last-join-component)]
+                 (doseq [c (:children ast)]
+                   (walk-ast c visitor join-component))))))
+          (merge-union [{:keys [type component query children] :as n} last-join-component]
+            (when (= :union type)
+              (let [default-branch (and last-join-component (implements? InitialAppState last-join-component) (initial-state last-join-component nil))
+                    to-many? (vector? default-branch)]
+                (doseq [element (->> query vals (map (comp :component meta)))]
+                  (let [state (and (implements? InitialAppState element) (initial-state element nil))]
+                    (cond
+                      (and state (not default-branch)) (log/warn "Subelements of union with query " query " have initial state, but the union component itself has no initial app state. Your app state may not have been initialized correctly.")
+                      (not to-many?) (merge-state! app last-join-component state)))))))]
+    (walk-ast
+      (om/query->ast (om/get-query root-component))
+      merge-union)))


Added support for hidden directories from other operating systems

--- src/video_server/directory.clj
+++ src/video_server/directory.clj
@@ -22,6 +22,13 @@
 (def ^:private fs-events
   (into-array (type StandardWatchEventKinds/ENTRY_CREATE) (keys events)))

+(defn hidden?
+  "Returns whether the file or directory is hidden using common file
+  nameing conventions."
+  [^File file]
+  (or (.isHidden file)
+      (some #(.startsWith (.getName file) %) ["." "$"])))
+
 (defn- register
   "Recursively registers a directory, calling the dir-fn with a
   :create event for each one that is registered. A depth-first
@@ -32,7 +39,7 @@
               (.register (.toPath dir) ws fs-events)
               (swap! dirs conj (.toPath dir))
               (doseq [subdir (.listFiles dir)]
-                (when (and (.isDirectory subdir) (not (.isHidden subdir)))
+                (when (and (.isDirectory subdir) (not (hidden? subdir)))
                   (register subdir)))
               (when dir-fn (dir-fn :create dir)))]
       (register dir)


formatting

formatting

--- src/midje/checking/checkers/simple.clj
+++ src/midje/checking/checkers/simple.clj
@@ -24,7 +24,9 @@
   (not actual))
 (defalias FALSEY falsey)

-(defchecker & "Any arity" [])
+(defchecker &
+  "Any arity"
+  [actual])

 (defchecker anything
   "Accepts any value."


consumers initialised only once

consumers initialised only once

--- src/trending_lisps/core.clj
+++ src/trending_lisps/core.clj
@@ -40,24 +40,21 @@
                 (update-cache repo)
                 (if cached?
                   (prn (str (:name repo) " is not trending"))
-                  (prn (str (:name repo) " is trending")))))))
+                  (prn (str (:name repo) " is TRENDING")))))))
         (recur))))
-
-(defn post-trending-repos [ch-lang-repos ch-repos langs]
-  ;; communication via two channels
-  ;; channel 1: a collection of repos of a particular lang
-  ;; channel 2: an individual repo
-  (produce-lang-repos ch-lang-repos langs)
-  (consume-lang-repos ch-lang-repos ch-repos)
-  (consume-repos ch-repos))

 (defn -main []
   (let [ch-lang-repos (chan)
         ch-repos (chan)
         langs (:langs cfg)]
-    (at-at/every check-frequency
-                 (partial post-trending-repos
-                          ch-lang-repos
-                          ch-repos
-                          langs)
-                 my-pool)))
+    (do
+      ;; communication via two channels
+      ;; channel 1: a collection of repos of a particular lang
+      ;; channel 2: an individual repo
+      (consume-lang-repos ch-lang-repos ch-repos)
+      (consume-repos ch-repos)
+      (at-at/every check-frequency
+                   (partial produce-lang-repos
+                            ch-lang-repos
+                            langs)
+                   my-pool))))


only show icons in new entry that make sense

--- iwaswhere-web/src/cljs/iwaswhere_web/ui/entry/actions.cljs
+++ iwaswhere-web/src/cljs/iwaswhere_web/ui/entry/actions.cljs
@@ -124,16 +124,19 @@
                           (put-fn [:entry/trash entry]))
             open-external (up/add-search ts tab-group put-fn)
             upvotes (:upvotes entry)
-            show-pvt? (:show-pvt cfg)]
+            show-pvt? (:show-pvt cfg)
+            prev-saved? (:last-saved entry)]
         [:div {:on-mouse-enter #(reset! visible true)
                :on-drag-over   #(do (hide-fn nil) (reset! visible true))
                :on-mouse-leave hide-fn
                :style          {:opacity (if (or edit-mode? @visible) 1 0)}}
-         [:span.fa.toggle
-          {:on-click (upvote-fn entry inc put-fn)
-           :class    (if (pos? upvotes) "fa-thumbs-up" "fa-thumbs-o-up")}]
+         (when prev-saved?
+           [:span.fa.toggle
+            {:on-click (upvote-fn entry inc put-fn)
+             :class    (if (pos? upvotes) "fa-thumbs-up" "fa-thumbs-o-up")}])
          (when map? [:span.fa.fa-map-o.toggle {:on-click toggle-map}])
-         [edit-icon toggle-edit edit-mode? entry]
+         (when prev-saved?
+           [edit-icon toggle-edit edit-mode? entry])
          (when-not (:comment-for entry)
            [:span.fa.fa-clock-o.toggle {:on-click new-pomodoro}])
          (when-not (:activity entry)
@@ -142,7 +145,7 @@
            [:span.fa.fa-coffee.toggle {:on-click add-consumption}])
          (when-not (:comment-for entry)
            [:span.fa.fa-comment-o.toggle {:on-click create-comment}])
-         (when-not (:comment-for entry)
+         (when (and (not (:comment-for entry)) prev-saved?)
            [:span.fa.fa-external-link.toggle {:on-click open-external}])
          (when-not (:comment-for entry)
            [new-link entry put-fn create-linked-entry])


Add missing help: valid-flux-policy-min-max-n-peers

--- src/onyx/static/helpful_job_errors.clj
+++ src/onyx/static/helpful_job_errors.clj
@@ -37,6 +37,9 @@

    :n-peers-with-min-or-max
    [":onyx/n-peers cannot be used with :onyx/min-peers or :onyx/max-peers."]
+
+   :valid-flux-policy-min-max-n-peers
+   ["When using a flux policy, a valid :onyx/min-peers and :onyx/max-peers, or :onyx/n-peers must be set."]

    :range-and-slide-incompatible
    ["Units specified for :window/range and :window/slide are incompatible with each other."]
@@ -416,6 +419,10 @@
   [entry error-data]
   [(str (semantic-error-msgs :sliding-window-needs-range-and-slide))])

+(defmethod predicate-error-msg 'valid-flux-policy-min-max-n-peers
+  [entry error-data]
+  [(str (semantic-error-msgs :valid-flux-policy-min-max-n-peers))])
+
 (defn missing-required-key* [job context error-data structure-type]
   (let [faulty-key (:missing-key error-data)
         path-len (count (:path error-data))


add company-slug and section-name fields to placeholder sections

this allows the schema to remain consistent and wherever sections
are passed we can be certain they will have those properties

--- src/open_company/resources/company.clj
+++ src/open_company/resources/company.clj
@@ -131,13 +131,19 @@
   {:pre [(string? slug)]}
   (common/read-resource table-name slug))

-(defn placeholder-sections []
+(defn placeholder-sections [company-slug]
   (reduce (fn [s sec]
-            (assoc s (-> sec :name keyword)
-                     (assoc sec :placeholder true)))
+            (assoc s
+                   (-> sec :name keyword)
+                   (-> sec
+                       (assoc :section-name (-> sec :name keyword))
+                       (assoc :company-slug company-slug)
+                       (assoc :placeholder true)
+                       (dissoc :name))))
           {}
           (filter :core common/sections)))

+;; ----- Slug -----
 (declare list-companies)
 (defn taken-slugs []
   (set (map :slug (list-companies))))


Add a small delay for history fetching (beter user experience).

--- src/uxbox/data/history.cljs
+++ src/uxbox/data/history.cljs
@@ -114,8 +114,8 @@
                       (rx/take 1))]
       (->> (rx/filter udp/page-synced? s)
            (rx/take-until stoper)
+           (rx/delay 1000)
            (rx/map (comp :id :page))
-           (rx/pr-log "watcher:")
            (rx/mapcat #(rx/of
                         (fetch-page-history %)
                         (fetch-pinned-page-history %)))))))


cleanup

cleanup

--- src/version_parser/core.clj
+++ src/version_parser/core.clj
@@ -16,24 +16,19 @@
 (defn -main
   "Entry Point"
   [& args]
-
-  (let [opts (:options (clojure.tools.cli/parse-opts args cli-options))]
+  (let [opts (:options (clojure.tools.cli/parse-opts args cli-options))
+        output (:output opts)
+        pipelines (:pipelines conf (:config opts))
+        otherjars (:system-jar-info (:config conf (:config opts)))]
     ; clear out the file before writing to it
-    (def output (:output opts))
     (spit output "")

-    (def pipelines (:pipelines conf (:config opts)))
-
     ; for each pipeline, create <key>/jarname jarname pairs and write to file
-    (doseq [[k v]pipelines]
+    (doseq [[k v] pipelines]
       (spit output
         (clojure.string/join " "
           [(:pail v) (clojure.string/join "/" [(:key v) (:transform-jar v)]) (:transform-jar v) "\n"]) :append true))

-
-    ; find the non-pipeline jars
-    (def otherjars (:system-jar-info (:config conf(:config opts))))
-
     (doseq [[k v]otherjars]
       (spit output
         (clojure.string/join " "


parens!  but it works again.  hooray.

parens!  but it works again.  hooray.

--- src/version_parser/core.clj
+++ src/version_parser/core.clj
@@ -18,10 +18,11 @@
   [& args]
   (let [opts (:options (clojure.tools.cli/parse-opts args cli-options))
         output (:output opts)
-        pipelines (:pipelines conf (:config opts))
+        pipelines (:pipelines (conf (:config opts)))
         otherjars (:system-jar-info (:config conf (:config opts)))]
     ; clear out the file before writing to it
     (spit output "")
+

     ; for each pipeline, create <key>/jarname jarname pairs and write to file
     (doseq [[k v] pipelines]


[#244] Modify stats end-to-end test

[#244] Modify stats end-to-end test

--- api/test/clojure/org/akvo/flow_api/end_to_end.clj
+++ api/test/clojure/org/akvo/flow_api/end_to_end.clj
@@ -1,7 +1,8 @@
 (ns org.akvo.flow-api.end-to-end
   (:require [clojure.test :refer [use-fixtures deftest testing is]]
             [clj-http.client]
-            [org.akvo.flow-api.fixtures :as fixtures]))
+            [org.akvo.flow-api.fixtures :as fixtures])
+  (:import clojure.lang.ExceptionInfo))

 (use-fixtures :once (fn [f]
                       (fixtures/check-servers-up)
@@ -10,48 +11,69 @@
 (deftest huge-headers
   (testing "Keycloak Bearer token header is bigger than 8k"
     (is (= 200
-          (:status (clj-http.client/get "http://mainnetwork:3000/"
+          (:status (clj-http.client/get "http://localhost:3000/"
                      {:as :json
                       :headers {"huge" (apply str (repeat 30000 "x"))}
                       :content-type :json}))))))

 (deftest answer-stats
   (testing "Random email trying to get a statistic"
-    (is (thrown? Exception
-                 (clj-http.client/get "http://mainnetwork:3000/orgs/akvoflowsandbox/stats"
-                                      {:as :json
-                                       :headers {"x-akvo-email" "random.email@gmail.com"}
-                                       :query-params {:survey_id "148412306"
-                                                      :form_id "145492013"
-                                                      :question_id "147432013"}
-                                       :content-type :json}))))
+    (is (thrown-with-msg? ExceptionInfo #"status 403"
+        (try
+          (clj-http.client/get "http://localhost:3000/orgs/akvoflowsandbox/stats"
+                               {:as :json
+                                :headers {"x-akvo-email" "random.email@gmail.com"}
+                                :query-params {:survey_id "148412306"
+                                               :form_id "145492013"
+                                               :question_id "147432013"}
+                                :content-type :json})
+          (catch ExceptionInfo e
+            (is (= (-> e ex-data :status) 403))
+            (is (.contains ^String (-> e ex-data :body) "User does not exist"))
+            (throw e))))))
   (testing "Survey Not Found"
-    (is (thrown? Exception
-                 (clj-http.client/get "http://mainnetwork:3000/orgs/akvoflowsandbox/stats"
-                                      {:as :json
-                                       :headers {"x-akvo-email" "akvo.flow.user.test@gmail.com"}
-                                       :query-params {:survey_id "999"
-                                                      :form_id "145492013"
-                                                      :question_id "147432013"}
-                                       :content-type :json}))))
+    (is (thrown-with-msg? ExceptionInfo #"status 404"
+                          (try
+                            (clj-http.client/get "http://localhost:3000/orgs/akvoflowsandbox/stats"
+                                                 {:as :json
+                                                  :headers {"x-akvo-email" "akvo.flow.user.test@gmail.com"}
+                                                  :query-params {:survey_id "999"
+                                                                 :form_id "145492013"
+                                                                 :question_id "147432013"}
+                                                  :content-type :json})
+                            (catch ExceptionInfo e
+                              (is (= (-> e ex-data :status) 404))
+                              (is (.contains ^String (-> e ex-data :body) "Survey not found"))
+                              (throw e))))))
   (testing "Question Not Found"
-    (is (thrown? Exception
-                 (clj-http.client/get "http://mainnetwork:3000/orgs/akvoflowsandbox/stats"
-                                      {:as :json
-                                       :headers {"x-akvo-email" "akvo.flow.user.test@gmail.com"}
-                                       :query-params {:survey_id "148412306"
-                                                      :form_id "145492013"
-                                                      :question_id "999"}
-                                       :content-type :json}))))
+    (is (thrown-with-msg? ExceptionInfo #"status 404"
+                          (try
+                            (clj-http.client/get "http://localhost:3000/orgs/akvoflowsandbox/stats"
+                                                 {:as :json
+                                                  :headers {"x-akvo-email" "akvo.flow.user.test@gmail.com"}
+                                                  :query-params {:survey_id "148412306"
+                                                                 :form_id "145492013"
+                                                                 :question_id "999"}
+                                                  :content-type :json})
+                            (catch ExceptionInfo e
+                              (is (= (-> e ex-data :status) 404))
+                              (is (.contains ^String (-> e ex-data :body) "Question not found"))
+                              (throw e))))))
   (testing "Question is not an Option Question"
-    (is (thrown? Exception
-                 (clj-http.client/get "http://mainnetwork:3000/orgs/akvoflowsandbox/stats"
-                                      {:as :json
-                                       :headers {"x-akvo-email" "akvo.flow.user.test@gmail.com"}
-                                       :query-params {:survey_id "148412306"
-                                                      :form_id "145492013"
-                                                      :question_id "148442013"}
-                                       :content-type :json}))))
+    (is (thrown-with-msg? ExceptionInfo #"status 400"
+                          (try
+                            (clj-http.client/get "http://localhost:3000/orgs/akvoflowsandbox/stats"
+                                                 {:as :json
+                                                  :headers {"x-akvo-email" "akvo.flow.user.test@gmail.com"}
+                                                  :query-params {:survey_id "148412306"
+                                                                 :form_id "145492013"
+                                                                 :question_id "148442013"}
+                                                  :content-type :json})
+                            (catch ExceptionInfo e
+                              (is (= (-> e ex-data :status) 400))
+                              (prn (-> e ex-data :body))
+                              (is (.contains ^String (-> e ex-data :body) "Not an OPTION question"))
+                              (throw e))))))
   (testing "Answer summary of an option type of question"
     (let [response (clj-http.client/get "http://mainnetwork:3000/orgs/akvoflowsandbox/stats"
                      {:as :json


use keyword_ignore_case analyzer with wbid

--- src/wb_es/mappings/core.clj
+++ src/wb_es/mappings/core.clj
@@ -13,7 +13,7 @@
 (def generic-mapping
   {:properties
    {:wbid {:type "string"
-           :analyzer "keyword"
+           :analyzer "keyword_ignore_case"
            :include_in_all false
            :fields {:autocomplete_keyword {:type "string"
                                            :analyzer "autocomplete"


Remove logs

Remove logs

--- backend/src/akvo/lumen/endpoint/visualisation.clj
+++ backend/src/akvo/lumen/endpoint/visualisation.clj
@@ -12,7 +12,6 @@
 (defn routes [{:keys [windshaft-url tenant-manager] :as opts}]
   ["/visualisations"
    ["" {:get {:handler (fn [{tenant :tenant}]
-                         (log/error "HERE!")
                          (visualisation/all (p/connection tenant-manager tenant)))}
         :post {:parameters {:body map?}
                :handler (fn [{tenant :tenant


Rewrite the handler to be threaded for middleware

--- src/leiningen/new/chestnut/src/clj/chestnut/server.clj
+++ src/leiningen/new/chestnut/src/clj/chestnut/server.clj
@@ -23,9 +23,11 @@
 (defn- wrap-browser-caching-opts [handler] (wrap-browser-caching handler (or (env :browser-caching) {})))

 (def http-handler
-  (if is-dev?
-    (wrap-browser-caching-opts (reload/wrap-reload (wrap-defaults #'routes {{ring-defaults}})))
-    (wrap-gzip (wrap-browser-caching-opts (wrap-defaults routes {{ring-defaults}})))))
+    (-> routes
+        (wrap-defaults {{ring-defaults}})
+        (if is-dev? reload/wrap-reload identity)
+        wrap-browser-caching-opts
+        wrap-gzip))

 (defn run-web-server [& [port]]
   (let [port (Integer. (or port (env :port) 10555))]


AST bugfixes

AST bugfixes

--- src/aurora/ast.cljs
+++ src/aurora/ast.cljs
@@ -17,11 +17,10 @@
          (js! (:js x))))

 (defn ref! [x]
-  (check
-   (case (:type x)
-     :ref/id (ref-id! x)
-     :ref/js (ref-js! x)
-     false)))
+  (case (:type x)
+    :ref/id (check (ref-id! x))
+    :ref/js (check (ref-js! x))
+    (check false)))

 (defn tag! [x]
   (check (= :tag (:type x))
@@ -35,21 +34,22 @@
          (every? id! (:args x))))

 (defn data! [x]
-  (check
-   (cond
-    (= :tag (:type x)) (tag! x)
-    (#{:ref/id :ref/page} (:type x)) (ref! x)
-    (number? x) true
-    (string? x) true
-    (vector? x) (every? data! x)
-    (map? x) (and (every? data! (keys x)) (every? data! (vals x))))))
+  (cond
+   (= :tag (:type x)) (check (tag! x))
+   (#{:ref/id :ref/js} (:type x)) (check (ref! x))
+   (number? x) true
+   (string? x) true
+   (vector? x) (check (every? data! x))
+   (map? x) (check (every? data! (keys x))
+                   (every? data! (vals x)))
+   :else (check false)))

 (defn constant! [x]
   (check (= :constant (:type x))
          (data! (:data x))))

 (defn match-any! [x]
-  (check (= :match/any) (:type x)))
+  (check (= :match/any (:type x))))

 (defn match-bind! [x]
   (check (= :match/bind (:type x))
@@ -57,26 +57,23 @@
          (pattern! (:pattern x))))

 (defn pattern! [x]
-  (check
-   (cond
-    (= :match/any (:type x) (match-any! x))
-    (= :match/bind (:type x) (match-bind! x))
-    (= :tag (:type x)) (tag! x)
-    (#{:ref/id :ref/page} (:type x)) (ref! x)
-    (number? x) true
-    (string? x) true
-    (vector? x) (every? pattern! x)
-    (map? x) (and (every? data! (keys x)) (every? pattern! (vals x))))))
-
-(defn pattern! [x]
-  (check (= :type )))
+  (cond
+   (= :match/any (:type x)) (check (match-any! x))
+   (= :match/bind (:type x)) (check (match-bind! x))
+   (= :tag (:type x)) (check (tag! x))
+   (#{:ref/id :ref/js} (:type x)) (check (ref! x))
+   (number? x) true
+   (string? x) true
+   (vector? x) (check (every? pattern! x))
+   (map? x) (check (every? data! (keys x))
+                   (every? pattern! (vals x)))
+   :else (check false)))

 (defn action! [x]
-  (check
-   (case (:type x)
-     :call (call! x)
-     :constant (constant! x)
-     false)))
+  (case (:type x)
+    :call (check (call! x))
+    :constant (check (constant! x))
+    (check false)))

 (defn branch! [x]
   (check (= :match/branch (:type x))
@@ -90,11 +87,11 @@
          (every? branch! (:branches x))))

 (defn step! [x]
-  (check (id! (:id x))
-         (case (:type x)
-           :call (call! x)
-           :constant (constant! x)
-           :match (match! x))))
+  (check (id! (:id x)))
+  (case (:type x)
+    :call (check (call! x))
+    :constant (check (constant! x))
+    :match (check (match! x))))

 (defn page! [x]
   (check (= :page (:type x))


CMR-4135: Disabled Gorilla Repl.

CMR-4135: Disabled Gorilla Repl.

--- dev-system/src/cmr/dev_system/system.clj
+++ dev-system/src/cmr/dev_system/system.clj
@@ -318,9 +318,7 @@
      :pre-components (u/remove-nil-keys
                        {:elastic-server elastic-server
                         :broker-wrapper queue-broker})
-     :post-components {:control-server control-server
-                       :gorilla-repl (when-not (zero? (gorilla-repl-port))
-                                       (gorilla-repl/create-gorilla-repl-server (gorilla-repl-port)))}}))
+     :post-components {:control-server control-server}}))

 (defn- stop-components
   [system components-key]


VIP-744: Add notify flag to optionally suppress dashboard emails (#373)

add notify flag

--- src/vip/data_processor.clj
+++ src/vip/data_processor.clj
@@ -30,7 +30,8 @@
          stop (:stop result)
          completed-message {:initialInput message
                             :status "complete"
-                            :publicId (:public-id result)}]
+                            :publicId (:public-id result)
+                            :notify (:notify? message)}]
      (psql/complete-run result)
      (log/info "New run completed:"
                (psql/get-run result))


Renamed loop state vars with suffixes.

Renamed loop state vars with suffixes.

--- src/cbfg/fence.cljs
+++ src/cbfg/fence.cljs
@@ -37,39 +37,39 @@
 ;; request format
 ;; {:rq function-to-call :fence true-or-false}

-(defn make-fenced-pump [actx in-ch out-ch max-inflights]
+(defn make-fenced-pump [actx in-ch out-ch max-inflight-chs]
   (ago-loop fenced-pump actx
-   [inflights #{}              ; chans of requests currently being processed.
-    fenced nil                 ; chan of last, inflight "fenced" request.
-    fenced-res nil]            ; last received result from last fenced request.
-   (let [i (vec (if (or fenced ; if we're fenced or too many inflight requests,
-                        (>= (count inflights) max-inflights))
-                  inflights    ; then ignore in-ch & finish existing inflight requests.
-                  (conj inflights in-ch)))
-         [v ch] (if (empty? i) ; empty when in-ch is closed and no inflights.
+   [inflight-chs #{}              ; chans of requests currently being processed.
+    fenced-ch nil                 ; chan of last, inflight "fenced" request.
+    fenced-ch-res nil]            ; last received result from last fenced request.
+   (let [i (vec (if (or fenced-ch ; if we're fenced or too many inflight requests,
+                        (>= (count inflight-chs) max-inflight-chs))
+                  inflight-chs    ; then ignore in-ch & finish existing inflight requests.
+                  (conj inflight-chs in-ch)))
+         [v ch] (if (empty? i)    ; empty when in-ch is closed and no inflight-chs.
                   [nil nil]
                   (aalts fenced-pump i))]
      (cond
       (= nil v ch) (aclose fenced-pump out-ch)
       (= ch in-ch) (if (nil? v)
-                     (recur inflights out-ch nil)
+                     (recur inflight-chs out-ch nil)
                      (let [new-inflight ((:rq v) fenced-pump)]
-                       (recur (conj inflights new-inflight)
+                       (recur (conj inflight-chs new-inflight)
                               (if (:fence v) new-inflight nil)
                               nil)))
-      (= v nil) (let [new-inflights (disj inflights ch)] ; an inflight request is done.
-                  (if (empty? new-inflights)             ; if inflight requests are all done,
-                    (do (when fenced-res                 ; finally send the fenced-res that
-                          (aput fenced-pump              ; we have been holding onto.
-                                out-ch fenced-res))
-                        (recur new-inflights nil nil))
-                    (recur new-inflights fenced fenced-res)))
-      (= ch fenced) (do (when fenced-res
-                          (aput fenced-pump              ; send any previous fenced-res so
-                                out-ch fenced-res))      ; we can hold v as last fenced-res.
-                        (recur inflights fenced v))
+      (= v nil) (let [new-inflight-chs (disj inflight-chs ch)] ; an inflight request is done.
+                  (if (empty? new-inflight-chs)                ; if inflight requests are all done,
+                    (do (when fenced-ch-res                    ; finally send the fenced-ch-res that
+                          (aput fenced-pump                    ; we have been holding onto.
+                                out-ch fenced-ch-res))
+                        (recur new-inflight-chs nil nil))
+                    (recur new-inflight-chs fenced-ch fenced-ch-res)))
+      (= ch fenced-ch) (do (when fenced-ch-res
+                          (aput fenced-pump            ; send any previous fenced-res so
+                                out-ch fenced-ch-res)) ; we can hold v as last fenced-ch-res.
+                        (recur inflight-chs fenced-ch v))
       :else (do (aput fenced-pump out-ch v)
-                (recur inflights fenced fenced-res))))))
+                (recur inflight-chs fenced-ch fenced-ch-res))))))

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

@@ -121,13 +121,13 @@
                        "pass"
                        "FAIL")
                      %)
-              [["test with 2 max-inflights"
+              [["test with 2 max-inflight-chs"
                 (let [ch (test-helper test 100 1 2 reqs)
                       res (atake test ch)]
                   (atake test ch)
                   res)
                 '(6 3 12 40 41 42 43 44 11 11 6 7 8 0 1 9 32)]
-               ["test with 200 max-inflights"
+               ["test with 200 max-inflight-chs"
                 (let [ch (test-helper test 100 1 200 reqs)
                       res (atake test ch)]
                   (atake test ch)


added labels to cells, simplified empty cell

--- src/cellf/core.cljs
+++ src/cellf/core.cljs
@@ -118,20 +118,20 @@

 (defn cell [app [n idx]]
-  (let [is-adj   (adj? app idx)
-        is-empty (= n :empty)]
-    (dom/div #js {
-      :react-key n
-      :className (str
-        "cell"
-        (if is-empty " empty" (when is-adj " adjacent")))
-      :style   (get-cell-transform app idx)
-      :onClick #(when is-adj (move! app n))}
-        (when-not is-empty
+  (let [is-adj (adj? app idx)]
+    (if (= n :empty)
+      (dom/div #js {:react-key n :className "cell empty"})
+      (dom/div #js {
+        :react-key n
+        :className (str "cell" (when is-adj " adjacent"))
+        :style     (get-cell-transform app idx)
+        :onClick   #(when is-adj (move! app n))}
           (dom/video #js {
             :src      (:stream app)
             :autoPlay "autoplay"
-            :style    (get-bg-transform app n)})))))
+            :style    (get-bg-transform app n)})
+          (dom/label nil n)))))
+

 (defn grid [{:keys [grid-px] :as app}]
   (om/component


Remove not relvant tests at this moment.

--- test/catacumba/stomp_tests.clj
+++ test/catacumba/stomp_tests.clj
@@ -1,18 +0,0 @@
-(ns catacumba.stomp-tests
-  (:require [clojure.core.async :refer [put! take! chan <! >! go close! go-loop onto-chan timeout]]
-            [clojure.test :refer :all]
-            [clojure.java.io :as io]
-            [clojure.pprint :refer [pprint]]
-            [clojure.core.async :as async]
-            [clj-http.client :as client]
-            [catacumba.core :as ct]
-            [catacumba.experimental.stomp :as stomp]))
-
-
-(deftest message-broker-tests
-  (testing "Simple subscription."
-    (let [p (promise)]
-      (with-open [broker (stomp/message-broker {})]
-        (stomp/subscribe! broker "topic" :foo (fn [m] (deliver p m)))
-        (stomp/send! broker "topic" 123)
-        (is (= (deref p 2000 nil) 123))))))


use sente router+handler instead of directly consuming the ch-recv channel

--- cljx/plongeur-cljs/src/kierros/sente_client_driver.cljs
+++ cljx/plongeur-cljs/src/kierros/sente_client_driver.cljs
@@ -1,7 +1,8 @@
 (ns kierros.sente-client-driver
-  "Sente websocket client driver. See https://github.com/ptaoussanis/sente"
+  "Sente websocket client driver.
+  See https://github.com/ptaoussanis/sente"
   (:require [cljs.core.async :as a :refer [<! >! put! close! chan pipe]]
-            [taoensso.sente  :as s])
+            [taoensso.sente :as s])
   (:require-macros [cljs.core.async.macros :refer [go go-loop]]))

 (defn make-sente-client-driver
@@ -9,11 +10,14 @@
   Returns a websocket client driver powered by Sente."
   [path & options]
   (fn [request-chan]
-    (let [{:keys [chsk ch-recv send-fn]} (s/make-channel-socket-client! path options)]
+    (let [{:keys [chsk ch-recv send-fn]} (s/make-channel-socket-client! path options)
+          server-response-chan           (chan 10)
+          router-shutdown-fn             (s/start-chsk-router! ch-recv #(go (>! server-response-chan %)))]
       (go-loop []
-               (if-let [request (<! request-chan)]
-                 (do (send-fn request)
+               (if-let [request->server (<! request-chan)]
+                 (do (send-fn request->server)
                      (recur))
                  (do (some-> chsk s/chsk-disconnect!)
+                     (router-shutdown-fn)
                      (prn "sente client driver stopped"))))
-      ch-recv)))+      server-response-chan)))


Allow custom groups.

Allow custom groups.

--- src/clojars/scp.clj
+++ src/clojars/scp.clj
@@ -109,11 +109,11 @@
             [model jarmap] (read-metadata metafile act-group)
             :let [names (jar-names jarmap)]]

-      (when (not= (:group jarmap) act-group)
-        (throw (Exception.
-                (str "Custom group ids are not supported yet. "
-                     " For now please use "
-                     act-group " instead of " (:group jarmap)))))
+      (comment (when (not= (:group jarmap) act-group)
+         (throw (Exception.
+                 (str "Custom group ids are not supported yet. "
+                      " For now please use "
+                      act-group " instead of " (:group jarmap))))))

       (if-let [jarfile (some jarfiles names)]
         (do