adding lookup tests

adding lookup tests

--- sample/test/sample/rangemap_test.clj
+++ sample/test/sample/rangemap_test.clj
@@ -78,3 +78,64 @@
     (let [m (-> (range-map :find-ceiling)
                 (dissoc :a))]
       (is (= m {})))))
+
+
+(deftest test-lookup-ceiling-even
+  (testing "lookup (ceiling, even no. of keys)"
+    (let [m (range-map :find-ceiling 5 [3 4 5], 2 [1 2], 8 [6 7 8], 12 [9 10 11 12], 15 [13 14 15], 16 [16])]
+      (is (= [6 7 8] (get m 8)))      ;; exact match
+      (is (= [6 7 8] (get m 7)))      ;; range match
+      (is (= [1 2]   (get m 0)))      ;; lower key
+      (is (= nil     (get m 100)))    ;; higher key
+      )))
+
+
+(deftest test-lookup-ceiling-odd
+  (testing "lookup (ceiling, odd no. of keys)"
+    (let [m (range-map :find-ceiling 5 [3 4 5], 2 [1 2], 8 [6 7 8], 12 [9 10 11 12], 15 [13 14 15])]
+      (is (= [6 7 8] (get m 8)))      ;; exact match
+      (is (= [6 7 8] (get m 7)))      ;; range match
+      (is (= [1 2]   (get m 0)))      ;; lower key
+      (is (= nil     (get m 100)))    ;; higher key
+      )))
+
+
+(deftest test-lookup-ceiling-empty
+  (testing "lookup (ceiling, empty map)"
+    (let [m (range-map :find-ceiling)]
+      (is (= nil (get m 0)))
+      (is (= nil (get m 100))))))
+
+
+(deftest test-lookup-floor-even
+  (testing "lookup (floor, even no. of keys)"
+    (let [m (range-map :find-floor 5 [3 4 5], 2 [1 2], 8 [6 7 8], 12 [9 10 11 12], 15 [13 14 15], 16 [16])]
+      (is (= [6 7 8] (get m 8)))      ;; exact match
+      (is (= [3 4 5] (get m 7)))      ;; range match
+      (is (= nil     (get m 0)))      ;; lower key
+      (is (= [16]    (get m 100)))    ;; higher key
+      )))
+
+
+(deftest test-lookup-floor-odd
+  (testing "lookup (floor, odd no. of keys)"
+    (let [m (range-map :find-floor 5 [3 4 5], 2 [1 2], 8 [6 7 8], 12 [9 10 11 12], 15 [13 14 15])]
+      (is (= [6 7 8]    (get m 8)))      ;; exact match
+      (is (= [3 4 5]    (get m 7)))      ;; range match
+      (is (= nil        (get m 0)))      ;; lower key
+      (is (= [13 14 15] (get m 100)))    ;; higher key
+      )))
+
+
+(deftest test-lookup-floor-empty
+  (testing "lookup (floor, empty map)"
+    (let [m (range-map :find-floor)]
+      (is (= nil (get m 0)))
+      (is (= nil (get m 100))))))
+
+
+(deftest test-fn
+  (testing "function invocation"
+    (let [m (range-map :find-ceiling 5 [3 4 5], 2 [1 2], 8 [6 7 8], 12 [9 10 11 12], 15 [13 14 15])]
+      (is (= [6 7 8] (m 8)))
+      (is (= [6 7 8] (m 7))))))


Removed spaces

Removed spaces

--- modules/datomic/src/modular/datomic.clj
+++ modules/datomic/src/modular/datomic.clj
@@ -46,8 +46,8 @@

 (defn new-datomic-connection []
   (component/using
-    (->DatomicConnection)
-    [:database]))
+   (->DatomicConnection)
+   [:database]))

 (defrecord DatomicSchema [res]
   component/Lifecycle


Fix for logconfig 0.7.3

Fix for logconfig 0.7.3

--- src/cyanite_remover/logging.clj
+++ src/cyanite_remover/logging.clj
@@ -26,6 +26,7 @@
   (swap! stop-on-error? (fn [_] (:stop-on-error options @stop-on-error?)))
   (if-not @disable-log?
     (logconfig/start-logging! {:level (:log-level options default-log-level)
+                               :console false
                                :files [(:log-file options default-log-file)]})
     (log-disable-logging!)))


Fix user info modal refresh

Fix user info modal refresh

--- src/cljs/daveconservatoire/site/ui.cljs
+++ src/cljs/daveconservatoire/site/ui.cljs
@@ -1155,10 +1155,12 @@
     (modal #:ui.modal {:title   "Update your Profile"
                        :onClose #(do
                                    (um/set-value! this :ui/editing-info? false)
-                                   (um/set-value! this :ui/tmp-about about))
+                                   (um/set-value! this :ui/tmp-about about)
+                                   (om/transact! this [:ui/editing-info?]))
                        :onSave  #(do
                                    (om/transact! this `[(user/update {:user/about ~tmp-about})])
-                                   (um/set-value! this :ui/editing-info? false))}
+                                   (um/set-value! this :ui/editing-info? false)
+                                   (om/transact! this [:ui/editing-info?]))}
       (dom/form #js {:id "user-form" :action "profile/update" :method "post"}
         (dom/div #js {:id "user-form_es_" :className "errorSummary" :style #js {:display "none"}}
           (dom/p nil
@@ -1205,7 +1207,9 @@
                   (user-info-modal this))
                 (dom/a #js {:href        "#myModal"
                             :role        "button"
-                            :onClick     #(um/set-value! this :ui/editing-info? true)
+                            :onClick     #(do
+                                            (um/set-value! this :ui/editing-info? true)
+                                            (om/transact! this [:ui/editing-info?]))
                             :className   "btn dc-btn-red pull-right"
                             :data-toggle "modal"}
                   "Update your info")


Add vector? validator on sith-lords state

--- src/cljs/flux_challenge_reagent/sith_lords.cljs
+++ src/cljs/flux_challenge_reagent/sith_lords.cljs
@@ -4,7 +4,7 @@
               [flux-challenge-reagent.util :as util]
               [flux-challenge-reagent.current-planet :as current-planet]))

-(defonce coll (r/atom (vec (repeat 5 nil))))
+(defonce coll (r/atom (vec (repeat 5 nil)) :validator vector?))

 (defn frozen? []
   (let [sith-lords-homeworlds (map #(get-in % [:sith-lord "homeworld"]) @coll)]


Minor docstring fix

Minor docstring fix

--- src/icecap/crypto.clj
+++ src/icecap/crypto.clj
@@ -7,7 +7,9 @@
   - A key derivation function. Used to generate the index (the
   location of the blob in the database) and the cap key (the key used
   to encrypt the blob).
-  - An authenticated encryption scheme."
+  - An authenticated encryption scheme.
+
+  This namespace defines those components."
   (:require [caesium.crypto.generichash :refer [blake2b]]
             [caesium.crypto.secretbox :as secretbox]
             [crypto.random :as csprng])


Document the :swagger option

Document the :swagger option

--- src/io/aviso/rook.clj
+++ src/io/aviso/rook.clj
@@ -152,6 +152,11 @@
   them to the endpoint function).
   The default leaves the basic handler unchanged.

+  :swagger
+  : _Default: false_
+  : If true, then the *expermental* swagger support is enabled.
+  : See the [[io.aviso.rook.swagger]] namespace for more details.
+
   Example call:

        (namespace-handler


Reintegrate discuss.integration

Reintegrate discuss.integration

--- src/devcards/discuss/devcards/core.cljs
+++ src/devcards/discuss/devcards/core.cljs
@@ -7,6 +7,7 @@
             [discuss.debug :as debug]
             [discuss.utils.extensions]
             [discuss.find :as find]
+            [discuss.integration]
             [discuss.references.main :as ref]
             [discuss.utils.common :as lib]
             [discuss.utils.views :as vlib]


Fixed regen-stats.

Fixed regen-stats.

--- src/hxgm30/language/syntagmata/core.clj
+++ src/hxgm30/language/syntagmata/core.clj
@@ -79,9 +79,10 @@

 (defn regen-stats
   []
-  (run!
+  (doall
     (for [language lang/supported]
-      (corpus/dump :stats language (generate-stats language)))))
+      (corpus/dump :stats language (generate-stats language))))
+  :ok)

 (defn stats
   [language]


Added unit tests for testutils.logging/logs-matching.

--- test/puppetlabs/trapperkeeper/logging_test.clj
+++ test/puppetlabs/trapperkeeper/logging_test.clj
@@ -46,3 +46,16 @@
       (let [lines (line-seq reader)]
         (is (= 1 (count lines)))
         (is (re-matches #".*Hi! I shouldn't get filtered\..*" (first lines)))))))
+
+(deftest test-logs-matching
+  (let [log-lines '([puppetlabs.trapperkeeper.logging-test :info nil "log message1 at info"]
+                    [puppetlabs.trapperkeeper.logging-test :debug nil "log message1 at debug"]
+                    [puppetlabs.trapperkeeper.logging-test :warn nil "log message2 at warn"])]
+
+    (testing "logs-matching can filter on message"
+      (is (= 2 (count (logs-matching #"log message1" log-lines)))))
+
+    (testing "logs-matching can filter on message and level"
+      (is (= 1 (count (logs-matching #"log message1" log-lines :debug))))
+      (is (= "log message1 at debug" (-> (logs-matching #"log message1" log-lines :debug) first :message)))
+      (is (empty? (logs-matching #"log message2" log-lines :info))))))


URI encode sourceURL of js files

URI encode sourceURL of js files

--- src/lt/util/load.cljs
+++ src/lt/util/load.cljs
@@ -32,7 +32,7 @@
 (defn- prep [code file]
   (-> code
       (abs-source-mapping-url file)
-      (str "\n\n//# sourceURL=" file)))
+      (str "\n\n//# sourceURL="  (js/encodeURI file))))

 (defn js
   ([file] (js file false))


Fix missing on-js-reload

Fix missing on-js-reload

--- resources/leiningen/new/nw/core.cljs
+++ resources/leiningen/new/nw/core.cljs
@@ -3,3 +3,5 @@
 (enable-console-print!)

 (println "Hello World!")
+
+(defn on-js-reload [])


Fix indentation of one-item? function spec

--- src/main/workflo/macros/query/util.cljc
+++ src/main/workflo/macros/query/util.cljc
@@ -8,12 +8,12 @@
             [clojure.string :refer [capitalize]]))

 (s/fdef one-item?
-        :args (s/cat :coll coll?)
-        :ret  boolean?
-        :fn   (s/or :true  (s/and #(= 1 (count (:coll (:args %))))
-                                  #(true? (:ret %)))
-                    :false (s/and #(not= 1 (count (:coll (:args %))))
-                                  #(false? (:ret %)))))
+  :args (s/cat :coll coll?)
+  :ret  boolean?
+  :fn   (s/or :true  (s/and #(= 1 (count (:coll (:args %))))
+                            #(true? (:ret %)))
+              :false (s/and #(not= 1 (count (:coll (:args %))))
+                            #(false? (:ret %)))))

 (defn one-item?
   [coll]


Use partial instead of inline fn

Use partial instead of inline fn

--- src/github_changelog/github.clj
+++ src/github_changelog/github.clj
@@ -37,15 +37,14 @@
 (defn- make-requests [config links]
   (map #(make-request config {:page %}) (gen-pages links)))

-(defn- issue-request-fn [endpoint]
-  (fn [request]
-    (let [response (http/get endpoint request)]
-      (update response :body j/read-value))))
+(defn- issue-request [endpoint request]
+  (let [response (http/get endpoint request)]
+    (update response :body j/read-value)))

 (defn- call-api-fn [config]
-  (let [rate-limit (get config :rate-limit 5)
-        end-point (pulls-url config)]
-    (throttler/throttle-fn (issue-request-fn end-point) rate-limit :second)))
+  (let [ratelimit (get config :rate-limit 5)
+        endpoint  (pulls-url config)]
+    (throttler/throttle-fn (partial issue-request endpoint) ratelimit :second)))

 (defn- get-pulls [config]
   (let [call-api (call-api-fn config)


statistics template fixed

statistics template fixed

--- src/notehub/views.clj
+++ src/notehub/views.clj
@@ -83,16 +83,17 @@
   (let [page-title (get-message :statistics)
         info (assoc stats :publisher publisher)]
     (layout :no-js {} page-title
-            [:h2.central-element note-title]
-            [:h3.central-element.helvetica page-title]
-            [:table#stats.helvetica.central-element
-             (map
-               #(when-let [v (% info)]
-                 [:tr
-                  [:td (str (get-message %) ":")]
-                  [:td (if (or (= % :published) (= % :edited))
-                         (str (java.util.Date. (Long/parseLong v))) v)]])
-               [:published :edited :publisher :views])])))
+            [:div.central-element.helvetica {:style "width: 80%"}
+             [:h2 note-title]
+             [:h3.helvetica page-title]
+             [:table#stats
+              (map
+                #(when-let [v (% info)]
+                   [:tr
+                    [:td (str (get-message %) ":")]
+                    [:td (if (or (= % :published) (= % :edited))
+                           (str (java.util.Date. (Long/parseLong v))) v)]])
+                [:published :edited :publisher :views])]])))

 (defn note-update-page [note-id note]
   (input-form "/update-note"
@@ -113,7 +114,7 @@
           (let [urls {:short-url short-url
                       :notehub "/"}
                 links (map #(link-to
-                             (urls % (str (:longURL note) "/" (name %)))
-                             (get-message %))
+                              (urls % (str (:longURL note) "/" (name %)))
+                              (get-message %))
                            [:notehub :stats :edit :export :short-url])]
             [:div#footer (interpose [:span.middot "·"] links)])))


fix "name" as in "my name is Luisa"

fix "name" as in "my name is Luisa"

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1333,11 +1333,12 @@
      {:synsem {:agr agr
                :cat :noun
                :sem {:pred :name
+                     :mod '()
                      :subj of}
                :subcat {:1 {:agr agr
                             :cat :det
                             :def :possessive
-                            :sem of}}}})
+                            :sem {:of of}}}}})

    "new" {:synsem {:cat :adjective
                    :sem {:mod {:pred :new}


add 2 meanings of "short": one for physical objects, and one for events

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1704,11 +1704,18 @@
                     :subcat {:1 {:cat :det}
                              :2 '()}}})
    "short"
-   [;; non-comparative:
+   [(unify adjective
+           {:synsem {:cat :adjective
+                     :sem {:mod {:pred :short}
+                           :comparative false
+                           :physical-object true}
+                     :subcat {:1 {:cat :det}
+                              :2 '()}}})
     (unify adjective
            {:synsem {:cat :adjective
                      :sem {:mod {:pred :short}
-                           :comparative false}
+                           :comparative false
+                           :event true}
                      :subcat {:1 {:cat :det}
                               :2 '()}}})]


+professor,pupil,student

+professor,pupil,student

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1420,6 +1420,18 @@
    "print"  {:synsem {:cat :verb
                       :sem {:pred :stampare}}}

+   "professor" {:synsem {:agr :top
+                         :cat :noun
+                         :sem {:human true
+                               :pred :professor}}}
+
+   "pupil" {:synsem {:agr :top
+                     :cat :noun
+                     :sem {:human true
+                           ;; example of a synonym, where we use the convention of making the
+                           ;; :pred (i.e. :student) the more common case (c.f. "student")
+                           :pred :student}}}
+
    "put" {:english {:past "put"
                     :participle "putting"}
           :synsem {:cat :verb
@@ -1642,6 +1654,11 @@
    "strike" {:english {:past "struck"}
              :synsem {:cat :verb
                       :sem {:pred :strike}}}
+
+   "student" {:synsem {:agr :top
+                       :cat :noun
+                       :sem {:human true
+                             :pred :student}}}

    "study"  {:synsem {:cat :verb
                       :sem {:pred :study}}


+tall

+tall

--- src/babel/english/lexicon.cljc
+++ src/babel/english/lexicon.cljc
@@ -1496,7 +1496,22 @@
    {:synsem {:cat :verb
              :sem {:pred :talk
                    :subj {:human true}}}}
-
+
+   "tall"
+   [;; non-comparative:
+    (let [subject-sem (atom {:human true}) ;; only humans can be tall.
+          subject-agr (atom :top)]
+      (unify adjective
+             {:synsem {:cat :adjective
+                       :sem {:pred :alto
+                             :comparative false
+                             :arg1 subject-sem
+                             :human true}
+                       :subcat {:1 {:cat :det
+                                    :agr subject-agr
+                                    :sem subject-sem}
+                                :2 '()}}}))]
+
    "teach"  {:synsem {:cat :verb
                       :sem {:pred :teach}}
                             :english {:past "taught"}}


+clojure.repl/doc; +dag_unify.core/fail?

--- src/babel/english/workbook.clj
+++ src/babel/english/workbook.clj
@@ -18,11 +18,12 @@
    [clojail.testers :refer :all]
    [clojure.core :exclude [get-in]]
    [clojure.core :as core] ;; This allows us to use core's get-in by doing "(core/get-in ..)"
+   [clojure.repl :refer [doc]]
    [clojure.set :as set]
    [clojure.string :as string]
    [clojure.tools.logging :as log]
    [compojure.core :as compojure :refer [GET PUT POST DELETE ANY]]
-   [dag_unify.core :refer [fail-path-between get-in remove-false strip-refs unify]]
+   [dag_unify.core :refer [fail? fail-path-between get-in remove-false strip-refs unify]]
    [hiccup.core :refer [html]]))

 (defn analyze


remove (atom)

remove (atom)

--- src/babel/espanol/grammar.cljc
+++ src/babel/espanol/grammar.cljc
@@ -501,9 +501,8 @@
                           (merge tree
                                  (morph-walk-tree tree))))
      :grammar grammar
-     :lexical-cache (atom (cache/fifo-cache-factory {} :threshold 1024))
-     :lexicon lexicon
-     }))
+     :lexical-cache (cache/fifo-cache-factory {} :threshold 1024)
+     :lexicon lexicon}))

 (defn parse [surface]
   (parse/parse surface


whitespace

whitespace

--- src/babel/espanol/lexicon.cljc
+++ src/babel/espanol/lexicon.cljc
@@ -73,7 +73,7 @@
                          :sem {:pred :abandon}}}

    "abrazar" {:synsem {:cat :verb
-                         :sem {:pred :hug}}}
+                       :sem {:pred :hug}}}

    "acabar" {:synsem {:cat :verb
                       :sem {:pred :finish}}}


Add handler for loading anonymous group

Add handler for loading anonymous group

duplicating the anonymous handler for logged-in users, so they can
also view groups without joining

--- src/braid/core/server/sync.clj
+++ src/braid/core/server/sync.clj
@@ -20,7 +20,7 @@
     [braid.core.server.events :as events]
     [braid.core.server.invite :as invites]
     [braid.core.server.socket :refer [chsk-send! connected-uids]]
-    [braid.core.server.sync-handler :refer [event-msg-handler]]
+    [braid.core.server.sync-handler :as sync-handler :refer [event-msg-handler]]
     [braid.core.server.sync-helpers :as helpers :refer [broadcast-group-change]]
     [braid.core.server.util :refer [valid-url?]]))

@@ -374,3 +374,18 @@
           :invitations (invitation/invites-for-user user-id)
           :tags (tag/tags-for-user user-id)}
          dynamic-data)])))
+
+;; need to duplicate the anonymous handler for logged in users; this
+;; is used when clicking on a public group from group explore while
+;; logged in. Difference is we want to add the "anonymous" reader as
+;; the logged-in user
+(defmethod event-msg-handler :braid.server.anon/load-group
+  [{:as ev-msg :keys [event id ?data ring-req ?reply-fn send-fn user-id]}]
+  (when-let [group (group/group-by-id ?data)]
+    (when (:public? group)
+      (?reply-fn (reduce (fn [m f] (f (group :id) m))
+                         {:tags (group/group-tags ?data)
+                          :group (assoc group :readonly true)
+                          :threads (thread/public-threads ?data)}
+                         @sync-handler/anonymous-load-group))
+      (helpers/add-anonymous-reader ?data user-id))))


minor cleanup: making destructuring syntax more uniform

--- src/lambdacd/pipeline_state.clj
+++ src/lambdacd/pipeline_state.clj
@@ -21,7 +21,7 @@
   (let [path (str home-dir "/" "history.json")]
     (write-as-json path new-state))))

-(defn update [{step-id :step-id state :_pipeline-state build :build-number {:keys [home-dir]} :config } step-result]
+(defn update [{step-id :step-id state :_pipeline-state build :build-number { home-dir :home-dir } :config } step-result]
   (if (not (nil? state)) ; convenience for tests: if no state exists we just do nothing
     (let [new-state (swap! state (partial update-pipeline-state build step-id step-result))]
       (write-state-to-disk home-dir new-state))))


[WIP] per-user signing

[WIP] per-user signing

--- src/layzee/adapters/twitter.clj
+++ src/layzee/adapters/twitter.clj
@@ -60,9 +60,24 @@
   (let [token (bearer-token-for (:consumer-key oauth-credential) (:consumer-secret oauth-credential))]
     (replies-for token tweet-id)))

-(defn- connect[bearer-token]
+(defn param[name,value] (struct signature-base-string/parameter name value))
+
+(defn- oauth-sign[url oauth-credential]
+  (let [parameters {
+    :verb "GET"
+    :url url
+    :parameters (list
+      (param "oauth_consumer_key"     (:consumer-key oauth-credential))
+      (param "oauth_token"            (:token-key oauth-credential))
+      (param "oauth_timestamp"        "1191242096")
+      (param "oauth_nonce"            "kllo9940pd9333jh")
+      (param "oauth_signature_method" "HMAC-SHA1")
+      (param "oauth_version"          "1.0"))}]
+    (signature-base-string/signature-base-string parameters)))
+
+(defn- connect[oauth-credential]
   (let [url "https://stream.twitter.com/1.1/statuses/firehose.json"]
-    (http/get url {:headers (bearer-auth bearer-token)})))
+    (http/get url {:headers {"Authorization" (oauth-sign url oauth-credential)} })))

 (defn stream-connect[oauth-credential]
   (connect oauth-credential))


Fixed warnings

Fixed warnings

--- src/leiningen/amp/run_jetty.clj
+++ src/leiningen/amp/run_jetty.clj
@@ -11,9 +11,9 @@

 (ns leiningen.amp.run-jetty
   (:require [leiningen.amp.install :as install]
-            [clojure.string :refer [replace]]
-            [stencil.core :refer [render-file]]
-            [stencil.loader :refer [set-cache]])
+            [clojure.string        :as s]
+            [stencil.core          :refer [render-file]]
+            [stencil.loader        :refer [set-cache]])
   (:import [org.eclipse.jetty.runner Runner]))

 (defn- temp-jetty-xml
@@ -36,7 +36,7 @@
   "Retrieves a file handle of the requested maven dependency"
   [dep]
   (str (System/getProperty "user.home")
-       (replace dep "/" java.io.File/separator)))
+       (s/replace dep "/" java.io.File/separator)))

 (defn run-amp-jetty!
   "Start a Jetty webserver to serve the given handler according to the


(PDB-2905) annotate cmdref for all retries

--- src/puppetlabs/puppetdb/mq_listener.clj
+++ src/puppetlabs/puppetdb/mq_listener.clj
@@ -199,12 +199,9 @@
   (dlo/discard-cmdref message exception q dlo))

 (defn message-handler
-  "This function processes the message, retrying messages that fail
-  and discarding messages that have fatal errors or have exceeded
-  their maximum allowed attempts. `delay-message-fn` is a function of
-  two arguments, a `message` and an `exception`, and
-  `process-message-fn` is a function that accepts a message as its
-  argument"
+  "Processes the message via (process-message msg), retrying messages
+  that fail via (delay-message msg exception), and discarding messages that have
+  fatal errors or have exceeded their maximum allowed attempts."
   [q dlo delay-message process-message]
   (fn [cmdref]
     (try+
@@ -228,7 +225,7 @@
               (-> cmd
                   (annotate-with-attempt ex)
                   (discard-message ex q dlo))))
-          (catch Exception exception
+          (catch Exception _
             (let [ex (:throwable &throw-context)
                   log-str (i18n/trs "[{0}] [{1}] Retrying after attempt {2} for {3}, due to: {4}"
                                     id command retries certname ex)]
@@ -236,13 +233,13 @@
               (cond
                 (< retries 4)
                 (do
-                  (log/debug exception log-str)
-                  (delay-message cmd exception))
+                  (log/debug ex log-str)
+                  (-> cmd (annotate-with-attempt ex) (delay-message ex)))

                 (< retries maximum-allowable-retries)
                 (do
-                  (log/errorf exception log-str)
-                  (delay-message cmd exception))
+                  (log/errorf ex log-str)
+                  (-> cmd (annotate-with-attempt ex) (delay-message ex)))

                 :else
                 (do


Improve docstring

Improve docstring

--- src/caesium/magicnonce/secretbox.clj
+++ src/caesium/magicnonce/secretbox.clj
@@ -7,10 +7,11 @@
      resulting system safer or easier to use,
    * schemes that produce the nonce for you automatically.

-  See individual function docstrings for details, but the most interesting
-  function in this namespace is almost certainly [[secretbox-nmr]]. If you
-  just want a random nonce and do not care about nonce-misuse resistance,
-  use [[secretbox-rnd]]. The other functions are fairly limited use.")
+  See individual function docstrings for details, but the most
+  interesting function in this namespace is [[secretbox-nmr]]. If you
+  just want a random nonce and do not care about nonce-misuse
+  resistance, use [[secretbox-rnd]]. The other functions are fairly
+  limited use.")

 (defn secretbox-pfx
   "secretbox, with the given nonce embedded in the ciphertext as a prefix.


rm old colours

rm old colours


fix okta-config.xml config | sg/fs | #35

--- src/clj/conference_rating/server.clj
+++ src/clj/conference_rating/server.clj
@@ -11,9 +11,11 @@
   (:gen-class))

 (defn do-wrap-okta [handler okta-active]
-  (if okta-active
-    (wrap-okta handler {:okta-home "https://dev-133267-admin.oktapreview.com/" :okta-config-location (io/resource "okta-ci-config.xml")})
-    handler))
+  (let [config-res (io/resource "okta-ci-config.xml")]
+    (println "initialize okta?" okta-active " config location: " config-res)
+    (if okta-active
+      (wrap-okta handler {:okta-home "https://dev-133267-admin.oktapreview.com/" :okta-config config-res})
+      handler)))

  (defn -main [& args]
    (let [port (Integer/parseInt (or (env :port) "3000"))


New functions: format-day, format-hours, format-minutes and format-seconds

--- src/clj_calendar/format_datetime.clj
+++ src/clj_calendar/format_datetime.clj
@@ -31,3 +31,36 @@
             (= amount2 1) (format "%d %ss and one %s ago" amount1 unit1 unit2)
             :else         (format "%d %ss and %d %ss ago" amount1 unit1 amount2 unit2))))

+
+(defn format-month
+    "Format month into human readable format."
+    [months days]
+    (if (> months 1)
+        (format "%d months ago" months)
+        (cond
+            (== days 0) "one month ago"
+            (>  days 1) (format "one month and %d days ago" days)
+            :else       (format "one month and one day ago"))))
+
+(defn format-day
+    "Format days/hours in case the given build is younger than one month."
+    [days hours]
+    (format-time- days hours "day" "hour"))
+
+(defn format-hours
+    "Format hours/minutes in case the given build is younger than one day."
+    [hours minutes]
+    (format-time- hours minutes "hour" "minute"))
+
+(defn format-minutes
+    "Format minutes/seconds in case the given build is younger than one hour"
+    [minutes seconds]
+    (format-time- minutes seconds "minute" "second"))
+
+(defn format-seconds
+    "Format seconds into human readable format."
+    [seconds]
+    (if (= seconds 1)
+        (format "one second ago")
+        (format "%d seconds ago" seconds)))
+


Bug fix for `timetable-get-closest-TimetableLessonInfo-on-or-after-time`

When determining if we should select a new lesson as the immediate one
on/after a given time over the currently selected one, we should check
to see if the start time of the new lesson is before that of currently
selected lesson.

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

--- src/cljs/cljs_nusmods/timetable.cljs
+++ src/cljs/cljs_nusmods/timetable.cljs
@@ -588,7 +588,7 @@

                       (and (not (nil? ttLessonInfoAfter))
                            (>= startTime timeIdx)
-                           (< startTime (:endTime ttLessonInfoAfter)))
+                           (< startTime (:startTime ttLessonInfoAfter)))
                       ttLessonInfo

                       :else ttLessonInfoAfter)))


Throttle scroll events a LOT more

Throttle scroll events a LOT more

One per second is totally fine

--- src/cljs/comic_reader/scrolling.cljs
+++ src/cljs/comic_reader/scrolling.cljs
@@ -8,10 +8,12 @@
         throttler (fn []
                     (when (not @running)
                       (toggle!)
-                      (js/requestAnimationFrame
-                       (fn []
-                         (rf/dispatch [key])
-                         (toggle!)))))]
+                      (.setTimeout js/window
+                                   #(js/requestAnimationFrame
+                                     (fn []
+                                       (rf/dispatch [key])
+                                       (toggle!)))
+                                   1000)))]
     (.addEventListener target type throttler)))

 (defn setup-scrolling-events! []


Move state transition into draw card handler

--- src/cljs/love_letter_cljs/views.cljs
+++ src/cljs/love_letter_cljs/views.cljs
@@ -30,8 +30,7 @@

 (defn draw-button [id]
   [:button {:type "button"
-            :on-click #(do (dispatch [:draw-card id])
-                           (dispatch [:set-phase :play]))} "Draw"])
+            :on-click #(dispatch [:draw-card id])} "Draw"])

 (defn player-component [player]
   (let [{:keys [id hand alive? protected?]} player]


Remove println

Remove println

--- test/cljc/reitit/core_test.cljc
+++ test/cljc/reitit/core_test.cljc
@@ -89,7 +89,6 @@
             (is (= 2 @compile-times))))))
     (testing "default compile"
       (let [router (reitit/router ["/ping" (constantly "ok")])]
-        (println (reitit/match-by-path router "/ping"))
         (let [{:keys [handler]} (reitit/match-by-path router "/ping")]
           (is handler)
           (is (= "ok" (handler)))))))


Add a failing test

Add a failing test

--- test/cljc/reitit/ring_test.cljc
+++ test/cljc/reitit/ring_test.cljc
@@ -3,7 +3,8 @@
             [clojure.set :as set]
             [reitit.middleware :as middleware]
             [reitit.ring :as ring]
-            [reitit.core :as r])
+            [reitit.core :as r]
+            [reitit.trie :as trie])
   #?(:clj
      (:import (clojure.lang ExceptionInfo))))

@@ -577,3 +578,19 @@
        (fn [{:keys [::r/router]} _ _]
          (is router)))
      {} ::respond ::raise)))
+
+#?(:clj
+   (deftest invalid-path-parameters-parsing-concurrent-requests-277-test
+     (testing "in enought concurrent system, path-parameters can bleed"
+       (doseq [compiler [trie/java-trie-compiler trie/clojure-trie-compiler]]
+         (let [app (ring/ring-handler
+                     (ring/router
+                       ["/:id" (fn [request]
+                                 {:status 200
+                                  :body (-> request :path-params :id)})])
+                     {::trie/trie-compiler compiler})]
+           (dotimes [_ 10]
+             (future
+               (dotimes [n 100000]
+                 (let [body (:body (app {:request-method :get, :uri (str "/" n)}))]
+                   (is (= body (str n))))))))))))


small fix

small fix

--- src/clj/salava/badge/parse.clj
+++ src/clj/salava/badge/parse.clj
@@ -218,7 +218,9 @@
                     :genre nil
                     :audience nil
                     :ctime now
-                    :mtime now})])))
+                    :mtime now})]
+      :endorsement []
+      )))

 ; old v0.5.0 badge content
@@ -409,33 +411,8 @@
                      (map #(http/json-get (:id %)))
                      (remove #(nil? ((keyword "@language") %))))
         default-language (get badge (keyword "@language") "")
-        endorsement (get-assertion-endorsement assertion) #_(cond
-                                                    (map? (:endorsement assertion)) [{:id nil
-                                                                                :external_id (get-in assertion [:endorsement :id])
-                                                                                :user_badge_id nil
-                                                                                :issuer_id nil
-                                                                                :issuer_name (get-in assertion [:endorsement :issuer :name])
-                                                                                :issuer_url (get-in assertion [:endorsement :issuer :id])
-                                                                                :content (get-in assertion [:endorsement :claim :endorsementComment])
-                                                                                :status "accepted"
-                                                                                :ctime (u/str->epoch (get-in assertion [:endorsement :issuedOn]))
-                                                                                :mtime (u/str->epoch (get-in assertion [:endorsement :issuedOn]))
-                                                                                }]
-
-                                                    (coll? (:endorsement assertion)) (mapv (fn [e]
-                                                                                {:id nil
-                                                                                :external_id (get-in assertion [:endorsement :id])
-                                                                                :user_badge_id nil
-                                                                                :issuer_id nil
-                                                                                :issuer_name (get-in assertion [:endorsement :issuer :name])
-                                                                                :issuer_url (get-in assertion [:endorsement :issuer :id])
-                                                                                :content (get-in assertion [:endorsement :claim :endorsementComment])
-                                                                                :status "accepted"
-                                                                                :ctime (u/str->epoch (get-in assertion [:endorsement :issuedOn]))
-                                                                                :mtime (u/str->epoch (get-in assertion [:endorsement :issuedOn]))
-                                                                                }) (:endorsement assertion))
-                                                    :else []
-                                                    ) ]
+        endorsement (get-assertion-endorsement assertion)]
+
     (assoc initial
       :badge (merge {:id ""
                      :remote_url nil
@@ -518,7 +495,9 @@
                     :genre nil
                     :audience nil
                     :ctime now
-                    :mtime now})])))
+                    :mtime now})]
+      :endorsement []
+      )))

 ; old v1.0/v1.1 badge content
 #_{:badge_url    (:badge assertion)


hack to allow mouse clicks

hack to allow mouse clicks

--- src/cljs/pain_tetris/core.cljs
+++ src/cljs/pain_tetris/core.cljs
@@ -1,6 +1,7 @@
 (ns pain-tetris.core
   (:require [quil.core :as q :include-macros true]
             [quil.middleware :as m]
+            [pain-tetris.movement :as mo]
             [pain-tetris.pieces :as p]
             [pain-tetris.util :as util]
             [pain-tetris.movement :as mo]
@@ -47,6 +48,24 @@
   []
   (swap! t/timer js/clearInterval))

+;; FIXME: This method is here due to a quil bug not calling handler if
+;; in another ns
+(defn mouse-pressed
+  [state event]
+  (let [x (q/mouse-x)
+        y (q/mouse-y)
+        piece-num (g/get-current-piece)]
+    (if (and (> y 200) (< y 500))
+      (if (> x 150)
+        (when (mo/can-move? @t/grid piece-num :right)
+          (swap! t/grid #(mo/move % piece-num :right)))
+        (when (mo/can-move? @t/grid piece-num :left)
+          (swap! t/grid #(mo/move % piece-num :left))))
+      (if (> y 350)
+        (swap! t/grid #(mo/slam-piece % piece-num @t/gravity-direction))
+        (swap! t/grid #(mo/rotate % (g/piece-num-to-coords @t/grid piece-num))))))
+  state)
+
 (q/defsketch canvas
   :host "canvas"
   :size (d/canvas-size t/grid-dims)
@@ -54,6 +73,7 @@
   :update update-state
   :draw draw-state
   :key-pressed t/key-pressed
+  :mouse-pressed mouse-pressed
   :middleware [m/fun-mode]
   :features [:global-key-events]
   :settings q/smooth)


theatralia.views/tag-view: Add attribute "key"

Because React wants me to.

--- src/cljs/theatralia/views.cljs
+++ src/cljs/theatralia/views.cljs
@@ -113,6 +113,7 @@

        [:input]
        (kioo/set-attr :id input-id
+                      :key index
                       :value tag
                       :onChange #(rf/dispatch [:tag-change index (value %)])
                       :onFocus #(when (empty? (value %))


Added a documentation devcard at the top.

It repeats the documentation in the README file to remind that the
server-side examples won't work with just figwheel.

--- src/cljs/word_finder/core.cljs
+++ src/cljs/word_finder/core.cljs
@@ -15,6 +15,28 @@

 ;;
 (enable-console-print!)
+
+;; this devcard just has Markdown and no extra code running.  It's
+;; great for documentation.
+(defcard
+  "#Getting started
+
+To get started with the server-side examples you will need to run
+`lein repl` instead of `lein figwheel`.
+
+Once the REPL has started run:
+```clojure
+(dev)
+;; => #namespace[dev]
+(reset)
+;; :reloading...
+
+;; then run:
+(start-fighweel!)
+
+;; you can jump into the ClojureScript REPL by running:
+(cljs-repl)
+```")

 (defcard first-card
   (sab/html [:div "This is your first devcard :{"]))


Recover pretty-printing for promises

Recover pretty-printing for promises

--- src/promesa/core.cljc
+++ src/promesa/core.cljc
@@ -394,3 +394,25 @@
                   `(promise (do ~@body))))))

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pretty printing
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defn promise->str
+  [p]
+  (str "#<Promise["
+       (cond
+         (pending? p) "~"
+         (rejected? p) (str "error=" (extract p))
+         :else (str "value=" (extract p)))
+       "]>"))
+
+#?(:clj
+   (defmethod print-method java.util.concurrent.CompletableFuture
+     [p ^java.io.Writer writer]
+     (.write writer (promise->str p)))
+   :cljs
+   (extend-type js/Promise
+     IPrintWithWriter
+     (-pr-writer [p writer opts]
+       (.write writer (promise->str p)))))


Minor fixes for cljs.

Minor fixes for cljs.

--- src/promesa/exec.cljc
+++ src/promesa/exec.cljc
@@ -197,12 +197,12 @@
      (-run! [this f]
        (-> (pt/-promise nil)
            (pt/-map (fn [_] (f) nil))
-           (pt/-catch (fn [e] (js/setTimeout #(throw e)) nil))))
+           (pt/-mapErr (fn [e] (js/setTimeout #(throw e)) nil))))

      (-submit! [this f]
        (-> (pt/-promise nil)
            (pt/-map (fn [_] (f)))
-           (pt/-catch (fn [e] (js/setTimeout #(throw e)) nil))))))
+           (pt/-mapErr (fn [e] (js/setTimeout #(throw e)) nil))))))

 ;; Executor that executes the task in the calling thread
 #?(:clj


Fix reader conditional typo

Fix reader conditional typo

The correct reader conditional is #?, not #. This was preventing
default-forkjoin-thread-factory from being defined.

--- src/promesa/exec.cljc
+++ src/promesa/exec.cljc
@@ -182,18 +182,18 @@
              (.setDaemon ^Boolean daemon)
              (.setName (format name (.getAndIncrement along)))))))))

-#(:clj
-  (defn default-forkjoin-thread-factory
-    ^ForkJoinPool$ForkJoinWorkerThreadFactory
-    [& {:keys [name daemon] :or {name "promesa/forkjoin/%s" daemon true}}]
-    (let [^AtomicLong counter (AtomicLong. 0)]
-      (reify ForkJoinPool$ForkJoinWorkerThreadFactory
-        (newThread [_ pool]
-          (let [thread (.newThread ForkJoinPool/defaultForkJoinWorkerThreadFactory pool)
-                tname  (format name (.getAndIncrement counter))]
-            (.setName ^ForkJoinWorkerThread thread ^String tname)
-            (.setDaemon ^ForkJoinWorkerThread thread ^Boolean daemon)
-            thread))))))
+#?(:clj
+   (defn default-forkjoin-thread-factory
+     ^ForkJoinPool$ForkJoinWorkerThreadFactory
+     [& {:keys [name daemon] :or {name "promesa/forkjoin/%s" daemon true}}]
+     (let [^AtomicLong counter (AtomicLong. 0)]
+       (reify ForkJoinPool$ForkJoinWorkerThreadFactory
+         (newThread [_ pool]
+           (let [thread (.newThread ForkJoinPool/defaultForkJoinWorkerThreadFactory pool)
+                 tname  (format name (.getAndIncrement counter))]
+             (.setName ^ForkJoinWorkerThread thread ^String tname)
+             (.setDaemon ^ForkJoinWorkerThread thread ^Boolean daemon)
+             thread))))))

 #?(:clj
    (defn- opts->thread-factory


Start turning the server-test into something real

It's really just a baby step. But that's still progress.

--- test/frereth_cp/server_test.clj
+++ test/frereth_cp/server_test.clj
@@ -4,7 +4,12 @@
             [frereth-cp.server.state :as state]
             [frereth-cp.shared :as shared]
             [frereth-cp.shared.constants :as K]
+            [frereth-cp.shared.serialization :as serial]
+            [frereth-cp.shared.specs :as specs]
             [manifold.stream :as strm]))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Helpers

 (defn system-options
   []
@@ -42,6 +47,29 @@
    ::state/client-read-chan {::state/chan nil}
    ::state/client-write-chan {::state/chan nil}})

+(defn build-hello
+  [srvr-xtn
+   {:keys [::specs/public-short]
+    :as my-short-keys}]
+  ;; frereth-cp.client.hello is really my model for setting
+  ;; this up.
+  ;; I'm not overly fond of the current implementation.
+  ;; Still, it's silly not to use whatever the client does.
+  ;; TODO: Make what the client does less objectionable
+  (let [empty-crypto-box "Q: What is this?"  ; A: a B] of (- K/hello-crypto-box-length K/box-zero-bytes) zeros
+        crypto-box "FIXME: How do I encrypt this?"
+        hello-dscr {::K/hello-prefix K/hello-header
+                    ::K/srvr-xtn srvr-xtn
+                    ::K/clnt-xtn (byte-array (take K/extension-length (drop 256 (range))))
+                    ::K/clnt-short-pk public-short
+                    ::K/zeros (K/zero-bytes K/zero-box-length)
+                    ::K/client-nonce-suffix (byte-array [0 0 0 0 0 0 0 1])
+                    ::K/crypto-box crypto-box}]
+     (serial/compose K/hello-packet-dscr hello-dscr)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Tests
+
 (deftest start-stop
   (testing "That we can start and stop successfully"
     (let [inited (build)
@@ -61,13 +89,21 @@
     (println "Server should be started now")
     (try
       (println "Sending bogus HELLO")
-      (let [msg "Howdy!"
-            client (get-in started [::state/client-write-chan ::state/chan])
-            recvd (strm/try-take! client ::drained 500 ::timed-out)
-            success (deref (strm/try-put! client msg 1000 ::timed-out))]
+      (let [msg (build-hello)
+            ->srvr (get-in started [::state/client-read-chan ::state/chan])
+            success (deref (strm/try-put! ->srvr msg 1000 ::timed-out))]
         (println "put! success:" success)
         (is (not= ::timed-out success))
-        (is (= @recvd msg)))
+        (when (not= ::timed-out success)
+          (let [srvr-> (get-in started [::state/client-write-chan ::state/chan])
+                cookie @(strm/try-take! srvr-> ::drained 1000 ::timeout)]
+            (is (not= ::drained cookie))
+            (is (not= ::timeout cookie))
+            (when (and (not= ::drained cookie)
+                       (not= ::timeout cookie))
+              ;; A: Decrypt the cookie and send an Initiate to get the server
+              ;; to fork a child to handle messages with this client
+              (throw (RuntimeException. "Q: What next?"))))))
       (finally
         (println "Triggering event loop exit")
         (stop started)))))


moved to public api server

moved to public api server

--- src/spekl_package_manager/constants.clj
+++ src/spekl_package_manager/constants.clj
@@ -9,7 +9,7 @@

 (def org-name "Spekl")

-(def spm-home "http://10.173.204.196/")
+(def spm-home "http://api.spekl-project.org/")
 (defn spm-package-list [] (str spm-home "static-package-list.json"))
 (defn git-base [] "https://github.com/Spekl/")


Add the ability to import images to workspace.

--- src/uxbox/main/ui/workspace/images.cljs
+++ src/uxbox/main/ui/workspace/images.cljs
@@ -6,53 +6,159 @@
 ;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>

 (ns uxbox.main.ui.workspace.images
-  (:require [sablono.core :as html :refer-macros [html]]
-            [rum.core :as rum]
-            [lentes.core :as l]
+  (:require [lentes.core :as l]
             [uxbox.util.i18n :as t :refer (tr)]
+            [uxbox.util.rstore :as rs]
+            [uxbox.util.mixins :as mx :include-macros true]
+            [uxbox.util.data :as data :refer (read-string)]
+            [uxbox.util.dom :as dom]
             [uxbox.main.state :as st]
-            [uxbox.util.rstore :as rs]
-            [uxbox.main.library :as library]
-            [uxbox.main.data.dashboard :as dd]
             [uxbox.main.data.lightbox :as udl]
-            [uxbox.main.data.images :as di]
+            [uxbox.main.data.images :as udi]
+            [uxbox.main.data.workspace :as udw]
+            [uxbox.main.data.shapes :as uds]
             [uxbox.main.ui.icons :as i]
-            [uxbox.util.mixins :as mx :include-macros true]
-            [uxbox.main.ui.lightbox :as lbx]
-            [uxbox.main.ui.keyboard :as k]
-            [uxbox.main.ui.library-bar :as ui.library-bar]
-            [uxbox.main.ui.dashboard.header :refer (header)]
-            [uxbox.util.lens :as ul]
-            [uxbox.util.dom :as dom]))
+            [uxbox.main.ui.lightbox :as lbx]))

-;; --- Helpers & Constants
+(def ^:private collections-ref
+  (-> (l/key :image-colls-by-id)
+      (l/derive st/state)))

-(defn- new-image-lightbox-render
+(def ^:private images-ref
+  (-> (l/key :images-by-id)
+      (l/derive st/state)))
+
+(mx/defcs import-image-lightbox
+  {:mixins [mx/static]}
   [own]
-  (html
-   [:div.lightbox-body
-    [:h3 "New image"]
-    [:div.row-flex
-     [:div.lightbox-big-btn
-      [:span.big-svg i/shapes]
-      [:span.text "Go to workspace"]]
-     [:div.lightbox-big-btn
-      {:on-click #(dom/click (dom/get-element-by-class "upload-image-input"))}
-      [:span.big-svg.upload i/exit]
-      [:span.text "Upload file"]
-      [:input.upload-image-input {:style {:display "none"}
-                                  :type "file"
-                                  :on-change #(rs/emit! (di/create-images nil (dom/get-event-files %)))}]]]
-    [:a.close {:href "#"
-               :on-click #(do (dom/prevent-default %)
-                              (udl/close!))}
-     i/close]]))
+  (letfn [(on-upload-click [event]
+            (let [input (mx/ref-node own "input")]
+              (dom/click input)))
+          (on-uploaded [images]
+            (println "on-uploaded" images)
+            (udl/close!))
+          (on-files-selected [event]
+            (let [files (dom/get-event-files event)]
+              (rs/emit! (udi/create-images nil files on-uploaded))))
+          (on-select-from-library [event]
+            (dom/prevent-default event)
+            (udl/open! :import-image-from-collections))
+          (on-close [event]
+            (dom/prevent-default event)
+            (udl/close!))]
+    [:div.lightbox-body
+     [:h3 "New image"]
+     [:div.row-flex
+      [:div.lightbox-big-btn
+       {:on-click on-select-from-library}
+       [:span.big-svg i/image]
+       [:span.text "Select from library"]]
+      [:div.lightbox-big-btn
+       {:on-click on-upload-click}
+       [:span.big-svg.upload i/exit]
+       [:span.text "Upload file"]
+       [:input.upload-image-input
+        {:style {:display "none"}
+         :type "file"
+         :ref "input"
+         :on-change on-files-selected}]]]
+     [:a.close {:href "#" :on-click on-close} i/close]]))

-(def ^:private new-image-lightbox
-  (mx/component
-   {:render new-image-lightbox-render
-    :name "new-image-lightbox"}))
+(mx/defc image-item
+  {:mixins [mx/static]}
+  [{:keys [thumbnail name id width height] :as image}]
+  (letfn [(on-double-click [event]
+            (let [shape {:type :image
+                         :name name
+                         :metadata {:width width
+                                    :height height}
+                         :image id}]
+              (rs/emit! (udw/select-for-drawing shape))
+              (udl/close!)))]
+    [:div.library-item {:key (str id)
+                        :on-double-click on-double-click}
+     [:div.library-item-th
+      {:style {:background-image (str "url('" thumbnail "')")}}]
+     [:span name]]))

-(defmethod lbx/render-lightbox :new-image
+(mx/defc image-collection
+  {:mixins [mx/static]}
+  [images]
+  [:div.library-content
+   (for [image images]
+     (-> (image-item image)
+         (mx/with-key (str (:id image)))))])
+
+(defn will-mount
+  [own]
+  (let [local (:rum/local own)]
+    (rs/emit! (udi/fetch-collections))
+    (rs/emit! (udi/fetch-images nil))
+    (add-watch local ::key (fn [_ _ _ v]
+                             (rs/emit! (udi/fetch-images (:id v)))))
+    own))
+
+(defn will-unmount
+  [own]
+  (let [local (:rum/local own)]
+    (remove-watch local ::key)
+    own))
+
+(mx/defcs image-collections-lightbox
+  {:mixins [mx/reactive (mx/local)]
+   :will-mount will-mount
+   :will-unmount will-unmount}
+  [own]
+  (let [local (:rum/local own)
+        id (:id @local)
+        type (:type @local :own)
+        own? (= type :own)
+        builtin? (= type :builtin)
+        colls (mx/react collections-ref)
+        colls (->> (vals colls)
+                   (filter #(= type (:type %)))
+                   (sort-by :name))
+        id (if (and (nil? id) builtin?)
+             (:id (first colls) ::no-value)
+             id)
+        images (mx/react images-ref)
+        images (->> (vals images)
+                    (filter #(= id (:collection %))))]
+    (letfn [(on-close [event]
+              (dom/prevent-default event)
+              (udl/close!))
+            (select-type [event type]
+              (swap! local assoc :type type))
+            (on-coll-change [event]
+              (let [value (dom/event->value event)
+                    value (read-string value)]
+                (swap! local assoc :id value)))]
+      [:div.lightbox-body.big-lightbox
+       [:h3 "Import image from library"]
+       [:div.import-img-library
+        [:div.library-actions
+         [:ul.toggle-library
+          [:li.your-images {:class (when own? "current")
+                            :on-click #(select-type % :own)}
+           "YOUR IMAGES"]
+          [:li.standard {:class (when builtin? "current")
+                         :on-click #(select-type % :builtin)}
+           "IMAGES STORE"]]
+         [:select.input-select {:on-change on-coll-change}
+          (when own?
+            [:option {:value (pr-str nil)} "Storage"])
+          (for [coll colls
+                :let [id (:id coll)
+                      name (:name coll)]]
+            [:option {:key (str id) :value (pr-str id)} name])]]
+        (image-collection images)]
+       [:a.close {:href "#" :on-click on-close} i/close]])))
+
+(defmethod lbx/render-lightbox :import-image
   [_]
-  (new-image-lightbox))
+  (import-image-lightbox))
+
+
+(defmethod lbx/render-lightbox :import-image-from-collections
+  [_]
+  (image-collections-lightbox))


Fix in ifup plugin

Fix in ifup plugin

Signed-off-by: Javeria Khan <09d287669e47feb54c0cb63e33022fc8a1434dfe@plumgrid.com>

--- plugins/ifup.clj
+++ plugins/ifup.clj
@@ -8,7 +8,7 @@
   (fn [e]
     (process-state-ek1-mk2val
       360 [] e
-      #"EVENT 'ifup (\S+) (\S+) (\S+) (\S+) ip (\S+)' txn_id (\S+) pid (\d+)"
+      #"EVENT 'ifup (\S+) (\S+) (\S+) (\S+).* ip (\S+)' txn_id (\S+) pid (\d+)"
       "ifup started"
       "pgtxn"
       "ifup"


fix bug with cluster evaluation (distinct on a matrixlist from matrix/columns); some cleanup

--- src/polismath/math/clusters.clj
+++ src/polismath/math/clusters.clj
@@ -2,6 +2,7 @@
   (:refer-clojure :exclude [* - + == /])
   (:require [taoensso.timbre.profiling :as profiling
              :refer (pspy pspy* profile defnp p p*)]
+            [taoensso.timbre :as log]
             [plumbing.core :as pc
              :refer (fnk map-vals <-)]
             [plumbing.graph :as gr]
@@ -22,8 +23,7 @@
   "Append an item to a cluster, where item is a (mem_id, vector) pair"
   [clst item]
   (assoc clst
-         ; Note that order is important here, and assumed to be the same for the weighted-mean call in
-         ; `cluster-step`.
+         ; Note that order is important here, and assumed to be the same for the weighted-mean call in `cluster-step`.
          :members (conj (:members clst) (first item))
          :positions (conj (:positions clst) (last item))))

@@ -42,11 +42,14 @@
 (defn init-clusters
   "Effectively random initial clusters for initializing a new kmeans comp"
   [data k]
-  (take k
-    (map-indexed
-      (fn [id position] {:id id :members [] :center (matrix/matrix position)})
-      ; Have to make sure we don't have identical cluster centers
-      (distinct (matrix/rows (nm/get-matrix data))))))
+  (->> data
+       nm/get-matrix
+       matrix/rows
+       vec ;; Have to cast to vec before we can distinct cause rows gives us a matrixlist
+       distinct
+       (map-indexed
+         (fn [id position] {:id id :members [] :center (matrix/matrix position)}))
+       (take k)))

 (defn same-clustering?
@@ -63,7 +66,11 @@
 (defn cleared-clusters
   "Clears a cluster's members so that new ones can be assoced on a new clustering step"
   [clusters]
-  (into {} (map #(vector (:id %) (assoc % :members [] :positions [])) clusters)))
+  (->> clusters
+       (map (fn [cluster]
+              [(:id cluster)
+               (assoc cluster :members [] :positions [])]))
+       (into {})))

 (defmulti weighted-mean


Fix clojure.set reference

Fix clojure.set reference

--- src/pz_discover/broadcaster.clj
+++ src/pz_discover/broadcaster.clj
@@ -1,5 +1,6 @@
 (ns pz-discover.broadcaster
   (:require [clojure.data.json :as json]
+            [clojure.set :as set]
             [clj-kafka.new.producer :as p]
             [zookeeper :as zk])
   (:import [java.util UUID]))
@@ -27,11 +28,11 @@

 (defn add-nodes-to-listener! [zookeeper producer topic nodes]
   (let [l-nodes ((keyword topic) @listener-nodes)
-        new-nodes (clojure.set/difference (set nodes) l-nodes)]
+        new-nodes (set/difference (set nodes) l-nodes)]
     (swap! listener-nodes (fn [curr]
                             (let [topic-key (keyword topic)
                                   curr-nodes (topic-key curr)]
-                              (assoc curr topic-key (clojure.set/union curr-nodes (set nodes))))))
+                              (assoc curr topic-key (set/union curr-nodes (set nodes))))))
     (doseq [node new-nodes]
       (watch-node! zookeeper producer node))))


[#1450] Refactor

[#1450] Refactor

--- backend/dev/src/dev.clj
+++ backend/dev/src/dev.clj
@@ -45,13 +45,6 @@
   (check-specs!))

 (defn go []
-  (alter-var-root #'flow/adapter (fn [f]
-                                   (fn [{:keys [version rows-cols instance survey-id form-id]} data]
-                                     (let [file-name (->> (format "%s-%s-%s-%s-%s" instance survey-id form-id (name rows-cols) version)
-                                                          (format "./dev/resources/%s/%s.edn" dev-flow-datasets-dir))]
-                                       (doseq [d data]
-                                         (spit file-name d :append true)))
-                                     (f nil data))))
   (commons/config)
   (ir/go))

@@ -144,6 +137,24 @@
     :records-v3 (read-edn-filename (format "%s-%s-%s.edn" base-name "rows" 3))
     :records-v4 (read-edn-filename (format "%s-%s-%s.edn" base-name "rows" 4))}))

+(defn activate-write-locally-flow-data []
+  (alter-var-root #'flow/adapter
+                  (fn [f]
+                    (fn [{:keys [version rows-cols instance survey-id form-id] :as m} data]
+                      (let [file-name (->> (format "%s-%s-%s-%s-%s" instance survey-id form-id (name rows-cols) version)
+                                           (format "./dev/resources/%s/%s.edn" dev-flow-datasets-dir))]
+                        (doseq [d data]
+                          (spit file-name d :append true)))
+                      (f m data))))
+  :activated-write-locally-flow-data)
+
+(defn deactivate-write-locally-flow-data []
+  (alter-var-root #'flow/adapter
+                  (fn [f]
+                    (fn [{:keys [version rows-cols instance survey-id form-id] :as m} data]
+                      (f m data))))
+  :deativated-write-locally-flow-data)
+
 (comment
   (read-edn-filename "uat1-638889127-638879132-cols-3.edn")
   (def dataset-id (tu/import-file (db-conn)


Request handlers for API calls and non-API calls as well

--- src/emender_jenkins/server.clj
+++ src/emender_jenkins/server.clj
@@ -1,13 +1,57 @@
 (ns emender-jenkins.server)

-(require '[ring.util.response              :as http-response])
+(require '[clojure.pprint           :as pprint])
+(require '[ring.util.response       :as http-response])
+
+(require '[emender-jenkins.config   :as config])
+(require '[emender-jenkins.rest-api :as rest-api])
+
+(defn return-file
+    [file-name content-type]
+    (http-response/file-response file-name {:root "www"}))
+
+(defn render-front-page
+    "Create front page."
+    [request]
+    (return-file "index.html" "text/html"))
+
+(defn render-error-page
+    "Create error page."
+    [request]
+    (return-file "error.html" "text/html"))
+
+(defn get-hostname
+    []
+    (.. java.net.InetAddress getLocalHost getHostName))
+
+(defn get-api-command
+    "Retrieve the actual command from the API call."
+    [request uri]
+    (if uri
+        (re-find #"/[^/]*" (subs uri (count (config/get-api-prefix request))))))
+
+(defn api-call-handler
+    [request uri method]
+    (if (= uri "/api")
+        (rest-api/info-handler request (get-hostname))
+        (condp = [method (get-api-command request uri)]
+            [:get  "/"]             (rest-api/info-handler request (get-hostname))
+                                    (rest-api/unknown-call-handler uri method))))
+
+(defn non-api-call-handler
+    [request uri]
+    (condp = uri
+        "/"                      (render-front-page request)
+                                 (render-error-page request)))

 (defn handler
     "Handler that is called by Ring for all requests received from user(s)."
     [request]
-    ;(config/load-all-configuration-options-if-necessary)
-    ;(product-list/read-product-list-if-necessary config/load-product-list-from-database)
-    ;(job-data-fetcher/load-books-if-necessary)
-    (println "Config: " (:configuration request))
-    (println "request URI: " (:uri request)))
+    (if (config/verbose? request)
+        (pprint/pprint request))
+    (let [uri    (:uri request)
+          method (:request-method request)]
+         (if (.startsWith uri (config/get-api-prefix request))
+             (api-call-handler     request uri method)
+             (non-api-call-handler request uri))))


Implemented final split function.

Implemented final split function.

--- PersistentDataStructures/finger_trees.clj
+++ PersistentDataStructures/finger_trees.clj
@@ -231,6 +231,28 @@
                 (let [[a b c] (split-digit p vm r ems cfn)]
                     [(deep-r monoid l m a) b (to-tree monoid c)])))))

+(defmulti split (fn [tree p] (class tree)))
+(defmethod split finger-tree-empty [tree _] [tree tree])
+(defmethod split ::any [tree p]
+    (let [monoid (:monoid tree)
+        [l x r] (split-tree tree p ((:combine-fn monoid)))]
+        (if (p (extract-measure tree monoid))
+            [l (push-front r x)]
+            [tree (make-finger-tree-empty monoid)])))
+
+(defn take-until [tree p]
+    (first (split tree p)))
+(defn drop-until [tree p]
+    (second (split tree p)))
+
+(defn as-lazy-seq
+    ([tree]
+        (apply as-lazy-seq (view-left tree)))
+    ([a next]
+        (lazy-seq
+            (cons a (apply as-lazy-seq (view-left (force next))))))
+    ([] []))
+
 ; Functions to print finger-trees to graphviz
 (defn object-id [x] (System/identityHashCode x))

@@ -297,11 +319,11 @@
 (println "Splitting")

 (defn split-test [tree idx]
-    (let [[l x r] (split-tree tree (fn [i] (< idx i)) 0)]
+    (let [[l r] (split tree (fn [i] (< idx i)))]
         (do
             (print-finger-tree-to-file l (str "/tmp/forwards-t1-" (print-str idx) "-l.dot"))
             (print-finger-tree-to-file r (str "/tmp/forwards-t1-" (print-str idx) "-r.dot"))
-            x)))
+            (println idx ": " (map as-lazy-seq [l r])))))

 (doall (map (fn [x] (split-test t1 x)) (range -3 23)))


index

index

--- src/govalert/elastic/store.clj
+++ src/govalert/elastic/store.clj
@@ -11,12 +11,12 @@

 (defn index-agenda [& {id :id title :title url :url date :date summary :summary content :content} ]
   (assert (string? id))
-  (esd/put db/current-index "agenda" id
+  (upsert db/current-index "agenda" id
             {:title title :url url :date date :summary summary :content content}))

 (defn index-attachment [& {id :id label :label title :title url :url content :content groupurl :groupurl groupname :groupname agenda :agenda timestamp :timestamp  :as args}]
   (assert (string? id))
-  (esd/put db/current-index "attachment" (str agenda "_" id)
+  (upsert db/current-index "attachment" (str agenda "_" id)
     (merge {:label label :title title :url url :content content :groupurl groupurl :groupname groupname :agenda agenda}
            (if timestamp {:timestamp (to-long timestamp)} ))))


More properties notes

More properties notes

--- src/simple_check/properties.clj
+++ src/simple_check/properties.clj
@@ -1,5 +1,19 @@
 (ns simple-check.properties
   (:require [simple-check.generators :as gen]))
+
+;; The fields that should be returned from each test
+;; run:
+;;
+;; pass?: boolean or nil (nil implies test was discarded)
+;; expect: boolean or (maybe?) exception
+;; values: the realized values during this test
+;;
+;;
+;; These fields could be returned:
+;;
+;; interrupted?
+;; stamp: haskell QC nomenclature for stats/values collected
+;; callbacks: maybe this is where printing/clojure.test stuff goes?

 (defn apply-gen
   [function]


More doubles

More doubles

--- src/spec_tools/json_schema.cljc
+++ src/spec_tools/json_schema.cljc
@@ -96,12 +96,12 @@

 ; bigdec? (fmap #(BigDecimal/valueOf %)
 ;               (double* {:infinite? false :NaN? false}))
-(defmethod accept-spec 'clojure.core/bigdec? [_ _ _] {:type "double"})
+(defmethod accept-spec 'clojure.core/bigdec? [_ _ _] {:type "number" :format "double"})

 ; inst? (fmap #(java.util.Date. %)
 ;             (large-integer))
-(defmethod accept-spec 'clojure.core/bigdec? [_ _ _] {:type "double"})
+(defmethod accept-spec 'clojure.core/bigdec? [_ _ _] {:type "number" :format "double"})

 ; seqable? (one-of [(return nil)
 ;                   (list simple)


meh meh

meh meh

--- src/util/funxions.clj
+++ src/util/funxions.clj
@@ -89,7 +89,7 @@
    passedDefBlock; a map
    & codeblocks ;multiple forms as code
    ]
-  (let [
+  (let [;XXX: you cannot move these inside the ` because of what defn expects therefore you cannot catch any thrown exceptions here and stuck to using eval
         readyforeval_fname (list 'backtick/template fname)
         evaluated_fname (eval readyforeval_fname) ;the fname after ~ are evaluated
         ;fn_name


`format` > `str`

`format` > `str`

--- exercism/clojure/two-fer/src/two_fer.clj
+++ exercism/clojure/two-fer/src/two_fer.clj
@@ -2,4 +2,4 @@

 (defn two-fer
   ([] (two-fer "you"))
-  ([n] (str "One for " n ", one for me.")))
+  ([n] (format "One for %s, one for me." n)))


Minor verbiage change to doc string.

Minor verbiage change to doc string.

--- src/clojure/bookmark_writer/core.clj
+++ src/clojure/bookmark_writer/core.clj
@@ -35,7 +35,7 @@
 (defn populate-bookmarks!
   "Reads the file identified by input-document (which must be a valid Office XML document), replaces the text
    of all bookmarks in that document with the values defined in the bookmark-map (keys=bookmark names, values=desired text
-   for those bookmarks), and then writes the resulting Word document to the file identified by output-document."
+   for each bookmark), and then writes the resulting Word document to the file identified by output-document."
   [input-document
    output-document
    bookmark-map]


util.clj: refactored the (unique) function

--- clojure/org/gavrog/clojure/util.clj
+++ clojure/org/gavrog/clojure/util.clj
@@ -22,13 +22,13 @@
    If key-fun is given, it is applied to the original values before
    determining equality."
   ([key-fun coll]
-    (letfn [(step [[seen _] x]
-                  (let [key (key-fun x)]
-                    (if (seen key)
-                      [seen nil false]
-                      [(conj seen key) x true])))]
-           (map second
-                (filter second (reductions step [#{} nil false] coll)))))
+    (letfn [(step [coll seen]
+                  (when-let [x (first coll)]
+                    (let [key (key-fun x)]
+                      (if (seen key)
+                        (recur (rest coll) seen)
+                        (lazy-seq (cons x (step (rest coll)
+                                                (conj seen key))))))))]
+           (step coll #{})))
   ([coll]
     (unique identity coll)))
-


Fixed test to match examples after the change.

--- test/blutwurst/tuple_formatter_test.clj
+++ test/blutwurst/tuple_formatter_test.clj
@@ -10,14 +10,14 @@
 (deftest csv-formatter-test
   (testing "Generating a CSV from rows."
     (let [spec {:format :csv}
-          table {:name "Example" :schema "foo" :columns '({:name "A" :type "INTEGER"} {:name "B" :type "INTEGER"})}
+          table {:name "Example" :schema "foo" :properties '({:name "A" :type :integer} {:name "B" :type :integer})}
           rows `({:table ~table :tuples ({:A 1 :B 2})})]
       (is (= `[{:table ~table :tuples ["A,B\n1,2\n"]}]
              (format-rows spec rows)))))

   (testing "Flattens out embedded objects."
     (let [spec {:format :csv}
-          person-table {:name "Person" :schema nil :columns [{:name "Address" :type "OBJECT"} {:name "Name" :type "STRING"}]
+          person-table {:name "Person" :schema nil :properties [{:name "Address" :type :complex} {:name "Name" :type :string}]
                         :dependencies [{:target-schema nil :target-name "Address" :dependency-name nil :links {"Address" :embedded}}]}
           data `({:table ~person-table :tuples ~(list {:name "John Doe" :Address {:Address1 "123 Main" :City "Springfield"}})})]
       (is (= [{:table person-table :tuples ["name,Address.Address1,Address.City\nJohn Doe,123 Main,Springfield\n"]}]
@@ -26,16 +26,16 @@
 (deftest sql-formatter-test
   (testing "Basic SQL generation with integer-only values."
     (let [spec {:format :sql}
-          table {:name "Example" :schema "foo" :columns '({:name "A" :type "INTEGER"} {:name "B" :type "INTEGER"})}
+          table {:name "Example" :schema "foo" :properties '({:name "A" :type :integer} {:name "B" :type :integer})}
           rows `({:table ~table
                   :tuples ({:A 1 :B 2})})]
-      (is (= '({:table {:name "Example" :schema "foo" :columns ({:name "A" :type "INTEGER"} {:name "B" :type "INTEGER"})}
+      (is (= '({:table {:name "Example" :schema "foo" :properties ({:name "A" :type :integer} {:name "B" :type :integer})}
                 :tuples ["INSERT INTO \"foo\".\"Example\" (\"A\",\"B\") VALUES (1,2);\n"]})
              (format-rows spec rows)))))

   (testing "SQL generation quotes and escapes string values."
     (let [spec {:format :sql}
-          table {:name "Example" :schema "foo" :columns '({:name "A" :type "INTEGER"} {:name "B" :type "VARCHAR"})}
+          table {:name "Example" :schema "foo" :properties '({:name "A" :type :integer} {:name "B" :type :string})}
           rows `({:table ~table
                   :tuples ({:A 1 :B  "Then O'Kelly came in with the \t hatchett."})})]
       (is (= `({:table ~table
@@ -44,7 +44,7 @@

   (testing "SQL generation flattens out embedded objects."
     (let [spec {:format :sql}
-          person-table {:name "Person" :schema nil :columns [{:name "Address" :type "OBJECT"} {:name "Name" :type "STRING"}]
+          person-table {:name "Person" :schema nil :properties [{:name "Address" :type :complex} {:name "Name" :type :string}]
                         :dependencies [{:target-schema nil :target-name "Address" :dependency-name nil :links {"Address" :embedded}}]}
           data `({:table ~person-table :tuples ~(list {:Name "John Doe" :Address {:Address1 "123 Main" :City "Springfield"}})})]
       (is (= [{:table person-table :tuples ["INSERT INTO \"Person\" (\"Name\",\"Address.Address1\",\"Address.City\") VALUES ('John Doe','123 Main','Springfield');\n"]}]
@@ -52,7 +52,7 @@

   (testing "SQL generation formats DATE values."
     (let [spec {:format :sql}
-          table {:name "Example" :schema "foo" :columns '({:name "A" :type "INTEGER"} {:name "B" :type "DATE"})}
+          table {:name "Example" :schema "foo" :properties '({:name "A" :type :integer} {:name "B" :type :datetime})}
           rows `({:table ~table
                   :tuples ({:A 1 :B ~(Date. 1109741401000)})})]
       (is (= `({:table ~table
@@ -63,7 +63,7 @@
 (deftest json-formatter-test
   (testing "Basic JSON generation."
     (let [spec {:format :json}
-          table {:name "Example" :schema "foo" :columns '({:name "A" :type "INTEGER"} {:name "B" :type "VARCHAR"})}
+          table {:name "Example" :schema "foo" :properties '({:name "A" :type :integer} {:name "B" :type :string})}
           rows `({:table ~table
                   :tuples ({:A 1 :B  "\"Thus sayeth...\""})})]
       (is (= `[{:table ~table


running generation with pmap rather than map

--- src/babel/english.cljc
+++ src/babel/english.cljc
@@ -103,10 +103,10 @@
                         (println log-message)
                         (println)
                         (let [expressions (run-demo-with n spec)]
-                          (count (map (fn [expression]
-                                        (do
-                                          (println (fo expression))))
-                                      expressions))))))
+                          (count (pmap (fn [expression]
+                                         (do
+                                           (println (fo expression))))
+                                       expressions))))))
                 demo-specs))))

 (defn run-demo-with [ & [n spec]]


Add cancelled support to future

Add cancelled support to future

--- src/beehive/future.clj
+++ src/beehive/future.clj
@@ -25,7 +25,8 @@
     (= Status/PENDING status-enum) :pending
     (= Status/SUCCESS status-enum) :success
     (= Status/ERROR status-enum) :error
-    (= Status/TIMEOUT status-enum) :timeout))
+    (= Status/TIMEOUT status-enum) :timeout
+    (= Status/CANCELLED status-enum) :cancelled))

 (deftype CLJResilientFuture [^PrecipiceFuture future]
   IDeref
@@ -50,6 +51,7 @@
       :timeout? (identical? :timeout (status (.getStatus future)))
       :error? (identical? :error (status (.getStatus future)))
       :pending? (identical? :pending (status (.getStatus future)))
+      :cancelled (identical? :cancelled (status (.getStatus future)))
       :result (.result future)
       :error (.error future)
       :rejected? false


Fix failing map-entry lens laws test

Fix failing map-entry lens laws test

Possibly also better performance for vectors

--- src/active/clojure/lens.cljc
+++ src/active/clojure/lens.cljc
@@ -315,15 +315,18 @@
         lenses))

 (defn- at-index-shove [coll v n]
-  (let [[front back] (split-at n coll)]
-    (let [s (concat front
-                    (list v)
-                    (rest back))]
-      (if (list? coll)
-        (apply list s)
-        (if (seq? coll)
-          s
-          (into (empty coll) s))))))
+  (if (associative? coll)
+    ;; hitting vectors and map-entries
+    (assoc coll n v)
+    (let [[front back] (split-at n coll)]
+      (let [s (concat front
+                      (list v)
+                      (rest back))]
+        (if (list? coll)
+          (apply list s)
+          (if (seq? coll)
+            s
+            (into (empty coll) s)))))))

 (defn at-index
   "Returns a lens that focuses on the value at index n in a collection.


Ugh, typos

Ugh, typos

--- src/ansel/db.clj
+++ src/ansel/db.clj
@@ -167,9 +167,9 @@
     (str base "_" size ext)))

 (defn add-thumbs-to-image [img]
-  (let [small (get-thumb-name (:filename p) 200)
-        big (get-thumb-name (:filename p) 900)]
-    (assoc p :small-thumb small :big-thumb big)))
+  (let [small (get-thumb-name (:filename img) 200)
+        big (get-thumb-name (:filename img) 900)]
+    (assoc img :small-thumb small :big-thumb big)))

 (defn add-thumb-urls [db]
   (let [thumbed (map add-thumbs-to-image (:images db))]
@@ -230,9 +230,6 @@
   (load-data-from-disk)
   (assert-fs))

-(init)
-
-
 ;; Background saving ----------------------------------------------------------

 (defn start-saving []


azulenoids.clj: changed synopsis of unique; added some comments.

--- clojure/org/gavrog/clojure/azulenoids.clj
+++ clojure/org/gavrog/clojure/azulenoids.clj
@@ -4,18 +4,33 @@
            (org.gavrog.joss.dsyms.generators CombineTiles DefineBranching2d))
   (:gen-class))

+;; General purpose functions
+
 (defn iterate-cycle [coll x]
+  "Returns a lazy sequence of intermediate results, starting at x, of
+   cycling through the functions in coll and applying each to the
+   previous result."
   (reductions #(%2 %1) x (cycle coll)))

-(defn unique [coll key-fun]
-  (letfn [(step [[seen _] x]
-                (let [key (key-fun x)]
-                  (if (seen key)
-                    [seen false]
-                    [(conj seen key) x])))]
-         (filter identity (map second (reductions step [#{} false] coll)))))
+(defn unique
+  "Returns a lazy sequence of values from coll with duplicates removed.
+   If key-fun is given, it is applied to the original values before
+   determining equality."
+  ([key-fun coll]
+    (letfn [(step [[seen _] x]
+                  (let [key (key-fun x)]
+                    (if (seen key)
+                      [seen false]
+                      [(conj seen key) x])))]
+           (filter identity (map second (reductions step [#{} false] coll)))))
+  ([coll]
+    (unique identity coll)))
+
+;; General D-symbol functions

 (defn walk [ds D & idxs]
+  "Returns the result of applying the D-symbol operators on ds with the
+   given indices in order, starting with the element D."
   (reduce #(.op ds %2 %1) D idxs))

 (defn chain-end [ds D i j]
@@ -42,6 +57,8 @@
               (/ (s D) (v D)))))
   ([ds]
     (curvature ds 0)))
+
+;; Azulenoid-specific functions

 (def template
   (DSymbol. (str "1.1:60:"
@@ -82,8 +99,10 @@

 (def azul-syms
   (let [raw (for [ds octa-syms o2t boundary-mappings] (on-template ds o2t))]
-    (for [ds (unique raw #(-> %1 .minimal .invariant))]
+    (for [ds (unique #(-> %1 .minimal .invariant) raw)]
       (-> ds .dual .minimal .canonical))))
+
+;; Main entry point when used as a script

 (defn -main []
   (do


Use read-config all up in dat server.

Use read-config all up in dat server.

--- src/cadence/server.clj
+++ src/cadence/server.clj
@@ -4,7 +4,7 @@
             [cemerick.friend :as friend]
             (cadence [model :as model]
                      [state :as state]
-                     [config :as config]
+                     [config :refer [storage read-config]]
                      [routes :refer [app-routes]]
                      [security :refer [friend-settings]])
             (compojure [route :as route]
@@ -28,12 +28,12 @@

 (defn attempt-model-connection []
   (try
-    (model/connect config/storage)
+    (model/connect storage)
     (catch java.io.IOException e
       (println "ERROR: Could not connect to MongoDB."))
     (catch java.lang.NullPointerException e
       (println "ERROR: Could not authenticate with Mongo. See config: \n\t"
-               (str (assoc config/storage :password "**********"))))))
+               (str (assoc storage :password "**********"))))))

 (def app
   "Create the application from its routes and middlewares."
@@ -54,11 +54,12 @@

 (defn -main
   "Run the application."
-  ([options] (let [env (partial get (memfn System/getenv))
-                   mode (:mode options (if (= (env "PRODUCTION" "no") "yes")
-                                         :production
-                                         :development))
-                   port (:port options (Integer. (env "PORT" "5000")))]
+  ([options] (let [mode (:mode options
+                               (if (= (read-config "PRODUCTION" "no") "yes")
+                                 :production
+                                 :development))
+                   port (:port options
+                               (Integer. (read-config "PORT" "5000")))]
                (attempt-model-connection)
                (state/merge {:mode mode :port port})
                (run-server (if (state/production?)


Simplify remoting code...

Simplify remoting code...

- Incorporates pull request #99
- Updates it to work with new property access syntax
- Fixes bug with nil headers throwing an exception

--- src/lib/cljs/one/browser/remote.cljs
+++ src/lib/cljs/one/browser/remote.cljs
@@ -1,29 +1,6 @@
-(ns ^{:doc "Make network requests.
-
-  Adapted from Bobby Calderwood's Trail framework:
-  <https://github.com/bobby/trail>"}
+(ns ^{:doc "Make network requests."}
   one.browser.remote
-  (:require [cljs.reader :as reader]
-            [clojure.browser.net :as net]
-            [clojure.browser.event :as event]
-            [goog.net.XhrManager :as manager]))
-
-(def ^:private responders (atom {}))
-
-(defn- add-responders [id success error]
-  (when (or success error)
-    (swap! responders assoc id {:success success :error error})))
-
-(extend-type goog.net.XhrManager
-
-  event/EventType
-  (event-types [this]
-    (into {}
-          (map
-           (fn [[k v]]
-             [(keyword (. k (toLowerCase)))
-              v])
-           (js->clj goog.net.EventType)))))
+  (:require [goog.net.XhrManager   :as manager]))

 (def ^:private
   *xhr-manager*
@@ -32,6 +9,30 @@
                         nil
                         0
                         5000))
+
+(defn success?
+  [{status :status}]
+  (and (>= status 200)
+       (<  status 300)))
+
+(defn redirect?
+  [{status :status}]
+  (boolean (#{301 302 303 307} status)))
+
+(defn error?
+  [{status :status}]
+  (>= status 400))
+
+(defn- handle-response
+  [on-success on-error e]
+  (let [response {:id     (.-id e)
+                  :body   (. e/currentTarget (getResponseText))
+                  :status (. e/currentTarget (getStatus))
+                  :event  e}
+        handler  (if (success? response)
+                   on-success
+                   on-error)]
+    (handler response)))

 (defn request
   "Asynchronously make a network request for the resource at url. If
@@ -44,42 +45,23 @@
   Other allowable keyword arguments are `:method`, `:content`, `:headers`,
   `:priority`, and `:retries`. `:method` defaults to \"GET\" and `:retries`
   defaults to `0`."
-  [id url & {:keys [method content headers priority retries on-success
-                    on-error]
+  [id url & {:keys [method content headers priority retries
+                    on-success on-error]
              :or   {method   "GET"
                     retries  0}}]
   (try
-    (add-responders id on-success on-error)
     (.send *xhr-manager*
            id
            url
            method
            content
-           headers
+           (when headers (.-strobj headers))
            priority
-           ;; This next one is a callback, and we could use it to get
-           ;; rid of the atom and figure out success/failure ourselves
-           nil
+           (partial handle-response on-success on-error)
            retries)
     (catch js/Error e
       nil)))

-(defn- response-success [e]
-  (when-let [{success :success} (get @responders (:id e))]
-    (success e)
-    (swap! responders dissoc (:id e))))
-
-(defn- response-error [e]
-  (when-let [{error :error} (get @responders (:id e))]
-    (error e)
-    (swap! responders dissoc (:id e))))
-
-(defn- response-received
-  [f e]
-  (f {:id     (.-id e)
-      :body   (. e/xhrIo (getResponseText))
-      :status (. e/xhrIo (getStatus))
-      :event  e}))
-
-(event/listen *xhr-manager* "success" (partial response-received response-success))
-(event/listen *xhr-manager* "error"   (partial response-received response-error))
+(defn url
+  [path]
+  (str (.-origin (.-location js/document)) path))


stop autocompleting tag after space

stop autocompleting tag after space

--- src/chat/client/new-message.cljs
+++ src/chat/client/new-message.cljs
@@ -25,7 +25,7 @@
             thread-tag-ids (-> (store/id->thread (config :thread-id))
                                :tag-ids
                                set)
-            partial-tag (second (re-matches #"(?:.|\n)*#(.*)" text))
+            partial-tag (second (re-matches #"(?:.|\n)*#(\S*)" text))
             results (->> (store/all-tags)
                          (remove (fn [t]
                                    (contains? thread-tag-ids (t :id))))


Fix typo

Fix typo

--- cortex/src/cortex/nn/protocols.cljc
+++ cortex/src/cortex/nn/protocols.cljc
@@ -50,7 +50,7 @@
   (forward [this input]
     "Run a forward computation pass and return the updated module. output will be
   available for later retrieval. Input and intermediate states will be stored for
-  futuere backward pass usage.")
+  future backward pass usage.")

   (backward [this input output-gradient]
     "Back propagate errors through the module with respect to the input.  Returns the


add pprint

add pprint

--- src/bluebell/utils/debug.clj
+++ src/bluebell/utils/debug.clj
@@ -1,4 +1,5 @@
-(ns bluebell.utils.debug)
+(ns bluebell.utils.debug
+  (:require [clojure.pprint]))

 (defn dout-sub [label x]
   `(let [x# ~x]


remove unused imports & fn from routes

remove unused imports & fn from routes

--- src/braid/client/routes.cljs
+++ src/braid/client/routes.cljs
@@ -2,9 +2,7 @@
   (:require [secretary.core :as secretary :refer-macros [defroute]]
             [braid.client.store :as store]
             [braid.client.state :as state]
-            [braid.client.router :as router])
-  (:import [goog.history Html5History]
-           [goog Uri]))
+            [braid.client.router :as router]))

 (defn go-to! [path]
   (router/go-to path))
@@ -64,6 +62,3 @@

 (defn current-group []
   (store/open-group-id))
-
-(defn current-path? [path]
-  (= path (.getPath (.parse Uri js/window.location))))


added back the track-parallelism-button-impression but in a IDidMount so it won't be called more than once per render

--- src-cljs/frontend/components/build.cljs
+++ src-cljs/frontend/components/build.cljs
@@ -113,12 +113,15 @@

     om/IWillUnmount
     (will-unmount [_]
-      (scroll/dispose owner))
-
-    ))
+      (scroll/dispose owner))))

 (defn container-pills [{:keys [build-running? build container-data project-data user view]} owner]
   (reify
+    om/IDidMount
+    (did-mount [_]
+      (analytics/track-parallelism-button-impression  {:view view
+                                                       :project-data project-data
+                                                       :user user}))
     om/IRender
     (render [_]
       (let [{:keys [containers current-container-id]} container-data
@@ -194,6 +197,11 @@

 (defn upgrade-banner [{:keys [build project-data user view]} owner]
   (reify
+    om/IDidMount
+    (did-mount [_]
+      (analytics/track-parallelism-button-impression  {:view view
+                                                       :project-data project-data
+                                                       :user user}))
     om/IRender
     (render [_]
       (html


point the + buttton on the build page to add containers

--- src-cljs/frontend/components/build.cljs
+++ src-cljs/frontend/components/build.cljs
@@ -1,6 +1,7 @@
 (ns frontend.components.build
   (:require [clojure.string :as string]
             [frontend.async :refer [raise!]]
+            [frontend.routes :as routes]
             [frontend.analytics :as analytics]
             [frontend.datetime :as datetime]
             [frontend.models.build :as build-model]
@@ -290,7 +291,8 @@
             container-count (count filtered-containers)
             previous-container-count (max 0 (- paging-offset 1))
             subsequent-container-count (min paging-width (- container-count (+ paging-offset paging-width)))
-            show-upsell? (project-model/show-upsell? (get-in data [:project-data :project]) (get-in data [:project-data :plan]))
+            plan (get-in data [:project-data :plan])
+            show-upsell? (project-model/show-upsell? (get-in data [:project-data :project]) plan)
             div (html
                  [:div.container-list {:class (when (and (> previous-container-count 0)
                                                          (> subsequent-container-count 0))
@@ -321,8 +323,9 @@
                      [:div.nav-caret
                       [:i.fa.fa-2x.fa-angle-right]]]
                     [:a.container-selector.add-containers
-                     {:href (build-model/path-for-parallelism build)
-                      :title "Adjust parallelism"
+                     {:href (routes/v1-org-settings-subpage {:org (:org_name plan)
+                                                             :subpage "containers"})
+                      :title "Adjust containers"
                       :class (when show-upsell? "upsell")}
                      (if show-upsell?
                        [:span "Add Containers +"]


Add server-sent event simulation to check how map is rendered

--- src/cljs/loki/app.cljs
+++ src/cljs/loki/app.cljs
@@ -195,11 +195,29 @@
          "Loading...")])))

+(defn one-of [s] (first (shuffle s)))
+
+(defn simulate-server [regions]
+  (js/setInterval
+   (fn []
+     (dispatch [:tweet-received
+                {:tweet "tweet"
+                 :rating (one-of [:win :treason])
+                 :region (one-of regions)}]))
+   1000))
+
 (defn ^:export run []
   (dispatch [:initialize])
   (xhr/send "ua-regions.geojson"
             (fn [event]
-              (let [res (-> event .-target .getResponseText)]
-                (dispatch [:geojson-received (.parse js/JSON res)]))))
+              (let [res (-> event .-target .getResponseText)
+                    geojson (.parse js/JSON res)]
+                (dispatch [:geojson-received geojson])
+                (simulate-server
+                 (map
+                  (fn [r] (get-in r ["properties" "name"]))
+                  (-> geojson
+                      js->clj
+                      (get "features")))))))
   (reagent/render-component [page-component]
                             (.getElementById js/document "app")))


Remove random-instruction flag from random-plush-genome-with-size

Also, adjust formatting of this function so that it matches that on
master.

--- src/clojush/random.clj
+++ src/clojush/random.clj
@@ -75,14 +75,11 @@

 (defn random-plush-genome-with-size
   "Returns a random Plush genome containing the given number of points."
-  ([genome-size atom-generators argmap]
-   (random-plush-genome-with-size genome-size atom-generators false argmap))
-  ([genome-size atom-generators random-insertion argmap]
-   (vec (repeatedly genome-size
-               #(random-plush-instruction-map
-                 atom-generators
-                 random-insertion
-                 argmap)))))
+  [genome-size atom-generators argmap]
+  (vec (repeatedly genome-size
+                   #(random-plush-instruction-map
+                      atom-generators
+                      argmap))))

 (defn random-plush-genome
   "Returns a random Plush genome with size limited by max-genome-size."


No longer using <! directly.

No longer using <! directly.


Commented out test for listing buckets

Commented out test for listing buckets

--- test/silly_image_store/handler_test.clj
+++ test/silly_image_store/handler_test.clj
@@ -51,6 +51,14 @@
         (is (= (:status response) 404))
         (is (= (:body response) "No thing 'no-such-bucket' found")))))

+;  (testing "listing buckets"
+;    (let [response (app (mock/request :get "/buckets"))
+;          json-body (json/read-str (:body response))]
+;      (is (= (:status response) 200))
+;      (is (= json-body [{"name" "some-bucket",
+;                         "url" "http://localhost/buckets/some-bucket"}]))
+;      ))
+

   (testing "generic not-found route"
     (let [response (app (mock/request :get "/invalid"))]


add static flat bootstrap path

add static flat bootstrap path

--- src/clj/lesezeichen/core.clj
+++ src/clj/lesezeichen/core.clj
@@ -32,8 +32,7 @@
 (deftemplate static-page
   (io/resource "public/index.html")
   []
-  [:#bootstrap-css] (set-attr "href" "static/bootstrap/bootstrap-3.1.1-dist/css/bootstrap.min.css")
-  [:#bootstrap-theme-css] (set-attr "href" "static/bootstrap/bootstrap-3.1.1-dist/css/bootstrap-theme.min.css")
+  [:#bootstrap-css] (set-attr "href" "static/bootstrap/flatly/bootstrap.min.css")
   [:#react-js] (set-attr "src" "static/react/react-0.9.0.min.js")
   [:#jquery-js] (set-attr "src" "static/jquery/jquery-1.11.0.min.js")
   [:#bootstrap-js] (set-attr "src" "static/bootstrap/bootstrap-3.1.1-dist/js/bootstrap.min.js")


more specs

more specs

--- src/cljs/fluch/terminal.cljs
+++ src/cljs/fluch/terminal.cljs
@@ -43,6 +43,15 @@
                    ::font/style
                    ::text]))

+(s/fdef text-block
+        :args (s/cat :text ::text
+                     :options (s/keys :opt-un [::color/foreground-color
+                                               ::color/background-color
+                                               ::font/bold
+                                               ::font/underline
+                                               ::font/italic]))
+        :ret ::text-block)
+
 (defn empty-block
   [{:keys [foreground-color
            background-color]
@@ -56,6 +65,11 @@
   (s/keys :req-un [::type
                    ::color/foreground-color
                    ::color/background-color]))
+
+(s/fdef empty-block
+        :args (s/cat :options (s/keys :opt-un [::color/foreground-color
+                                               ::color/background-color]))
+        :ret ::empty-block)

 (s/def ::block (s/or ::text-block
                      ::empty-block))
@@ -119,8 +133,7 @@
                            ::content]))

 (s/fdef terminal
-        :args (s/cat :context
-                     ::context
+        :args (s/cat :context ::context
                      :terminal-options
                      (s/keys :req-un [::rows
                                       ::cols


Update questions.cljs

Update questions.cljs

--- src/cljs/quiz/questions.cljs
+++ src/cljs/quiz/questions.cljs
@@ -4,7 +4,7 @@
   [{:question "What is the Answer to the Ultimate Question of Life, Universe, and Everything?"
     :answer 42
     :choices [0 24 42 NaN "\"\""]}
-   {:question "What was eventually accepted for the Ultimate *Question* of Life, Universe, and Everything?"
+   {:question "...and what was eventually accepted for the Ultimate *Question* of Life, Universe, and Everything?"
     :choices ["What is yellow and dangerous?"
               "How many roads must a man walk down?"
               "How many Vogons does it take to change a lightbulb?"


Fix regression grumble grumble

Fix regression grumble grumble

--- src/cljx/transom/string.cljx
+++ src/cljx/transom/string.cljx
@@ -166,7 +166,7 @@

 (defn ^:private align-transform
   [edit1 edit2]
-  (loop [edit1 edit1, edit2 edit2, out []]
+  (loop [edit1 edit1, edit2 edit2, out [[] []]]
     (let [op1 (first edit1) op2 (first edit2)]
       (cond
         (nil? op1) (concat out (map #(vector nil %) edit2))


Fix typo in a docstring

Fix typo in a docstring

--- src/clojush/pushgp/breed.clj
+++ src/clojush/pushgp/breed.clj
@@ -92,7 +92,7 @@

 (defn update-instruction-map-uuids
   "Takes an individual and updates the UUIDs on every instruction-map in its
-   :geneome, except for the ones which are a random insertion."
+   :genome, except for the ones which are a random insertion."
   [individual]
   (update individual :genome
           (fn [genome]


Added a (basic) melody.

Added a (basic) melody.

--- src/overtunes/songs/before.clj
+++ src/overtunes/songs/before.clj
@@ -1,6 +1,10 @@
 (ns overtunes.songs.before
   (:use [overtone.live])
   (:use [overtunes.instruments.organ-cornet])
+)
+
+(def melody
+  [:C4 :Bb4 :Eb4 :G4]
 )

 (def starting-section [
@@ -57,7 +61,7 @@
   )
 ))

-(def metro (metronome 90))
+(def metro (metronome 60))
 (def bar 4)
 (defn beat-length [metro] (- (metro 1) (metro 0)))
 (defn bar-length [metro] (* (beat-length metro) bar))
@@ -69,8 +73,21 @@
   ))
 ))

-(defn play [] (
-  (play-progression
+(defn play-melody [melody metro start] ( do
+  (def duration (/ (* 2 (beat-length metro)) 1000))
+  (defn play-note [note] (organ-cornet note duration))
+  (if (not (empty? melody)) (do
+    (at (metro start) (play-note (midi->hz (note (first melody)))))
+    (play-melody (rest melody) metro (+ start 2))
+  ))
+))
+
+(defn n-times [items n]
+  (flatten (repeat n items))
+)
+
+(defn play [] ( do
+  (def chords
     (concat
       starting-section
       middle-section
@@ -78,6 +95,10 @@
       middle-section
       variation-section
     )
+  )
+  (play-melody (n-times melody (/ (count chords) 2)) metro (metro))
+  (play-progression
+    chords
     metro
     (metro)
   )


parentypo

parentypo

--- src/fxc/webpage.clj
+++ src/fxc/webpage.clj
@@ -120,7 +120,7 @@
       [:div {:class "container"}
        [:img {:src "/static/img/secret_ladies.jpg" :class "pull-right img-responsive" :style "width: 16em; border:1px solid #010a40"}]
        [:h1 "Simple Secret Sharing Service" ]
-       [:h2 "Decentralised Social Management of Secrets"
+       [:h2 "Decentralised Social Management of Secrets" ]
        [:h3 section]
        body]


Add ability to save images.

Add ability to save images.

--- src/main/clojure/clara/tools/viz.clj
+++ src/main/clojure/clara/tools/viz.clj
@@ -221,16 +221,22 @@
   (contains? (get-uses rule)
              (.getName fact)))

-(defn show-logic!
-  [& sources]
+(defn logic-to-dot
+  [sources]
   (let [productions (get-productions sources)]

-    (->>
+    (->
      (concat
       (mapcat production-to-dot productions)
       (insertions-to-dot productions))
      vec ; dorothy assumes a vector.
      dot/digraph
-     dot/dot
-     dot/show!
-     )))+     dot/dot)))
+
+(defn save-png!
+  [destination & sources]
+  (dot/save! (logic-to-dot sources) destination {:format :png}))
+
+(defn show-logic!
+  [& sources]
+  (dot/show! (logic-to-dot sources)))


Touch .clj source files on reload only when needed

--- src/main/clojure/lazytest/reload.clj
+++ src/main/clojure/lazytest/reload.clj
@@ -1,33 +1,55 @@
 (ns lazytest.reload
   (:require [clojure.set :as set]
-	    [clojure.string :as s]))
+	    [clojure.string :as str]))

-(defn remove-from-loaded-libs
+(defn- remove-from-loaded-libs
   "Removes symbols from the set in the private Ref clojure.core/*loaded-libs*"
   [& syms]
   (dosync
    (alter @#'clojure.core/*loaded-libs*
 	  set/difference (set syms))))

-(defn find-source-file
+(defn- basename
+  "Converts a namespace name symbol to a String file path, without
+  extension."
+  [sym]
+  (-> sym name (str/replace "-" "_") (str/replace "." "/")))
+
+(defn- find-file-on-classpath
+  "Given a path as a string, searches for that file on the classpath,
+  returns a java.io.File. Returns nil if the file cannot be found or
+  is embedded in a JAR."
+  [path]
+  (when-let [u (.. Thread currentThread getContextClassLoader (getResource path))]
+    (when (= "file" (.getProtocol u))
+      (when-let [p (.getPath u)]
+	(java.io.File. p)))))
+
+(defn- find-source-file
   "Attempts to find the source .clj file for the namespace with the
   given name, returns a java.io.File. Returns nil if the file cannot
   be found or is inside a JAR."
   [sym]
-  (let [path (-> sym name (s/replace "-" "_") (s/replace "." "/") (str ".clj"))]
-    (when-let [u (.. Thread currentThread getContextClassLoader (getResource path))]
-      (when (= "file" (.getProtocol u))
-	(when-let [p (.getPath u)]
-	  (java.io.File. p))))))
+  (find-file-on-classpath (str (basename sym) ".clj")))

-(defn touch-source-file
-  "Attempts to find the .clj source file for the namespace with the
-  given name, and sets its modification time to the current time.
-  Ensures future loads will use the .clj source file and not the
-  AOT-compiled .class file."
+(defn- has-class-file?
+  "Returns true if the namespace has an AOT-compiled .class file on
+  the classpath."
   [sym]
-  (when-let [f (find-source-file sym)]
-    (.setLastModified f (System/currentTimeMillis))))
+  (boolean (.. Thread currentThread getContextClassLoader
+	       (getResource (str (basename sym) ".class")))))
+
+(defn- ensure-source-file-newer
+  "If the given namespace name has an AOT-compiled .class file,
+  attempts to find the .clj source file and set its modification time
+  to the current time.  Ensures future loads will use the .clj source
+  file and not the AOT-compiled .class file."
+  [sym]
+  (when (has-class-file? sym)
+    (if-let [f (find-source-file sym)]
+      (when-not (.setLastModified f (System/currentTimeMillis))
+	(println "WARNING: failed to update timestamp on source file for namespace" sym))
+      (println "WARNING: failed to find normal source file for namespace" sym))))

 (defn reload
   "Removes all namespaces named by symbols, then reloads them."
@@ -35,5 +57,5 @@
   {:pre (every? symbol? symbols)}
   (doseq [sym symbols] (remove-ns sym))
   (apply remove-from-loaded-libs symbols)
-  (doseq [sym symbols] (touch-source-file sym))
+  (doseq [sym symbols] (ensure-source-file-newer sym))
   (apply require symbols))