hack to make routing predictable for now, will use a Trie or something spiffy later

--- src/caws/core.clj
+++ src/caws/core.clj
@@ -7,15 +7,6 @@
            (java.io IOException))
   (:require [clojure.core.async :as async :refer [go go-loop >! <! <!! >!! chan]]
             [clojure.string :as string :refer [join split]]))
-
-;; concept...
-;; every view gets an in-port and an out-port
-;; they can be socket ports, in which case you push bytes onto them
-;; or they can be HTTP ports, in which case you push content onto them
-;; you can also use symbols to push other stuff
-;; like: (go (>! out-port {:headers {:content-type "text/html" :status 200}}))
-;;       (go (>! out-port "<html></html">))
-;;       (go (>! out-port :close))

 (def *buffer* (ByteBuffer/allocate 16384)) ;; 16k...

@@ -163,23 +154,6 @@
                      :or {ip "0.0.0.0" port 8080}}]
   (apply react (conj (setup port) router)))

-
-;; what I want to do:
-;;
-;; read the full HTTP request in (asynchronously)
-;; then put any content into the in-channel
-;; then route based on the path
-;; so GET /foo HTTP/1.1 will route a :get
-;; (route :get path in-port out-port)
-;;
-;; to do this, I need to buffer all of the content until I've read all of the header
-;; information, and then I'll immediately route, and take any content I have at that
-;; point and dump it onto in-chan.
-;; if/when I get more content, I dump that onto in-chan as well,
-;; and I dump a :closed token onto in-chan when I get there.
-;;
-;;
-
 (def ^:dynamic ^{:private true} *out-channel nil)
 (def ^:dynamic ^{:private true} *in-channel nil)
 (def ^:dynamic ^{:private true} *path nil)
@@ -188,7 +162,7 @@
 (defn route [mappings]
   "TODO: add regex support, too, cuz we should."
   (let [route** (fn route* [mappings full-path path in-chan out-chan]
-                  (loop [prefixes (keys mappings)]
+                  (loop [prefixes (sort (fn [x] (count (str x))) > (keys mappings))]
                     (if (empty? prefixes)
                       (go (>! out-chan 404)
                           (>! out-chan :end))
@@ -256,4 +230,5 @@

 (run (route {:get
              {"/foo" {"/bing" bing}
+              "/slow-thing"
               "/" home}}))


Rename /documents/:index/:pagesize to /documents/paging/:index/:pagesize

--- src/rrms/core.clj
+++ src/rrms/core.clj
@@ -30,7 +30,7 @@
 (defroutes app-routes
   (GET "/" [] home)

-  (GET "/documents/:index/:pagesize" [index pagesize]
+  (GET "/documents/paging/:index/:pagesize" [index pagesize]
        (rr/content-type
         (rr/response (db/get-all-documents-by-index-pagesize
                       {:index (parse-int index)


s/'()/[]/

s/'()/[]/

--- src/babel/ug.cljc
+++ src/babel/ug.cljc
@@ -81,9 +81,9 @@
 ;; H subcat<1>  C[1]
 (def subcat-1-principle
   (let [comp-synsem (atom :top)]
-    {:synsem {:subcat '()}
+    {:synsem {:subcat []}
      :head {:synsem {:subcat {:1 comp-synsem
-                              :2 '()}}}
+                              :2 []}}}
      :comp {:synsem comp-synsem}}))

 ;;     subcat<>
@@ -92,9 +92,9 @@
 ;; H subcat<1>  C[1]
 (def subcat-1-principle-no-complement-subcat-restrictions
   (let [comp-synsem (atom {:subcat :top})]
-    {:synsem {:subcat '()}
+    {:synsem {:subcat []}
      :head {:synsem {:subcat {:1 comp-synsem
-                              :2 '()}}}
+                              :2 []}}}
      :comp {:synsem comp-synsem}}))

 ;;     subcat<1>
@@ -104,10 +104,10 @@
 (def subcat-1-1-principle
   (let [subcat (atom :top)]
     {:synsem {:subcat {:1 subcat
-                       :2 '()}}
-     :comp {:synsem {:subcat '()}}
+                       :2 []}}
+     :comp {:synsem {:subcat []}}
      :head {:synsem {:subcat {:1 subcat
-                              :2 '()}}}}))
+                              :2 []}}}}))

 ;;     subcat<1,2>
@@ -119,14 +119,14 @@
         subcat2 (atom {:cat :top})
         subcat3 (atom {:subcat {:1 subcat1
                                :2 subcat2
-                               :3 '()}})]
+                               :3 []}})]
     {:synsem {:subcat {:1 subcat1
                        :2 subcat2
-                       :3 '()}}
+                       :3 []}}
      :comp {:synsem subcat3}
      :head {:synsem {:subcat {:1 subcat1
                               :2 subcat3
-                              :3 '()}}}}))
+                              :3 []}}}}))

 ;;     subcat<1>
 ;;     /      \
@@ -135,11 +135,11 @@
 (def subcat-1-1-principle-comp-subcat-1
   (let [subcat (atom :top)]
     {:synsem {:subcat {:1 subcat
-                       :2 '()}}
+                       :2 []}}
      :comp {:synsem {:subcat {:1 :top
-                              :2 '()}}}
+                              :2 []}}}
      :head {:synsem {:subcat {:1 subcat
-                              :2 '()}}}}))
+                              :2 []}}}}))

 ;;     subcat<1>
@@ -150,10 +150,10 @@
   (let [comp-synsem (atom {:cat :top})
         parent-subcat (atom {:cat :top})]
     {:synsem {:subcat {:1 parent-subcat
-                       :2 '()}}
+                       :2 []}}
      :head {:synsem {:subcat {:1 parent-subcat
                               :2 comp-synsem
-                              :3 '()}}}
+                              :3 []}}}
      :comp {:synsem comp-synsem}}))

 ;;     subcat<1,3>
@@ -167,10 +167,10 @@
                                 :2 subcat-3}})]
     {:synsem {:subcat {:1 subcat-1
                        :2 subcat-3
-                       :3 '()}}
+                       :3 []}}
      :head {:synsem {:subcat {:1 subcat-1
                               :2 subcat-2
-                              :3 '()}}}
+                              :3 []}}}
      :comp {:synsem subcat-2}}))

 ;;     subcat<1>
@@ -181,7 +181,7 @@
   (let [subcat-1 (atom :top)
         subcat-2 (atom {:subcat {:1 subcat-1}})]
     {:synsem {:subcat {:1 subcat-1
-                       :2 '()}}
+                       :2 []}}
      :head {:synsem {:subcat {:1 subcat-2}}}
      :comp {:synsem subcat-2}}))

@@ -191,12 +191,12 @@
 ;; H subcat<1,2,3>  C[3]
 (def subcat-5-principle
   ;; we specify {:cat :top} rather than simply :top
-  ;; because we want to prevent matching with '()
+  ;; because we want to prevent matching with []
   ;; that is, a verb which only subcats for :1 and 2: (transitive)
-  ;; would match :3 because (unify '() :top) => :top,
+  ;; would match :3 because (unify [] :top) => :top,
   ;; and would fit in here erroneously.
   ;; This is prevented by {:cat :top},
-  ;; because (unify '() {:cat :top}) => :fail.
+  ;; because (unify [] {:cat :top}) => :fail.
   (let [subcat-1 (atom {:cat :top})
         subcat-2 (atom {:cat :top})
         subcat-3 (atom {:cat :top})]
@@ -206,7 +206,7 @@
      :comp {:synsem subcat-3}
      :synsem {:subcat {:1 subcat-1
                        :2 subcat-2
-                       :3 '()}}}))
+                       :3 []}}}))

 (def head-semantics
   (let [semantics (atom :top)]
@@ -232,7 +232,7 @@
    subcat-1-principle
    head-principle
    {:first :comp
-    :comp {:synsem {:subcat '()}}}))
+    :comp {:synsem {:subcat []}}}))

 (def c10
   (unify-check
@@ -244,13 +244,13 @@
     ;; Can't embed object in code, maybe print-dup not defined: clojure.lang.Ref@11819f3c
     :schema-symbol 'c10 ;; used by over-each-parent to know where to put children.
     :first :comp
-    :comp {:synsem {:subcat '()}}}))
+    :comp {:synsem {:subcat []}}}))

 (def c21
   (unify
    subcat-2-principle
    head-principle
-   {:comp {:synsem {:subcat '()}}
+   {:comp {:synsem {:subcat []}}
     :schema-symbol 'c21 ;; used by over-each-parent to know where to put children.
     :first :comp
     :comment "c21"}))


whitespace

whitespace

--- src/babel/ug.cljc
+++ src/babel/ug.cljc
@@ -258,7 +258,6 @@
   #?(:cljs
      (throw (js/Error. error-string))))

-
 (defn unify-check [ & vals]
   (let [result (apply unifyc vals)]
     (if (fail? result)


abstract out task-run-file

abstract out task-run-file

--- src/cake/core.clj
+++ src/cake/core.clj
@@ -83,12 +83,15 @@
     `(swap! tasks update '~name update-task '~deps '~doc
             (fn [~destruct] (when ~pred ~@actions)))))

+(defn task-run-file [task-name]
+  (file ".cake" "run" task-name))
+
 (defn run-file-task? [target-file deps]
   (let [{file-deps true task-deps false} (group-by string? deps)]
     (or (not (.exists target-file))
         (some (partial mtime< target-file)
               (into file-deps
-                    (map #(file ".cake" "run" (name %))
+                    (map #(task-run-file %)
                          task-deps)))
         (empty? deps))))

@@ -105,6 +108,7 @@
             (fn [~destruct]
               (when (and ~pred
                          (run-file-task? (file ~name) '~deps))
+                (println "inside defile")
                 (mkdir (.getParentFile *File*))
                 ~@actions)))))

@@ -127,10 +131,10 @@
           (doseq [dep (:deps task)] (run-task dep))
           (binding [*current-task* name
                     *File* (if-not (symbol? name) (file name))]
-            (doseq [action (:actions task)] (action *opts*)))
-          (set! run? (assoc run? name true))
-          (if (symbol? name)
-            (touch (file ".cake" "run" name) :verbose false)))))))
+            (doseq [action (:actions task)] (action *opts*))
+            (set! run? (assoc run? name true))
+            (if (symbol? name)
+              (touch (task-run-file name) :verbose false))))))))

 (defmacro invoke [name & [opts]]
   `(binding [*opts* (or ~opts *opts*)]


Add CORS, again.

Add CORS, again.

--- src/cavm/core.clj
+++ src/cavm/core.clj
@@ -102,14 +102,19 @@

 (def port 7222)

+; XXX need better home for this list
+(def hosts
+  ["https://tcga1.kilokluster.ucsc.edu"
+   "https://tcga1-b.kilokluster.ucsc.edu"
+   "https://cancer-beta.kilokluster.ucsc.edu"
+   "https://genome-cancer.ucsc.edu"])
+
 (defn wrap-access-control [handler]
   (fn [request]
     (let [response (handler request)]
-      (if (= nil response)
-        response              ; If we add headers to nil 404 become 200.
-        (-> response
-            (assoc-in [:headers "Access-Control-Allow-Origin"] "https://tcga1.kilokluster.ucsc.edu")
-            (assoc-in [:headers "Access-Control-Allow-Headers"] "Cancer-Browser-Api"))))))
+      (-> response
+          (assoc-in [:headers "Access-Control-Allow-Origin"] (s/join " " hosts))
+          (assoc-in [:headers "Access-Control-Allow-Headers"] "Cancer-Browser-Api")))))

 (defn- db-middleware [app db]
   (fn [req]
@@ -130,6 +135,7 @@
       (wrap-resource "public")
       (wrap-content-type)
       (wrap-not-modified)
+      (wrap-access-control)
       (wrap-gzip)))

 (defn- serv [app]


replace old public xena with the four current xena hubs on AWS

--- src/cavm/core.clj
+++ src/cavm/core.clj
@@ -60,8 +60,11 @@
   #".*")

 (def public-url "https://genome-cancer.ucsc.edu/")
-(def public-xena (str public-url "proj/public/xena"))
-
+;(def public-xena (str public-url "proj/public/xena"))
+(def tcga-xena "https://tcga.xenahubs.net")
+(def toil-xena "https://toil.xenahubs.net")
+(def icgc-xena "https://icgc.xenahubs.net")
+(def ucscPublic-xena "https://ucscpublic.xenahubs.net")
 (defn local-url [port] (str "https://local.xena.ucsc.edu:" (inc port)))
 (defn local-xena [port] (str "http://local.xena.ucsc.edu:" port))

@@ -86,10 +89,13 @@
         update (fn [cohorts]
                  (swap! x (fn [all]
                             (let [ret (conj all cohorts)]
-                              (when (= 2 (count ret))
+                              (when (= 5 (count ret))
                                 (cb (filter identity (apply concat ret))))
                               ret))))]
-    (async-post (str public-xena "/data/") cohort-query update)
+    (async-post (str tcga-xena "/data/") cohort-query update)
+    (async-post (str icgc-xena "/data/") cohort-query update)
+    (async-post (str toil-xena "/data/") cohort-query update)
+    (async-post (str ucscPublic-xena "/data/") cohort-query update)
     (async-post (str (local-xena port) "/data/") cohort-query update)))

 (defn- wrap-access-control [handler]


Renamed to snapshot as it captures entire kvs-mgr.

--- src/cbfg/kvs.cljs
+++ src/cbfg/kvs.cljs
@@ -58,7 +58,7 @@

 (defn make-scan-fn [scan-kind res-key get-entry]
   (fn [actx state-ch m]
-     (let [{:keys [kvs-ident kvs-snapshot kind from to include-deleted res-ch]} m
+     (let [{:keys [kvs-ident snapshot kind from to include-deleted res-ch]} m
            cb (fn [state kvs]
                 (act scan-work actx
                      (let [kc ((or kind :dirty) kvs)] ; Either :clean or :dirty.
@@ -73,7 +73,7 @@
                        (aput-close scan-work res-ch (assoc m :status :ok))))
                 nil)]
        (kvs-do actx state-ch res-ch
-               (fn [state] ((kvs-checker m cb) (or kvs-snapshot state)))))))
+               (fn [state] ((kvs-checker m cb) (or snapshot state)))))))

 (def default-op-handlers
   {:kvs-list
@@ -110,7 +110,7 @@

    :multi-get
    (fn [actx state-ch m]
-     (let [{:keys [kvs-ident kvs-snapshot kind keys include-deleted res-ch]} m
+     (let [{:keys [kvs-ident snapshot kind keys include-deleted res-ch]} m
            res-m (dissoc m :keys)
            cb (fn [state kvs]
                 (act multi-get actx
@@ -127,7 +127,7 @@
                        (aput-close multi-get res-ch (assoc res-m :status :ok))))
                 nil)]
        (kvs-do actx state-ch res-ch
-               (fn [state] ((kvs-checker m cb) (or kvs-snapshot state))))))
+               (fn [state] ((kvs-checker m cb) (or snapshot state))))))

    :multi-change
    (fn [actx state-ch m]
@@ -156,7 +156,7 @@
    :snapshot
    (fn [actx state-ch m]
      (kvs-do actx state-ch (:res-ch m)
-             (fn [state] [state (assoc m :status :ok :kvs-snapshot state)])))
+             (fn [state] [state (assoc m :status :ok :snapshot state)])))

    :sync
    (fn [actx state-ch m]


Fix broken earlier stuff.

Fix broken earlier stuff.

--- src/exp/sahdd.clj
+++ src/exp/sahdd.clj
@@ -164,7 +164,7 @@
             (if (< @index-atom (count @result-vec-atom))
                 (let [[_ rew :as result] (nth @result-vec-atom @index-atom)]
                  ;; TODO: remove
-                  (util/assert-is (<= (count @result-vec-atom) 1) "%s" [@result-vec-atom])
+;                  (util/assert-is (<= (count @result-vec-atom) 1) "%s" [@result-vec-atom])
                   (if (>= rew min-reward)
                       (do (swap! index-atom inc)
                           (PartialResult [result]
@@ -175,7 +175,8 @@
                   (let [{:keys [result-pairs max-reward]} (next-partial-solution search-problem min-reward)]
                     (reset! next-reward-atom max-reward)
                     ;; TODO: remove!
-                    (doseq [x1 @result-vec-atom x2 result-pairs] (assert (not (= (first x1) (first x2)))))
+ ;                   (doseq [x1 @result-vec-atom x2 result-pairs]
+ ;                     (util/assert-is (not (= (first x1) (first x2))) "%s" [@result-vec-atom result-pairs]))
                     (swap!  result-vec-atom into result-pairs)
                     (recur min-reward))
                 (PartialResult nil @next-reward-atom)))))))))
@@ -228,10 +229,10 @@
   (expand-node        [se new-threshold]
     "Returns PartialResult of SearchNodes."))

-(defn make-goal-node [goal-state]
-  (reify SearchNode
-       (extract-goal-state [] goal-state)
-       (expand-node        [min-reward] (throw (UnsupportedOperationException.)))))
+(deftype GoalNode [goal-state]
+  SearchNode
+   (extract-goal-state [] goal-state)
+   (expand-node        [min-reward] (throw (UnsupportedOperationException.))))

 ;; Named node is simple non-terminal node whose equality semantics are given by name.
 (deftype NamedNode [name root-sa expand-fn] :as this
@@ -277,7 +278,7 @@
             (make-recursive-expander
              (delay (make-exhaustive-search
                      (make-abstracted-incremental-dijkstra-sa-search state reward f))) r)))
-     (make-goal-node state))
+     (GoalNode state))
    reward])

@@ -358,7 +359,7 @@
 (defn make-inverted-root-node [state action]
   (connect-downward-cache state action
     [(reify InvertedItem
-      (notify-upward [outcome-pair] [(update-in outcome-pair 0 make-goal-node)]))
+      (notify-upward [outcome-pair] [(update-in outcome-pair 0 GoalNode)]))
      0]))

 (defn make-inverted-sa-search [state action]
@@ -420,6 +421,13 @@

+(comment
+ (let [e (make-random-taxi-env 3 3 3 2) h (simple-taxi-hierarchy e)]
+  (println "ucs" (run-counted #(second (uniform-cost-search e))))
+  (doseq [alg `[sahtn-dijkstra sahucs-flat sahucs-simple sahucs-dijkstra sahucs-inverted]]
+         (time (println alg (run-counted #(second ((resolve alg) h)))))))
+ )
+

 ;; TODO: compare performance to other algorithms.


peppering printlns to debug stack overflow

--- src/flax/core.clj
+++ src/flax/core.clj
@@ -425,6 +425,7 @@
         config (assoc config :env (evaluate (:env config) config))
         exit (when-let [main (:main program)]
                (doall (pmap #(evaluate % config) main)))]
+    (println "before destroying all nodes")
     (doall
       (pmap
         (fn [[k n]]
@@ -471,9 +472,13 @@

           ;; Write the raw return value of the entire program to the
           ;; logs directory.
+          (println "before raw.json")
           (spit "target/logs/raw.json" (json/generate-string return))

+          (println "before env.json")
           (spit "target/logs/env.json" (json/generate-string (evaluate (:env config) config)))
+
+          (println "before harvest.json")
           ;; Write any harvested values to the logs directory.
           (spit "target/logs/harvest.json"
                 (json/generate-string
@@ -485,6 +490,7 @@
                            {(keyword hkey) (harvest return config hkey [])})
                          (-> config :harvest)))))

+          (println "before collecting failures")
           ;; Write the failing returns to the logs directory and exit with
           ;; the count of the failures.
           (let [failures (->> (returns return)
@@ -492,6 +498,7 @@
                               (filter #(and (-> % :throw)
                                             (-> % :exit :value zero? not))))
                 num-failures (count failures)]
+            (println "before failures.json")
             (spit "target/logs/failures.json" (json/generate-string failures))
             (log logger :info (str "Failures: " num-failures))
             (log logger :info (str "Seed: " (.getTime effective)))


entity[CLJ]: add not-found to IFn entity[CLJS]: remove superfluous -lookup -> lookup-entity chains

--- src/datascript/impl/entity.cljc
+++ src/datascript/impl/entity.cljc
@@ -68,7 +68,7 @@
               (if (dc/reverse-ref? attr)
                 (-> (-lookup-backwards db eid (dc/reverse-ref attr) nil)
                     multival->js)
-                (cond-> (-lookup this attr)
+                (cond-> (lookup-entity this attr)
                   (dc/multival? db attr) multival->js))))
        (forEach [this f]
                 (doseq [[a v] (js-seq this)]
@@ -105,13 +105,13 @@

        IAssociative
        (-contains-key? [this k]
-                       (not= ::nf (-lookup this k ::nf)))
+                       (not= ::nf (lookup-entity this k ::nf)))

        IFn
        (-invoke [this k]
-                (-lookup this k))
+                (lookup-entity this k))
        (-invoke [this k not-found]
-                (-lookup this k not-found))
+                (lookup-entity this k not-found))

        IPrintWithWriter
        (-pr-writer [_ writer opts]
@@ -140,7 +140,8 @@
        (valAt [e k not-found] (lookup-entity e k not-found))

        clojure.lang.IFn
-       (invoke [e k]      (c/get e k))
+       (invoke [e k]      (lookup-entity e k))
+       (invoke [e k not-found] (lookup-entity e k not-found))
        ]))

 (defn entity? [x] (instance? Entity x))


implement type-exact-match?

implement type-exact-match?

--- src/app/find.clj
+++ src/app/find.clj
@@ -10,11 +10,19 @@
   (:require [instaparse.core :as insta])
   (:import [app.operations Operation]))

+(defn type-exact-match? [type-ref1 type-ref2]
+  (and
+    (= (nil? type-ref1) (nil? type-ref2))
+    (= (array? ref1) (array? ref2))
+    (= (primitive? ref1) (primitive? ref2))
+    (= (typeName ref1) (typeName ref2))
+    (type-exact-match? (baseType ref1) (baseType ref2))))
+
 (defn param-match-type? [pair]
   (let [[param expected-type] pair
         paramType (.getType param)
         paramSolvedType (solveType paramType)]
-    (exact-match? paramSolvedType expected-type)))
+    (type-exact-match? paramSolvedType expected-type)))

 (defn method-match-exactly-parameters? [param-expected-types method]
   (let [params (.getParameters method)


Add a test for just parsing IPv4 addresses

--- test/desdemona/query_test.clj
+++ test/desdemona/query_test.clj
@@ -2,6 +2,10 @@
   (:require
    [desdemona.query :as q]
    [clojure.test :refer [deftest is are testing]]))
+
+(deftest infx-parser-tests
+  (is (= nil
+         (#'q/infix-parser "10.0.0.1"))))

 (deftest infix->dsl-tests
   (is (= '(= 1 1)


Add tests for mux-codec.

Add tests for mux-codec.

--- test/multicodec/core_test.clj
+++ test/multicodec/core_test.clj
@@ -74,3 +74,47 @@
       (is (thrown-with-msg? IOException #"a newline"
             (multicodec/read-header! bais)))))
   (test-stream-roundtrip "/b16" "0123456789abcdef"))
+
+
+(defn mock-codec
+  [tag header]
+  (reify
+    clojure.lang.ILookup
+    (valAt [_ k]
+      (when (= :header k) header))
+    multicodec/Encoder
+    (encode [_ output value]
+      (let [content (.getBytes (pr-str value))]
+        (.write output content)
+        (count content)))
+    multicodec/Decoder
+    (decode [_ input]
+      [tag (slurp input)])))
+
+
+(deftest multiplex-codec
+  (testing "codec construction"
+    (is (thrown? IllegalArgumentException (multicodec/mux-codec))
+        "construction with no codecs should throw exception")
+    (is (thrown? IllegalArgumentException (multicodec/mux-codec (mock-codec :foo nil)))
+        "construction with no-header arg should throw exception"))
+  (testing "encoding with no selected codec"
+    (let [mux (assoc (multicodec/mux-codec (mock-codec :foo "/bar"))
+                     :select-encoder (constantly nil))]
+      (is (thrown? IllegalStateException (multicodec/encode mux nil nil)))))
+  (let [mux (multicodec/mux-codec
+              (mock-codec :foo "/foo")
+              (mock-codec :bar "/bar"))]
+    (testing "encoding roundtrip"
+      (let [baos (ByteArrayOutputStream.)
+            out-len (multicodec/encode mux baos 1234)
+            encoded (.toByteArray baos)]
+        (is (= 10 out-len) "should write the correct number of bytes")
+        (is (= "/foo" (multicodec/read-header! (ByteArrayInputStream. encoded))))
+        (is (= [:foo "1234"] (multicodec/decode mux (ByteArrayInputStream. encoded))))))
+    (testing "no-matching decoder"
+      (let [baos (ByteArrayOutputStream.)]
+        (multicodec/write-header! baos "/baz/qux")
+        (.write baos (.getBytes "abcd"))
+        (is (thrown? IllegalStateException
+                     (multicodec/decode mux (ByteArrayInputStream. (.toByteArray baos)))))))))


Add exec task execute any command

Add exec task execute any command

--- src/npm/boot.cljs
+++ src/npm/boot.cljs
@@ -3,7 +3,7 @@
             [cljs.analyzer.api :as analy]
             [npm.mvn :as mvn]))

-(def telnet (js/require "telnet-client"))
+(def Telnet (js/require "telnet-client"))

 (def PACKAGE
   (if (js/fs.existsSync (str js/process.env.PWD "/package.json"))
@@ -11,6 +11,15 @@
     {"cljs" {"source-paths" ["src"]}}))

 (declare reload)
+
+(let [processers (atom nil)]
+  (defn spawnx [key cmd opts conf]
+    (let [p    (atom nil)
+          opts (clj->js (vec opts))
+          conf (clj->js conf)]
+      (some-> @p (get key) .kill)
+      (swap! processers assoc key
+             (js/child_process.spawn cmd opts conf)))))

 (defn file-seq [root]
   (tree-seq #(and (js/fs.existsSync %)
@@ -22,8 +31,7 @@
             root))

 (defn ^:export lumo [& opts]
-  (let [process        (atom nil)
-        source-paths   (get-in PACKAGE ["cljs" "source-paths"])
+  (let [source-paths   (get-in PACKAGE ["cljs" "source-paths"])
         source-pattern (re-pattern (str \( (str/join "|" source-paths) \) "/?"))
         cache-path     (or (when (some #{"-K"} opts)
                              ".lumo_cache")
@@ -64,9 +72,7 @@
                              ["-c" (str/join ":" (concat source-paths (:classpath fileset)))]
                              opts))]
           (invalid-cache!)
-          (some-> @process .kill)
-          (reset! process
-                  (js/child_process.spawn "lumo" opts #js {:stdio "inherit"}))
+          (spawnx ::lumo "lumo" opts #js {:stdio "inherit"})
           (next-handler (assoc fileset
                                :lumo/invalid-cache! invalid-cache!
                                :lumo/repl (merge {:host "127.0.0.1" :port 5555} repl))))))))
@@ -99,7 +105,7 @@
                      (str (pr-str `(require '~@(map file->ns resources) :reload))
                           \newline)
                      (fn [err res]))))
-          (let [c (new telnet)]
+          (let [c (Telnet.)]
             (doto c
               (.on "ready" (fn [prompt]
                              (reset! conn c)
@@ -113,6 +119,13 @@
                              :port        (:port repl)
                              :shellPrompt "cljs.user=> "
                              :timeout     1500}))))))))
+
+(defn ^:export exec [cmd & opts]
+  (fn [next-handler]
+    (fn [fileset]
+      (spawnx (str "exec-" cmd) cmd (clj->js opts) #js {:stdio "inherit"}))))
+
+(def ^:export node (partial exec "node"))

 (defn run-task [task fileset]
   ((task (constantly :nothing)) fileset))
@@ -129,7 +142,7 @@
                         (partition-all 2))]
     (apply comp (for [[[t] args] task-specs]
                   (do
-                    (println "compile" (pr-str (cons t args)) "...")
+                    (println "compile" (pr-str (cons (symbol t) args)) "...")
                     (apply (aget NS-EXPORTS (munge t)) args))))))

 (defn -main [& argv]


Allow only users to edit their own data.

--- src/forces_assemble/handler.clj
+++ src/forces_assemble/handler.clj
@@ -69,11 +69,16 @@

 (def protected-resource authorization-required)

+(defn is-request-from-user?
+  [context expected-user-id]
+  (= expected-user-id (.getUid (::auth context))))
+
 (defresource user-tokens [user-id] protected-resource
   :allowed-methods [:put]
   :available-media-types [application-json]
   :known-content-type? #(check-content-type % [application-json])
   :malformed? #(parse-json % ::data)
+  :allowed? #(is-request-from-user? % user-id)
   :put! (fn [context]
           (db/refresh-user-token user-id (:token (::data context)))))

@@ -102,8 +107,9 @@
   :available-media-types [application-json]
   :known-content-type? #(check-content-type % [application-json])
   :malformed? #(parse-json % ::data)
+  :allowed? #(is-request-from-user? % (get-in % [::data :user-id]))
   :post! (fn [context]
-           (db/subscribe-to-channel channel-id (:user-id (::data context)))))
+           (db/subscribe-to-channel channel-id (get-in context [::data :user-id]))))

 (defresource events [event-id] protected-resource
   :allowed-methods [:get]


working on indexing and reindexing transactions for both properties and edges

--- src/ophion/db.clj
+++ src/ophion/db.clj
@@ -39,6 +39,12 @@
    (.getEdgeLabel manage (name edge-label))
    (.make (.makeEdgeLabel manage (name edge-label)))))

+(defn janus-get-edge-index
+  [manage edge-label index]
+  (let [index-name (edge-index-name edge-label index)
+        edge (janus-get-edge-label manage edge-label)]
+    (.getRelationIndex manage edge index-name)))
+
 (defn janus-apply-index
   [manage db-index index]
   (let [db (reduce
@@ -50,7 +56,12 @@

 (defn property-index-name
   [index]
-  (string/join "-" (concat (keys index) ["index"])))
+  (string/join "-" (concat (map name (keys index)) ["index"])))
+
+(defn janus-get-property-index
+  [manage index]
+  (let [index-name (property-index-name index)]
+    (.getGraphIndex manage index-name)))

 (defn janus-property-index
   [graph index]
@@ -62,6 +73,18 @@
       (.commit manage))
     (catch Exception e
       (.printStackTrace e))))
+
+(defn close-transactions!
+  [graph]
+  (map #(.rollback %) (.getOpenTransactions graph)))
+
+(defn janus-property-reindex
+  [graph index]
+  (close-transactions! graph)
+  (let [manage (.openManagement graph)
+        property-index (janus-get-property-index manage index)]
+    (.get (.updateIndex manage property-index SchemaAction/REINDEX))
+    (.commit manage)))

 (defn edge-index-name
   [edge-label index]
@@ -88,11 +111,10 @@
 (defn janus-edge-reindex
   [graph edge-label index]
   (try
-    (let [index-name (edge-index-name edge-label index)
-          manage (.openManagement graph)
-          edge (janus-get-edge-label manage edge-label)
-          index (.getRelationIndex manage edge index-name)]
-      (.updateIndex index SchemaAction/REINDEX)
+    (close-transactions! graph)
+    (let [manage (.openManagement graph)
+          index (janus-get-edge-index manage edge-label index)]
+      (.get (.updateIndex index SchemaAction/REINDEX))
       (.commit manage))
     (catch Exception e
       (.printStackTrace e))))


fix some problems with svg rendering

fix some problems with svg rendering

--- src/pc/render.clj
+++ src/pc/render.clj
@@ -20,6 +20,9 @@
   [layer opts]
   [:path (svg/layer->svg-path layer opts)])

+(defn nan? [thing]
+  (or (not thing) (.isNaN thing)))
+
 ;; Getting placement here is a bit tricky.
 ;; Goal is to reproduce the canvas exactly as it is in the app, except in
 ;; black-and-white so they can print it.
@@ -27,11 +30,13 @@
 ;; If they've drawn in negative directions, then we to shift the viewport in the
 ;; that direction with a transform.
 (defn render-layers [layers & {:keys [invert-colors? size-limit]}]
-  (let [layers (map #(into {} %) (filter #(not= :layer.type/group (:layer/type %)) layers))
-        start-xs (remove #(.isNaN %) (map :layer/start-x layers))
-        start-ys (remove #(.isNaN %) (map :layer/start-y layers))
-        end-xs (remove #(.isNaN %) (map :layer/end-x layers))
-        end-ys (remove #(.isNaN %) (map :layer/end-y layers))
+  (def mylayers layers)
+  (let [layers (map #(into {} %) (filter #(and (:layer/type %)
+                                               (not= :layer.type/group (:layer/type %))) layers))
+        start-xs (remove nan? (map :layer/start-x layers))
+        start-ys (remove nan? (map :layer/start-y layers))
+        end-xs (remove nan? (map :layer/end-x layers))
+        end-ys (remove nan? (map :layer/end-y layers))
         xs (or (seq (concat start-xs end-xs)) [0])
         ys (or (seq (concat start-ys end-ys)) [0])
         min-x (apply min xs)


added a GET /api/article/new to be used by Google Reader

--- src/instapapure/servlet.clj
+++ src/instapapure/servlet.clj
@@ -168,6 +168,9 @@
   ;;  API
   (POST "/api/article"
     (new-article (:location params) (:title params) (:summary params)))
+  ;;  for Google Reader
+  (GET "/api/article/new"
+    (new-article (:location params) (:title params) (:summary params)))
   (POST "/api/article/delete"
     (delete-article (:id params)))
   (POST "/api/article/:id"


Quorum consistency on sessions to avoid problems.

Eventual consistency isn't great when you only check one server and keep
getting bounced around.

--- src/kixi/hecuba/session.clj
+++ src/kixi/hecuba/session.clj
@@ -16,7 +16,8 @@
         (let [user-session (first (db/execute
                                    db-session
                                    (hayt/select :sessions
-                                                (hayt/where [[= :id key]]))))]
+                                                (hayt/where [[= :id key]]))
+                                   {:consitency :quorum}))]
           (log/debugf "Retrieved session %s" user-session)
           (clojure.edn/read-string (:data user-session))))
       {}))
@@ -32,7 +33,8 @@
          (hayt/update :sessions
                       (hayt/set-columns
                        (dissoc session-data :id))
-                      (hayt/where [[= :id key]]))))
+                      (hayt/where [[= :id key]]))
+         {:consitency :quorum}))
       key))
   (delete-session [_ key]
     (log/debugf "Deleting sessiong for key: %s" key)


Handle uint16, rewind buffer before compare (#26)

--- src/lcmap/aardvark/tile.clj
+++ src/lcmap/aardvark/tile.clj
@@ -107,13 +107,19 @@
 (defn +spec
   "Retrieve a spec (for the given UBID) and add it to the band. This assumes
    only one tile-spec will be found. If multiple tile-specs exists, behavior
-   is undefined."
+   is undefined.
+
+   If a tile-spec is not found, then this function returns nil. The band should
+   not be ingested."
   [band]
   (log/debugf "looking for tile-spec for %s" (:ubid band))
   (let [spec (first (tile-spec/query {:ubid (:ubid band)}))]
-    (if (nil? spec)
-      (throw (ex-info (format "no tile-spec for %s" (:ubid band)) {}))
-      (merge band spec))))
+    (if (some? spec)
+      ;; then add the spec properties to the band
+      (merge band spec)
+      ;; this returns nil, the band will be filtered out
+      ;; by `conforms?`
+      (log/warnf "no tile-spec present, skipping %s"))))

 (defn int16-fill
   "Produce a buffer used to detect INT16 type buffers containing all fill data."
@@ -127,7 +133,7 @@
           (.put shorts))
       buffer)))

-(defn- uint8-fill
+(defn uint8-fill
   "Produce a buffer used to detect UINT8 type buffers all fill data."
   [data-size data-fill]
   (if data-fill
@@ -138,12 +144,24 @@
           (.put bytes))
       buffer)))

+(defn uint16-fill
+  "Produce a buffer used to detect UINT16 type buffers all fill data."
+  [data-size data-fill]
+  (if data-fill
+    (let [buffer (java.nio.ByteBuffer/allocate (* 2 data-size))
+          bytes (byte-array data-size (unchecked-byte data-fill))]
+      (-> buffer
+          (.order java.nio.ByteOrder/LITTLE_ENDIAN)
+          (.put bytes))
+      buffer)))
+
 (def fill-buffer
   "Create a buffer memoized on data-size and data-fill."
   (memoize/lu
    (fn [data-size data-fill data-type]
      (cond (= data-type "INT16") (int16-fill data-size data-fill)
-           (= data-type "UINT8") (uint8-fill data-size data-fill)))))
+           (= data-type "UINT8") (uint8-fill data-size data-fill)
+           (= data-type "UINT16") (uint16-fill data-size data-fill)))))

 (defn +fill
   "Make a fill buffer used to detect no-data tiles"
@@ -158,7 +176,8 @@
   [tile]
   (let [data (:data tile)
         fill (:fill tile)]
-    (and (some? fill) (some? data) (zero? (.compareTo data fill)))))
+    (and (some? fill) (some? data) (zero? (.compareTo (.rewind data)
+                                                      (.rewind fill))))))

 (defn locate-fn
   "Build projection coordinate point calculator for GDAL dataset."
@@ -190,7 +209,7 @@
    This ensures the raster is the same projection and that the boundaries
    precisely align to the tile-specs grid values."
   [band]
-  true)
+  (some? band))

 (defn scene->bands
   "Create sequence of from ESPA XML metadata."
@@ -229,10 +248,10 @@
   "Saves all bands in dir referenced by path."
   ([scene-dir source]
    (let [band-xf   (comp (map +spec)
+                         (filter conforms?)
                          (map +fill)
                          (map +locate)
-                         (map (fn [band] (assoc band :source (:id source))))
-                         (filter conforms?))]
+                         (map (fn [band] (assoc band :source (:id source)))))]
      (dorun (map #(process-band % source) (scene->bands scene-dir band-xf)))
      :done)))


remove filterer option before passing into pod

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -299,7 +299,7 @@
     (boot/with-pre-wrap fileset
       (let [files (filter (:filterer options) (perun/get-meta fileset))]
         (pod/with-call-in @pod
-          (io.perun.sitemap/generate-sitemap ~(.getPath tmp) ~files ~options))
+          (io.perun.sitemap/generate-sitemap ~(.getPath tmp) ~files ~(dissoc options :filterer)))
         (commit fileset tmp)))))

 (def ^:private rss-deps
@@ -326,7 +326,7 @@
             options       (merge +rss-defaults+ global-meta *opts*)
             files         (filter (:filterer options) (perun/get-meta fileset))]
         (pod/with-call-in @pod
-          (io.perun.rss/generate-rss ~(.getPath tmp) ~files ~options))
+          (io.perun.rss/generate-rss ~(.getPath tmp) ~files ~(dissoc options :filterer)))
         (commit fileset tmp)))))

 (def ^:private atom-deps
@@ -354,7 +354,7 @@
             options       (merge +atom-defaults+ global-meta *opts*)
             files         (filter (:filterer options) (perun/get-meta fileset))]
         (pod/with-call-in @pod
-          (io.perun.atom/generate-atom ~(.getPath tmp) ~files ~options))
+          (io.perun.atom/generate-atom ~(.getPath tmp) ~files ~(dissoc options :filterer)))
         (commit fileset tmp)))))

 (defn- wrap-pool [pool]


ok got it, add-hook(well attachTimes) that accepts either the symbol or the var - format

--- src/runtime/q.clj
+++ src/runtime/q.clj
@@ -535,7 +535,9 @@
   ;3. zsym is defined and bound, returns :bound
   ;4. zsym is an expression ie. #() or (list 1 2 3), throws exception
   ;5. zsym is a special symbol ie. def   test this via (special-symbol? 'def) , returns :special
-  ;6. zsym is a macro ie. defn, returns :macro
+  ;6. zsym is a macro ie. defn, returns :macro
+  ;7. FIXME: handle this: (#(sym-state %) prn2) ;CompilerException java.lang.RuntimeException: Unable to resolve symbol: prn2 in this context, compiling:(NO_SOURCE_PATH:1:1)
+
   `(try
      (let [qsym# (quote ~zsym)]
            (if (not (symbol? qsym#)) ;ie. #() or (list 1 2 3)
@@ -630,12 +632,51 @@
   nil
   )

-(defn attachTimes [varfunc]
-  {:pre [(assumedTrue (var? varfunc) )] }
-  (add-hook varfunc #'incTimes_hook)
-  )
-
-(attachTimes #'dummy1)
+(defmacro get-as-var
+"
+=> (get-as-var #'prn)
+#'clojure.core/prn
+=> (get-as-var prn)
+#'clojure.core/prn
+
+=> (var prn)
+#'clojure.core/prn
+=> (var #'prn)
+CompilerException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:1:1)
+
+"
+  [sym-or-var]
+  `(let [qsym# (quote sym-or-var)
+         ;moo2# ~sym-or-var
+         ;xxx# (println (var-get moo2#))
+         ]
+    (if (var? ~sym-or-var)
+      ~sym-or-var
+      (if (symbol? qsym#)
+        (encast
+          (var ~sym-or-var)
+          )
+        (throw
+          (new RuntimeException
+            (str "you should pass a symbol or a var not `" qsym# "`")
+            )
+          )
+        )
+      )
+    )
+  )
+
+(defmacro xx [x]
+  (prn x)
+  )
+
+(defmacro attachTimes [func]
+  {:pre [(assumedTrue (or (symbol? func) (var? func) ))]}
+  (list `add-hook (list `get-as-var func) (var incTimes_hook))
+  )
+;both work
+;(attachTimes #'dummy1)
+(attachTimes dummy1)

 (deftest a-test2
@@ -657,28 +698,14 @@
 (defmacro sym-info [zsym]
   `(let [ss# (sym-state ~zsym)]
      (if (not= :bound ss#)
-       {:state ss# :value nil}
+       {:state ss# :value ~zsym};nil} ; works: ~zsym};not-works: (encast ~zsym) -> when (#(sym-info %) prn) , CompilerException java.lang.RuntimeException: Unable to resolve symbol: p1__5531# in this context, compiling:(NO_SOURCE_PATH:1:1)
        {:state ss# :value (encast ~zsym)}
        )
      )
   )

-(defmacro get-as-var [sym-or-var]
-  `(let [qsym# (quote sym-or-var)]
-    (if (var? ~sym-or-var)
-      ~sym-or-var
-      (if (symbol? qsym#)
-        (encast (var ~sym-or-var))
-        (throw
-          (new RuntimeException
-            (str "you should pass a symbol or a var not `" qsym# "`")
-            )
-          )
-        )
-      )
-    )
-  )
+

 #_(defmacro get-as-var [sym-or-var]
   `(let [qsym# (quote sym-or-var)]


Add comment.

Add comment.

--- src/cavm/core.clj
+++ src/cavm/core.clj
@@ -148,7 +148,7 @@
                   (println error))
                 (do
                   (h2/set-tmp-dir! tmp)
-                  (let [db (h2/create-xenadb (str (:database options) ";MVCC=TRUE"))
+                  (let [db (h2/create-xenadb (str (:database options) ";MVCC=TRUE")) ; XXX guard against double semicolon
                         detector (apply cr/detector docroot detectors)
                         loader (cl/loader-agent db detector docroot)]
                     (when (:auto options)


Don't round integers in json.

Don't round integers in json.

--- src/cavm/json.clj
+++ src/cavm/json.clj
@@ -20,9 +20,11 @@
   (json/-write (seq arr) out)) ; XXX is the seq here expensive? Using vec fails.

 (defn- write-floating-point [x ^PrintWriter out]
-  (if (Double/isNaN x)
-    (.print out "\"NaN\"")
-    (.print out (RyuFloat/floatToString x RoundingMode/ROUND_EVEN 4))))
+  (let [lx (long x)]
+    (cond
+      (Double/isNaN x) (.print out "\"NaN\"")
+      (== x lx) (json/-write lx out)
+      :else (.print out (RyuFloat/floatToString x RoundingMode/ROUND_EVEN 4)))))

 (extend mikera.arrayz.INDArray json/JSONWriter {:-write write-array})
 (extend java.lang.Float json/JSONWriter {:-write write-floating-point})


Remove unnecessary requires

Remove unnecessary requires

--- src/mdr2/pipeline2/core.clj
+++ src/mdr2/pipeline2/core.clj
@@ -1,8 +1,5 @@
 (ns mdr2.pipeline2.core
   (:require [clojure.data.xml :as xml]
-            [clojure.zip :as zip]
-            [clojure.data.zip.xml :refer [xml-> xml1-> attr text]]
-            [clojure.string :as s]
             [clj-time.core :as t]
             [clj-time.format :as f]
             [pandect.core :as pandect]


add paths to links

add paths to links

--- frontend/components/landing_b.cljs
+++ frontend/components/landing_b.cljs
@@ -255,24 +255,24 @@
                    (common/ico :logo)]
                   [:nav.home-footer-about
                    [:h5 "CircleCI"]
-                   [:a "Tour"]
-                   [:a "About"]
+                   [:a {:href "/tour"} "Tour"]
+                   [:a {:href "/about"} "About"]
                    [:a "Support"]
-                   [:a "Press"]
-                   [:a "Jobs"]
-                   [:a "Blog"]]
+                   [:a {:href "/about#contact"} "Press"]
+                   [:a {:href "/jobs"} "Jobs"]
+                   [:a {:href "http://blog.circleci.com"} "Blog"]]
                   [:nav.home-footer-product
                    [:h5 "Product"]
-                   [:a "Documentation"]
-                   [:a "Privacy"]
-                   [:a "Security"]
-                   [:a "Enterprise"]
-                   [:a "Changelog"]
-                   [:a "Pricing"]]
+                   [:a {:href "/pricing"} "Pricing"]
+                   [:a {:href "/docs"} "Documentation"]
+                   [:a {:href "/privacy"} "Privacy"]
+                   [:a {:href "/security"} "Security"]
+                   [:a {:href "/enterprise"} "Enterprise"]
+                   [:a {:href "/changelog"} "Changelog"]]
                   [:nav.home-footer-contact
                    [:h5 "Contact"]
-                   [:a "Twitter"]
-                   [:a "Email"]
-                   [:a "Support Chat"]
-                   [:a "Phone"]
-                   [:a "San Francisco, CA"]]]]]])))))
+                   [:a {:href "https://twitter.com/circleci"} "Twitter"]
+                   [:a {:href "mailto:sayhi@circleci.com"} "Email"]
+                   [:a {:href ""} "Support Chat"]
+                   [:a {:href ""} "Phone"]
+                   [:a {:href "https://goo.gl/maps/uhkLn"} "San Francisco, CA"]]]]]])))))


Add new interspaced timing fn.

Add new interspaced timing fn.

--- src/overtone/music/time.clj
+++ src/overtone/music/time.clj
@@ -24,7 +24,7 @@

 (defn periodic
   "Calls fun every ms-period, and takes an optional initial-delay for
-  the first call in ms. Pool defaults to the player-pool."
+  the first call in ms."
   ([ms-period fun] (periodic ms-period fun 0))
   ([ms-period fun initial-delay] (periodic ms-period fun initial-delay "Overtone periodic fn"))
   ([ms-period fun initial-delay description]
@@ -33,6 +33,20 @@
                   player-pool
                   :initial-delay initial-delay
                   :desc description)))
+
+(defn interspaced
+  "Calls fun repeatedly with an interspacing of ms-period, i.e. the next
+   call of fun will happen ms-period milliseconds after the completion
+   of the previous call. Also takes an optional initial-delay for the
+   first call in ms."
+  ([ms-period fun] (interspaced ms-period fun 0))
+  ([ms-period fun initial-delay] (interspaced ms-period fun initial-delay "Overtone interspaced fn"))
+  ([ms-period fun initial-delay description]
+     (at-at/interspaced ms-period
+                        fun
+                        player-pool
+                        :initial-delay initial-delay
+                        :desc description)))

 ;;Ensure all scheduled player fns are stopped when Overtone is reset
 ;;(typically triggered by a call to stop)


0.2.2

--- src/kiln/core.clj
+++ src/kiln/core.clj
@@ -35,7 +35,6 @@
        (or (not (.isFile html-file)) (< (.lastModified html-file) (.lastModified f)))))
     file-s))

-(println (timef/formatter (timet/default-time-zone) "YYYY-MM-dd" "YYYY/MM/dd"))
 (def blogdate-formatter
   (timef/formatter
     (timet/default-time-zone)


get compiler api namespace descriptions (close #51)

--- src/main/cljs_api_gen/write.clj
+++ src/main/cljs_api_gen/write.clj
@@ -61,7 +61,15 @@

    :compiler
    {
-    ;; TODO: create namespace descriptions
+    "cljs.analyzer.api" "programmatic access to the analyzer (producing AST)"
+    "cljs.compiler.api" "programmatic access to the compiler (emitting JS)"
+    "cljs.build.api"    "programmatic access to project-building facilities"
+    "cljs.repl"         "REPL (read eval print loop)"
+    "cljs.repl.browser" "browser-connected REPL"
+    "cljs.repl.node"    "Node.js REPL"
+    "cljs.repl.nashorn" "Nashorn REPL (JS on Java 8)"
+    "cljs.repl.rhino"   "Rhino REPL (JS on Java 6+)"
+
     }})

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


minor refactoring

minor refactoring

--- cljs/src/main/plastic/main/editor/ops.cljs
+++ cljs/src/main/plastic/main/editor/ops.cljs
@@ -104,15 +104,15 @@
    :open-quote       editing/open-quote
    :open-deref       editing/open-deref})

-(defn dispatch-op [editors [editor-id op]]
+(defn dispatch-op* [editors [editor-id op]]
   (let [old-editor (get editors editor-id)]
     (if-let [handler (op ops)]
       (if-let [new-editor (handler old-editor)]
-        (assoc-in editors [editor-id] new-editor)
-        editors)
-      (do
-        (error (str "Unknown editor operation '" op "'"))
-        editors))))
+        (assoc-in editors [editor-id] new-editor))
+      (error (str "Unknown editor operation '" op "'")))))
+
+(defn dispatch-op [& args]
+  (or (apply dispatch-op* args) (first args)))

 ; ----------------------------------------------------------------------------------------------------------------------
 ; register handlers


Rename a var and add a docstring

Rename a var and add a docstring

--- src/refactor_nrepl/util.clj
+++ src/refactor_nrepl/util.clj
@@ -50,8 +50,12 @@
             read-string
             str)))))

-(defn sexp-at-point [cont line column]
-  (let [lines (str/split-lines cont)
+(defn sexp-at-point
+  "Gets the s-expression containing point.
+
+  line is 1 indexed and 0 is column indexed (this is how emacs does things)."
+  [file-content line column]
+  (let [lines (str/split-lines file-content)
         line-index (dec line)
         char-count (->> lines
                         (take line-index)
@@ -62,7 +66,7 @@
                    (take column)
                    search-backward-start-sexp
                    (+ char-count))]
-    (-> cont
+    (-> file-content
         (.substring start)
         read-first-form)))


handle or and and with key spec visitor

handle or and and with key spec visitor

--- src/spec_tools/visitor.cljc
+++ src/spec_tools/visitor.cljc
@@ -2,7 +2,8 @@
   "Tools for walking spec definitions."
   (:require [clojure.spec :as s]
             [spec-tools.core :as st]
-            [spec-tools.type :as type]))
+            [spec-tools.type :as type]
+            [spec-tools.impl :as impl]))

 (defn strip-fn-if-needed [form]
   (let [head (first form)]
@@ -67,8 +68,8 @@
   (accept ::set spec (vec (if (keyword? spec) (s/form spec) spec))))

 (defmethod visit 'clojure.spec/keys [spec accept]
-  (let [[_ & {:keys [req req-un opt opt-un]}] (s/form spec)]
-    (accept 'clojure.spec/keys spec (mapv #(visit % accept) (concat req req-un opt opt-un)))))
+  (let [keys (impl/extract-keys (s/form spec))]
+    (accept 'clojure.spec/keys spec (mapv #(visit % accept) keys))))

 (defmethod visit 'clojure.spec/or [spec accept]
   (let [[_ & {:as inner-spec-map}] (s/form spec)]


Add space between icon and link text.

Add space between icon and link text.

--- src/statuses/views/main.clj
+++ src/statuses/views/main.clj
@@ -20,7 +20,7 @@
   [:i {:class (str "glyphicon glyphicon-" icon)}])

 (defn nav-link [{:keys [url title icon]}]
-  [:li (link-to url (glyphicon icon) title)])
+  [:li (link-to url (glyphicon icon) (str " " title))])

 (defn nav-links [request]
   (let [links ["Statuses" [{:url base :title "Everything"


Restart the entire peer when there's a midway failure.

--- src/onyx/api.clj
+++ src/onyx/api.clj
@@ -110,12 +110,13 @@

                              (let [restart-ch (:dead-restart-tail-ch (:peer live))
                                    [v ch] (alts!! [stop-ch restart-ch] :priority true)]
-                               (when (= ch stop-ch)
+                               (if (= ch stop-ch)
                                  (try
                                    (component/stop live)
                                    (catch Exception e
                                      (warn e)
-                                     :stopped)))))
+                                     :stopped))
+                                 (throw (ex-info "Peer failed" {})))))
                            (catch Exception e
                              (warn e)
                              (warn "Virtual peer failed, backing off and rebooting...")


Request up-to-date version on reading student list.

--- src/rill/web.clj
+++ src/rill/web.clj
@@ -10,9 +10,9 @@
   (fn [request]
     (when-let [command (ring-handler request)]
       (log/info ["Executing command" command])
-      (let [[status events] (rill-handler/try-command event-store command)]
+      (let [[status events new-version] (rill-handler/try-command event-store command)]
         (case status
             :rejected {:status 422 :body {:status :command-rejected}} ; HTTP 422 Unprocessable Entity
             :conflict {:status 409 :body {:status :command-conflict}} ; HTTP 409 Conflict
-            :ok {:status 200 :body {:status :command-accepted, :events events}}
+            :ok {:status 200 :body {:status :command-accepted, :events events, :aggregate-version new-version :aggregate-id (message/primary-aggregate-id command)}}
             {:status 500 :body {:status :internal-error}})))))


s/map/pmap/

s/map/pmap/

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -100,7 +100,7 @@
                               (if (= false (get-in parent [:head :phrasal] false))
                                 (let [candidate-lexemes (get-lex parent :head index spec)]
                                   (over/overh parent
-                                              (map copy (lazy-shuffle candidate-lexemes))))))
+                                              (pmap copy (lazy-shuffle candidate-lexemes))))))
                             parents))
               phrasal ;; 2. generate list of all phrases where the head child of each parent is itself a phrase.
               (if (< depth max-total-depth)
@@ -148,19 +148,19 @@
                                   ",path=" path ",bolt=(" (show-bolt bolt path morph) ")=>"
                                   "'" (morph complement) "'"))
                   true)))
-            (map (fn [complement]
-                   (unify (copy bolt)
-                          (path-to-map path
-                                       (copy complement))))
-                 (let [debug (log/trace (str "add-complement(depth=" depth ",total-depth=" total-depth
-                                             ",path=" path ",bolt=(" (show-bolt bolt path morph)
-                                             "): calling generate-all(" (strip-refs spec) ");"
-                                             "input-spec: " input-spec))
-                       phrasal-complements (if (> max-total-depth total-depth)
-                                             (generate-all spec grammar lexicon cache morph (+ depth total-depth)))]
-                   (if (lexemes-before-phrases total-depth)
-                     (take 1 (lazy-cat shuffled-candidate-lexical-complements phrasal-complements))
-                     (take 1 (lazy-cat phrasal-complements shuffled-candidate-lexical-complements))))))))
+            (pmap (fn [complement]
+                    (unify (copy bolt)
+                           (path-to-map path
+                                        (copy complement))))
+                  (let [debug (log/trace (str "add-complement(depth=" depth ",total-depth=" total-depth
+                                              ",path=" path ",bolt=(" (show-bolt bolt path morph)
+                                              "): calling generate-all(" (strip-refs spec) ");"
+                                              "input-spec: " input-spec))
+                        phrasal-complements (if (> max-total-depth total-depth)
+                                              (generate-all spec grammar lexicon cache morph (+ depth total-depth)))]
+                    (if (lexemes-before-phrases total-depth)
+                      (take 1 (lazy-cat shuffled-candidate-lexical-complements phrasal-complements))
+                      (take 1 (lazy-cat phrasal-complements shuffled-candidate-lexical-complements))))))))

 (defn path-to-map [path val]
   (let [feat (first path)]


improve comments and logging

improve comments and logging

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -139,15 +139,17 @@
     (cond
       (not (nil? bolts))
       (do
-        (log/trace (str "found compiled bolts."))
+        (log/debug (str "found compiled bolts."))
         (shufflefn (->> bolts
                         (map #(unify spec %))
                         (filter #(not (= :fail %))))))
       true
-      (shufflefn (lightning-bolts model spec 0 depth)))))
-
-;; a 'lightning bolts' is a dag that
-;; has among paths, paths like [:head :head :head] and
+      (do
+        (log/debug (str "no compiled bolts."))
+        (shufflefn (lightning-bolts model spec 0 depth))))))
+
+;; a 'lightning bolt' is a dag that
+;; has among its paths, paths like [:head :head :head] and
 ;; pictorially look like:
 ;;
 ;;
@@ -187,7 +189,8 @@
         (let [candidate-parent (first candidate-parents)]
           (log/debug (str "creating bolts with: "
                           (:rule candidate-parent)
-                          " and cat: " (get-in candidate-parent [:head :synsem :cat])))
+                          " and cat: " (get-in candidate-parent [:head :synsem :cat])
+                          " at depth: " depth))
           (lazy-cat
            (->> (lightning-bolts model
                                  (get-in candidate-parent [:head])


use lexiconfn/unify rather than unifyc: the former throws exceptions as we desire in this case

--- src/babel/lexiconfn.clj
+++ src/babel/lexiconfn.clj
@@ -5,6 +5,7 @@
    [clojure.set :as set]
    [clojure.tools.logging :as log]
    [clojure.core :as core]
+   [clojure.string :as string]
    [babel.pos :refer :all]
    [dag-unify.core :refer :all :exclude (unify)])) ;; exclude unify because we redefine it here using unifyc (copy each arg)

@@ -66,12 +67,25 @@
         (merge-with concat lexicon-stage-3 exceptions)]
     lexicon))

+(declare get-fail-path)
+
 (defn unify [ & args]
   "like unify/unify, but unify/copy each argument before unifying."
   (do
     (log/trace (str "(lexfn)unify args: " args))
     (log/trace (str "(lexfn)unify first arg: " (first args)))
-    (apply unifyc args)))
+    (let [retval (apply unifyc args)]
+      (if (not (fail? retval))
+        retval
+
+        (let [message (str "Failed to unify args:" (string/join " , " (map strip-refs args))
+                           (if (= 2 (.size args))
+                             (str "failed path: " (get-fail-path (first args)
+                                                                 (second args)))
+                             ""))]
+
+          (log/error message)
+          (throw (Exception. message)))))))

 (defn cache-serialization [entry]
   "Copying ((unify/copy)ing) lexical entries during generation or parsing is done by serializing and then deserializing.
@@ -786,15 +800,15 @@
                           (not (= '() (get-in val [:synsem :subcat :2]))))

                      (do
-                       (list (unifyc val
-                                     transitive) ;; Make a 2-member list. member 1 is the transitive version..
+                       (list (unify val
+                                    transitive) ;; Make a 2-member list. member 1 is the transitive version..

                              ;; .. and the other member of the list being the intransitive version.
                              ;; Turn the singular, transitive form into an intransitive form by
                              ;; doing some surgery on it: (remove the object) and intransitivize it
                              (let [without-object  ;; intransitive version
-                                   (unifyc intransitive-unspecified-obj
-                                           (dissoc-paths val
+                                   (unify intransitive-unspecified-obj
+                                          (dissoc-paths val
                                                          (list [:serialized]
                                                                [:synsem :sem :obj]
                                                                [:synsem :subcat :2])))]
@@ -809,8 +823,8 @@
                      (and (= (get-in val [:synsem :cat])
                              :verb)
                           (= :none (get-in val [:synsem :subcat :2] :none)))
-                     (list (unifyc val intransitive))
-
+                     (list (unify val intransitive))
+
                      ;; else just return vals:
                      true
                      (do (if (= :verb (get-in val [:synsem :cat]))
@@ -830,12 +844,12 @@
                        (not (= :unspec (get-in val [:synsem :sem :obj])))
                        (not (= '() (get-in val [:synsem :subcat :2])))
                        (not (nil? (get-in val [:synsem :sem :obj] nil))))
-                  (unifyc val
-                          transitive)
+                  (unify val
+                         transitive)

                   (= (get-in val [:synsem :cat]) :verb)
-                  (unifyc val
-                          verb-subjective)
+                  (unify val
+                         verb-subjective)
                   true
                   val))
           vals))))
@@ -854,12 +868,13 @@
    lexicon
    (fn [k vals]
      (mapcat (fn [val]
-               (cond (not (fail? (unify val if-has)))
-                     (do
-                       (log/debug (str val ": matches: if: " if-has " then " unify-with))
-                       (list (unify val unify-with)))
+               (let [result (unifyc val if-has)]
+                 (cond (not (fail? result))
+                       (do
+                         (log/debug (str val ": matches: if: " if-has " then " unify-with))
+                         (list result))
                      true
-                     (list val)))
+                     (list val))))
              vals))))

 (defn get-fail-path [map1 map2]


Exclude clojure.core update function on buddy.core.hash ns.

--- src/buddy/core/hash.clj
+++ src/buddy/core/hash.clj
@@ -15,6 +15,7 @@
 (ns buddy.core.hash
   "Basic crypto primitives that used for more high
   level abstractions."
+  (:refer-clojure :exclude [update])
   (:require [buddy.core.codecs :refer :all]
             [clojure.java.io :as io])
   (:import org.bouncycastle.crypto.Digest


Remove unused prefix

Remove unused prefix

--- src/caesium/binding.clj
+++ src/caesium/binding.clj
@@ -95,11 +95,6 @@

 (assert (#{0 1} (.sodium_init sodium)))

-(defn prefix
-  "Gets the parts of the current namespace, minus the leading `caesium`."
-  []
-  (-> *ns* ns-name str (s/split #"\.") rest vec))
-
 (defmacro defconsts
   "Given constant names (syms) in the C pseudo-namespace corresponding
   to the current namespace, call the corresponding libsodium function


CMR-5684: Addressed review comment.

CMR-5684: Addressed review comment.

--- system-int-test/test/cmr/system_int_test/search/service/collection_service_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/service/collection_service_search_test.clj
@@ -115,7 +115,7 @@
        {:has-formats true :has-transforms false :has-spatial-subsetting true :has-variables false}
        [serv1-concept-id serv2-concept-id serv3-concept-id])

-      ; update service3 to also have InterpolationTypes
+      ;; update service3 to also have InterpolationTypes
       (service-util/ingest-service-with-attrs
        {:native-id "serv3"
         :Name "service3"


Document create-default-session fns

Document create-default-session fns

--- src/uruk/core.clj
+++ src/uruk/core.clj
@@ -605,6 +605,9 @@
     :transaction-mode :transaction-timeout})

 (defn validate-session-config-options
+  "Raises an error if the given configuration options are invalid for
+  a MarkLogic session. See `valid-session-config-options` and
+  https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/Session.html"
   [config-options]
   (when-not (clojure.set/subset? (set (keys config-options))
                                  valid-session-config-options)
@@ -614,7 +617,8 @@
                  " are recognized keywords.")))))

 (defn configure-session
-  ;; TODO docstring
+  "Configures the given MarkLogic `session` according to the given
+  `config-options`. See `create-session`."
   [session {:keys [default-request-options logger user-object
                    transaction-mode transaction-timeout]
             :as config-options}]
@@ -672,7 +676,13 @@
    (configure-session (create-session* db-info content-source) config-options)))

 (defn create-default-session
-  ;; TODO docstring
+  "Returns a session according to the default login credentials of the
+  given `content-source`, which must be a
+  com.marklogic.xcc.ContentSource object (see
+  https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/ContentSource.html),
+  presumably created with one of Uruk's `make-*-content-source`
+  functions. Optionally takes a map of `config-options` to configure
+  the session."
   ([content-source]
    (create-default-session content-source nil))
   ([content-source {:keys [default-request-options logger user-object


Fix render-all to forbid forceUpdate on falsy comp

The `when` condition passes in following situations:
- component is unmounted
- when it's a falsy value (nil, false)
This commit forbids exec of forceRender on falsy components, so such an action will not trigger an error.

https://imgur.com/a/SB6ys2E

--- src/rum/core.cljs
+++ src/rum/core.cljs
@@ -193,7 +193,7 @@

 (defn- render-all [queue]
   (doseq [comp queue
-          :when (not (gobj/get comp ":rum/unmounted?"))]
+          :when (and (some? comp) (not (gobj/get comp ":rum/unmounted?")))]
     (.forceUpdate comp)))


Fix the test's overambitious expectations

Closes #76.
Refs #62. Clearly doesn't do anything to fix it.
Refs Prismatic/schema#205.


langs and topics strings and keywords

langs and topics strings and keywords

--- src-cljs/tranjlator/master_view.cljs
+++ src-cljs/tranjlator/master_view.cljs
@@ -116,7 +116,7 @@
                    (= :original topic) (om/transact! app :original (fn [col] (conj col msg)))
                    (= :user-join topic) (om/transact! app :users (fn [col] (conj col (:user-name msg []))))
                    (= :user-part topic) (om/transact! app :users (fn [col] (remove (fn [x] (= x (:user-name msg))) col)))
-                   (= lang topic) (om/transact! app :translated (fn [col] (conj col msg)))
+                   (= (str lang) (str topic)) (om/transact! app :translated (fn [col] (conj col msg)))
                    :default (println "RECVD:" msg "type: " (keys msg))))
                 (recur))))))
     om/IDidMount


HTTP client: high level get and post. add form-params and basic-auth support

--- src/me/shenfeng/http/client.clj
+++ src/me/shenfeng/http/client.clj
@@ -1,7 +1,9 @@
 (ns me.shenfeng.http.client
+  (:refer-clojure :exclude [get])
   (:require [clojure.string :as str])
   (:import [me.shenfeng.http.client HttpClientConfig HttpClient
             IResponseHandler RespListener RespListener$IFilter]
+           javax.xml.bind.DatatypeConverter
            (java.net URI URLEncoder)
            me.shenfeng.http.HttpMethod))

@@ -10,6 +12,30 @@
             (assoc m (if keywordize-headers? (keyword (str/lower-case k))
                          (str/lower-case k)) v))
           {} headers))
+
+(defn- url-encode [unencoded] (URLEncoder/encode unencoded "UTF-8"))
+(defn- utf8-bytes [#^String s] (.getBytes s "UTF-8"))
+(defn- base64-encode [bytes]
+  (DatatypeConverter/printBase64Binary bytes))
+(defn- basic-auth-value [basic-auth]
+  (let [basic-auth (if (string? basic-auth)
+                     basic-auth
+                     (str (first basic-auth) ":" (second basic-auth)))]
+    (str "Basic " (base64-encode (utf8-bytes basic-auth)))))
+
+(defn- form-body [params]
+  (.getBytes (str/join "&"
+                       (mapcat (fn [[k v]]
+                                 (if (sequential? v)
+                                   (map #(str (url-encode (name %1))
+                                              "="
+                                              (url-encode (str %2)))
+                                        (repeat k) v)
+                                   [(str (url-encode (name k))
+                                         "="
+                                         (url-encode (str v)))]))
+                               params))
+             "UTF-8"))

 (defonce default-client (atom nil))

@@ -21,38 +47,53 @@
 (defn get-default-client "Returns default HTTP client, initializing as neccesary."
   [] (if-let [c @default-client] c (reset! default-client (init-client))))

+(defn- coerce-req [{:keys [headers client method body form-params timeout basic-auth]
+                    :as req}]
+  (merge req  ;; TODO cookie
+         {:headers
+          (merge headers
+                 (when form-params
+                   {"Content-Type" "application/x-www-form-urlencoded"})
+                 (when basic-auth
+                   {"Authorization" (basic-auth-value basic-auth)}))}
+         {:body (or (when form-params
+                      (form-body form-params)) body)}
+         {:client (or client (get-default-client))
+          :method (or method :get)}))
+
 (defn request*
-  "Issues an async HTTP request and returns a promise object to which the value
-  of `(callback <http-response>)` or `((or error-callback callback) <exception>)`
-  will be delivered. See also `request`."
-  [{:keys [client url method headers data timeout]
-    :or   {method :get client (get-default-client)}}
-   callback & [error-callback]]
-  (let [uri (URI. url)
+  "Issues an async HTTP request and returns a promise object to which
+   <http-response> or <exception> will be delivered
+  `(callback <http-response>)` or `((or error-callback callback) <exception>)`
+   See also `request`."
+  [req callback & [error-callback]]
+  (let [{:keys [client url method headers body timeout]} (coerce-req req)
+        uri (URI. url)
         method (case method
                  :get  HttpMethod/GET
+                 :delete HttpMethod/DELETE
                  :post HttpMethod/POST
                  :put  HttpMethod/PUT)
         response (promise)]
-    (.exec ^HttpClient client uri method headers data
+    (.exec ^HttpClient client uri method headers body
            (or timeout -1) ; -1 for client default
            (RespListener.
             (reify IResponseHandler
               (onSuccess [this status headers body]
-                (deliver response
-                         (callback {:body body
-                                    :headers (normalize-headers headers true)
-                                    :status status})))
+                (let [resp {:body body
+                            :headers (normalize-headers headers true)
+                            :status status}]
+                  (deliver response resp)
+                  (callback resp)))
               (onThrowable [this t]
-                (deliver response
-                         (try ((or error-callback callback) (Exception. t))
-                              (catch Exception e e)))))))
+                (deliver response t)
+                ((or error-callback callback) t)))))
     response))

 (defmacro request
   "Issues an asynchronous HTTP request, binds the HTTP response or exception to
   `resp`, then executes the given handler body in the context of that binding.
-  Returns a promise object to which the handler's return value will be delivered:
+  Returns a promise object to which the HTTP response or exception will be delivered:

      ;; Asynchronous
      (request {:url \"http://www.cnn.com/\"}
@@ -68,38 +109,30 @@
   [options resp & handler]
   `(request* ~options (fn [~resp] ~@handler)))

+(defmacro get
+  ([url]
+     `(request {:method :get :url ~url} resp# nil))
+  ([url req]
+     `(get ~url ~req resp# nil))
+  ([url req resp & forms]
+     `(let [req# (assoc ~req :method :get :url ~url)]
+        (request req#  ~resp ~@forms))))
+
+(defmacro post
+  ([url]
+     `(request {:method :post :url ~url} resp# nil))
+  ([url req]
+     `(post ~url ~req resp# nil))
+  ([url req resp & forms]
+     `(let [req# (merge {:method :post :url ~url} ~req)]
+        (request req# ~resp ~@forms))))
+
 (comment
-  @(request {:url "http://www.cnn.com/"}
-            {:keys [status body headers] :as resp}
-            (if status ; nil on exceptions
-              (do (println "Body: " body) body)
-              (do (println "Exceptiond: " resp) resp))))
-
-(comment ; TODO
-
-  (defn- url-encode
-    "Returns an UTF-8 URL encoded version of the given string."
-    [unencoded]
-    (URLEncoder/encode unencoded "UTF-8"))
-
-  (defn- generate-query-string
-    "Params: {:param1 \"value1\" :params2 \"value2\" :param3 [\"value3\" \"value4\"}
-
-    Return Http Form encoded bytes array. used as HTTP body. Need to set
-
-    Content-Type: application/x-www-form-urlencoded
-
-    in the Request's Headers for server to properly understand it"
-    [params]
-    (.getBytes (str/join "&"
-                         (mapcat (fn [[k v]]
-                                   (if (sequential? v)
-                                     (map #(str (url-encode (name %1))
-                                                "="
-                                                (url-encode (str %2)))
-                                          (repeat k) v)
-                                     [(str (url-encode (name k))
-                                           "="
-                                           (url-encode (str v)))]))
-                                 params))
-               "UTF-8")))+  (let [a (post "http://127.0.0.1:9091" {:timeout 900
+                                         :form-params {:param1 "abc" :param2 ["a" "b"]}
+                                         :basic-auth ["user" "password"]}
+                {:keys [status headers body] :as resp}
+                (if status
+                  (println status)
+                  (do (.printStackTrace resp))))]
+    (println @a)))


fix clob issue.

fix clob issue.

--- src/metabase/models/setting.clj
+++ src/metabase/models/setting.clj
@@ -265,6 +265,11 @@
   "The model that underlies `defsetting`."
   :setting)

+(u/strict-extend (class Setting)
+  i/IEntity
+  (merge i/IEntityDefaults
+         {:types (constantly {:value :clob})}))
+
 (defn- settings-list
   "Return a list of all Settings (as created with `defsetting`).
    This excludes Settings created with the option `:internal`."


hardcode music category

hardcode music category

--- src/tonal/rss.clj
+++ src/tonal/rss.clj
@@ -63,7 +63,7 @@
            [:url (:podcast-artwork config)]
            [:title (:title config)]
            [:link (:url config)]]
-          [:category "Arts"]
+          [:category "Music"]
           [:explicit "no"]
           [:itunes:author (:author config)]
           [:itunes:subtitle (:description config)]
@@ -71,8 +71,7 @@
            [:itunes:name (:author config)]
            [:itunes:email (:email config)]]
           [:itunes:explicit "no"]
-          [:itunes:category {:text "Arts"}
-           [:itunes:category {:text "Design"}]]
+          [:itunes:category {:text "Music"}]
           [:itunes:image {:href (:podcast-artwork config)}]
           (map (partial podcast-entry config) (filter :podcast posts))]])
       (xml/emit-str)))


Enforce new naming regime

Enforce new naming regime

--- src/uruk/core.clj
+++ src/uruk/core.clj
@@ -29,8 +29,8 @@
    :version-minor (Version/getVersionMinor)
    :version-patch (Version/getVersionPatch)})

-(def doc-format
-  "Enumeration of allowed document formats. Used at insertion
+(def ->doc-format
+  "Mapping of keywords to allowed document formats. Used at insertion
   time.
   See https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/DocumentFormat.html"
   {:xml DocumentFormat/XML
@@ -39,23 +39,23 @@
    :none   DocumentFormat/NONE
    :binary DocumentFormat/BINARY})

-(def doc-repair-level
-  "Enumeration of document repair levels. Used at insertion time.
+(def ->doc-repair-level
+  "Mapping of keywords to document repair levels. Used at insertion time.
   See https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/DocumentRepairLevel.html"
   {:default DocumentRepairLevel/DEFAULT
    :full    DocumentRepairLevel/FULL
    :none    DocumentRepairLevel/NONE})

-(def content-capability
-  "Enumeration of content permission capability values.
+(def ->content-capability
+  "Mapping of keywords to content permission capability values.
   See https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/ContentCapability.html"
   {:execute ContentCapability/EXECUTE
    :insert  ContentCapability/INSERT
    :read    ContentCapability/READ
    :update  ContentCapability/UPDATE})

-(def transaction-modes
-  "Enumeration of valid Session transaction modes. See
+(def ->transaction-mode
+  "Mapping of keywords to valid Session transaction modes. See
   https://docs.marklogic.com/javadoc/xcc/com/marklogic/xcc/Session.TransactionMode.html"
   {:auto Session$TransactionMode/AUTO
    :query Session$TransactionMode/QUERY
@@ -67,7 +67,7 @@
 ;;;; Type conversion
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn convert-number
+(defn java->num
   "Reads a number from a numeric Java object of a type from
   com.marklogic.xcc.types. Returns nil if not a number. Designed for
   robust number-handling while preventing read-string security
@@ -108,7 +108,7 @@

    ;; JsonItem TODO
    "null-node()" java-json->clj-json ;; NullNode
-   "number-node()" convert-number ;; NumberNode
+   "number-node()" java->num ;; NumberNode
    "object-node()" java-json->clj-json ;; ObjectNode

    ;; XdmAtomic TODO
@@ -128,10 +128,10 @@
    "xs:date" str
    "xs:dateTime" str
    "xs:dayTimeDuration" str
-   "xs:decimal" convert-number
-   "xs:double" convert-number
+   "xs:decimal" java->num
+   "xs:double" java->num
    "xs:duration" str
-   "xs:float" convert-number
+   "xs:float" java->num
    ;; Maybe strip hyphens from all Gregorian date-parts?
    ;; or make conform to a particular date type?
    "xs:gDay" str
@@ -140,7 +140,7 @@
    "xs:gYear" str
    "xs:gYearMonth" str
    "xs:hexBinary" str ;; looks OK but test with real doc
-   "xs:integer" convert-number
+   "xs:integer" java->num
    "xs:QName" str
    "xs:string" str
    "xs:time" str
@@ -216,7 +216,7 @@
           (fn (k options)))))
     request))

-(defn describe-request-options
+(defn request-options->map
   "Given a RequestOptions object, returns a map describing those
   request options."
   [req-opts]
@@ -394,14 +394,14 @@
                                    transaction-mode transaction-timeout]}]
    (let [session (create-session* db-info content-source)]
      (when (map? default-request-options)
-       (.setDefaultRequestOptions session (request-options default-request-options)))
+       (.setDefaultRequestOptions session (make-request-options default-request-options)))
      (when (instance? Logger logger)
        (.setLogger session logger))
      ;; XXX the following is not the strictest test!
      (when (instance? Object user-object)
        (.setUserObject session user-object))
      (when (keyword? transaction-mode)
-       (.setTransactionMode session (transaction-modes transaction-mode)))
+       (.setTransactionMode session (->transaction-mode transaction-mode)))
      (when (integer? transaction-timeout)
        (.setTransactionTimeout session transaction-timeout))
      session)))
@@ -456,7 +456,7 @@
    :closed? (.isClosed session) ;; TODO maybe create (defn closed? [session] ...) ? Except it wouldn't be specific to Session in this ns, and ResultSequence also has isClosed, so it's ambiguous.
    :cached-transaction-timeout (.getCachedTxnTimeout session)
    :transaction-timeout (.getTransactionTimeout session)
-   :transaction-mode ((clojure.set/map-invert transaction-modes)
+   :transaction-mode ((clojure.set/map-invert ->transaction-mode)
                       (.getTransactionMode session))})

@@ -796,7 +796,7 @@
               (reduce (fn [permissions-acc permission]
                         (conj permissions-acc
                               (ContentPermission.
-                               (content-capability (val (first permission)))
+                               (->content-capability (val (first permission)))
                                (key (first permission)))))
                       []
                       permissions)))
@@ -813,7 +813,7 @@
     (let [xs [[:buffer-size #(.setBufferSize cco %)]
               [:collections #(.setCollections cco (into-array String %))]
               [:encoding    #(.setEncoding cco %)]
-              [:format      #(.setFormat cco (doc-format %))]
+              [:format      #(.setFormat cco (->doc-format %))]
               [:graph       #(.setGraph cco %)]
               [:language    #(.setLanguage cco %)]
               [:locale      #(.setLocale cco %)]
@@ -821,7 +821,7 @@
               [:permissions #(.setPermissions cco (make-content-permissions %))]
               [:placement-keys      #(.setPlaceKeys cco %)]
               [:quality             #(.setQuality cco %)]
-              [:repair-level        #(.setRepairLevel cco (doc-repair-level %))]
+              [:repair-level        #(.setRepairLevel cco (->doc-repair-level %))]
               [:resolve-buffer-size #(.setResolveBufferSize cco %)]
               [:resolve-entities    #(.setResolveEntities cco %)]
               [:temporal-collection #(.setTemporalCollection cco %)]]]
@@ -830,12 +830,12 @@
           (fn x))))
     cco))

-(defn describe-content-creation-options
+(defn content-creation-options->map
   [opts]
   {:buffer-size (.getBufferSize opts)
    :collections (mapv #(.toString %) (.getCollections opts))
    :encoding (.getEncoding opts)
-   :format ((clojure.set/map-invert doc-format) (.getFormat opts))
+   :format ((clojure.set/map-invert ->doc-format) (.getFormat opts))
    :graph (.getGraph opts)
    :language (.getLanguage opts)
    :locale (.getLocale opts)
@@ -844,7 +844,7 @@
                                  (keyword (.toString (.getCapability %))))
                       (.getPermissions opts))
    :quality (.getQuality opts)
-   :repair-level ((clojure.set/map-invert doc-repair-level) (.getRepairLevel opts))
+   :repair-level ((clojure.set/map-invert ->doc-repair-level) (.getRepairLevel opts))
    :resolve-buffer-size (.getResolveBufferSize opts)
    :resolve-entities (.getResolveEntities opts)
    :temporal-collection (.getTemporalCollection opts)})


Document resume point event map key.

Document resume point event map key.

--- src/onyx/information_model.cljc
+++ src/onyx/information_model.cljc
@@ -774,7 +774,7 @@
                                                 :doc "The replica that this peer has currently accrued."}
                        :onyx.core/resume-point {:type :any
                                                 :optional? true
-                                                :doc ""}
+                                                :doc "Resume point provided as part of onyx job `:resume-point` key."}
                        :onyx.core/monitoring {:type :record
                                               :doc "Onyx monitoring component implementing the [IEmitEvent](https://github.com/onyx-platform/onyx/blob/master/src/onyx/extensions.clj) protocol"}
                        :onyx.core/input-plugin {:type :any


Fix issue where protocol trigger fn was passed in, not the trigger data.

--- src/onyx/peer/window_state.cljc
+++ src/onyx/peer/window_state.cljc
@@ -51,7 +51,7 @@

 (defn refine! [trigger-record state-store idx group-id extent state-event extent-state]
   (if (:create-state-update trigger-record)
-    (let [{:keys [create-state-update apply-state-update]} trigger-record
+    (let [{:keys [create-state-update apply-state-update trigger]} trigger-record
           state-update (create-state-update trigger @extent-state state-event)
           next-extent-state (apply-state-update trigger @extent-state state-update)]
       (st/put-extent! state-store idx group-id extent next-extent-state)


Improve core.async/buffer validation.

Improve core.async/buffer validation.

--- src/onyx/plugin/core_async.cljc
+++ src/onyx/plugin/core_async.cljc
@@ -20,10 +20,16 @@
     [@replica-version @epoch])

   (recover! [this replica-version* checkpoint]
-    (when-not (map? @(:core.async/buffer event))
-      (throw (ex-info "A buffer atom must now be supplied to the core.async plugin under :core.async/buffer.
-                          This atom must contain a map." {})))
-    (let [buf @(:core.async/buffer event)
+
+    (let [buffer (:core.async/buffer event)
+          _ (when-not (and buffer
+                           #?(:clj  (instance? clojure.lang.IDeref buffer)
+                              :cljs (satisfies? cljs.core/IDeref buffer))
+                           (map? @buffer))
+              (throw (ex-info "A buffer atom must now be supplied to the core.async plugin under :core.async/buffer.
+                               This atom must contain a map."
+                              {})))
+          buf @buffer
           resume-to (or checkpoint (first (sort (keys buf))))
           resumed* (get buf resume-to)]
       (reset! completed? false)


Add day-of-month

Add day-of-month

--- src/tick/core.clj
+++ src/tick/core.clj
@@ -112,6 +112,7 @@
   (second [_] "Return the second field of the given time")
   (minute [_] "Return the minute field of the given time")
   (hour [_] "Return the hour field of the given time")
+  ;; Should this be day-of-week or at least an alias?
   (day [_] "Make a java.time.DayOfWeek instance.")
   (day-of-month [_] "Return value of the day in the month as an integer.")
   (inst [_] "Make a java.util.Date instance.")
@@ -165,6 +166,7 @@
   (minute [t] (minute (zoned-date-time t)))
   (hour [t] (hour (zoned-date-time t)))
   (day [i] (day (date i)))
+  (day-of-month [i] (day-of-month (date i)))
   (inst [i] (Date/from i))
   (instant [i] i)
   (int [i] (.getNano i))
@@ -179,9 +181,10 @@
   (inst [s] (inst (instant s)))
   (instant [s] (instant (parse s)))
   (day [s] (or (parse-day s) (day (date s))))
+  (day-of-month [s] (day-of-month (date s)))
   (date [s] (date (parse s)))
   (time [s] (time (parse s)))
-  (month [s] (parse-month s))
+  (month [s] (or (parse-month s) (month (date s))))
   (year [s] (year (parse s)))
   (year-month [s] (year-month (parse s)))
   (zone [s] (ZoneId/of s))


Avoid prefix lists in r.m.stacktrace.

Avoid prefix lists in r.m.stacktrace.

--- ring-devel/src/ring/middleware/stacktrace.clj
+++ ring-devel/src/ring/middleware/stacktrace.clj
@@ -1,7 +1,9 @@
 (ns ring.middleware.stacktrace
   "Catch exceptions and render web and log stacktraces for debugging."
-  (:use (hiccup core page-helpers)
-        (clj-stacktrace core repl)
+  (:use hiccup.core
+        hiccup.page-helpers
+        clj-stacktrace.core
+        clj-stacktrace.repl
         (clojure.contrib [def :only (defvar-)])
         ring.util.response))


Allow passing of non-XS_STRING type variables

Addresses #3.

--- src/uruk/core.clj
+++ src/uruk/core.clj
@@ -257,8 +257,60 @@

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;; Working with sessions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Queries
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(def variable-types
+  "TODO docstring"
+  {:array-node ValueType/ARRAY_NODE
+   :attribute ValueType/ATTRIBUTE ;; FIXME Causes "Unhandled java.lang.InternalError | Unrecognized valueType: attribute()" if passed as variable :type
+   :binary ValueType/BINARY
+   :boolean-node ValueType/BOOLEAN_NODE
+   :comment ValueType/COMMENT ;; FIXME if passed as variable :type, causes: com.marklogic.xcc.exceptions.XQueryException: XDMP-LEXVAL: xs:QName("comment()") -- Invalid lexical value "comment()"
+   :cts-box ValueType/CTS_BOX
+   :cts-circle ValueType/CTS_CIRCLE
+   :cts-point ValueType/CTS_POINT
+   :cts-polygon ValueType/CTS_POLYGON
+
+   :document ValueType/DOCUMENT
+   :element ValueType/ELEMENT
+   :js-array ValueType/JS_ARRAY
+   :js-object ValueType/JS_OBJECT
+   :node ValueType/NODE
+   :null-node ValueType/NULL_NODE
+   :number-node ValueType/NUMBER_NODE
+   :object-node ValueType/OBJECT_NODE
+   :processing-instruction ValueType/PROCESSING_INSTRUCTION
+   :sequence ValueType/SEQUENCE
+   :text ValueType/TEXT ;; FIXME causes XDMP-LEXVAL
+
+   :xs-any-uri ValueType/XS_ANY_URI
+   :xs-base64-binary ValueType/XS_BASE64_BINARY
+   :xs-boolean ValueType/XS_BOOLEAN
+   :xs-date ValueType/XS_DATE
+   :xs-date-time ValueType/XS_DATE_TIME
+   :xs-day-time-duration ValueType/XS_DAY_TIME_DURATION
+   :xs-decimal ValueType/XS_DECIMAL
+   :xs-double ValueType/XS_DOUBLE
+   :xs-duration ValueType/XS_DURATION
+   :xs-float ValueType/XS_FLOAT
+
+   :xs-gday ValueType/XS_GDAY
+   :xs-gmonth ValueType/XS_GMONTH
+   :xs-gmonth-day ValueType/XS_GMONTH_DAY
+   :xs-gyear ValueType/XS_GYEAR
+   :xs-gyear-month ValueType/XS_GYEAR_MONTH
+
+   :xs-hex-binary ValueType/XS_HEX_BINARY
+   :xs-integer ValueType/XS_INTEGER
+   :xs-qname ValueType/XS_QNAME
+   :xs-string ValueType/XS_STRING
+   :xs-time ValueType/XS_TIME
+   :xs-untyped-atomic ValueType/XS_UNTYPED_ATOMIC
+   :xs-year-month-duration ValueType/XS_YEAR_MONTH_DURATION
+
+   ;; default:
+   nil ValueType/XS_STRING})

 (defn submit-request
   "Construct, submit, and return raw results of request for the given
@@ -269,10 +321,15 @@
   [request-factory session query options variables types]
   (let [ro      (request-options options)
         request (reduce-kv (fn [acc vname vval]
-                             (.setNewVariable acc (name vname)
-                                              ;; TODO handle other variable types
-                                              ;; XXX see com.marklogic.xcc.examples.ModuleRunner for example of XS_DOCUMENT type
-                                              ValueType/XS_STRING (str vval))
+                             (if (string? vval)
+                               (.setNewVariable acc (name vname)
+                                                ValueType/XS_STRING vval)
+                               (let [{:keys [namespace type value]} vval]
+                                 (if (string? namespace)
+                                   (.setNewVariable acc (name vname) namespace
+                                                    (variable-types type) value)
+                                   (.setNewVariable acc (name vname)
+                                                    (variable-types type) value))))
                              acc)
                            (doto request-factory (.setOptions ro))
                            variables)]


Remove : from wiki-urls

Remove : from wiki-urls

--- src/beebster_clj/core.clj
+++ src/beebster_clj/core.clj
@@ -137,7 +137,7 @@
   "return wikipedia url for search queries."
   [searchterm]
   (let [term (str/replace searchterm #" " "_")]
-    (apply str wiki-search-string term )))
+    (apply str wiki-search-string (str/replace term #":" "") )))

 (def imdb-search-string
   "http://imdb.com/find?q=")


add sha256

add sha256

--- src/block_chain/utils.clj
+++ src/block_chain/utils.clj
@@ -1,7 +1,10 @@
 (ns block-chain.utils
   (:require [cheshire.core :as json]
             [clojure.math.numeric-tower :as math]
+            [pandect.algo.sha256 :as pandect]
             [clojure.java.io :as io]))
+
+(def sha256 pandect/sha256)

 (defn cat-keys
   "take a map and a vector of keys and create a concatenated


fix drop on orig square when move is free

--- src/chessground/ctrl.cljs
+++ src/chessground/ctrl.cljs
@@ -6,25 +6,23 @@

 (defn- move-piece [app [orig dest]]
   "A move initiated through the UI"
-  (or (when (data/can-move? app orig dest)
-        (-> app
-            (data/move-piece orig dest)
-            data/unselect))
-      (when (data/can-premove? app orig dest)
-        (-> app
-            (data/set-premovable-current [orig dest])
-            data/unselect))
-      (if (= orig dest)
-        app
+  (if (= orig dest)
+    app
+    (or (when (data/can-move? app orig dest)
+          (-> app
+              (data/move-piece orig dest)
+              data/unselect))
+        (when (data/can-premove? app orig dest)
+          (-> app
+              (data/set-premovable-current [orig dest])
+              data/unselect))
         (data/set-selected app (when (or (data/movable? app dest)
                                          (data/premovable? app dest))
                                  dest)))))

 (defn select-square [app key]
   (if-let [orig (:selected app)]
-    (if (= orig key)
-      app
-      (move-piece app [orig key]))
+    (move-piece app [orig key])
     (if (or (data/movable? app key) (data/premovable? app key))
       (data/set-selected app key)
       (data/set-premovable-current app nil))))


Slight clode cleanup. Done?

Slight clode cleanup. Done?

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -875,6 +875,8 @@
   (throw (Error. (str "Cannot provide arguments " args " on property access " prop))))

 (defn- build-method-call
+  "Builds the intermediate method call map used to reason about the parsed form during
+  compilation."
   [target meth args]
   (if (symbol? meth)
     {:dot-action ::call :target target :method (munge meth) :args args}


Simplest possible grid.

Simplest possible grid.

--- src/cljs/beatha/core.cljs
+++ src/cljs/beatha/core.cljs
@@ -6,8 +6,8 @@

 (enable-console-print!)

-(def app-state
-  (atom {:cells [{:state :dead} {:state :alive} {:state :alive}]}))
+(def app-state (atom {:grid {:width 10 :height 10}}))
+

 (defn alive-cell-view
   [cell owner]
@@ -31,13 +31,19 @@
 (defmethod cell-view :dead
   [cell owner] (dead-cell-view cell owner))

+
 (defn grid-view
   [data owner]
   (reify
     om/IRender
     (render [_]
-      (apply dom/div #js {:className "grid"}
-             (om/build-all cell-view (:cells data))))))
+      (apply dom/div #js {:className "automaton-grid"}
+             (mapv (fn [y]
+                     (apply dom/div #js {:className "automaton-row"}
+                            (mapv (fn [x] (+ x y))
+                                  (range (get-in data [:grid :width])))))
+                   (range (get-in data [:grid :height])))))))
+

 (om/root grid-view
          app-state


Add key handlers options.

Add key handlers options.

--- src/cljs/quil/applet.cljs
+++ src/cljs/quil/applet.cljs
@@ -12,8 +12,10 @@

 (defn sketch [opts]
-  (let [draw-fn   (or (:draw opts) no-fn)
-        setup-fn  (or (:setup opts) no-fn)]
+  (let [draw-fn       (or (:draw opts) no-fn)
+        setup-fn      (or (:setup opts) no-fn)
+        key-pressed   (or (:key-pressed opts) no-fn)
+        key-released  (or (:key-released opts) no-fn)]
     (fn [prc]
       (set! (.-draw prc)
             (fn []
@@ -25,7 +27,19 @@
               (with-applet prc
                 (when (:size opts)
                   (apply cljs.quil.core/size (:size opts)))
-                (setup-fn)))))))
+                (setup-fn))))
+
+      (set! (.-keyPressed prc)
+            (fn []
+              (with-applet prc
+                (key-pressed))))
+
+      (set! (.-keyReleased prc)
+            (fn []
+              (with-applet prc
+                (key-released))))
+      )
+    ))

 (defn ^:export make-processing


Failing tests for service/equiv? for wrapped indexes

--- test/riemann/index_test.clj
+++ test/riemann/index_test.clj
@@ -4,7 +4,8 @@
         riemann.query
         [riemann.common :only [event]]
         [riemann.time :only [unix-time]]
-        clojure.test))
+        clojure.test)
+  (:require [riemann.service :as service]))

 (deftest missing-time-throws
   (riemann.logging/suppress
@@ -129,3 +130,21 @@
   (testing "two hosts"
     (let [ast (ast "host = \"h1\" and host = \"h2\"")]
       (is (= nil (query-for-host-and-service ast))))))
+
+(deftest service-interface
+  (testing "service equivelance of indexes"
+    (let [one-index (index)
+          two-index (index)]
+      (is (service/equiv? one-index two-index))))
+
+  (testing "service equivelance of wrapped indexes"
+    (let [one-index (wrap-index (index))
+          two-index (wrap-index (index))]
+      (is (service/equiv? one-index two-index))))
+
+  (testing "service equivelance of wrapped to unwrapped index"
+    (let [one-index (wrap-index (index))
+          two-index (index)]
+      (is (service/equiv? one-index two-index))))
+
+  )


test/riemann/xymon_test.clj: service->xymon test suite

--- test/riemann/xymon_test.clj
+++ test/riemann/xymon_test.clj
@@ -12,6 +12,14 @@
                ["foo.example.com" "foo,example,com"]]]
     (doseq [[hostname xymon-hostname] pairs]
       (is (= xymon-hostname (host->xymon hostname))))))
+
+(deftest ^:xymon-service-xymon service->xymon-test
+  (let [pairs [["foo" "foo"]
+               ["service name" "service_name"]
+               ["service.name" "service_name"]
+               ["s   erv..ice" "s___erv__ice"]]]
+    (doseq [[service xymon-service] pairs]
+      (is (= xymon-service (service->xymon service))))))

 (deftest ^:xymon-format event->status-test
   (let [pairs [[{}


Improve docstring

Improve docstring

--- src/caesium/magicnonce/secretbox.clj
+++ src/caesium/magicnonce/secretbox.clj
@@ -18,8 +18,8 @@

   This is only useful if there is an obvious nonce in your protocol
   that can not repeat, you have ways of detecting when your peer
-  repeats nonces, your nonce is not implicitly part of your protocol
-  so you have to specify it as part of the ciphertext, and you can not
+  epeats nonces, your nonce is not implicitly part of your protocol so
+  you have to specify it as part of the ciphertext, and you can not
   afford to use a nonce-misuse resistant scheme. As you can see,
   that's a fairly rare circumstance; this function is mainly used
   internally by other, easier to use schemes in this namespace. Check


Refactoring clean-probs.

Refactoring clean-probs.

--- src/clj/forma/postprocess/output.clj
+++ src/clj/forma/postprocess/output.clj
@@ -36,11 +36,17 @@
   (vector (vec series)))

 (defn backward-looking-mavg
-  "Moving average calculated up to a given element (i.e. looking backwards), rather than starting with a given element. Ensures that only information up to and including given element is incorporated in the moving average.
+  "Moving average calculated up to a given element (i.e. looking backwards),
+   rather than starting with a given element. Ensures that only information up
+   to and including given element is incorporated in the moving average.

-Expanded timeseries includes pre-pended nils. So moving average is actually forward looking, but starting with non-existing (and filtered out) 'prior' nil values.
+   Expanded timeseries includes pre-pended nils. So moving average is actually
+   forward looking, but starting with non-existing (and filtered out) 'prior'
+   nil values.

-Ex. (backward-looking-mavg 3 [1 2 3 4]) expands to [nil nil 1 2 3 4]. Nils are filtered out, so the output is effectively [(average [1]) (average [1 2]) (average [1 2 3]) (average 2 3 4)]"
+   Ex. (backward-looking-mavg 3 [1 2 3 4]) expands to [nil nil 1 2 3 4]. Nils are
+   filtered out, so the output is effectively:
+    [(average [1]) (average [1 2]) (average [1 2 3]) (average 2 3 4)]"
   [window series]
   (let [expanded-ts (concat (repeat (dec window) nil) (flatten series))]
     (map (comp float average (partial filter not-nil?))