Null pointer fix to case when tracker is not found in database. Improved logging.

--- src/ruuvi_server/api.clj
+++ src/ruuvi_server/api.clj
@@ -104,18 +104,41 @@
         (app request)))))

 (defn wrap-create-event-auth
-  "Sets key :create-event-auth"
+"Marks authentication status to request:
+Sets keys
+- :authenticated-tracker, if properly authenticated.
+- :not-authenticated, if client chooses not to use autentication.
+- :unknown-tracker, if client tracker is not known in database.
+- :authentication-failed, autentication was attempted, but macs do not match.
+"
   [app]
   (fn [request]
-    (let [params (request :form-params)]
-      (if (not (params "mac"))
-        (app request)
-        (let [computed-mac (compute-mac params (request :tracker))
-              request-mac (params "mac")]
-          (if (= computed-mac request-mac)
-            (app (merge request {:authenticated-tracker true}))
-            (app request)
-            ))))))
+    (let [params (request :form-params)
+          tracker (request :tracker)]
+      (cond
+       ;; mac not found
+       (not (params "mac")) (do
+                              (.debug logger "Client does not use authentication")
+                              (app (merge request {:not-authenticated true} )))
+       ;; tracker not found in db
+       (not tracker) (do
+                       (.debug logger "Tracker does not exist in system")
+                       (app (merge request {:unknown-tracker true})))
+
+       :else
+       ;; compute mac and compare
+       (let [computed-mac (compute-mac params (request :tracker))
+             request-mac (params "mac")]
+         (if (= computed-mac request-mac)
+           ;; mac matches
+           (do
+             (.debug logger "Tracker is authenticated successfully")
+             (app (merge request {:authenticated-tracker true})))
+           ;; mac not matching
+           (do
+             (.debug logger "Tracker failed authentication")
+             (app (merge request {:authentication-failed true})))
+           ))))))

 (defn wrap-request-logger
   "Logs each incoming request"


4clojure (10-15)

4clojure (10-15)

--- src/sandbox/4clojure.clj
+++ src/sandbox/4clojure.clj
@@ -29,3 +29,18 @@

 ;;10 Intro to Maps
 20
+
+;;11 Maps: conj
+[:b 2]
+
+;;12 Intro to Sequences
+3
+
+;;13 Sequences: rest
+[20 30 40]
+
+;;14 Intro to Functions
+8
+
+;;15 Double Down
+(partial * 2)


Add utilities to trace values inside expressions

--- src/sinusoides/util.cljs
+++ src/sinusoides/util.cljs
@@ -5,8 +5,15 @@
             [om.dom :as dom :include-macros true]))

 (defn trace [obj & more]
-  (apply prn (if more (conj more obj) ["TRACE:" obj]))
-    obj)
+  (apply prn (if more more ["TRACE:"]))
+  (.dir js/console obj)
+  obj)
+
+(defn trace-debug [obj & more]
+  (apply prn (if more more ["TRACE:"]))
+  (.dir js/console obj)
+  (js/eval "debugger")
+  obj)

 (defn to-slug [str]
   (-> str


More clean up in sports

More clean up in sports

--- src/skidskytte/namer.clj
+++ src/skidskytte/namer.clj
@@ -18,7 +18,6 @@
                 "brännboll"
                 "bågskytte"
                 "bänkpress"
-                "casting"
                 "curling"
                 "cykel"
                 "dart"
@@ -159,14 +158,12 @@
                 "tennis"
                 "tjurfäktning"
                 "tyngdlyftning"
-                "trampolin"
                 "slungboll"
                 "slägga"
                 "skidor"
                 "skridsko"
                 "speedway"
                 "spjut"
-                "sprint"
                 "taekwando"
                 "tresteg"
                 "volleyboll"


settings sm breakpoint

settings sm breakpoint

--- src/cljs/swarmpit/component/account_settings.cljs
+++ src/cljs/swarmpit/component/account_settings.cljs
@@ -27,7 +27,7 @@
       [:div.Swarmpit-form
        [:div.Swarmpit-form-toolbar
         (comp/container
-          {:maxWidth  "md"
+          {:maxWidth  "sm"
            :className "Swarmpit-container"}
           (form-password)
           (form-api-access))]])))


Pulled out the drawing into a separate function.

--- src/cljs/wombats_web_client/components/arena.cljs
+++ src/cljs/wombats_web_client/components/arena.cljs
@@ -8,6 +8,34 @@
     (set! (.-onload img) (fn [evt]
       (canvas/draw-image canvas-element evt.srcElement x y width height)))
     (set! (.-src img) url)))
+
+(defn- draw-cell
+  "Draw an arena cell on the canvas"
+  [cell-type x y width height canvas-element]
+  (case cell-type
+
+    :wood-barrier
+      (draw-image canvas-element "images/arena-wall3.png" x y width height)
+
+    :steel-barrier
+      (draw-image canvas-element "images/arena-wall.png" x y width height)
+
+    :food
+      (draw-image canvas-element "images/arena-food.png" x y width height)
+
+    :poison
+      (draw-image canvas-element "images/arena-poison.png" x y width height)
+
+    :zakano
+      (draw-image canvas-element "images/arena-zakano.png" x y width height)
+
+    :wombat
+      (draw-image canvas-element "images/arena-wombat.png" x y width height)
+
+    :open
+      nil
+
+    (js/console.log "Unhandled: " cell)))

 (defn arena
   "Renders the arena on a canvas element, and subscribes to arena updates"
@@ -29,29 +57,6 @@
             (def x-coord (* x width))
             (def y-coord (* y height))

-            (case (get cell :cell-type)
-
-              :wood-barrier
-                (draw-image canvas-element "images/arena-wall3.png" x-coord y-coord width height)
-
-              :steel-barrier
-                (draw-image canvas-element "images/arena-wall.png" x-coord y-coord width height)
-
-              :food
-                (draw-image canvas-element "images/arena-food.png" x-coord y-coord width height)
-
-              :poison
-                (draw-image canvas-element "images/arena-poison.png" x-coord y-coord width height)
-
-              :zakano
-                (draw-image canvas-element "images/arena-zakano.png" x-coord y-coord width height)
-
-              :wombat
-                (draw-image canvas-element "images/arena-wombat.png" x-coord y-coord width height)
-
-              :open
-                nil
-
-              (js/console.log "Unhandled: " cell))))
+            (draw-cell (get cell :cell-type) x-coord y-coord width height canvas-element)

         canvas-element))))


Fix backtracking (but it's not perfect)

Fix backtracking (but it's not perfect)

--- src/spectrace/trace.cljc
+++ src/spectrace/trace.cljc
@@ -193,13 +193,19 @@

 (defn trace [{:keys [path in val pred] :as problem} spec value]
   (letfn [(rec [{:keys [spec] :as state} fail ret]
-            (if (= spec pred)
-              ret
-              (step (assoc state :pred pred)
-                    (fn [{:keys [spec] :as state'} fail]
-                      (let [state' (normalize state')]
-                        #(rec state' fail (conj ret state'))))
-                    (fn [] fail))))]
+            (cond (= spec pred)
+                  ret
+
+                  ;; immature failure condition
+                  (symbol? spec)
+                  fail
+
+                  :else
+                  (step (assoc state :pred pred)
+                        (fn [state' fail]
+                          (let [state' (normalize state')]
+                            #(rec state' fail (conj ret state'))))
+                        (fn [] fail))))]
     (let [state (normalize {:spec spec :path path :val value :in in})]
       (trampoline rec state (constantly nil) [state]))))


Add additional db-client options (timeouts, etc.)

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -81,12 +81,17 @@
 (def ^:private db-client*
   "Returns a new AmazonDynamoDBClient instance for the supplied IAM credentials."
   (memoize
-   (fn [{:keys [access-key secret-key endpoint proxy-host proxy-port] :as creds}]
-     (let [aws-creds     (BasicAWSCredentials. access-key secret-key)
-           client-config (ClientConfiguration.)]
-       (when proxy-host (.setProxyHost client-config proxy-host))
-       (when proxy-port (.setProxyPort client-config proxy-port))
-       (let [client (AmazonDynamoDBClient. aws-creds client-config)]
+   (fn [{:keys [access-key secret-key endpoint proxy-host proxy-port
+               conn-timeout max-conns max-error-retry socket-timeout] :as creds}]
+     (let [aws-creds (BasicAWSCredentials. access-key secret-key)
+           cc        (ClientConfiguration.)]
+       (when proxy-host (.setProxyHost cc proxy-host))
+       (when proxy-port (.setProxyPort cc proxy-port))
+       (when conn-timeout    (.setConnectionTimeout cc (long conn-timeout)))
+       (when max-conns       (.setMaxConnections    cc (long max-conns)))
+       (when max-error-retry (.setMaxErrorRetry     cc (long max-error-retry)))
+       (when socket-timeout  (.setSocketTimeout     cc (long socket-timeout)))
+       (let [client (AmazonDynamoDBClient. aws-creds cc)]
          (when endpoint (.setEndpoint client endpoint))
          client)))))


Update layouts

Update layouts

--- src/server/clojure_template/templates/layouts.clj
+++ src/server/clojure_template/templates/layouts.clj
@@ -12,9 +12,9 @@
           [:title "Application"]
           (include-css "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css")
           (include-css "https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css")
-          (include-css "css/app.css")
+          (include-css "/css/app.css")
           [:body
            content
            (include-js "https://code.jquery.com/jquery-2.2.4.min.js")
            (include-js "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js")
-           (include-js "js/app.js")]]))+           (include-js "/js/app.js")]]))


more tests

more tests

--- src/test/clj/clojure/core/matrix/test_complex.clj
+++ src/test/clj/clojure/core/matrix/test_complex.clj
@@ -9,3 +9,11 @@
     (is (== 1 (cm/real c)))
     (is (== 2 (cm/imag c)))))

+(deftest test-complex-array
+  (let [ca (cm/complex-array [1 2] [3 4])]
+    (is (= [2] (m/shape ca)))
+    (is (m/equals [1 2] (cm/real ca)))
+    (is (m/equals [3 4] (cm/imag ca)))
+    (is (= (c/complex-number 1 3) (m/mget ca 0)))
+    (is (= (c/complex-number 2 4) (m/mget ca 1)))))
+


triverb

triverb

--- src/ontrail/nlp.clj
+++ src/ontrail/nlp.clj
@@ -40,7 +40,7 @@
                "Sähly" "pelasi sählyä"
                "Tanssi" "tanssi"
                "Tennis" "pelasi tennistä"
-               "Triathlon" "juoksi, hiihti ja pyöräili"
+               "Triathlon" "ui, pyöräili ja juoksi"
                "Uinti" "ui"
                "Vaellus" "vaelsi"
                "Venyttely" "venytteli"


no NPE if sport-id is null

no NPE if sport-id is null

--- src/ontrail/nlp.clj
+++ src/ontrail/nlp.clj
@@ -9,7 +9,9 @@
                "Sulkapallo" "sulkapalloili"})

 (defn get-verb [sport-id]
-  (let [verb (get verb-map sport-id)]
-    (if (= nil verb)
-      (str "harrasti lajia " (.toLowerCase sport-id))
-      verb)))+  (if (string? sport-id)
+    (let [verb (verb-map sport-id)]
+      (if (= nil verb)
+        (str "harrasti lajia " (.toLowerCase sport-id))
+        verb))
+    "nil-sport-id"))


More code for azulenoids.clj

More code for azulenoids.clj

--- clojure/org/gavrog/clojure/azulenoids.clj
+++ clojure/org/gavrog/clojure/azulenoids.clj
@@ -31,7 +31,8 @@
 (defn syms-for [ds]
   (if (.isNegative (max-curvature ds))
     []
-    (new DefineBranching2d ds 3 2 Whole/ZERO)))
+    (filter (fn [ds] (= 0 (.curvature2D ds)))
+            (new DefineBranching2d ds 3 2 Whole/ZERO))))

 (def template
   (new DSymbol (str "1.1:60:"
@@ -46,14 +47,31 @@
 (def octagon
   (new DSymbol "1.1:16 1:2 4 6 8 10 12 14 16,16 3 5 7 9 11 13 15:8"))

-(def sets (new CombineTiles octagon))
-
-(def syms (mapcat syms-for sets))
-
 (def boundary-mappings
   (let [start (fn [p] (mod (- 20 p) 16))
-        template-boundary (boundary-chambers template (Integer. 1) 0 1 2)
-        octagon-boundary (cycle (range (Integer. 1) (Integer. 17)))
+        box (fn [i] (Integer. i))
+        template-boundary (boundary-chambers template (box 1) 0 1 2)
+        octagon-boundary (cycle (map box (range 1 17)))
         mapping (fn [p] (zipmap (drop (start p) octagon-boundary)
                                 (take 16 template-boundary)))]
     (map mapping (range 1 16 2))))
+
+(defn apply-to-template [ds oct2tmp]
+  (let [tmp2oct (clojure.set/map-invert oct2tmp)
+        tmp (DynamicDSymbol. template)
+        finish (fn [D]
+                 (if (not (.definesOp tmp 2 D))
+                   (.redefineOp tmp 2 D (oct2tmp (.op ds 2 (tmp2oct D)))))
+                 (if (not (.definesV tmp 1 2 D))
+                   (.redefineV tmp 1 2 D (.v ds 1 2 (tmp2oct D)))))]
+    (doall (map finish (keys tmp2oct)))
+    (-> tmp .dual .minimal .canonical)))
+
+(def octa-sets (new CombineTiles octagon))
+
+(def octa-syms (mapcat syms-for octa-sets))
+
+(def azul-syms-raw
+  (mapcat (fn [ds] (map (partial apply-to-template ds) boundary-mappings))
+          octa-syms))
+


simplify3d.clj: fixed cut-face; refactoring

--- clojure/org/gavrog/clojure/simplify3d.clj
+++ clojure/org/gavrog/clojure/simplify3d.clj
@@ -60,6 +60,11 @@
     (pinch-face ds D E)
     ds))

+(defn- o-range [ds i j start end]
+  (if (= start end)
+    (list end)
+    (lazy-seq (cons start (o-range ds i j (walk ds start i j) end)))))
+
 (defn- local-2-cuts [ds]
   (let [ori (partial-orientation ds)
         faces (vec (orbits ds [0 1]))]
@@ -68,11 +73,13 @@
                 marked (set (for [D f, E (orbit-elements ds [1 2] D)
                                   :when (not (f (s ds 2 E)))] E))]
           j (range (inc i) (count faces))
-          :let [cut (filter #(and (marked %) (pos? (ori %))) (faces j))]
-          :when (<= 2 (count cut))]
-      (apply concat (for [D cut]
-                      [D (first (filter #(and (f %) (pos? (ori %)))
-                                        (orbit-elements ds [1 2] D)))])))))
+          :let [cut (set (filter #(and (marked %) (pos? (ori %))) (faces j)))]
+          :when (<= 2 (count cut))
+          :let [A (first (filter #(not (cut (walk ds % 0 1))) cut))
+                B (first (filter f (o-range ds 2 1 (walk ds A 2 1) A)))
+                C (first (filter cut (o-range ds 0 1 (walk ds A 0 1) A)))
+                D (first (filter f (o-range ds 2 1 (walk ds C 2 1) C)))]]
+      [A B C D])))

 (defn- pinch-tile [ds D E]
   (let [[D* E*] (map (partial s ds 0) [D E])
@@ -86,7 +93,7 @@
   (dsymbol "8:2 4 6 8,3 4 7 8,3 4 7 8,5 6 7 8:2 2,1 1 1 1,2 2"))

 (defn- cut-face [ds D E]
-  (cond (= E (walk ds D 1 0)) [ds (s ds 1 D)]
+  (cond (= E (walk ds D 1 0)) [ds (walk ds D 1 2)]
         (= E (walk ds D 0 1)) [ds D]
         :else
         (let [tmp (append ds wedge)
@@ -106,11 +113,6 @@
                                            [E 1]))]))]
           [(make-dsymbol (dim t) (size t) ops* vs*) d*])))

-(defn- o-range [ds i j start end]
-  (if (= start end)
-    (list end)
-    (lazy-seq (cons start (o-range ds i j (walk ds start i j) end)))))
-
 (defn- liftable? [ds [A B C D]]
   (->> (o-range ds 0 1 A C) (map #(walk ds % 3 1)) (filter #{B D}) count
     (not= 1)))
@@ -121,13 +123,15 @@
 (defn- complexity [ds]
   [(kf-complexity ds) (size ds)])

+(defn- pinch-local-2-cut [ds A B C D]
+  (let [[ds E1] (cut-face ds A C)
+        [ds E2] (cut-face ds D B)
+        ds (pinch-tile ds E1 E2)]
+    (merge-volumes ds)))
+
 (defn pinch-first-local-2-cut [ds]
   (if-let [[A B C D] (first (filter (partial liftable? ds) (local-2-cuts ds)))]
-    (let [[ds E1] (cut-face ds A C)
-          [ds E2] (cut-face ds D B)
-          ds (pinch-tile ds E1 E2)
-          _ (println ds)]
-      (merge-volumes ds))
+    (pinch-local-2-cut ds A B C D)
     ds))

 (defn simplified [ds]


fix q14

fix q14

--- src/puzzule/q14.clj
+++ src/puzzule/q14.clj
@@ -1,3 +1,5 @@
+(ns puzzule.q14)
+
 (def countries_org ["Brazil", "Croatia", "Mexico", "Cameroon", "Spain", "Netherlands",
                    "China", "Australia", "Colombia", "Greece", "Cote d'Ivoire", "Japan",
                    "Uruguay", "Costa Rica", "England", "Italy", "Switzerland", "Euador",


Added event tags for change types.

Added event tags for change types.

--- src/dragon/event/tag.clj
+++ src/dragon/event/tag.clj
@@ -47,4 +47,7 @@
 (def file-change ::file-change)
 (def file-create ::file-create)
 (def file-modify ::file-modify)
-(def file-delete ::file-delete)+(def file-delete ::file-delete)
+(def content-regen ::content-change)
+(def css-regen ::content-change)
+(def system-restart ::content-change)


adding numeric conversion for csv parsing

--- src/spcr/parser.clj
+++ src/spcr/parser.clj
@@ -1,6 +1,20 @@
 (ns spcr.parser
   (:require [clojure.data.csv :as csv]
             [clojure.java.io :as io]))
+
+;;move to new utils namespace
+(defn numeric? [s]
+  (if-let [s (seq s)]
+    (let [s (if (= (first s) \-) (next s) s)
+          s (drop-while #(Character/isDigit %) s)
+          s (if (= (first s) \.) (next s) s)
+          s (drop-while #(Character/isDigit %) s)]
+      (empty? s))))
+
+(defn cast-numerics [str]
+  (if (numeric? str)
+    (Float. str)
+    str))

 (defn file->list [path]
   (with-open [input-file (io/reader path)]
@@ -9,7 +23,7 @@

 (defn list->dicts [[header & body]]
   (let [keys (map keyword header)]
-    (map #(zipmap keys %)
+    (map #(zipmap keys (map cast-numerics %))
          body)))

 (defn file->dicts [path]


Fix benchmark.

Fix benchmark.

--- test/clojure_method_call_benchmark/benchmarks.clj
+++ test/clojure_method_call_benchmark/benchmarks.clj
@@ -262,7 +262,7 @@
   (let [t (->MyType 1)]
     (cc/with-progress-reporting
       (cc/quick-bench
-        (bar t 2)
+        (.bar t 2)
         :verbose))))

 (deftest type-self-fn


adding newlines to all the h1-h5 and p tags and removing the \newline at the top of the file

--- src/watney/core.clj
+++ src/watney/core.clj
@@ -39,13 +39,15 @@
          (->> html-tree
               (map (fn [node]
                      (case (:tag node)
-                       :h1 (str "# " (convert-content node))
-                       :h2 (str "## " (convert-content node))
-                       :h3 (str "### " (convert-content node))
-                       :h4 (str "#### " (convert-content node))
+                       :h1 (str "\n# " (convert-content node))
+                       :h2 (str "\n## " (convert-content node))
+                       :h3 (str "\n### " (convert-content node))
+                       :h4 (str "\n#### " (convert-content node))
                        :p  (str "\n" (convert-content node))
                        :a  (str "[" (first (:content node)) "](" (:href (:attrs node)) ")")
                        :img (str "![" (:alt (:attrs node)) "](" (:src (:attrs node)) ")")
+
+                       :ul (str "\n" (convert-entity (:content node) 0))

                        ;; if any of the children of this :li is a :ul, then return 2 spaces here
                        :li (if (contains-node? (:content node) :ul)
@@ -64,14 +66,23 @@
               (remove empty?)
               (str/join "\n")))))

+(defn ^:private without-first-character
+  "Returns the content string without the first character"
+  [content]
+  (->> content
+       rest
+       (apply str)))
+
 (defn convert
   "Convert the HTML string given into Markdown"
   [html-string]
   (-> html-string
       parse
       (convert-entity 0)
-      (str "\n")))
-
+      (str "\n")
+
+      ;; remove the first newline character (top of the file) introduced when converting the html
+      without-first-character))


More correct solution to binding parent shadow var

--- src/derive/core.clj
+++ src/derive/core.clj
@@ -4,16 +4,16 @@
   "Evaluate the body, tracking dependencies, and call the handler
    with a map of {src dep} and result"
   [[handler & [shadow?]] & body]
-  `(binding [derive.core/*tracker* (if derive.core/*shadow*
-                                     derive.core/*tracker*
-                                     (derive.core/default-tracker))
-             parent-shadow?#      derive.core/*shadow*
-             derive.core/*shadow* (or derive.core/*shadow* ~shadow?)]
-     (let [result# (do ~@body)]
-       (when-not parent-shadow?#
-         (let [dmap# (derive.core/dependencies derive.core/*tracker*)]
-           (~handler result# dmap#)))
-       result#)))
+  `(let [parent-shadow# derive.core/*shadow*]
+     (binding [derive.core/*tracker* (if derive.core/*shadow*
+                                       derive.core/*tracker*
+                                       (derive.core/default-tracker))
+               derive.core/*shadow* (or derive.core/*shadow* ~shadow?)]
+       (let [result# (do ~@body)]
+         (when-not parent-shadow#
+           (let [dmap# (derive.core/dependencies derive.core/*tracker*)]
+             (~handler result# dmap#)))
+         result#))))

 (defmacro on-changes
   "Useful in contexts like an om render loop where we simply


Allow explicit source dir parameter.

Allow explicit source dir parameter.

--- src/dragon/blog.clj
+++ src/dragon/blog.clj
@@ -70,10 +70,12 @@
    :posts auth-data})

 (defn get-posts
-  []
-  (map (fn [x]
-         {:file x})
-       (util/get-files (config/posts-path-))))
+  ([]
+    (get-posts "posts"))
+  ([posts-path]
+    (map (fn [x]
+           {:file x})
+         (util/get-files posts-path))))

 (defn process
   [uri-base]


Add equality check for local mixin for avoid rerenders.

--- src/uxbox/ui/mixins.cljs
+++ src/uxbox/ui/mixins.cljs
@@ -119,8 +119,9 @@
       (let [local-state (atom initial)
             component   (:rum/react-component state)]
         (add-watch local-state key
-                   (fn [_ _ _ _]
-                     (rum/request-render component)))
+                   (fn [_ _ oldv newv]
+                     (when (not= oldv newv)
+                       (rum/request-render component))))
         (assoc state key local-state)))
     }))


Performance improvements on attrs transformations on render.

--- src/uxbox/ui/shapes.cljs
+++ src/uxbox/ui/shapes.cljs
@@ -15,11 +15,8 @@
 ;; Attribute transformations
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn- extract-style-attrs
-  "Extract predefinet attrs from shapes."
-  [shape]
-  (select-keys shape [:fill :opacity :stroke :stroke-opacity :stroke-width
-                      :stroke-type]))
+(def ^:static ^:private +style-attrs+
+  #{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type})

 (defn- transform-stroke-type
   [attrs]
@@ -28,14 +25,17 @@
                   :dotted "1,1"
                   :dashed "10,10")]
       (-> attrs
-          (assoc :stroke-dasharray value)
-          (dissoc :stroke-type)))
+          (assoc! :stroke-dasharray value)
+          (dissoc! :stroke-type)))
     attrs))

-(defn- transform-attrs
-  [attrs]
-  (-> attrs
-      (transform-stroke-type)))
+(defn- extract-style-attrs
+  "Extract predefinet attrs from shapes."
+  [shape]
+  (let [attrs (select-keys shape +style-attrs+)]
+    (-> (transient attrs)
+        (transform-stroke-type)
+        (persistent!))))

 (defn- make-debug-attrs
   [shape]
@@ -52,12 +52,9 @@
   [{:keys [data id] :as shape} _]
   (let [key (str id)
         rfm (svg/calculate-transform shape)
-        attrs (-> (extract-style-attrs shape)
-                  (transform-attrs))
         attrs (merge {:id key :key key :transform rfm}
-                     ;; (select-keys shape [:x :y :width :height])
-                     (make-debug-attrs shape)
-                     attrs)]
+                     (extract-style-attrs shape)
+                     (make-debug-attrs shape))]
     (html
      [:g attrs data])))

@@ -66,7 +63,6 @@
   (let [key (str id)
         props (select-keys shape [:x1 :x2 :y2 :y1])
         attrs (-> (extract-style-attrs shape)
-                  (transform-attrs)
                   (merge {:id key :key key})
                   (merge props))]
     (html


Remove function stub

Remove function stub

--- src/extremo/db.cljs
+++ src/extremo/db.cljs
@@ -4,8 +4,6 @@
 (def path (js/require "path"))

 (def repo-path "./content/notes/.git")
-
-(defn build-fild-data [file blob])

 (defn open-repo []
   (-> (.resolve path "./content/notes/.git")


Add a couple more ring optimizations

Add a couple more ring optimizations

Remove some unnecessary delay usages and optimize for
the common case of headers with only a single value.

--- web/src/immutant/web/undertow/http.clj
+++ web/src/immutant/web/undertow/http.clj
@@ -42,9 +42,11 @@
     (fn [accum ^HttpString header-name]
       (assoc accum
         (-> header-name .toString .toLowerCase)
-        (->> header-name
-          (.get headers)
-          (str/join ","))))
+        (if (> 1 (.count headers header-name))
+          (->> header-name
+            (.get headers)
+            (str/join ","))
+          (.getFirst headers header-name))))
     {}
     (.getHeaderNames headers)))

@@ -59,12 +61,12 @@
                :query-string (delay (.getQueryString exchange))
                :scheme (delay (-> exchange .getRequestScheme keyword))
                :request-method (delay (-> exchange .getRequestMethod .toString .toLowerCase keyword))
-               :content-type @content-type
+               :content-type content-type
                :content-length (delay (.getRequestContentLength exchange))
-               :character-encoding (delay (if @content-type
-                                            (Headers/extractTokenFromHeader @content-type "charset")))
+               :character-encoding (delay (if content-type
+                                            (Headers/extractTokenFromHeader content-type "charset")))
                ;; TODO: :ssl-client-cert
-               :headers (delay (headers->map @headers))
+               :headers (delay (headers->map headers))
                :body (delay (.getInputStream exchange))})))

 (defn- merge-headers [^HeaderMap to-headers from-headers]


Update docstring to reflect latest changes

--- src/fqcss/core.cljc
+++ src/fqcss/core.cljc
@@ -65,7 +65,7 @@
   (atom {}))

 (defn- replace-css-classes
-  "replace-css helper. Replaces the CSS classes ({app.example/something} -> .something--PG__1)"
+  "replace-css helper. Replaces the CSS classes ({app.example/something} -> .something__-301316910)"
   [css]
   (let [matches (re-seq #"\{[a-zA-Z0-9\-\.\/]*?\}" css)]
     (reduce (fn [acc item]


tidy up org grant permission endpoint and add a little more validation.

--- src/metabase/api/org.clj
+++ src/metabase/api/org.clj
@@ -59,9 +59,11 @@
         (hydrate :user :organization))))

-(defendpoint POST "/:org-id/members" [org-id :as {{:keys [first_name last_name email orgId admin]} :body}]
-  (check (= org-id orgId) 400 (format "Org IDs don't match: %d != %d" org-id orgId)) ; why do we need to POST Org ID if it's already in the URL????
-  (let-404 [{:keys [can_write] :as org} (sel :one Org :id org-id)]
+(defendpoint POST "/:id/members" [id :as {{:keys [first_name last_name email admin]} :body}]
+  ; we require 4 attributes in the body
+  (check-400 (and first_name last_name email admin))
+  ; user must have admin perms on org to proceed
+  (let-404 [{:keys [can_write] :as org} (sel :one Org :id id)]
     (check-403 @can_write)
     (let [user-id (:id (or (sel :one [User :id] :email email)                        ; find user with existing email - if exists then grant perm
                            (ins User
@@ -69,9 +71,9 @@
                              :first_name first_name
                              :last_name last_name
                              :password (str (java.util.UUID/randomUUID)))))]         ; TODO - send welcome email
-      (grant-org-perm org-id user-id admin)
-      (-> (sel :one OrgPerm :user_id user-id :organization_id org-id)
-          (hydrate :user)))))
+      (grant-org-perm id user-id admin)
+      (-> (sel :one OrgPerm :user_id user-id :organization_id id)
+          (hydrate :user :organization)))))

 (defendpoint POST "/:id/members/:user-id" [id user-id :as {body :body}]


refactor

refactor

--- src/zmq_clj/rrbroker.clj
+++ src/zmq_clj/rrbroker.clj
@@ -4,7 +4,7 @@

 (defn -main [ ]
   (let [ context (zmq/context 1)
-         poller (zmq/poller context 2) ]
+         poller (-> context (zmq/poller 2)) ]
     (with-open [ frontend (-> context (zmq/socket :router) ; fair queueing
                             (zmq/bind "tcp://*:5559")) ; async server
                  backend (-> context (zmq/socket :dealer) ; distributed load balancing


Fixing access group search.

Fixing access group search.

--- access-control-app/src/cmr/access_control/data/access_control_index.clj
+++ access-control-app/src/cmr/access_control/data/access_control_index.clj
@@ -91,6 +91,10 @@
   [_]
   {:provider :provider-id})

+(defmethod q2e/field->lowercase-field-mappings :access-group
+  [_]
+  {:provider "provider-id.lowercase"})
+
 (defmethod esi/concept-type->index-info :access-group
   [context _ _]
   {:index-name group-index-name


typo - fixes #104

typo - fixes #104

--- src/node/game/cards.cljs
+++ src/node/game/cards.cljs
@@ -274,7 +274,7 @@
    {:effect (effect (gain :memory 2)) :leave-play (effect (lose :memory 2))}

    "D4v1d"
-   {:data {:counter 3} :abilities [{:counter-cost 1 :msg "break 1 suroutine"}]}
+   {:data {:counter 3} :abilities [{:counter-cost 1 :msg "break 1 subroutine"}]}

    "Daily Business Show"
    {:events {:corp-draw


Increase poll time to improve test reliability

--- src/onyx/kafka/utils.clj
+++ src/onyx/kafka/utils.clj
@@ -40,7 +40,7 @@
      (let [c (make-consumer zk-addr)]
        (assign-partitions! c [{:topic topic :partition 0}])
        (loop [results []]
-         (let [msgs (into [] (poll! c))
+         (let [msgs (into [] (poll! c {:poll-timeout-ms 5000}))
                segments
                (map #(consumer-record->message decompress-fn %) msgs)]
            (if (= :done (:value (last segments)))
@@ -54,7 +54,7 @@
   (log/info {:msg "Taking now..." :topic topic})
   (let [c (make-consumer zk-addr)]
     (assign-partitions! c [{:topic topic :partition 0}])
-    (mapv #(consumer-record->message decompress-fn %) (poll! c))))
+    (mapv #(consumer-record->message decompress-fn %) (poll! c {:poll-timeout-ms 5000}))))

 (defn take-segments
   "Reads segments from a topic until a :done is reached."


Add missing } in docstring

Add missing } in docstring

--- src/overtone/sc/node.clj
+++ src/overtone/sc/node.clj
@@ -49,7 +49,7 @@
   (node \"foo\")
   (node \"foo\" {:pitch 60})
   (node \"foo\" {:pitch 60} {:target 0})
-  (node \"foo\" {:pitch 60  {:target 2 :position :tail})
+  (node \"foo\" {:pitch 60} {:target 2 :position :tail})
   "
   ([synth-name arg-map] (node synth-name arg-map {:position :tail, :target 0}))
   ([synth-name arg-map location]


More env var refactor

More env var refactor

--- src/polismath/server.clj
+++ src/polismath/server.clj
@@ -442,8 +442,8 @@
       (log/info "SERVER_REQUIRE_SSL unset; ssl not being required.")
       handler)))

-;; config env var?
-(def valid-remote-addresses #{"pol.is" "preprod.pol.is" "127.0.0.1" "polis.herokuapp.com" "polis-preprod.herokuapp.com"})
+;; Should add to component
+(def valid-remote-addresses (-> env/env :valid-remote-addresses (clojure.string/split #"\s+")))
 (defn restrict-remote-address
   [handler]
   (fn [request]


write directory token probabilities to a files

--- src/quark/slp_runner.clj
+++ src/quark/slp_runner.clj
@@ -15,7 +15,8 @@
             ))

 (defn pair->vec [p] [(.left p) (.right p)])
-(def pairlist->map (%->> .iterator iterator-seq (map pair->vec) (into {})))
+(def pairlist->seq (%->> .iterator iterator-seq (map pair->vec)))
+(def pairlist->map (%->> pairlist->seq (into {})))

 (defn init-java-lexer []
   (doto (LexerRunner. (JavaLexer.))
@@ -28,8 +29,8 @@
     (.perLine false)
     (.selfTesting self-test)))

-(defn ngram-java
-  ([train-path] (ngram-java train-path train-path))
+(defn ngram-dir
+  ([train-path] (ngram-dir train-path train-path))
   ([train-path test-path]
    (let [train-set (java.io.File. (expand-home train-path))
          test-set (java.io.File. (expand-home test-path))
@@ -44,7 +45,8 @@

        {:model model
         :model-runner model-runner
-        :modeled-files (-> model-runner (.model model test-set) pairlist->map)}
+        ;:modeled-files (-> model-runner (.model model test-set) pairlist->map)
+        }
        ))))

 ;(def dir-path (expand-home "~/atom-finder/src/java"))
@@ -52,11 +54,12 @@
 (def dir-path (expand-home "~/opt/src/atom-finder"))
 (def dir-file (->> dir-path java.io.File.))

-(def ngram-res (time-mins (ngram-java dir-path)))
+;; 5 mins on all of atom-finder corpus if modeled results are not calculated/returned
+(def ngram-res (time-mins (ngram-dir dir-path)))

-(def statistics (-> ngram-res :model-runner (.getStats (-> ngram-res :modeled-files))))
+;(def statistics (-> ngram-res :model-runner (.getStats (-> ngram-res :modeled-files))))

-(printf "Modeled %d tokens, average entropy:\t%.4f\n" (.getCount statistics) (.getAverage statistics))
+;(printf "Modeled %d tokens, average entropy:\t%.4f\n" (.getCount statistics) (.getAverage statistics))

 (defn random-split [amount lst]
   (let [shuffled-lst (shuffle lst)]
@@ -95,19 +98,27 @@
         model-runner (init-modeler lexer :self-test true)]
     (->> dir-file
          (.model model-runner model)
-         pairlist->map
-         (take 10)
+         pairlist->seq
          (mapcat (fn [[file problist]]
                    (map-indexed (fn [idx probs]
                                   {:file (-<>> file .getPath (str/replace <> dir-path ""))
                                    :line (inc idx)
                                    :probability probs})
                                 problist)))
-         (maps-to-csv "atom-finder-token-probabilities.csv"))))
+         )))
+
+(defmacro ignore-output
+  [& block]
+  `(with-open [w# (clojure.java.io/writer "/dev/null")]
+    (binding [*out* w#, *err* w#]
+      ~@block)))

 (->> ngram-res :model
      model-all-lines
-     (map (fn [[file line]]
+     (maps-to-csv "atom-finder-token-probabilities.csv")
+     ignore-output)
+
+     '((map (fn [[file line]]
             (print-line-context 0 (str dir-path "/" file) line :top-border false)
             (println "\n")))
      time-mins


Made maps simpler

Made maps simpler

--- src/re_com/validate.cljs
+++ src/re_com/validate.cljs
@@ -3,12 +3,21 @@
              [re-com.util           :refer [deref-or-value]]
              [reagent.impl.template :refer [valid-tag?]]))

+
+;; -- Global Switch ------------------------------------------------------------------------------------
+
+;; if true, then validation occurs.
+;; It is expected that will be flicked to off, in production systems.
 (defonce arg-validation (atom true))

-(defn set-validation
+
+(defn set-validation!
   "Turns argument validation on or off based on a boolean argument."
   [val]
   (reset! arg-validation val))
+
+
+;; -- Helpers ------------------------------------------------------------------------------------

 (defn left-string
   "Converts obj to a string and truncates it to max-len chars if necessary.
@@ -35,10 +44,10 @@
   [args-desc]
   {:names       (set (map :name args-desc))
    :required    (->> args-desc
-                     (filter #(:required %))
+                     (filter :required)
                      (map :name)
                      set)
-   :validate-fns (filter #(:validate-fn %) args-desc)})
+   :validate-fns (filter :validate-fn args-desc)})

 ;; ----------------------------------------------------------------------------
 ;; Primary validation functions


Improve message formatting and fn descriptions

--- src/riemann/campfire.clj
+++ src/riemann/campfire.clj
@@ -1,6 +1,6 @@
 (ns riemann.campfire
   "Forwards events to Campfire"
-  (:use [clojure.string :only [join]])
+  (:use [clojure.string :only [join upper-case]])
   (:require [clj-campfire.core :as cf]))

 (defn cf-settings
@@ -15,15 +15,15 @@
   [settings room-name]
   (cf/room-by-name settings room-name))

-(defn format_string
+(defn campfire_message
+  "Formats an event into a string"
   [e]
-  (str (join " " ["HOST:" (str (:host e)) "SERVICE:" (str (:service e)) "STATE:" (str (:state e)) "DESC:" (str (:description e))]))
-  )
+  (str (join " " ["Riemann alert on" (str (:host e)) "-" (str (:service e)) "is" (upper-case (str (:state e))) "- Description:" (str (:description e))])))

 (defn campfire
-  "Creates an adaptor to forward events to campfire.
-  TODO: write more here once the event formatting is better.
-  TODO: tests
+  "Creates an adaptor to forward events to campfire. The campfire event will
+  contain the host, state, service, metric and description.
+
   Tested with:
   (streams
     (by [:host, :service]
@@ -31,7 +31,6 @@
         camp)))"
   [token ssl sub-domain room-name]
   (fn [e]
-    (let [string (format_string e)
-          settings (cf-settings token ssl sub-domain)
-          ]
+    (let [string (campfire_message e)
+          settings (cf-settings token ssl sub-domain)]
       (cf/message (room settings room-name) string))))


Very basic reading of config.

Very basic reading of config.

We should probably also read in extension config from another location.

--- src/staircase/config.clj
+++ src/staircase/config.clj
@@ -3,7 +3,7 @@
         [clojure.string :only (replace-first)])
   (:require [clojure.tools.reader.edn :as edn]))

-(defn from-edn [fname]
+(defn- from-edn [fname]
   (if-let [is (io/resource fname)]
     (with-open [rdr (-> is
                         io/reader
@@ -11,10 +11,10 @@
       (edn/read rdr))
     (throw (IllegalArgumentException. (str fname " not found")))))

-(defn config [env]
-  (let [conf (from-edn "config.edn")
-        env-conf (conf env)]
-    (merge-with merge (:default conf) env-conf)))
+(def configuration (delay (from-edn "config.edn")))
+
+(defn config [k]
+  (k @configuration))

 (defn- options [opts prefix]
   (->> opts


Clarify some instructions

Clarify some instructions

--- webapp/src/org/teamweek/webapp/endpoint/views.clj
+++ webapp/src/org/teamweek/webapp/endpoint/views.clj
@@ -70,7 +70,7 @@

                      (form/label "schedule_cron" "Cron expression")
                      (form/text-field "schedule_cron" "")])
-            (list (form/label "schedule_cron" "Cron expression (use a cron expression like
0 0 12 ? * FRI *
 to get the checkboxes back):")
+            (list (form/label "schedule_cron" "(use the following expression to get the checkboxes back)
0 0 12 ? * FRI *
")
                   (form/text-field "schedule_cron" schedule)))]
           (form/label "members" "Members:")
           (form/text-area {:style "width: 100%; height: 150px;"}


(SERVER-547) Fix test assertions

(SERVER-547) Fix test assertions

--- test/unit/puppetlabs/services/legacy_routes/legacy_routes_core_test.clj
+++ test/unit/puppetlabs/services/legacy_routes/legacy_routes_core_test.clj
@@ -124,8 +124,10 @@
                     "certificate_requests"]]
         (let [resp (request (str "/" environment "/" path "/" route-val))]
           (is (= 200 (:status resp)))
-          (is (= (str ca-mount "/" ca-api-version "/" path "/" route-val)))
-          (is (= (ring-codec/form-encode {:environment environment}))))))))
+          (is (= (str ca-mount "/" ca-api-version "/" path "/" route-val)
+                 (:uri resp)))
+          (is (= (ring-codec/form-encode {:environment environment})
+                 (:query-string resp))))))))

 (deftest test-v3-header-munging
   (testing "(SERVER-548) Header munging"


debugger: Load->Open; removed dead code

debugger: Load->Open; removed dead code

--- examples/_common/middleware/devtools.cljs
+++ examples/_common/middleware/devtools.cljs
@@ -167,9 +167,6 @@

                  (record-and-dispatch-to-app :on-stop nil))

-               ::on-did-load-from-storage
-               (dispatch-action ::replay)
-
                [::on-toggle-signal id]
                (do
                  (dispatch-action [::toggle-signal id])
@@ -203,7 +200,7 @@
                ::on-save
                (-save-file "debugger-session.txt" (with-out-str (cljs.pprint/pprint @model)))

-               [::on-load content]
+               [::on-open content]
                (dispatch-action [::load (cljs.reader/read-string content)])

                [::on-highlight-signal id]
@@ -386,8 +383,8 @@
    [-menu-button {} "Clear" #(dispatch ::on-clear) "Clears debugger history"]
    [-menu-button {} "Vacuum" #(dispatch ::on-vacuum) "Removes disabled actions and signals with no actions from history"]
    [-menu-button {} "Reset" #(dispatch ::on-reset) "Removes all actions and signals resetting the model to initial state"]
+   [-menu-file-selector "Open" #(dispatch [::on-open %]) "Loads debugger session from file (without replaying)"]
    [-menu-button {} "Save" #(dispatch ::on-save) "Saves current debugger session into file"]
-   [-menu-file-selector "Load" #(dispatch [::on-load %]) "Loads debugger session from file (without replaying)"]
    [-menu-button (if replay-mode? {:color -color-replay} {:color "grey"}) "Replay⥀" #(dispatch ::on-toggle-replay-mode) "Replay current session before next app start?"]
    [-menu-button {} "Hide" #(dispatch ::on-toggle-visibility) (str "Hides debugger view (" toggle-visibility-shortcut ")")]])


Test to verify repl does not compile clojure

--- modules/gradle-clojure-plugin/src/compatTest/clojure/gradle_clojure/compat_test/repl.clj
+++ modules/gradle-clojure-plugin/src/compatTest/clojure/gradle_clojure/compat_test/repl.clj
@@ -68,3 +68,15 @@
     (with-client [client "CiderTest" "--handler=cider.nrepl/cider-nrepl-handler"]
       (is (= "0.17.0" (-> (send-repl client {:op "cider-version"}) :cider-version :version-string)))
       (is (pr-str 7) (eval-repl client '(do (require 'basic-project.core) (basic-project/use-ns 4)))))))
+
+(deftest task-dependencies
+  (testing "No Clojure compiles happen when REPL is requested, but other languages are compiled"
+    (gradle/with-project "MixedJavaClojureTest"
+      (let [result (gradle/build "clojureRepl" "--dry-run")]
+        (is (str/includes? (.getOutput result) ":compileJava SKIPPED"))
+        (is (not (str/includes? (.getOutput result) ":compileClojure SKIPPED")))
+        (is (not (str/includes? (.getOutput result) ":compileTestClojure SKIPPED")))
+        (is (not (str/includes? (.getOutput result) ":compileDevClojure SKIPPED")))
+        (is (not (str/includes? (.getOutput result) ":compileClojurescript SKIPPED")))
+        (is (not (str/includes? (.getOutput result) ":compileTestClojurescript SKIPPED")))
+        (is (not (str/includes? (.getOutput result) ":compileDevClojurescript SKIPPED")))))))


add examples to docstring of collection parsers

--- src/keypin/util.clj
+++ src/keypin/util.clj
@@ -139,7 +139,10 @@

 (defn str->vec
-  "Given a delimited text, tokenize it and return a vector of tokens. By default, the delimiter is a comma."
+  "Given a delimited text, tokenize it and return a vector of tokens. By default, the delimiter is a comma.
+  Example:
+  => (str-vec :foo \"a, b, c\")
+  [\"a\" \"b\" \"c\"]"
   ([tokenizer the-key text]
     (str->coll tokenizer identity the-key text))
   ([the-key text]
@@ -148,7 +151,10 @@

 (defn str->map
   "Given a delimted text, where each token is a delimited pair text, tokenize it and return a map of tokens. By default,
-  the pair delimiter is a comma and the key-value delimiter is a colon."
+  the pair delimiter is a comma and the key-value delimiter is a colon.
+  Example:
+  => (str->map :foo \"a: 10, b: 20, c: 30\")
+  {\"a\" \"10\" \"b\" \"20\" \"c\" \"30\"}"
   ([pair-tokenizer kv-tokenizer the-key text]
     (str->coll
       pair-tokenizer
@@ -172,7 +178,12 @@

 (defn str->nested
   "Given a delimited text, where each token is again a delimited text, tokenize it and return a vector of nested
-  vectors of tokens. By default, the outer delimiter is a comma and the inner delimiter is a colon."
+  vectors of tokens. By default, the outer delimiter is a comma and the inner delimiter is a colon.
+  Example:
+  => (str->nested :foo \"joe: 30: male, sue: 35: female, max: 40: male\")
+  [[\"joe\" \"30\" \"male\"]
+   [\"sue\" \"35\" \"female\"]
+   [\"max\" \"40\" \"male\"]]"
   ([outer-tokenizer inner-tokenizer the-key text]
     (str->coll
       outer-tokenizer
@@ -185,7 +196,12 @@

 (defn str->tuples
   "Given a delimited text, where each token is again a delimited text, tokenize it and return a vector of maps. By
-  default, the outer delimiter is a comma and the inner delimiter is a colon."
+  default, the outer delimiter is a comma and the inner delimiter is a colon.
+  Example:
+  => (str->tuples [:name :age :gender] :foo \"joe: 30: male, sue: 35: female, max: 40: male\")
+  [{:name \"joe\" :age \"30\" :gender \"male\"}
+   {:name \"sue\" :age \"35\" :gender \"female\"}
+   {:name \"max\" :age \"40\" :gender \"male\"}]"
   ([outer-tokenizer inner-tokenizer ks the-key text]
     (->> (str->nested outer-tokenizer inner-tokenizer the-key text)
       (mapv #(zipmap ks %))))


Parse the notifier section of the config. Fixes a bug w/ email

--- backend/src/circle/backend/project/circle.clj
+++ backend/src/circle/backend/project/circle.clj
@@ -67,6 +67,12 @@
    (string? cmd) (bash cmd)
    (map? cmd) (parse-action-map cmd)))

+(defn parse-notify [notifies]
+  (for [n notifies]
+    (if (re-find #"^:" n)
+      (keyword (.substring n 1))
+      n)))
+
 (defn fetch-data [num name]
   "Return a build object by combining config files, db contents and defaults"
   (let [config (circle-read-config-file)
@@ -75,7 +81,7 @@
         after (map #(apply % []) (-> known-actions name :suffix))
         config-data {:build-num num
                      :actions (concat before actions after)
-                     :notify-email (-> config name :notify-email)}]
+                     :notify-email (-> config name :notify-email (parse-notify))}]
     (merge config-data circle-db-data)))

 (defn circle-build []


Add the ability to pass parameters to lightboxes.

--- frontend/uxbox/ui/lightbox.cljs
+++ frontend/uxbox/ui/lightbox.cljs
@@ -12,9 +12,11 @@

 (defonce +current+ (atom nil))

-(defn set!
-  [kind]
-  (reset! +current+ kind))
+(defn open!
+  ([kind]
+   (open! kind nil))
+  ([kind params]
+   (reset! +current+ (merge {:name kind} params))))

 (defn close!
   []
@@ -24,7 +26,7 @@
 ;; UI
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defmulti render-lightbox identity)
+(defmulti render-lightbox :name)
 (defmethod render-lightbox :default [_] nil)

 (defn- on-esc-clicked
@@ -33,30 +35,34 @@
     (close!)))

 (defn- lightbox-will-mount
-  [state]
-  (events/listen js/document
-                 EventType.KEYDOWN
-                 on-esc-clicked)
-  state)
+  [own]
+  (let [key (events/listen js/document
+                           EventType.KEYDOWN
+                           on-esc-clicked)]
+    (assoc own ::eventkey key)))

 (defn- lightbox-will-umount
-  [state]
-  (events/unlisten js/document
-                   EventType.KEYDOWN
-                   on-esc-clicked)
-  state)
+  [own]
+  (let [key (::eventkey own)]
+    (events/unlistenByKey key)
+    (dissoc own ::eventkey)))
+
+(defn- lightbox-transfer-state
+  [old-own own]
+  (assoc own ::eventkey (::eventkey old-own)))

 (defn- lightbox-render
   [own]
-  (let [name (rum/react +current+)]
+  (let [params (rum/react +current+)]
     (html
-     [:div.lightbox {:class (when (nil? name) "hide")}
-      (render-lightbox name)])))
+     [:div.lightbox {:class (when (nil? params) "hide")}
+      (render-lightbox params)])))

 (def ^:static lightbox
   (util/component
    {:name "lightbox"
     :render lightbox-render
+    :transfer-state lightbox-transfer-state
     :will-mount lightbox-will-mount
     :will-unmount lightbox-will-umount
     :mixins [rum/reactive]}))


Rewrite contains-any?

Rewrite contains-any?

--- src/str/core.clj
+++ src/str/core.clj
@@ -270,18 +270,10 @@
 (defn ^String contains-any?
   "Return s if s contains any of the needles."
   ([^String s needles]
-   (loop [needles needles]
-     (when (seq needles)
-       (if (case-sensitive-contains s (first needles))
-         s
-         (recur (rest needles))))))
+   (some (partial case-sensitive-contains s) needles))
   ([^String s needles ignore-case]
    (if ignore-case
-     (loop [needles needles]
-       (when (seq needles)
-         (if (case-insensitive-contains s (first needles))
-           s
-           (recur (rest needles)))))
+     (some (partial case-insensitive-contains s) needles)
      (contains-any? s needles))))

 (defn ^String truncate


Update post conditions for {camel,pascal}-case

The result can never be nil

--- src/str/core.clj
+++ src/str/core.clj
@@ -422,7 +422,7 @@
   This is also referred to as kebab-case in some circles."
   [^String s]
   {:pre [(string? s)]
-   :post [(or (nil? %) (string? %))]}
+   :post [(string? %)]}
   (join "-" (map lower-case (split-words s))))

 (defn ^String camel-case
@@ -433,6 +433,6 @@
   PascalCase => pascalCase"
   [^String s]
   {:pre [(string? s)]
-   :post [(or (nil? %) (string? %))]}
+   :post [(string? %)]}
   (let [words (split-words s)]
     (join ""  (conj (map capitalize (rest words)) (lower-case (first words))))))


Fix exampels in screaming-snake-case docstring

--- src/str/core.clj
+++ src/str/core.clj
@@ -445,9 +445,9 @@
 (defn ^String screaming-snake-case
   "Upper case s and use underscores to separate words.

-  foo bar => foo_bar
-  camelCase => camel_case
-  PascalCase => pascal_case"
+  foo bar => FOO_BAR
+  camelCase => CAMEL_CASE
+  PascalCase => PASCAL_CASE"
   [^String s]
   {:pre [(string? s)]
    :post [(string? %)]}


dsl: sane defaults for scenarios

dsl: sane defaults for scenarios

--- src/warp/dsl.clj
+++ src/warp/dsl.clj
@@ -50,7 +50,12 @@

 (defn scenario*
   [script-name directives]
-  (reduce merge {:name (name script-name)} directives))
+  (reduce merge
+          {:timeout  120
+           :matcher  {:type :none}
+           :profiles {}
+           :name     (name script-name)}
+          directives))

 (defn profiles
   [& profiles]


Adding a cache to speed it up to textgen.

Atom cache maps sentences to generated text, instead of constantly
regenerating the text.

--- wysitutwyg/src-cljs/wysitutwyg/textgen.cljs
+++ wysitutwyg/src-cljs/wysitutwyg/textgen.cljs
@@ -1,6 +1,8 @@
 (ns wysitutwyg.textgen
   (:require [wysitutwyg.markov :as markov]))

+(def cache (atom {}))
+
 (def text-delimiters #{\. \! \?})
 (def word-delimiters #{\space})

@@ -8,7 +10,7 @@
   (not (text-delimiters char)))
 (defn not-word-delim? [char]
   (not (word-delimiters char)))
-
+
 (defn seed-from-sentence
   "Takes a string and maps it to an integer by summing the unicode character
   codes of the characters in the string."
@@ -33,11 +35,20 @@
           num-words (count (break-text not-word-delim? sentence))]
       (markov/generate-text key num-words chain))))

+(defn text-from-sentence
+  "First attempts to find cached sentence in atom cache. If none, generates."
+  [sentence chain]
+  (if-let [cached (get @cache sentence)]
+    cached
+    (let [output (gen-from-sentence sentence chain)]
+      (do (swap! cache assoc sentence output)
+          output))))
+
 (defn gen-from-text
   "Generates a text from a text block (presumably of sentences)."
   [text chain]
   (->> text
        (break-text not-text-delim?)
-       (map #(gen-from-sentence % chain))
+       (map #(text-from-sentence % chain))
        (interpose \space)
        (apply str)))


style

style

--- src/java_time/graph.cljc
+++ src/java_time/graph.cljc
@@ -132,7 +132,7 @@
 (defn- add-conversion [m ^Types src dst conversion]
   (let [add #(update % (peek (.types src))
                      (fnil conj [])
-                     (vector dst conversion))]
+                     [dst conversion])]
     (if (> (.arity src) 1)
       (update-in m (pop (.types src)) add)
       (add m))))


Improved Code

Improved Code

--- src/lens/import.clj
+++ src/lens/import.clj
@@ -77,12 +77,81 @@
     (->> (async/chan 1 (assoc-xf :type :item-ref))
          (async/pipe (api/create-item-ref! item-group-def ref)))))

+(defn handle-study [state val]
+  (let [job (->> (async/chan 1 (assoc-xf :type :study))
+                 (async/pipe (api/upsert-study! (:parent state) val)))]
+    (update state :jobs #(add-job % :study job))))
+
+(defn handle-form-ref [state val]
+  (update state :refs #(collect-form-ref % val)))
+
+(defn handle-form-def [state val]
+  (let [job (submit-job! api/upsert-form-def! :form-def (:parent state) val)]
+    (update state :jobs #(add-job % :form job))))
+
+(defn handle-item-group-ref [state val]
+  (update state :refs #(collect-item-group-ref % val)))
+
+(defn handle-item-group-def [state val]
+  (let [job (submit-job! api/upsert-item-group-def! :item-group-def (:parent state) val)]
+    (update state :jobs #(add-job % :item-group job))))
+
 (defn- handle-item-ref [state val]
   (update state :refs #(collect-item-ref % val)))

 (defn- handle-item-def [state val]
   (let [job (submit-job! api/upsert-item-def! :item-def (:parent state) val)]
     (update state :jobs #(add-job % :item job))))
+
+(defn- handler [type]
+  (case type
+    :form-ref handle-form-ref
+    :form-def handle-form-def
+    :item-group-ref handle-item-group-ref
+    :item-group-def handle-item-group-def
+    :item-ref handle-item-ref
+    :item-def handle-item-def))
+
+(defn handle-study-job [state port val]
+  (-> (update state :jobs #(remove-job % :study port))
+      (assoc :parent val)))
+
+(defn handle-form-def-job [state port val]
+  (-> (update state :jobs #(remove-job % :form port))
+      (update :defs #(collect-form-def % val))))
+
+(defn handle-item-group-ref-job [state port _]
+  (update state :jobs #(remove-job % :item-group port)))
+
+(defn handle-item-group-def-job [state port val]
+  (let [create-ref (map #(create-item-group-ref-job (get-in state [:defs (:study-id val)]) %))
+        ref-vec [(:study-id val) :item-group-refs (:id (:data val))]
+        ref-jobs (eduction create-ref (get-in state [:refs ref-vec]))]
+    (-> (update state :jobs #(-> (remove-job % :item-group port)
+                                 (add-jobs :item-group ref-jobs)))
+        (update :defs #(collect-item-group-def % val))
+        (update :refs #(dissoc-in % ref-vec)))))
+
+(defn handle-item-ref-job [state port val]
+  (update state :jobs #(remove-job % :item port)))
+
+(defn handle-item-def-job [state port val]
+  (let [create-ref (map #(create-item-ref-job (get-in state [:defs (:study-id val)]) %))
+        ref-vec [(:study-id val) :item-refs (:id (:data val))]
+        ref-jobs (eduction create-ref (get-in state [:refs ref-vec]))]
+    (-> (update state :jobs #(-> (remove-job % :item port)
+                                 (add-jobs :item ref-jobs)))
+        (update :refs #(dissoc-in % ref-vec)))))
+
+(defn- job-handler [type]
+  (case type
+    :study handle-study-job
+    ;:form-ref handle-form-ref-job
+    :form-def handle-form-def-job
+    :item-group-ref handle-item-group-ref-job
+    :item-group-def handle-item-group-def-job
+    :item-ref handle-item-ref-job
+    :item-def handle-item-def-job))

 (defn import! [service-document n parse-ch]
   (let [constrain-jobs
@@ -93,84 +162,13 @@
                      :jobs {:count 0}
                      :defs {}
                      :refs {}}]
-      (log/debug "--------------------------------------------------")
-      (log/debug "Parent:" (:data (:parent state)))
-      (log/debug "Jobs:  " (map-vals count (dissoc (:jobs state) :count)))
-      (log/debug "--------------------------------------------------")
       (let [[val port] (async/alts! (into ports (select-jobs (:jobs state))))]
-        (if val
+        (if-let [type (:type val)]
           (if (= parse-ch port)
-            (do (log/debug "Parsed" (:type val) (:id val))
-                (case (:type val)
-                  :study
-                  (let [job (async/pipe (api/upsert-study! (:parent state) val)
-                                        (async/chan 1 (assoc-xf :type :study)))]
-                    (recur [] (update state :jobs #(add-job % :study job))))
-
-                  :form-ref
-                  (recur (constrain-jobs state)
-                         (update state :refs #(collect-form-ref % val)))
-
-                  :form-def
-                  (let [job (submit-job! api/upsert-form-def! :form-def (:parent state) val)]
-                    (recur (constrain-jobs state)
-                           (update state :jobs #(add-job % :form job))))
-
-                  :item-group-ref
-                  (recur (constrain-jobs state)
-                         (update state :refs #(collect-item-group-ref % val)))
-
-                  :item-group-def
-                  (let [job (submit-job! api/upsert-item-group-def! :item-group-def (:parent state) val)]
-                    (recur (constrain-jobs state)
-                           (update state :jobs #(add-job % :item-group job))))
-
-                  :item-ref
-                  (recur (constrain-jobs state) (handle-item-ref state val))
-
-                  :item-def
-                  (recur (constrain-jobs state) (handle-item-def state val))))
-
-            ;; jobs
-            (do
-              (log/debug "Finished" (:type val) (:id (:data val)))
-              (case (:type val)
-                :study
-                (recur (constrain-jobs state)
-                       (-> (update state :jobs #(remove-job % :study port))
-                           (assoc :parent val)))
-
-                :form-def
-                (recur (constrain-jobs state)
-                       (-> (update state :jobs #(remove-job % :form port))
-                           (update :defs #(collect-form-def % val))))
-
-                :item-group-ref
-                (recur (constrain-jobs state)
-                       (update state :jobs #(remove-job % :item-group port)))
-
-                :item-group-def
-                (let [create-ref (map #(create-item-group-ref-job (get-in state [:defs (:study-id val)]) %))
-                      ref-vec [(:study-id val) :item-group-refs (:id (:data val))]
-                      ref-jobs (eduction create-ref (get-in state [:refs ref-vec]))]
-                  (recur (constrain-jobs state)
-                         (-> (update state :jobs #(-> (remove-job % :item-group port)
-                                                      (add-jobs :item-group ref-jobs)))
-                             (update :defs #(collect-item-group-def % val))
-                             (update :refs #(dissoc-in % ref-vec)))))
-
-                :item-ref
-                (recur (constrain-jobs state)
-                       (update state :jobs #(remove-job % :item port)))
-
-                :item-def
-                (let [create-ref (map #(create-item-ref-job (get-in state [:defs (:study-id val)]) %))
-                      ref-vec [(:study-id val) :item-refs (:id (:data val))]
-                      ref-jobs (eduction create-ref (get-in state [:refs ref-vec]))]
-                  (recur (constrain-jobs state)
-                         (-> (update state :jobs #(-> (remove-job % :item port)
-                                                      (add-jobs :item ref-jobs)))
-                             (update :refs #(dissoc-in % ref-vec))))))))
+            (if (= :study type)
+              (recur [] (handle-study state val))
+              (recur (constrain-jobs state) ((handler type) state val)))
+            (recur (constrain-jobs state) ((job-handler type) state port val)))

           (if (= 0 (:count (:jobs state)))
             (log/info "Finished!")


Use GET instead of POST for Search Forms

--- src/lens/routes.clj
+++ src/lens/routes.clj
@@ -2,7 +2,7 @@
   (:use plumbing.core)
   (:require [clojure.string :as str]
             [clojure.edn :as edn]
-            [compojure.core :as compojure :refer [GET POST DELETE]]
+            [compojure.core :as compojure :refer [GET DELETE]]
             [ring.util.response :as ring-resp]
             [cemerick.url :as url]
             [lens.reducers :as lr]
@@ -146,7 +146,7 @@

 (defn search-item-groups-form [form]
   {:action (str "/forms/" (:form/id form) "/search-item-groups")
-   :method "POST"
+   :method "GET"
    :title (str "Search Item Groups of Form " (:form/id form))
    :params
    {:query
@@ -211,7 +211,7 @@

 (defn search-items-form [item-group]
   {:action (str "/item-groups/" (:item-group/id item-group) "/search-items")
-   :method "POST"
+   :method "GET"
    :title (str "Search Items of Item Group " (:name item-group))
    :params
    {:query
@@ -555,14 +555,14 @@

    (GET "/forms/:id/count" [db id] (form-count db id))

-   (POST "/forms/:id/search-item-groups" [db id query]
+   (GET "/forms/:id/search-item-groups" [db id query]
          (search-item-groups db id query))

    (GET "/item-groups/:id" [db id] (item-group db id))

    (GET "/item-groups/:id/count" [db id] (item-group-count db id))

-   (POST "/item-groups/:id/search-items" [db id query]
+   (GET "/item-groups/:id/search-items" [db id query]
          (search-items db id query))

    (GET "/items/:id" [db id] (item db id))


Remove redundant Slide code

Remove redundant Slide code

--- src-cljs/qcon/main.cljs
+++ src-cljs/qcon/main.cljs
@@ -17,11 +17,6 @@
 (enable-console-print!)

 (def debug false)
-
-;; A protocol for custom slides
-(defprotocol Slide
-  (init-slide-state [_])
-  (render-slide [_ data owner]))

 (defn put-and-take-slide [data owner opts]
   (reify
@@ -287,9 +282,7 @@
              )

            (when-let [custom (:custom data)]
-             (om/build custom data {:opts (:opts data)})
-             #_(when (satisfies? Slide (om/value custom))
-               (render-slide (om/value custom) data owner)))
+             (om/build custom data {:opts (:opts data)}))

            (when-let [event (:event data)]
              [:div {:style {:text-align "center" :margin-top "20pt"}}
@@ -308,10 +301,6 @@
                 )]
              )

-           #_[:p (:text data)]
-           #_(when-let [content (:content data)]
-             (apply vec content)
-             )
            (when-let [code (:code data)]
              (om/build source-snippet data {:opts "filter"})
              )


Rewrote power to use iterate rather than a loop

--- src/life/matrix.clj
+++ src/life/matrix.clj
@@ -64,14 +64,7 @@
 (defn power [f n]
   "Returns a function that applies f n times.
    e.g. ((power inc 3) 2) => 5"
-  (case n
-    0 identity
-    1 f
-    (fn [x]
-      (loop [r x, i n]
-        (if (zero? i)
-          r
-          (recur (f r) (dec i)))))))
+  #(nth (iterate f %) n))

 (defn power-limit
   "Finds the fixpoint of a function starting at a given argument.


ok this fails only on disable, but I think it's too outdated for me to figure out how to fix at the moment

--- src/memorystone/core.clj
+++ src/memorystone/core.clj
@@ -1,7 +1,8 @@
 (ns memorystone.core
   (:use cljminecraft.core)
   (:require [memorystone.structures :as struc])
-  (:import [org.bukkit.event Event Event$Type]))
+  ;(:import [org.bukkit.event Event Event$Type])
+  )

 (defn block-break [evt]
   (.sendMessage (.getPlayer evt) "You know. Breaking stuff should be illegal."))


ensure bounds

ensure bounds

--- test/edin/main_test.cljs
+++ test/edin/main_test.cljs
@@ -238,6 +238,12 @@
         (is (= newline-index 4))
     ))

+(deftest prev-newline2
+  (let [b (buffer/create-buffer "ed\nin\nd")
+        newline-index (buffer/prev-newline-index b 6)]
+        (is (= newline-index 5))
+    ))
+
 (deftest word-wrap-test
   (let [b (buffer/create-buffer "edindazdarevic")
     wrapped (buffer/word-wrap b 4)]


Update copy for alert emails.

Update copy for alert emails.

--- src/oc/email/content.clj
+++ src/oc/email/content.clj
@@ -429,7 +429,7 @@
 ;; Reminder alert

 (defn reminder-alert-headline [reminder-data]
-  (str "Hi " (:first-name (:author reminder-data)) ", it's time to share your post"))
+  (str "Hi " (:first-name (:author reminder-data)) ", it's time to update your team"))

 (defn reminder-alert-settings-footer [frequency]
   [:table {:class "row reminders-footer"
@@ -443,14 +443,13 @@
           [:th {:class "small-12 large-12"}
             [:p {:class "settings-footer"}
               (str
-              "You can always adjust or turn off reminders in "
               "This is a "
               (case (s/lower-case frequency)
                 "quarter" "quarterly"
                 "month" "monthly"
                 ;:else
                 "weekly")
-              " reminder. You can always adjust or turn off reminders in ")
+              " reminder. You can adjust or turn off reminders in ")
               [:a {:href profile-url}
                 "Carrot"]
               "."]]]]


start on parse deps

start on parse deps

--- src/mirror/core.clj
+++ src/mirror/core.clj
@@ -14,6 +14,12 @@
            java.math.BigInteger))

 ;; ===== Def Protocol Page =====
+
+(defn parse-deps
+  "given an ns form, extract deps in to a set"
+  [form]
+  (-> form
+      third))

 (defn md5 [s]
   (let [algorithm (MessageDigest/getInstance "MD5")


floor and image-floor

floor and image-floor

--- src/mosaic/tile.clj
+++ src/mosaic/tile.clj
@@ -68,12 +68,33 @@
 	    (first samples)
 	    (rest samples))))

-(defn assemble [tx ty n ^BufferedImage b]
-  (let [x (* tx n)
-	y (* ty n)
-	s (rescale x y b)
-	o (BufferedImage. x y BufferedImage.TYPE_INT_BGR)]
-    ))

 (defn match-tiles [coll tx ty n ^BufferedImage b]
-  )+  )
+
+
+(defn floor [n x]
+  "Round x down to the nearest multiple of n."
+  (int (* n (Math/floor (/ x n)))))
+
+(defn image-floor [n ^BufferedImage b]
+  "Crop image b down the a width and height which
+   is a multiple of n."
+  (let [x (.getWidth b)
+	y (.getHeight b)]
+    (.getSubimage b 0 0 (floor n x) (floor n y))))
+
+
+
+(defn mosaic [^BufferedImage source
+	      ^BufferedImage target
+	      tile-size tiles-wide]
+  (let []))
+
+
+; input: <tile_source> <target> <tile_size> <tile_width>
+; 1. resize the source image to tile_size * tile_width
+; 2. grid out the new source image
+; 3. replace the image with a sub image, cropped to height
+; 4. for each grid square replace it with the best matching tile
+


Better naming for units.

Better naming for units.

--- src/onyx/schema.clj
+++ src/onyx/schema.clj
@@ -103,7 +103,7 @@
    s/Keyword s/Any})

 (def Unit
-  [(s/one s/Int "number")
+  [(s/one s/Int "unit-count")
    (s/one s/Keyword "unit-type")])

 (def WindowType


Need this out of order T_T

Need this out of order T_T

--- src/grimoire/api.clj
+++ src/grimoire/api.clj
@@ -119,6 +119,8 @@
           :when (.isFile d)]
       (->T :def namespace (string/replace (.getName d) #".clj" "")))))

+(declare read-meta)
+
 (defn- thing->prior-versions
   "Returns a sequence of things representing itself at earlier or equal versions."


Add standard deviation to benchmark results

--- ring-bench/src/ring/bench/servlet.clj
+++ ring-bench/src/ring/bench/servlet.clj
@@ -44,4 +44,7 @@
   (println "Benchmarking...")
   (doseq [result (jmh/run bench-env bench-opts)]
     (let [[score unit] (:score result)]
-      (println (format "  %s - %.2f %s" (:fn result) score unit)))))
+      (println (format "  %s - %.2f ops/s (σ=%.2f)"
+                       (:name result)
+                       (-> result :statistics :mean)
+                       (-> result :statistics :stdev))))))


Formatting and a note.

Formatting and a note.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -572,19 +572,19 @@
         [:h3 {:id "sensors"} "Sensors"]
         (om/build sensors-table data {:opts {:histkey :sensors
                                              :path    :readings}})
-
-         (if (or (not agent/IE)
-                   (agent/isVersionOrHigher 9))
-             [:div {:id "chart-div"}
-              [:div {:id "date-picker"}
-               (om/build dtpicker/date-picker data {:opts {:histkey :range}})]
-              (om/build chart-feedback-box (get-in data [:chart :message]))
-              (om/build chart-summary (:chart data))
-              [:div {:className "well" :id "chart" :style {:width "100%" :height 600}}
-               (om/build chart/chart-figure (:chart data))]]
-             [:div.col-md-12.text-center
-              [:p.lead {:style {:padding-top 30}}
-               "Charting in Internet Explorer version " agent/VERSION " coming soon."]])]))))
+        ;; FIXME: We should have better handling for IE8 here.
+        (if (or (not agent/IE)
+                (agent/isVersionOrHigher 9))
+          [:div {:id "chart-div"}
+           [:div {:id "date-picker"}
+            (om/build dtpicker/date-picker data {:opts {:histkey :range}})]
+           (om/build chart-feedback-box (get-in data [:chart :message]))
+           (om/build chart-summary (:chart data))
+           [:div {:className "well" :id "chart" :style {:width "100%" :height 600}}
+            (om/build chart/chart-figure (:chart data))]]
+          [:div.col-md-12.text-center
+           [:p.lead {:style {:padding-top 30}}
+            "Charting in Internet Explorer version " agent/VERSION " coming soon."]])]))))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; property-details


Add TODOs

Add TODOs

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -2,7 +2,9 @@
   "Clojure DynamoDB client. A fork of Rotary by James Reeves,
   Ref. https://github.com/weavejester/rotary"
   {:author "Peter Taoussanis"}
-  (:require [clojure.string :as str])
+  (:require [clojure.string  :as str]
+            [taoensso.timbre :as timbre]
+            [taoensso.nippy  :as nippy])
   (:import  [com.amazonaws.services.dynamodb.model
              AttributeValue
              BatchGetItemRequest
@@ -36,6 +38,27 @@
             com.amazonaws.auth.BasicAWSCredentials
             com.amazonaws.services.dynamodb.AmazonDynamoDBClient))

+;;;; TODO Rotary PRs
+;; * Added proxy support (cesarpinera)
+;; * Feature/can update dynamo items (mrgordon)
+;; * Support conditional PUT (BestFriendChris)
+;; * More flexible key support and additional options from SDK (mrgordon)
+;; * Added support for binary values (mantree)
+;; * Add support for making conditional put requests (edpaget)
+;; * Upgrade to use dynamodb v2 api (edpaget)
+;; * Local secondary indexes (edpaget)
+;; * Non-PR forks.
+
+;;;; TODO
+;; * Missing deps.
+;; * Code walk-through.
+;; * Update SDK dep.
+;; * Update to v2 API.
+;; * Go through Rotary PRs.
+;; * Bin support + serialization.
+;; * Docs.
+;; * Tests!
+
 (defn- db-client*
   "Get a AmazonDynamoDBClient instance for the supplied credentials."
   [cred]


Move rand-argb to core

Move rand-argb to core

--- src/test_utils/core.cljc
+++ src/test_utils/core.cljc
@@ -1,5 +1,6 @@
 (ns test-utils.core
-  (:require [kixi.stats.distribution :as ksd]))
+  (:require [clojure.string :as cljstr]
+            [kixi.stats.distribution :as ksd]))

 #?(:cljs (enable-console-print!))

@@ -84,3 +85,12 @@
   "Return many random UUIDs."
   ([] (rand-uuids 3))
   ([n] (repeatedly n rand-uuid)))
+
+(defn rand-argb
+  ([] (rand-argb :bytes))
+  ([tag]
+   (let [floats->bytes (fn [x] (-> (* 256 x) int Integer/toHexString))]
+        (case tag
+          :float (vec (repeatedly 4 rand))
+          :bytes (vec (map floats->bytes (rand-argb :float)))
+          :hex-string (cljstr/join (rand-argb :bytes))))))


change queue

change queue

--- src/thread_exec/core.clj
+++ src/thread_exec/core.clj
@@ -1,13 +1,15 @@
 (ns thread-exec.core
   (:require [clojure.tools.logging :refer [info error]])
   (:import
-    [java.util.concurrent ThreadFactory BlockingQueue Callable ThreadPoolExecutor SynchronousQueue TimeUnit ExecutorService ThreadPoolExecutor$CallerRunsPolicy]))
+    [java.util.concurrent ThreadFactory BlockingQueue ArrayBlockingQueue Callable ThreadPoolExecutor SynchronousQueue TimeUnit ExecutorService ThreadPoolExecutor$CallerRunsPolicy]))

 (defn- create-exec-service [threads]
-   (doto (ThreadPoolExecutor. 0 threads 60 TimeUnit/SECONDS (SynchronousQueue.))
-     (.setRejectedExecutionHandler  (ThreadPoolExecutor$CallerRunsPolicy.))))
+  (let [queue (ArrayBlockingQueue. (int 100))
+			  exec  (doto (ThreadPoolExecutor. 0 threads 60 TimeUnit/SECONDS queue)
+					     (.setRejectedExecutionHandler  (ThreadPoolExecutor$CallerRunsPolicy.)))]
+    exec))

 (defn abs [n]


CMR-5182 Test fix.

CMR-5182 Test fix.

--- access-control-app/int-test/cmr/access_control/int_test/permission_check_test.clj
+++ access-control-app/int-test/cmr/access_control/int_test/permission_check_test.clj
@@ -31,14 +31,15 @@
                                "\"ORDER_AND_ORDER_ITEMS\" \"PROVIDER\" \"TAG_GROUP\" \"TAXONOMY\" "
                                "\"TAXONOMY_ENTRY\" \"USER_CONTEXT\" \"USER\" \"GROUP\" \"ANY_ACL\" "
                                "\"EVENT_NOTIFICATION\" \"EXTENDED_SERVICE\" \"SYSTEM_OPTION_DEFINITION\" "
-                               "\"SYSTEM_OPTION_DEFINITION_DEPRECATION\" \"INGEST_MANAGEMENT_ACL\" \"SYSTEM_CALENDAR_EVENT\"]")
+                               "\"SYSTEM_OPTION_DEFINITION_DEPRECATION\" \"INGEST_MANAGEMENT_ACL\" \"SYSTEM_CALENDAR_EVENT\" "
+                               "\"DASHBOARD_ADMIN\" \"DASHBOARD_ARC_CURATOR\"]")
         prov-target-err (str "Parameter [target] must be one of: [\"AUDIT_REPORT\" "
                              "\"OPTION_ASSIGNMENT\" \"OPTION_DEFINITION\" \"OPTION_DEFINITION_DEPRECATION\" "
                              "\"DATASET_INFORMATION\" \"PROVIDER_HOLDINGS\" \"EXTENDED_SERVICE\" \"PROVIDER_ORDER\" "
                              "\"PROVIDER_ORDER_RESUBMISSION\" \"PROVIDER_ORDER_ACCEPTANCE\" \"PROVIDER_ORDER_REJECTION\" "
                              "\"PROVIDER_ORDER_CLOSURE\" \"PROVIDER_ORDER_TRACKING_ID\" \"PROVIDER_INFORMATION\" "
                              "\"PROVIDER_CONTEXT\" \"AUTHENTICATOR_DEFINITION\" \"PROVIDER_POLICIES\" \"USER\" "
-                             "\"GROUP\" \"PROVIDER_OBJECT_ACL\" \"CATALOG_ITEM_ACL\" \"INGEST_MANAGEMENT_ACL\" "
+                             "\"GROUP\" \"DASHBOARD_DAAC_CURATOR\" \"PROVIDER_OBJECT_ACL\" \"CATALOG_ITEM_ACL\" \"INGEST_MANAGEMENT_ACL\" "
                              "\"DATA_QUALITY_SUMMARY_DEFINITION\" \"DATA_QUALITY_SUMMARY_ASSIGNMENT\" \"PROVIDER_CALENDAR_EVENT\"]")]
     (are [params errors]
       (= {:status 400 :body {:errors errors} :content-type :json}


Add index-of and classnames util functions.


Adds logging around node and pod watches (#1421)

--- scheduler/src/cook/kubernetes/api.clj
+++ scheduler/src/cook/kubernetes/api.clj
@@ -114,23 +114,25 @@
         [(make-atom-updater all-pods-atom) ; Update the set of all pods.
          (partial cook-pod-callback-wrap cook-pod-callback compute-cluster-name)] ; Invoke the cook-pod-callback if its a cook pod.
         old-all-pods @all-pods-atom]
-    (log/info "Processing pods for compute cluster" compute-cluster-name ":" (keys namespaced-pod-name->pod))
+    (log/info "In" compute-cluster-name "compute cluster, pod watch processing pods:" (keys namespaced-pod-name->pod))
     ; We want to process all changes through the callback process.
     ; So compute the delta between the old and new and process those via the callbacks.
     ; Note as a side effect, the callbacks mutate all-pods-atom
     (doseq [task (set/union (keys namespaced-pod-name->pod) (keys old-all-pods))]
-      (log/info "In" compute-cluster-name "compute cluster, doing (startup) callback for" task)
+      (log/info "In" compute-cluster-name "compute cluster, pod watch doing (startup) callback for" task)
       (doseq [callback callbacks]
         (try
           (callback task (get old-all-pods task) (get namespaced-pod-name->pod task))
           (catch Exception e
-            (log/error e "Error while processing callback for" task)))))
+            (log/error e "In" compute-cluster-name
+                       "compute cluster, pod watch error while processing callback for" task)))))

     (let [watch (WatchHelper/createPodWatch api-client (-> current-pods
                                                            .getMetadata
                                                            .getResourceVersion))]
       (fn []
         (try
+          (log/info "In" compute-cluster-name "compute cluster, handling pod watch updates")
           (handle-watch-updates all-pods-atom watch get-pod-namespaced-key
                                 callbacks)
           (catch Exception e
@@ -145,13 +147,15 @@
 (defn initialize-pod-watch
   "Initialize the pod watch. This fills all-pods-atom with data and invokes the callback on pod changes."
   [^ApiClient api-client compute-cluster-name all-pods-atom cook-pod-callback]
+  (log/info "In" compute-cluster-name "compute cluster, initializing pod watch")
   ; We'll iterate trying to connect to k8s until the initialize-pod-watch-helper returns a watch function.
   (let [{:keys [reconnect-delay-ms]} (config/kubernetes)
         tmpfn (fn []
                 (try
+                  (log/info "In" compute-cluster-name "compute cluster, initializing pod watch helper")
                   (initialize-pod-watch-helper api-client compute-cluster-name all-pods-atom cook-pod-callback)
                   (catch Exception e
-                    (log/error e "Error during initial setup of looking at pods for" compute-cluster-name
+                    (log/error e "Error during pod watch initial setup of looking at pods for" compute-cluster-name
                                "and sleeping" reconnect-delay-ms "milliseconds before reconnect")
                     (Thread/sleep reconnect-delay-ms)
                     nil)))
@@ -181,6 +185,7 @@
     (let [watch (WatchHelper/createNodeWatch api-client (-> current-nodes .getMetadata .getResourceVersion))]
       (fn []
         (try
+          (log/info "In" compute-cluster-name "compute cluster, handling node watch updates")
           (handle-watch-updates current-nodes-atom watch (fn [n] (-> n .getMetadata .getName))
                                 [(make-atom-updater current-nodes-atom)]) ; Update the set of all nodes.
           (catch Exception e
@@ -192,13 +197,15 @@
 (defn initialize-node-watch
   "Initialize the node watch. This fills current-nodes-atom with data and invokes the callback on pod changes."
   [^ApiClient api-client compute-cluster-name current-nodes-atom]
+  (log/info "In" compute-cluster-name "compute cluster, initializing node watch")
   ; We'll iterate trying to connect to k8s until the initialize-node-watch-helper returns a watch function.
   (let [{:keys [reconnect-delay-ms]} (config/kubernetes)
         tmpfn (fn []
                 (try
+                  (log/info "In" compute-cluster-name "compute cluster, initializing node watch helper")
                   (initialize-node-watch-helper api-client compute-cluster-name current-nodes-atom)
                   (catch Exception e
-                    (log/error e "Error during initial setup of looking at nodes for" compute-cluster-name
+                    (log/error e "Error during node watch initial setup of looking at nodes for" compute-cluster-name
                                "and sleeping" reconnect-delay-ms "milliseconds before reconnect")
                     (Thread/sleep reconnect-delay-ms)
                     nil)))


Adds pod name and namespace to submit error log (#1248)

--- scheduler/src/cook/kubernetes/api.clj
+++ scheduler/src/cook/kubernetes/api.clj
@@ -525,15 +525,16 @@
   ;; TODO: make namespace configurable
   (if launch-pod
     (let [{:keys [pod]} launch-pod
+          pod-name (-> pod .getMetadata .getName)
           namespace (-> pod .getMetadata .getNamespace)
           ;; TODO: IF there's an error, log it and move on. We'll try again later.
           api (CoreV1Api. api-client)]
-      (log/info "Launching pod in namespace" namespace pod)
+      (log/info "Launching pod with name" pod-name "in namespace" namespace ":" pod)
       (try
         (-> api
             (.createNamespacedPod namespace pod nil nil nil))
         (catch ApiException e
-          (log/error e "Error submitting pod:" (.getResponseBody e)))))
+          (log/error e "Error submitting pod with name" pod-name "in namespace" namespace ":" (.getResponseBody e)))))
     ; Because of the complicated nature of task-metadata-seq, we can't easily run the V1Pod creation code for a
     ; launching pod on a server restart. Thus, if we create a task, store into datomic, but then the cook scheduler
     ; fails --- before kubernetes creates a pod (either the message isn't sent, or there's a kubernetes problem) ---


Reduce some boilerplate with a macro

Reduce some boilerplate with a macro

--- src/kevin/loader.clj
+++ src/kevin/loader.clj
@@ -221,55 +221,56 @@
             (recur lines { :header (not= line start-at) })
             (parser lines))))))

-(defn ensure-transformed-movies [file out]
-  (when-not (.exists (io/as-file out))
-    (with-open [in (io/reader
-                     (java.util.zip.GZIPInputStream. (io/input-stream file))
-                     :encoding "ISO-8859-1")
-                out (io/writer out)]
-      (loop [[line & lines] (drop-while #(not= % "MOVIES LIST") (line-seq in))]
-        (when line
-          (when (movie-line? line)
-            (when-let [title (movie-title line)]
-              (.write out title)
-              (.newLine out)))
+
+(defmacro ensure-transformed-file
+  "in and out are bound for you"
+  [[file outfile] & body]
+  `(when-not (.exists (io/as-file ~outfile))
+     (with-open [~'in (io/reader
+                      (java.util.zip.GZIPInputStream. (io/input-stream ~file))
+                      :encoding "ISO-8859-1")
+                 ~'out (io/writer ~outfile)]
+       ~@body)))
+
+(defn ensure-transformed-movies [file outfile]
+  (ensure-transformed-file [file outfile]
+    (loop [[line & lines] (drop-while #(not= % "MOVIES LIST") (line-seq in))]
+      (when line
+        (when (movie-line? line)
+          (when-let [title (movie-title line)]
+            (doto out
+              (.write title)
+              (.newLine))))
+        (recur lines)))))
+
+(defn ensure-transformed-actors [file outfile & {:keys [start-at]}]
+  (ensure-transformed-file [file outfile]
+    (loop [lines (drop 3 (drop-while #(not= % start-at) (line-seq in)))]
+      (let [[actor-lines lines] (split-with (complement empty?) (rest lines))]
+        (when (seq actor-lines)
+          (when-let [actor-data (try (parse-actor actor-lines) (catch Throwable t nil))]
+            (let [{:keys [actor movies]} actor-data]
+              (doseq [movie movies]
+                (doto out
+                  (.write actor)
+                  (.write char-tab)
+                  (.write movie)
+                  (.newLine)))))
           (recur lines))))))

-(defn ensure-transformed-actors [file out & {:keys [start-at]}]
-  (when-not (.exists (io/as-file out))
-    (with-open [in (io/reader
-                     (java.util.zip.GZIPInputStream. (io/input-stream file))
-                     :encoding "ISO-8859-1")
-                out (io/writer out)]
-      (loop [lines (drop 3 (drop-while #(not= % start-at) (line-seq in)))]
-        (let [[actor-lines lines] (split-with (complement empty?) (rest lines))]
-          (when (seq actor-lines)
-            (when-let [actor-data (try (parse-actor actor-lines) (catch Throwable t nil))]
-              (let [{:keys [actor movies]} actor-data]
-                (doseq [movie movies]
-                  (doto out
-                    (.write actor)
-                    (.write char-tab)
-                    (.write movie)
-                    (.newLine)))))
-            (recur lines)))))))
-
-(defn ensure-transformed-genres [file out]
-  (when-not (.exists (io/as-file out))
-    (with-open [in (io/reader
-                     (java.util.zip.GZIPInputStream. (io/input-stream file))
-                     :encoding "ISO-8859-1")
-                out (io/writer out)]
-      (loop [[line & lines] (drop 3 (drop-while #(not= % "8: THE GENRES LIST") (line-seq in)))]
-        (when line
-          (when (movie-line? line)
-            (let [[title genre] (parse-genre line)]
-              (doto out
-                (.write title)
-                (.write char-tab)
-                (.write genre)
-                (.newLine ))))
-          (recur lines))))))
+(defn ensure-transformed-genres [file outfile]
+  (ensure-transformed-file [file outfile]
+    (loop [[line & lines] (drop 3 (drop-while #(not= % "8: THE GENRES LIST") (line-seq in)))]
+      (when line
+        (when (movie-line? line)
+          (let [[title genre] (parse-genre line)]
+            (doto out
+              (.write title)
+              (.write char-tab)
+              (.write genre)
+              (.newLine))))
+        (recur lines)))))
+

 (defn load-movies []
   (ensure-transformed-movies "data/movies.list.gz" "data/movies.transformed"))


update defentity validator, initializer & default handling, update/simplify all entity specs

- validators for colls (`:card :*`) now wrapped in {:* ..} automatically (and only if not already)
- add `:order :asc/:desc` opt for coll fields, inject into initializer as pre-step or if coll field and no initializer given use `pick-id-coll` as initializer
- missing defaults for coll fields are substituted w/ empty vector
- update pick-id-coll to check each (not just first) item if map, if only single value given, wrap in vector automatically
- remove extract-key fn (now obsolete)

--- src/imago/graph/model.clj
+++ src/imago/graph/model.clj
@@ -26,50 +26,71 @@
        (into {})
        (merge (select-keys rec (keys (apply dissoc rec :id (keys props)))))))

-(defn extract-key
-  [props key]
-  (reduce-kv
-   (fn [acc k v]
-     (if-let [v (key v)]
-       (assoc acc k v)
-       acc))
-   {} props))
-
-(defn wrap-optional [vals] (mapv #(v/optional %) vals))
-
-(defn build-validators
-  [props]
-  (->> (extract-key props :validate)
-       (reduce-kv
-        (fn [acc k v]
-          (assoc
-              acc k
-              (if (and (-> props k :optional) (not (map? v)))
-                (wrap-optional v)
-                ;;(reduce-kv (fn [a' k' v'] (assoc a' k' (wrap-optional v'))) v v)
-                v)))
-        {})))
-
-(defn apply-initializers
-  [props inits]
-  (reduce-kv
-   (fn [acc k v] (if (acc k) (assoc acc k (v acc)) acc))
-   props inits))
-
-(defn inject-defaults
-  [props defaults]
-  (reduce-kv
-   (fn [acc k v] (if (nil? (acc k)) (assoc acc k (if (fn? v) (v acc) v)) acc))
-   props defaults))
-
 (defn pick-id
   [id] (fn [x] (let [k (id x)] (if (map? k) (:id k) k))))

 (defn pick-id-coll
   [id]
   (fn [x]
-    (let [k (id x)]
-      (if (map? (first k)) (mapv :id k) (vec k)))))
+    (let [k (id x)
+          k (if (or (string? k) (number? k) (map? k)) [k] k)]
+      (mapv #(if (map? %) (:id %) %) k))))
+
+(defn wrap-optional [vals] (mapv #(v/optional %) vals))
+
+(defn build-validators
+  [props]
+  (reduce-kv
+   (fn [acc k {:keys [validate optional card]}]
+     (if validate
+       (let [v (if (and optional (not (map? validate)))
+                 (wrap-optional validate)
+                 validate)]
+         (assoc acc k (if (and (= card :*) (not (map? v))) {:* v} v)))
+       acc))
+   {} props))
+
+(defn build-sorter
+  [id dir]
+  (fn [props]
+    (let [p (props id)]
+      (if (coll? p)
+        (vec (if (= :asc dir) (sort p) (reverse (sort p))))
+        p))))
+
+(defn build-initializers
+  [props]
+  (reduce-kv
+   (fn [acc k {:keys [init card order]}]
+     (let [ordered (if order (build-sorter k order))]
+       (cond
+        init        (assoc acc k (if order (fn [_] (-> _ order init)) init))
+        ordered     (assoc acc k order)
+        (= :* card) (assoc acc k (pick-id-coll k))
+        :else       acc)))
+   {} props))
+
+(defn apply-initializers
+  [props inits]
+  (reduce-kv
+   (fn [acc k v] (if (acc k) (assoc acc k (v acc)) acc))
+   props inits))
+
+(defn build-defaults
+  [props]
+  (reduce-kv
+   (fn [acc k {:keys [card default]}]
+     (cond
+      default     (assoc acc k default)
+      (= :* card) (assoc acc k (fn [_] []))
+      :else       acc))
+   {} props))
+
+(defn inject-defaults
+  [props defaults]
+  (reduce-kv
+   (fn [acc k v] (if (nil? (acc k)) (assoc acc k (if (fn? v) (v acc) v)) acc))
+   props defaults))

 (defn entity-map-from-triples
   [triples props id]
@@ -98,14 +119,14 @@
         dctor-as2   (symbol (str 'describe-as- ctor-name '2))
         mctor      (symbol (str 'map-> name))]
     `(let [validators# (build-validators ~props)
-           defaults#   (extract-key ~props :default)
-           inits#      (extract-key ~props :init)]
+           inits#      (build-initializers ~props)
+           defaults#   (build-defaults ~props)]
        ;;(prn "-------- " ~type)
-       ;;(prn :props props)
-       ;;(prn :fields fields)
+       ;;(prn :props ~props)
+       ;;(prn :fields ~fields)
        ;;(prn :validators validators#)
-       ;;(prn :inits inits)
-       ;;(prn :defaults defaults)
+       ;;(prn :inits inits#)
+       ;;(prn :defaults defaults#)
        (defrecord ~name [~@fields]
          trio/PTripleSeq
          (~'triple-seq
@@ -136,7 +157,7 @@
            :from g#
            :query [{:where [['~'?id (-> ~props :type :prop) ~type]]}]
            :values {'~'?id #{id#}}}))
-
+
        (defn ~dctor-as
          {:doc ~(str "Constructs a new `" (namespace-munge *ns*) "." `~name "` entity based on a graph query\n"
                      "  for given entity ID and its specified props/rels (any additional rels will be included\n"
@@ -159,6 +180,7 @@
                :optional true}
    :homepage  {:prop (:homepage foaf)
                :validate [(v/url)]
+               :card :*
                :optional true}
    :password  {:prop (:passwordSha256Hash imago)
                :validate [(v/string) (v/fixed-length 64)]
@@ -177,11 +199,11 @@
                :default (fn [_] (utils/timestamp))}
    :modified  {:prop (:modified dcterms)
                :validate [(v/number) (v/pos)]
-               :default (fn [_] (utils/timestamp))}
+               :default (fn [_] [(utils/timestamp)])
+               :card :*}
    :rights    {:prop (:accessRights dcterms)
                :init (pick-id-coll :rights)
-               :default (fn [_] [])
-               :validate {:* [(v/uuid4)]}
+               :validate [(v/uuid4)]
                :card :*}})

 (defentity Collection (:MediaCollection imago)
@@ -196,29 +218,22 @@
               :default (fn [_] (utils/timestamp))}
    :modified {:prop (:modified dcterms)
               :validate [(v/number) (v/pos)]
-              :init (fn [{:keys [modified]}]
-                      (if (coll? modified)
-                        (last (sort modified))
-                        modified))
-              :default (fn [_] (utils/timestamp))}
+              :default (fn [_] [(utils/timestamp)])
+              :card :*
+              :order :asc}
    :repo     {:prop (:isPartOf dcterms)
               :validate [(v/uuid4)]
               :init (pick-id :repo)}
    :rights   {:prop (:accessRights dcterms)
-              :init (pick-id-coll :rights)
               :default (fn [_] [])
               :validate {:* [(v/uuid4)]}
               :card :*}
    :media    {:prop (:hasPart dcterms)
-              :init (pick-id-coll :media)
-              :default (fn [_] [])
               :validate {:* [(v/uuid4)]}
               :optional true
               :card :*}
    :presets  {:prop (:usesPreset imago)
-              :init (pick-id-coll :presets)
-              :default (fn [_] [])
-              :validate {:* [(v/uuid4)]}
+              :validate [(v/uuid4)]
               :card :*}})

 (defentity RightsStatement (:RightsStatement dctypes)
@@ -234,10 +249,14 @@
 (defentity ImageVersionPreset (:ImageVersionPreset imago)
   {:title    {:prop (:title dcterms)
               :validate [(v/string)]
-              :default (fn [{:keys [width height]}] (str width "x" height))}
+              :default (fn [{:keys [width height]}]
+                         (if (and width height)
+                           (str width "x" height)
+                           "Untitled"))}
    :restrict {:prop (:restrict imago)
-              :validate {:* [(v/string)]}
-              :default (fn [_] ["image/png" "image/jpeg"])}
+              :validate [(v/string)]
+              :default (fn [_] ["image/png" "image/jpeg" "image/gif" "image/tiff"])
+              :card :*}
    :width    {:prop (:width imago)
               :validate [(v/number) (v/pos)]
               :optional true}
@@ -259,13 +278,13 @@
                   :validate [(v/string)]
                   :default (fn [_] "Untitled")}
    :creator      {:prop (:creator dcterms)
-                  :validate [(v/optional (v/uuid4))]
-                  :init (pick-id :user)}
+                  :validate [(v/uuid4)]
+                  :init (pick-id :user)
+                  :optional true}
    :contributors {:prop (:contributor dcterms)
-                  :init (pick-id-coll :contributors)
-                  :default (fn [_] [])
-                  :validate {:* [(v/uuid4)]}
-                  :card :*}
+                  :validate [(v/uuid4)]
+                  :card :*
+                  :optional true}
    :publisher    {:prop (:publisher dcterms)
                   :validate [(v/uuid4)]
                   :init (pick-id :publisher)}
@@ -273,24 +292,19 @@
                   :validate [(v/number) (v/pos)]
                   :default (fn [_] (utils/timestamp))}
    :colls        {:prop (:isPartOf dcterms)
-                  :validate {:* [(v/uuid4)]}
-                  :init (pick-id-coll :colls)
-                  :default (fn [_] [])
+                  :validate [(v/uuid4)]
                   :card :*}
    :versions     {:prop (:hasVersion dcterms)
-                  :init (pick-id-coll :versions)
-                  :default (fn [_] [])
-                  :validate {:* [(v/uuid4)]}
-                  :card :*}})
+                  :validate [(v/uuid4)]
+                  :card :*
+                  :optional true}})

 (defentity ImageVersion (:ImageVersion imago)
   {:preset {:prop (:references dcterms)
             :validate [(v/uuid4)]
             :init (pick-id :preset)}
    :rights {:prop (:accessRights dcterms)
-            :init (pick-id-coll :rights)
-            :default (fn [_] [])
-            :validate {:* [(v/uuid4)]}
+            :validate [(v/uuid4)]
             :card :*}})

 (defn add-entity-rights


lightblue

lightblue

--- src/nonaga/draw.cljs
+++ src/nonaga/draw.cljs
@@ -99,7 +99,7 @@

 (def light-colors
   {"red" "pink"
-   "blue" "aqua"})
+   "blue" "lightblue"})

 (defn draw-marbles [svg-node coords color]
   (->> coords


switched to useing parsed integer

switched to useing parsed integer

--- kuona/src/kuona_api/handler.clj
+++ kuona/src/kuona_api/handler.clj
@@ -53,7 +53,7 @@
 (defn get-repositories
   [search page]
   (let [page-number (. Integer parseInt  page)]
-    (response (store/search repositories search 100 page repository-page-link))))
+    (response (store/search repositories search 100 page-number repository-page-link))))

 (defroutes app-routes
   (GET "/" [] (response service-data))


Separate loading to S3 from logging

Separate loading to S3 from logging

--- src/omnibus/core.clj
+++ src/omnibus/core.clj
@@ -177,6 +177,10 @@
    "./setup.sh"
    :dir OMNIBUS-HOME-DIR])

+
+(defn success? [{:keys [exit]}]
+  (zero? exit))
+
 (defn build-and-bucket-package
   "Builds a software bundle of `package-type` of the software described in `project` and subsequently stashes it in S3."
   [package-type {:keys [project-name]
@@ -185,22 +189,24 @@
   (let [name (asset-name package-type project)
         path (asset-path package-type project)
         status (apply sh (command-line package-type project))]
-    (log-sh-result
-     status
-     (do
-       (put-in-bucket path
-                      @*bucket-name*
-                      (str platform "-" platform_version "-" machine "/" name)
-                      @*s3-access-key*
-                      @*s3-secret-key*)
-       (str "Created " (name package-type) " package for "
-            project-name " on " platform " "
-            platform_version " "
-            machine))
-     (str "Failed to create " (name package-type) " package for "
-          project-name " on " platform
-          " " platform_version " "
-          machine))))
+
+    (log-sh-result status
+                   (str "Created " (name package-type) " package for "
+                        project-name " on " platform " "
+                        platform_version " "
+                        machine)
+                   (str "Failed to create " (name package-type) " package for "
+                        project-name " on " platform
+                        " " platform_version " "
+                        machine))
+    (if (success? status)
+      (put-in-bucket path
+                     @*bucket-name*
+                     (str platform "-" platform_version "-" machine "/" name)
+                     @*s3-access-key*
+                     @*s3-secret-key*))
+    status))
+
 (defn build-project
   "Build a project by building all the software in the appropriate build order"
   [project software-descs]


Allow nil OR a map for logging config schema validation

fixes onyx-platform/onyx-template#65

--- src/onyx/schema.cljc
+++ src/onyx/schema.cljc
@@ -517,7 +517,7 @@
    :onyx.peer/job-scheduler JobScheduler
    :onyx.messaging/impl Messaging
    :onyx.messaging/bind-addr s/Str
-   (s/optional-key :onyx.log/config) {s/Any s/Any}
+   (s/optional-key :onyx.log/config) (s/maybe {s/Any s/Any})
    (s/optional-key :onyx.messaging/peer-port) s/Int
    (s/optional-key :onyx.messaging/external-addr) s/Str
    (s/optional-key :onyx.peer/inbox-capacity) s/Int


pre-filter candidate parent rules by :cat

--- src/babel/generate.cljc
+++ src/babel/generate.cljc
@@ -12,6 +12,8 @@
                                         strip-refs show-spec unify unifyc)]))
 ;; during generation, will not search deeper than this:
 (def ^:const max-total-depth 6)
+
+;; use map or pmap.
 (def ^:const mapfn map)

 (declare add-complement)
@@ -131,8 +133,13 @@

 (defn candidate-parents [rules spec]
   "find subset of _rules_ for which each member unifies successfully with _spec_"
+  (log/trace (str "candidate-parents: spec: " (strip-refs spec)))
   (filter #(not (fail? %))
-          (mapfn (fn [rule] (unifyc spec rule))
+          (mapfn (fn [rule]
+                   (if (unifyc (get-in rule [:synsem :cat] :top)
+                               (get-in spec [:synsem :cat] :top))
+                     (unifyc spec rule)
+                     :fail))
                  (shuffle rules))))

 (defn lightning-bolt [grammar lexicon spec depth index morph total-depth]