Use last-activity-at as start parameter instead of published-at to make sure all posts will be returned.

--- src/oc/storage/representations/board.clj
+++ src/oc/storage/representations/board.clj
@@ -52,9 +52,7 @@
   (let [activity (:entries data)
         activity? (not-empty activity)
         last-activity (last activity)
-        first-activity (first activity)
-        last-activity-date (when activity? (or (:published-at last-activity) (:created-at last-activity)))
-        first-activity-date (when activity? (or (:published-at first-activity) (:created-at first-activity)))
+        last-activity-date (when activity? (:last-activity-at last-activity))
         next? (= (:next-count data) config/default-activity-limit)
         next-url (when next? (board-url/url org board sort-type {:start last-activity-date :direction direction}))
         next-link (when next-url (hateoas/link-map "next" hateoas/GET next-url {:accept mt/board-media-type}))]


Remove new-at property, replaceit with last-activity-at to make it more readable and to avoid confusion.

--- src/oc/storage/representations/entry.clj
+++ src/oc/storage/representations/entry.clj
@@ -24,7 +24,7 @@
                            :board-uuid :board-slug :board-name :board-access :publisher-board
                            :team-id :author :publisher :published-at :video-id :video-processed
                            :video-image :video-duration :created-at :updated-at :revision-id
-                           :new-at :new-comments-count :bookmarked-at :polls :last-read-at
+                           :new-comments-count :bookmarked-at :polls :last-read-at
                            :last-activity-at :sort-value])

 ;; ----- Utility functions -----
@@ -191,7 +191,7 @@
       (count (filterv #(pos? (compare (:created-at %) (:read-at entry-read))) filtered-comments))
       (count filtered-comments))))

-(defn- entry-new-at
+(defn- entry-last-activity-at
   "Return the most recent created-at of the comments, exclude comments from current user if needed."
   [user-id entry]
   (let [all-comments (filterv :body (:interactions entry))
@@ -258,8 +258,8 @@
                            :last-read-at (:read-at entry-read)
                            :new-comments-count (when enrich-entry?
                                                  (new-comments-count entry-with-comments user-id entry-read))
-                           :new-at (when enrich-entry?
-                                     (entry-new-at user-id entry-with-comments))}
+                           :last-activity-at (when enrich-entry?
+                                               (entry-last-activity-at user-id entry-with-comments))}
                           entry)
         reaction-list (if (= access-level :public)
                         []


print out :rate-name even if it's nil via with-out-str

--- src/overtone/sc/machinery/ugen/check.clj
+++ src/overtone/sc/machinery/ugen/check.clj
@@ -71,7 +71,7 @@
   (str "Rate mismatch: "
        (name-of (first inputs))
        " is at rate "
-       (:rate-name (first inputs))
+       (with-out-str (pr (:rate-name (first inputs))))
        " yet the containing ugen is at "
        (REVERSE-RATES rate))
   (= (:rate (first inputs)) rate))


More output differentiation.

More output differentiation.

--- test/ago/test.cljs
+++ test/ago/test.cljs
@@ -50,7 +50,7 @@
     (ago-restore agw @last-snapshot)
     (recur))
   (go-loop []
-    (println (<! out-ch))
+    (println :out (<! out-ch))
     (recur))
   (ago agw
        (loop [num-hi 0 num-bye 0]


fan shape for vision

fan shape for vision

--- clojure/src/dnd/showScreen.cljs
+++ clojure/src/dnd/showScreen.cljs
@@ -6,15 +6,35 @@

 (def bresenham (nodejs/require "bresenham-js"))

+(defn end-points [character]
+  (let [_width (inc width)
+        _height (inc height)]
+    (vec (case (:direction character)
+           "n" (map #(vec [% 0])      (range 0 _width))
+           "s" (map #(vec [% height]) (range 0 _width))
+           "w" (map #(vec [0 %])      (range 0 _height))
+           "e" (map #(vec [width %])  (range 0 _height))))))
+
+(defn draw-x [term coords]
+  (.color256    term 7)
+  (.bgColor256  term 0)
+  (let [[x y] coords]
+     (.moveTo term x y "X")))
+
+(defn draw-line [term line]
+  (run!
+    (partial draw-x term) line))
+
 (defn fov [term level character]
   (let [{:keys [x y direction]} character
-        coords (map js->clj (bresenham #js[(inc x) (inc y)] #js[10 10]))]
-    (.color256    term 7)
-    (.bgColor256  term 0)
-    (dorun
-      (map
-        #(let [[x y] % ]
-           (.moveTo term x y "X")) coords))))
+        ends (end-points character)
+        lines (map #(let [dx (first %)
+                          dy (second %)
+                          start #js[(inc x) (inc y)]
+                          end   #js[dx dy]]
+                      (js->clj (bresenham start end))) ends)]
+    (run!
+      (partial draw-line term) lines)))

 (defn draw-block [term block]
   (let [{:keys [x y solid inhabitants color] } block


refine transactions namespace

refine transactions namespace

add select-items-by-reconciliation-id
make polarize-item-amount public

--- src/clj_money/models/transactions.clj
+++ src/clj_money/models/transactions.clj
@@ -24,6 +24,7 @@
                                               select-transaction-items-by-account-id-and-starting-index
                                               select-transaction-items-by-account-id-on-or-after-date
                                               select-transaction-items-by-transaction-id
+                                              select-transaction-items-by-reconciliation-id
                                               update-transaction-item
                                               update-transaction-item-index-and-balance
                                               delete-transaction
@@ -60,7 +61,7 @@
   [item]
   (update-in item [:action] name))

-(defn- polarize-item-amount
+(defn polarize-item-amount
   [item account]
   (assoc item :polarized-amount (accounts/polarize-amount item account)))

@@ -323,6 +324,13 @@
          (select-transactions-by-entity-id s entity-id parsed-options)
          (map prepare-for-return)
          (map #(append-items s %)))))))
+
+(defn select-items-by-reconciliation-id
+  "Returns the transaction items associated with the specified reconciliation"
+  [storage-spec reconciliation-id]
+  (with-storage [s storage-spec]
+    (map prepare-item-for-return
+         (select-transaction-items-by-reconciliation-id s reconciliation-id))))

 (defn count-by-entity-id
   "Returns the number of transactions that belong to the specified entity"


refactor transactions/update for readability

--- src/clj_money/models/transactions.clj
+++ src/clj_money/models/transactions.clj
@@ -702,66 +702,92 @@
          (map #(or (get-previous-item storage %)
                    (assoc % :index -1 :balance (bigdec 0)))))))

-(defn remove-dereferenced-items
+(defn process-dereferenced-items
   "Removes transaction items that have been
   removed from the transaction and returns
   base items for the affected accounts"
-  [storage updated-transaction existing-transaction]
+  [{:keys [storage transaction existing] :as context}]
   (let [dereferenced-items (remove (fn [{existing-item-id :id}]
                                      (some #(= existing-item-id
                                                (:id %))
-                                           (:items updated-transaction)))
-                                   (:items existing-transaction))]
-    (->> dereferenced-items
-         (map (fn [item]
-                (delete-transaction-item storage (:id item) (:transaction-date item))
-                item))
-         (mapv #(get-previous-item storage %)))))
-
-(defn- dereferenced-account-base-items
+                                           (:items transaction)))
+                                   (:items existing))
+        base-items (->> dereferenced-items
+                        (map (fn [item]
+                               (delete-transaction-item
+                                 storage
+                                 (:id item)
+                                 (:transaction-date item))
+                               item))
+                        (mapv #(get-previous-item storage %)))]
+    (update-in context [:base-items] #(concat % base-items))))
+
+(defn- process-dereferenced-accounts
   "Find accounts IDs that are no longer referenced
   by the transaction and looks up base items for
   recalculating affected account items"
-  [storage updated-tx existing-tx]
-  (let [dereferenced-account-ids (apply difference (->> [existing-tx updated-tx]
+  [{:keys [storage transaction existing] :as context}]
+  (let [dereferenced-account-ids (apply difference (->> [existing transaction]
                                                         (map :items)
                                                         (map #(map :account-id %))
-                                                        (map set)))]
-    (->> dereferenced-account-ids
-         (map #(hash-map :account-id %
-                         :transaction-date (:transaction-date updated-tx) ; TODO: get the earlier date
-                         :index (Integer/MAX_VALUE)))
-         (map #(get-previous-item storage %)))))
-
-(defn- process-updated-transaction-items
-  [storage transaction existing-tx]
-  (->> (:items transaction)
-       (map #(as-> % i
-                (assoc i :transaction-id (:id transaction))
-                (before-save-item i)
-                (upsert-item storage i)))
-       (map (fn [current-item]
-              ; TODO: no need to find the matching item, just use the value from the transaction
-              (let [existing-item (some #(= (:id %) (:id current-item))
-                                        (:items existing-tx))]
-                (if (> 0 (compare (:transaction-date current-item)
-                                  (:transaction-date existing-item)))
-                  existing-item
-                  current-item))))
-       (mapv #(get-previous-item storage %))))
+                                                        (map set)))
+        base-items (->> dereferenced-account-ids
+                        (map #(hash-map :account-id %
+                                        :transaction-date (:transaction-date transaction) ; TODO: get the earlier date
+                                        :index (Integer/MAX_VALUE)))
+                        (map #(get-previous-item storage %)))]
+    (update-in context [:base-items] #(concat % base-items))))
+
+(defn- process-updated-items
+  "Processes the updated items in the transaction
+  in the context and appends items to the :base-items attribute
+  with the list of items that need to be processed for
+  index and balance."
+  [{:keys [storage transaction existing-tx] :as context}]
+  (let [base-items (->> (:items transaction)
+                        (map #(as-> % i
+                                (assoc i :transaction-id (:id transaction))
+                                (before-save-item i)
+                                (upsert-item storage i)))
+                        (map (fn [current-item]
+                               ; TODO: no need to find the matching item, just use the value from the transaction
+                               (let [existing-item (some #(= (:id %) (:id current-item))
+                                                         (:items existing-tx))]
+                                 (if (> 0 (compare (:transaction-date current-item)
+                                                   (:transaction-date existing-item)))
+                                   existing-item
+                                   current-item))))
+                        (mapv #(get-previous-item storage %)))]
+    (update-in context [:base-items] #(concat % base-items))))

 (defn- find-existing-transaction
   "Given a transaction that has been updated, find the existing
   transaction in storage. If none can be found, throw an exception."
-  [storage {:keys [id transaction-date original-transaction-date]}]
+  [{storage :storage
+    {:keys [id
+            transaction-date
+            original-transaction-date]} :transaction
+    :as context}]
   (let [search-date (or original-transaction-date transaction-date)]
-    (or (find-by-id storage id search-date)
-        (throw (ex-info
-                 (format "Unable to find transaction with id %s and date %s"
-                         id
-                         search-date)
-                 {:id id
-                  :search-date search-date})))))
+    (assoc context :existing
+           (or (find-by-id storage id search-date)
+               (throw (ex-info
+                        (format "Unable to find transaction with id %s and date %s"
+                                id
+                                search-date)
+                        {:id id
+                         :search-date search-date}))))))
+
+(defn- recalculate-indexes-and-balances-for-update
+  [{:keys [storage base-items] :as context}]
+  (doseq [item base-items]
+    (recalculate-account-items storage item))
+  context)
+
+(defn- update-transaction*
+  [{:keys [storage transaction] :as context}]
+  (let [updated (update-transaction storage transaction)]
+  (assoc context :transaction (reload storage transaction))))

 (defn update
   "Updates the specified transaction"
@@ -770,23 +796,16 @@
     (let [validated (validate storage ::existing-transaction transaction)]
       (if (validation/has-error? validated)
         validated
-
-        ; TODO: rewrite this using an "update-context" map that holds all necessary information
-
-        (let [existing (find-existing-transaction storage validated)
-              dereferenced-base-items (remove-dereferenced-items storage validated existing)
-              dereferenced-account-base-items (dereferenced-account-base-items storage validated existing)
-              current-base-items (process-updated-transaction-items storage validated existing)
-
-              ; process all item updates
-              _ (->> current-base-items
-                     (concat dereferenced-base-items
-                             dereferenced-account-base-items)
-                     (mapv #(recalculate-account-items storage %)))
-
-              ; update the transaction record itself
-              updated (update-transaction storage validated)]
-          (reload storage validated))))))
+        (-> {:transaction validated
+             :storage storage
+             :base-items []}
+            find-existing-transaction
+            process-dereferenced-items
+            process-dereferenced-accounts
+            process-updated-items
+            recalculate-indexes-and-balances-for-update
+            update-transaction*
+            :transaction)))))

 (defn- get-preceding-items
   "Returns the items that precede each item in the


Handle copy command, trivially handle paste by simply printing clipboard contents

--- src/cljs/goya/components/drawing.cljs
+++ src/cljs/goya/components/drawing.cljs
@@ -433,10 +433,19 @@
       (reset! guistate/transient-state (assoc @guistate/transient-state :mouse-pos [doc-x doc-y])))))

+;; =============================================================================
+
+(defn copy [app owner e]
+  (let [clipboard-image (om/get-state owner :selection-image)]
+    (om/set-state! owner :clipboard-image clipboard-image)))
+
+(defn paste [app owner e]
+  (let [clipboard-image (om/get-state owner :clipboard-image)]
+    (println clipboard-image)))

 (defn handle-command [app owner e]
-  (println (str "Command Request: " e))
-)
+  (when (= e :copy) (copy app owner e))
+  (when (= e :paste) (paste app owner e)))

 ;; =============================================================================


simplify matches-query

simplify matches-query

--- src/cljs/phonecat_re_frame/views.cljs
+++ src/cljs/phonecat_re_frame/views.cljs
@@ -23,9 +23,9 @@
   [search-input phone]
   (if (= "" search-input)
     true
-    (boolean (or
-               (re-find (re-pattern search-input) (:name phone))
-               (re-find (re-pattern search-input) (:snippet phone))))))
+    (or
+      (re-find (re-pattern search-input) (:name phone))
+      (re-find (re-pattern search-input) (:snippet phone)))))

 (defn phones-component
   "component for the list of phones"


analytics-setup no DOMContentLoaded

analytics-setup no DOMContentLoaded

--- src/clojurescript/nossal/app/app.cljs
+++ src/clojurescript/nossal/app/app.cljs
@@ -68,5 +68,5 @@
       ;    (.addEventListener element (:on conf) (fn [e] (println e))))))))

-(.addEventListener js/document "DOMContentLoaded" (fn [] (analytics-setup data-analytics)))
-; (analytics-setup data-analytics)
+; (.addEventListener js/document "DOMContentLoaded" (fn [] (analytics-setup data-analytics)))
+(analytics-setup data-analytics)


CMR-2111 Clean up a test file to remove unnecessary things.

--- system-int-test/test/cmr/system_int_test/search/collection_sorting_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/collection_sorting_search_test.clj
@@ -1,7 +1,7 @@
 (ns cmr.system-int-test.search.collection-sorting-search-test
   "Tests searching for collections using basic collection identifiers"
   (:require [clojure.test :refer :all]
-            [clojure.string :as string]
+            [clojure.string :as str]
             [cmr.system-int-test.utils.ingest-util :as ingest]
             [cmr.system-int-test.utils.search-util :as search]
             [cmr.system-int-test.utils.index-util :as index]
@@ -18,7 +18,6 @@
   [provider entry-title begin end]
   (d/ingest provider
             (dc/collection {:entry-title entry-title
-                            :short-name (string/join [entry-title "_sn"])
                             :beginning-date-time (d/make-datetime begin)
                             :ending-date-time (d/make-datetime end)})))
 (defn delete-coll
@@ -75,8 +74,8 @@
         ;; Revision ids are in reverse order by default
         (compare (:revision-id c2) (:revision-id c1))
         (compare (:concept-id c1) (:concept-id c2)))
-      (let [processed-value1 (if (string? value1) (string/lower-case value1) value1)
-            processed-value2 (if (string? value2) (string/lower-case value2) value2)]
+      (let [processed-value1 (if (string? value1) (str/lower-case value1) value1)
+            processed-value2 (if (string? value2) (str/lower-case value2) value2)]
         (if descending?
           (compare processed-value2 processed-value1)
           (compare processed-value1 processed-value2))))))
@@ -99,7 +98,6 @@
         c3 (make-coll-with-sn "Zebra")
         c4 (make-coll-with-sn "Schwartz")
         c5 (make-coll-with-sn "bob1")
-        all-colls [c1 c2 c3 c4]
         correct-sort [c2 c5 c1 c4 c3]]
     (index/wait-until-indexed)
     (is (sort-order-correct? correct-sort "short-name"))
@@ -183,8 +181,8 @@
         c4 (make-coll "PROV1" "et80" 24 35)
         all-colls [c1 c2 c3 c4]]
     (index/wait-until-indexed)
-    (let [sorted-colls (sort-by (juxt (comp string/lower-case :entry-title)
-                                      (comp string/lower-case :provider-id)) all-colls)]
+    (let [sorted-colls (sort-by (juxt (comp str/lower-case :entry-title)
+                                      (comp str/lower-case :provider-id)) all-colls)]
       (is (d/refs-match-order?
             sorted-colls
             (search/find-refs :collection {:page-size 20})))


typical-force uses force-as

typical-force uses force-as

--- src/test_utils/fracture_diagnostics.cljc
+++ src/test_utils/fracture_diagnostics.cljc
@@ -45,7 +45,6 @@
 (defn convert-units-f [from to]
   (let [factors   {[:lb-per-cu-ft :kg-per-m3] 16.0185
                    [:ft-lb :J]                1.35582
-                   [:lbf :N]                  4.44822
                    [:m :ft]                   3.28084
                    [:kg :lb]                  2.20462262185
                    [:hp :W]                   745.69987158227022
@@ -56,8 +55,6 @@
                    [:kg-per-m3 :lb-per-cu-ft] #(/ % (factors [:lb-per-cu-ft :kg-per-m3]))
                    [:ft-lb :J]                #(* % (factors [:ft-lb :J]))
                    [:J :ft-lb]                #(/ % (factors [:ft-lb :J]))
-                   [:lbf :N]                  #(* % (factors [:lbf :N]))
-                   [:N :lbf]                  #(/ % (factors [:lbf :N]))
                    [:ft :m]                   #(/ % (factors [:m :ft]))
                    [:m :ft]                   #(* % (factors [:m :ft]))
                    [:kg :lb]                  #(* % (factors [:kg :lb]))
@@ -611,8 +608,8 @@
          typical-pressure-psi                 (magnitude (typical-surface-treating-pressure :psi))
          typical-force-lbf                    (* typical-pressure-psi typical-casing-area-sq-inches)]
      (condp = force-unit
-       :lbf [typical-force-lbf force-unit]
-       :N   [((convert-units-f :lbf :N) typical-force-lbf) force-unit]))))
+       :lbf (make-measurement typical-force-lbf force-unit)
+       :N   (force-as (typical-force :lbf) :N)))))

 (defn typical-power
   ([] (typical-power (rand-power-unit)))
@@ -662,4 +659,4 @@
         measurement (generate-measurement-f unit)]
     [measurement (measurement-as-f measurement (first (remove (partial = unit) units)))]))

-(generate-pair #{:psi :kPa} rand-pressure-unit typical-surface-treating-pressure pressure-as)
+(generate-pair #{:lbf :N} rand-force-unit typical-force force-as)


додано визначення

додано визначення

--- src/uawa/core.clj
+++ src/uawa/core.clj
@@ -55,6 +55,12 @@

 ;; різні

+(функція текст "(див. str)" [] (str))
+(функція текст "(див. str)" [x] (str x))
+(функція текст "(див. str)" [x y] (str x y))
+(функція текст "(див. str)" [x y & більше] (зменш текст (текст x y) більше))
+
+
 (функція дай-випадкове "див. rand-int" [максимальне] (rand-int максимальне))

 (функція друкуй "див. println" [& більше]  (binding [*print-readably* nil] (apply prn більше)))


Document shape-response

Document shape-response

--- src/uruk/core.clj
+++ src/uruk/core.clj
@@ -258,7 +258,16 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defn shape-results
-  "TODO"
+  "Coerces the server's MarkLogic query response to the (possibly
+  `nil`) `shape` that the client would like the response to take. By
+  default, returns the unchanged server response.
+
+  Recognized shapes include:
+  :none - ignore the response
+  :single - return just the first element of the response
+  :single! - if the response is one element, return just that element;
+  if not (i.e. if the response is more than one element) throw an
+  error"
   [server-response shape]
   (case shape
     :none   nil


robot-kata-routes testing complete

robot-kata-routes testing complete

--- test/clj/robot_kata/server_test.clj
+++ test/clj/robot_kata/server_test.clj
@@ -14,4 +14,6 @@
                              (is (= "text/html" ((:headers resp) "Content-Type")) "GET of '/robot-kata.html' returns content type 'text/html'")
                              (is (> (Integer. ((:headers resp) "Content-Length")) 0) "GET of '/robot-kata.html' returns content of length > 0") ) )
                   (testing "Page not found"
-                           (is (= 0 1) "Implement page not found tests!") ) ) )
+                           (let [resp (robot-kata-routes {:request-method :get :uri "/bad-route-asdf"})]
+                             (is (= 404 (:status resp)) "GET of bad route returns 404 status")
+                             (is (= "Page not found" (:body resp)) "GET of bad route returns 'Page not found'") ) ) ) )


New test: test-get-calendar-for-week

New test: test-get-calendar-for-week

--- test/clj_calendar/calendar_test.clj
+++ test/clj_calendar/calendar_test.clj
@@ -258,3 +258,12 @@
                 (.set calendar 2000 01 day 00 00)
                 (is (= day (get-day calendar)))))))

+(deftest test-get-calendar-for-week
+    "Check the function clj-calendar.calendar/get-calendar-for-week"
+    (testing "the function clj-calendar.calendar/get-calendar-for-week"
+        (let [calendar (get-calendar-for-week 2000 2)] ; first week might be set for the previous year
+            (are [x y] (= x y)
+                2000 (get-year calendar)
+                1    (get-month calendar)
+                2    (get-week calendar)))))
+


debugging

debugging

--- src/clj/rumahsewa141/routes/admin.clj
+++ src/clj/rumahsewa141/routes/admin.clj
@@ -83,12 +83,10 @@
                                         nil
                                         (get-content-fn)))))

-(defn admin-page-test [section get-content-fn
-                       {{username :username} :identity} & [subsection]]
-  (layout/render "member.html" {:username username
+(defn admin-page-test []
+  (layout/render "member.html" {:username "dingdong"
                                 :admin true
-                                :section section
-                                :subsection subsection}))
+                                :section "overview"}))

 (defn settings-page [subsection req & [get-content-fn]]
   (admin-page "settings" get-content-fn req subsection))
@@ -97,7 +95,7 @@
   {:allowed (:value (db/get-registration-config))})

 (defroutes admin-routes
-  (GET "/admin" req (admin-page-test "overview" all-users-summary req))
+  (GET "/admin" req (admin-page-test))
   (GET "/admin/billing" req (admin-page "billing" all-users req))
   (GET "/admin/payment" req (admin-page "payment" all-users req))
   (GET "/admin/manage" req (admin-page "manage" (other-users req) req))


Don't add redundant entires to palette. Just select them if they already exist.

--- src/cljs/goya/components/palette.cljs
+++ src/cljs/goya/components/palette.cljs
@@ -59,12 +59,16 @@
   (om/update! app [:tools :paint-color] color))

 (defn add-color [app color]
-  (om/transact! app [:main-app :palette] #(conj % {:color color}))
+  (let [palette (get-in @app [:main-app :palette])
+        color-is-new (not (some #(= {:color color} %) palette))]
+  (when color-is-new
+    (om/transact! app [:main-app :palette] #(conj % {:color color})))
   (set-paint-color app color)
-  (om/transact! app
-                [:main-app :undo-history]
-                #(conj % {:action (str "Added Color: " color) :icon "droplet"})
-                :add-to-undo))
+  (when color-is-new
+    (om/transact! app
+                  [:main-app :undo-history]
+                  #(conj % {:action (str "Added Color: " color) :icon "droplet"})
+                  :add-to-undo))))

 (defn palette-component [app owner]


disable cljsdoc errors for detecting unknown related symbols for now

--- src/cljs_api_gen/cljsdoc/validate.clj
+++ src/cljs_api_gen/cljsdoc/validate.clj
@@ -9,10 +9,6 @@
     [clojure.string :refer [split split-lines join]]
     [clansi.core :refer [style]]
     [fuzzy-matcher.core :as fuzzy]))
-
-(def ^:dynamic *known-symbols*
-  "List of known autoparsed symbols.  We use this to validate symbol spelling (and presence)."
-  nil)

 ;;--------------------------------------------------------------------------------
 ;; Required Sections
@@ -180,9 +176,8 @@
 (defn related-missing-error-msg*
   [name-]
   (let [filename (str cljsdoc-dir "/" (str (encode-fullname name-) ".cljsdoc"))
-        pass? (or (exists? filename)
-                  (nil? *known-symbols*) ;; don't check if no known symbols supplied
-                  (*known-symbols* name-))]
+        pass? true ;; (exists? filename) ;; TODO: enable when we have enough cljsdoc files
+        ]
     (when-not pass?
       (str "Related symbol '" name- "' is an unknown symbol."))))


Create initial config without base dir if that one is not provided by the user.

--- src/clojure/catacumba/impl/server.clj
+++ src/clojure/catacumba/impl/server.clj
@@ -54,7 +54,7 @@
         sslcontext (build-ssl-context keystore)
         config (if (string? basedir)
                  (ServerConfig/baseDir ^Path (utils/str->path basedir))
-                 (ServerConfig/findBaseDir "catacumba.properties"))]
+                 (ServerConfig/noBaseDir))]
     (when sslcontext (.ssl config sslcontext))
     (when public-address (.publicAddress config (java.net.URI. public-address)))
     (when max-body-size (.maxContentLength config max-body-size))


switched to time series

switched to time series

--- test/forma/trends/analysis_test.clj
+++ test/forma/trends/analysis_test.clj
@@ -6,6 +6,7 @@
         [forma.trends.data]
         [forma.utils]
         [cascalog.api]
+        [midje.cascalog]
         [clojure.math.numeric-tower :only (sqrt floor abs expt)])
   (:require [incanter.core :as i]
             [incanter.stats :as s]
@@ -181,16 +182,20 @@
            (telescoping-long-trend 23 start end ndvi-ts reli-ts rain-ts))))))

 (def long-trend-query
-  (?<- (stdout) [?han-stat ?long-drop ?long-tstat]
+  (<- [?han-stat ?long-drop ?long-tstat]
       (ts-tap ?ts-map)
       (long-trend-results ?ts-map :> ?han-stat ?long-drop ?long-tstat)
       (:distinct false)))

 (fact
  "duplicate time series will produce two sets of identical results, given that :distinct is set to false; otherwise, results would "
- long-trend-query => (produces [[[1.2393550741169639 1.2133709085855648]
-                                 [2.4915869043482424 1.3049908881259853]
-                                 [1.1504228201940752 0.5951173333726173]]
-                                [[1.2393550741169639 1.2133709085855648]
-                                 [2.4915869043482424 1.3049908881259853]
-                                 [1.1504228201940752 0.5951173333726173]]]))
+ long-trend-query =>
+ (produces-some [[{:start-idx 135
+                   :end-idx 136
+                   :series [1.2393550741169639 1.2133709085855648]}
+                  {:start-idx 135
+                   :end-idx 136
+                   :series [2.4915869043482424 1.3049908881259853]}
+                  {:start-idx 135
+                   :end-idx 136
+                   :series [1.1504228201940752 0.5951173333726173]}]]))


removed test/handler.clj

removed test/handler.clj

--- test/taggie_server/test/handler.clj
+++ test/taggie_server/test/handler.clj
@@ -1,14 +0,0 @@
-(ns taggie-server.test.handler
-  (:require [clojure.test :refer :all]
-            [taggie-server.handler :refer :all]
-            [ring.mock.request :as mock]))
-
-(deftest test-app
-  (testing "main route"
-    (let [response (app (mock/request :get "/"))]
-      (is (= (:status response) 200))
-      (is (= (:body response) "Hello World"))))
-
-  (testing "not-found route"
-    (let [response (app (mock/request :get "/invalid"))]
-      (is (= (:status response) 404)))))


removed preamble

removed preamble

--- src/leiningen/new/reagent/project.clj
+++ src/leiningen/new/reagent/project.clj
@@ -38,7 +38,6 @@
                              :compiler {:output-to     "resources/public/js/app.js"
                                         :output-dir    "resources/public/js/out"
                                         :source-map    "resources/public/js/out.js.map"
-                                        :preamble      ["react/react.min.js"]
                                         :externs       ["react/externs/react.js"]
                                         :optimizations :none
                                         :pretty-print  true}}}}


Add more tests for jws and jwe backends.

--- test/buddy/auth/backends/token_tests.clj
+++ test/buddy/auth/backends/token_tests.clj
@@ -5,7 +5,7 @@
             [buddy.core.hash :as hash]
             [buddy.sign.jws :as jws]
             [buddy.sign.jwe :as jwe]
-            [buddy.auth :refer [throw-unauthorized]]
+            [buddy.auth :refer [throw-unauthorized authenticated?]]
             [buddy.auth.backends.token :as token]
             [buddy.auth.middleware :refer [wrap-authentication wrap-authorization]]))

@@ -54,20 +54,23 @@
   (testing "Jws token backend authentication"
     (let [request (make-jws-request jws-data jws-secret)
           handler (wrap-authentication identity jws-backend)
-          response (handler request)]
-      (is (= (:identity response) jws-data))))
+          request' (handler request)]
+      (is (authenticated? request'))
+      (is (= (:identity request') jws-data))))

   (testing "Jws token backend authentication with wrong key yields nil"
     (let [request (make-jws-request jws-data  "wrong-key")
           handler (wrap-authentication identity jws-backend)
-          response (handler request)]
-      (is (nil? (:identity response)))))
-
-  (testing "Jws token backend authentication with no token yields nil"
+          request' (handler request)]
+      (is (not (authenticated? request')))
+      (is (nil? (:identity request')))))
+
+  (testing "Jws token backend authentication without token yields nil"
     (let [request {}
           handler (wrap-authentication identity jws-backend)
-          response (handler request)]
-      (is (nil? (:identity response)))))
+          request' (handler request)]
+      (is (not (authenticated? request')))
+      (is (nil? (:identity request')))))

   (testing "Jws token authorizaton with wrong key yields 401"
     (let [request (make-jws-request jws-data "wrong-key")
@@ -75,7 +78,8 @@
                       (wrap-authorization jws-backend)
                       (wrap-authentication jws-backend))
           response (handler request)]
-      (is (= (:status response) 401))))
+      (is (= (:status response) 401))
+      (is (= (:body response) "Unauthorized"))))

   (testing "Jws token authorization - authenticated but unathorized thrown yields 403"
     (let [request (make-jws-request {:userid 1} jws-secret)
@@ -83,14 +87,26 @@
                       (wrap-authorization jws-backend)
                       (wrap-authentication jws-backend))
           response (handler request)]
-      (is (= (:status response) 403))))
-
-  (testing "Jws token unathorized - unauth handler called when provided"
+      (is (= (:status response) 403))
+      (is (= (:body response) "Permission denied"))))
+
+  (testing "Jws token unathorized - :unauthorized-handlercalled when provided"
     (let [request (make-jws-request jws-data "wrong-key")
           onerror (fn [_ _] {:status 3000})
           backend (token/jws-backend {:secret jws-secret
                                       :unauthorized-handler onerror})
           handler (-> (fn [req] (throw-unauthorized))
+                      (wrap-authorization backend)
+                      (wrap-authentication backend))
+          response (handler request)]
+      (is (= (:status response) 3000))))
+
+  (testing "Jws token wrongdata - onerror handler called when provided"
+    (let [request (make-jws-request jws-data "wrong-key")
+          onerror (fn [_ _] {:status 3000})
+          backend (token/jws-backend {:secret jws-secret
+                                      :on-error onerror})
+          handler (-> identity
                       (wrap-authorization backend)
                       (wrap-authentication backend))
           response (handler request)]
@@ -115,20 +131,23 @@
   (testing "Jwe token backend authentication"
     (let [request (make-jwe-request jwe-data jwe-secret)
           handler (wrap-authentication identity jwe-backend)
-          response (handler request)]
-      (is (= (:identity response) jwe-data))))
+          request' (handler request)]
+      (is (authenticated? request'))
+      (is (= (:identity request') jwe-data))))

   (testing "Jwe token backend authentication with wrong key yields nil"
     (let [request (make-jwe-request jwe-data (hash/sha256 "wrong-key"))
           handler (wrap-authentication identity jwe-backend)
-          response (handler request)]
-      (is (nil? (:identity response)))))
+          request' (handler request)]
+      (is (not (authenticated? request')))
+      (is (nil? (:identity request')))))

   (testing "Jwe token backend authentication with no token yields nil"
     (let [request {}
           handler (wrap-authentication identity jwe-backend)
-          response (handler request)]
-      (is (nil? (:identity response)))))
+          request' (handler request)]
+      (is (not (authenticated? request')))
+      (is (nil? (:identity request')))))

   (testing "Jwe token authorizaton with wrong key yields 401"
     (let [request (make-jwe-request jwe-data (hash/sha256 "wrong-key"))
@@ -155,7 +174,19 @@
                       (wrap-authorization backend)
                       (wrap-authentication backend))
           response (handler request)]
+      (is (= (:status response) 3000))))
+
+  (testing "Jwe token wrongdata - onerror handler called when provided"
+    (let [request (make-jwe-request jws-data (hash/sha256 "foobar"))
+          onerror (fn [_ _] {:status 3000})
+          backend (token/jwe-backend {:secret jwe-secret
+                                      :on-error onerror})
+          handler (-> identity
+                      (wrap-authorization backend)
+                      (wrap-authentication backend))
+          response (handler request)]
       (is (= (:status response) 3000)))))
+

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Update clj-time dependency to 0.9.0

Update clj-time dependency to 0.9.0

--- ring-core/project.clj
+++ ring-core/project.clj
@@ -9,7 +9,7 @@
                  [ring/ring-codec "1.0.0"]
                  [commons-io "2.4"]
                  [commons-fileupload "1.3"]
-                 [clj-time "0.6.0"]
+                 [clj-time "0.9.0"]
                  [crypto-random "1.2.0"]
                  [crypto-equality "1.0.0"]]
   :profiles


Better examples of tests

Better examples of tests

--- jupiter-launcher/src/sample/clojure.test/sample/other_test.clj
+++ jupiter-launcher/src/sample/clojure.test/sample/other_test.clj
@@ -2,10 +2,13 @@
     (:require [clojure.test :refer :all]))

 (deftest my-other-works
-  (is (= 1 (- 2 1))))
+  (is (= 1 (- 2 1)) "2 - 1 is 1"))

 (deftest my-other-fails
-  (is (= 5 (+ 2 2))))
+  (is (= 5 (+ 2 2)) "2 + 2 is 5"))
+
+(defn do-stuff [_]
+  (throw (ex-info "Yay it works!" {})))

 (deftest my-other-error
-  (throw (ex-info "Yay it works!" {})))
+  (is (= 1 (do-stuff 7)) "Do stuff always returns 1"))


Another vim note

Another vim note

--- resources/fragments/onvim.clj
+++ resources/fragments/onvim.clj
@@ -16,5 +16,6 @@
     [:li "Macros! Macros are the best. (Story about editing 23MB file here, long line lengths, v-a-t, automating in a macro)"]
     [:li "Going backwards through text or shrinking text selections seems arbitrarily hard"]
     [:li "The God-damned pound symbol (aka why I gave up on Emacs more than once) and how it works properly on the commandline for arbitrary reasons, but other keypresses just don't (forward & back in the repl?)"]
-    [:li "You can't contract selections, only expand them (cf. Drew Neil again, c. 47:30). BOOOOO."]]]]]
+    [:li "You can't contract selections, only expand them (cf. Drew Neil again, c. 47:30). BOOOOO."]
+    [:li "Inadvertent deletions: the delete key 'd' is on the home row in command mode, and idly resting your fingers there on a sensitive keyboard, then performing a motion without noticing you've pressed d first, means part of your work can be deleted without realising. This has happened me enough times to be embarrassing."]]]]]


core: reduce

core: reduce

--- core/data/core.clj
+++ core/data/core.clj
@@ -679,12 +679,21 @@
   {:added "1.0"}
   [x] (inc* x))

-(defn ^:private
-  reduce1
+(defn reduce
+  "f should be a function of 2 arguments. If val is not supplied,
+  returns the result of applying f to the first 2 items in coll, then
+  applying f to that result and the 3rd item, etc. If coll contains no
+  items, f must accept no arguments as well, and reduce returns the
+  result of calling f with no arguments.  If coll has only 1 item, it
+  is returned and f is not called.  If val is supplied, returns the
+  result of applying f to val and the first item in coll, then
+  applying f to that result and the 2nd item, etc. If coll contains no
+  items, returns val and f is not called."
+  {:added "1.0"}
   ([f coll]
    (let [s (seq coll)]
      (if s
-       (reduce1 f (first s) (next s))
+       (reduce f (first s) (next s))
        (f))))
   ([f val coll]
    (let [s (seq coll)]
@@ -696,7 +705,7 @@
   "Returns a seq of the items in coll in reverse order. Not lazy."
   {:added "1.0"}
   [coll]
-  (reduce1 conj () coll))
+  (reduce conj () coll))

 (defn +'
   "Returns the sum of nums. (+) returns 0. Supports arbitrary precision.
@@ -706,7 +715,7 @@
   ([x] (cast Number x))
   ([x y] (add'* x y))
   ([x y & more]
-   (reduce1 +' (+' x y) more)))
+   (reduce +' (+' x y) more)))

 (defn +
   "Returns the sum of nums. (+) returns 0. Does not auto-promote
@@ -716,7 +725,7 @@
   ([x] (cast Number x))
   ([x y] (add* x y))
   ([x y & more]
-   (reduce1 + (+ x y) more)))
+   (reduce + (+ x y) more)))

 (defn *'
   "Returns the product of nums. (*) returns 1. Supports arbitrary precision.
@@ -726,7 +735,7 @@
   ([x] (cast Number x))
   ([x y] (multiply'* x y))
   ([x y & more]
-   (reduce1 *' (*' x y) more)))
+   (reduce *' (*' x y) more)))

 (defn *
   "Returns the product of nums. (*) returns 1. Does not auto-promote
@@ -736,7 +745,7 @@
   ([x] (cast Number x))
   ([x y] (multiply* x y))
   ([x y & more]
-   (reduce1 * (* x y) more)))
+   (reduce * (* x y) more)))

 (defn /
   "If no denominators are supplied, returns 1/numerator,
@@ -745,7 +754,7 @@
   ([x] (/ 1 x))
   ([x y] (divide* x y))
   ([x y & more]
-   (reduce1 / (/ x y) more)))
+   (reduce / (/ x y) more)))

 (defn -'
   "If no ys are supplied, returns the negation of x, else subtracts
@@ -755,7 +764,7 @@
   ([x] (subtract'* x))
   ([x y] (subtract'* x y))
   ([x y & more]
-   (reduce1 -' (-' x y) more)))
+   (reduce -' (-' x y) more)))

 (defn -
   "If no ys are supplied, returns the negation of x, else subtracts
@@ -765,7 +774,7 @@
   ([x] (subtract* x))
   ([x y] (subtract* x y))
   ([x y & more]
-   (reduce1 - (- x y) more)))
+   (reduce - (- x y) more)))

 (defn <=
   "Returns non-nil if nums are in monotonically non-decreasing order,
@@ -825,7 +834,7 @@
   ([x] x)
   ([x y] (max* x y))
   ([x y & more]
-   (reduce1 max (max x y) more)))
+   (reduce max (max x y) more)))

 (defn min
   "Returns the least of the nums."
@@ -833,7 +842,7 @@
   ([x] x)
   ([x y] (min* x y))
   ([x y & more]
-   (reduce1 min (min x y) more)))
+   (reduce min (min x y) more)))

 (defn dec'
   "Returns a number one less than num. Supports arbitrary precision.
@@ -879,28 +888,28 @@
   {:added "1.0"}
   ([x y] (bit-and* x y))
   ([x y & more]
-   (reduce1 bit-and (bit-and x y) more)))
+   (reduce bit-and (bit-and x y) more)))

 (defn bit-or
   "Bitwise or"
   {:added "1.0"}
   ([x y] (bit-or* x y))
   ([x y & more]
-   (reduce1 bit-or (bit-or x y) more)))
+   (reduce bit-or (bit-or x y) more)))

 (defn bit-xor
   "Bitwise exclusive or"
   {:added "1.0"}
   ([x y] (bit-xor* x y))
   ([x y & more]
-   (reduce1 bit-xor (bit-xor x y) more)))
+   (reduce bit-xor (bit-xor x y) more)))

 (defn bit-and-not
   "Bitwise and with complement"
   {:added "1.0"}
   ([x y] (bit-and-not* x y))
   ([x y & more]
-   (reduce1 bit-and-not (bit-and-not x y) more)))
+   (reduce bit-and-not (bit-and-not x y) more)))

 (defn bit-clear
   "Clear bit at index n"
@@ -1222,7 +1231,7 @@
   where the keys will be the ordinals."
   {:added "1.0"}
   ([f init coll]
-   (reduce1 (fn [ret kv] (f ret (first kv) (second kv))) init coll)))
+   (reduce (fn [ret kv] (f ret (first kv) (second kv))) init coll)))

 (defn var-get
   "Gets the value in the var object"
@@ -1401,11 +1410,11 @@
   ([f g h & fs]
    (let [fs (list* f g h fs)]
      (fn
-       ([] (reduce1 #(conj %1 (%2)) [] fs))
-       ([x] (reduce1 #(conj %1 (%2 x)) [] fs))
-       ([x y] (reduce1 #(conj %1 (%2 x y)) [] fs))
-       ([x y z] (reduce1 #(conj %1 (%2 x y z)) [] fs))
-       ([x y z & args] (reduce1 #(conj %1 (apply %2 x y z args)) [] fs))))))
+       ([] (reduce #(conj %1 (%2)) [] fs))
+       ([x] (reduce #(conj %1 (%2 x)) [] fs))
+       ([x y] (reduce #(conj %1 (%2 x y)) [] fs))
+       ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs))
+       ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs))))))

 (defn partial
   "Takes a function f and fewer than the normal arguments to f, and
@@ -1640,7 +1649,7 @@
   {:added "1.0"}
   [& maps]
   (when (some identity maps)
-    (reduce1 #(conj (or %1 {}) %2) maps)))
+    (reduce #(conj (or %1 {}) %2) maps)))

 (defn merge-with
   "Returns a map that consists of the rest of the maps conj-ed onto
@@ -1656,8 +1665,8 @@
                             (assoc m k (f (get m k) v))
                             (assoc m k v))))
           merge2 (fn [m1 m2]
-                   (reduce1 merge-entry (or m1 {}) (seq m2)))]
-      (reduce1 merge2 maps))))
+                   (reduce merge-entry (or m1 {}) (seq m2)))]
+      (reduce merge2 maps))))

 (defn zipmap
   "Returns a map with the keys mapped to the corresponding vals."
@@ -2046,7 +2055,7 @@
   [coll]
   (if (set? coll)
     (with-meta coll nil)
-    (reduce1 conj #{} coll)))
+    (reduce conj #{} coll)))

 (defn ^:private filter-key
   [keyfn pred amap]
@@ -2285,9 +2294,9 @@
                                          (if (:as b)
                                            (conj ret (:as b) gmap)
                                            ret))))
-                              bes (reduce1
+                              bes (reduce
                                    (fn [bes entry]
-                                     (reduce1 #(assoc %1 %2 ((val entry) %2))
+                                     (reduce #(assoc %1 %2 ((val entry) %2))
                                               (dissoc bes (key entry))
                                               ((key entry) bes)))
                                    (dissoc b :as :or)
@@ -2313,7 +2322,7 @@
         process-entry (fn [bvec b] (pb bvec (first b) (second b)))]
     (if (every? symbol? (map first bents))
       bindings
-      (reduce1 process-entry [] bents))))
+      (reduce process-entry [] bents))))

 (defmacro let
   "binding => binding-form init-expr
@@ -2427,7 +2436,7 @@
       (let [vs (take-nth 2 (drop 1 bindings))
             bs (take-nth 2 bindings)
             gs (map (fn [b] (if (symbol? b) b (gensym))) bs)
-            bfs (reduce1 (fn [ret [b v g]]
+            bfs (reduce (fn [ret [b v g]]
                            (if (symbol? b)
                              (conj ret g v)
                              (conj ret g v b g)))
@@ -2476,7 +2485,7 @@
                (vector? seq-exprs) "a vector for its binding"
                (even? (count seq-exprs)) "an even number of forms in binding vector")
   (let [to-groups (fn [seq-exprs]
-                    (reduce1 (fn [groups [k v]]
+                    (reduce (fn [groups [k v]]
                                (if (keyword? k)
                                  (conj (pop groups) (conj (peek groups) [k v]))
                                  (conj groups [k v])))
@@ -2710,7 +2719,7 @@
   ([k x] x)
   ([k x y] (if (> (k x) (k y)) x y))
   ([k x y & more]
-   (reduce1 #(max-key k %1 %2) (max-key k x y) more)))
+   (reduce #(max-key k %1 %2) (max-key k x y) more)))

 (defn min-key
   "Returns the x for which (k x), a number, is least."
@@ -2718,7 +2727,7 @@
   ([k x] x)
   ([k x y] (if (< (k x) (k y)) x y))
   ([k x y & more]
-   (reduce1 #(min-key k %1 %2) (min-key k x y) more)))
+   (reduce #(min-key k %1 %2) (min-key k x y) more)))

 (defn distinct
   "Returns a lazy sequence of the elements of coll with duplicates removed."
@@ -2741,7 +2750,7 @@
   {:added "1.0"}
   [smap coll]
   (if (vector? coll)
-    (reduce1 (fn [v i]
+    (reduce (fn [v i]
                (if-let [e (find smap (nth v i))]
                  (assoc v i (val e))
                  v))
@@ -2929,7 +2938,7 @@
   (let [libs (binding [*loaded-libs* #{}]
                (load-one lib need-ns require)
                *loaded-libs*)]
-    (var-set #'*loaded-libs* (reduce1 conj *loaded-libs* libs))))
+    (var-set #'*loaded-libs* (reduce conj *loaded-libs* libs))))

 (defn- load-lib
   "Loads a lib with options"
@@ -3114,7 +3123,7 @@
   is not present, or the not-found value if supplied."
   {:added "1.0"}
   ([m ks]
-   (reduce1 get m ks))
+   (reduce get m ks))
   ([m ks not-found]
    (loop [sentinel {}
           m m


fix new permissions not sliding in properly

--- src-cljs/frontend/components/overlay.cljs
+++ src-cljs/frontend/components/overlay.cljs
@@ -168,7 +168,7 @@
 (defmethod render-access-entity :permission
   [entity cast!]
   (html
-   [:div.access-card.make
+   [:div.access-card.make {:key (:db/id entity)}
     [:div.access-avatar
      [:img.access-avatar-img
       {:src (utils/gravatar-url (:permission/cust entity))}]]
@@ -181,7 +181,7 @@
 (defmethod render-access-entity :access-grant
   [entity cast!]
   (html
-   [:div.access-card.make
+   [:div.access-card.make {:key (:db/id entity)}
     [:div.access-avatar
      [:img.access-avatar-img
       {:src (utils/gravatar-url (:access-grant/email entity))}]]
@@ -194,7 +194,7 @@
 (defmethod render-access-entity :access-request
   [entity cast!]
   (html
-   [:div.access-card.make
+   [:div.access-card.make {:key (:db/id entity)}
     {:class (if (= :access-request.status/denied (:access-request/status entity))
               "denied"
               "requesting")}


Fixed wrong URLs in entry summary.

Fixed wrong URLs in entry summary.

--- src/lambda_blog/templates/entries.clj
+++ src/lambda_blog/templates/entries.clj
@@ -52,9 +52,9 @@
   [ent]
   (page entry ent))

-(defn entry-summary
-  "Creates an HTML article representing a summarized `ent`ry."
-  [{:keys [author contents path path-to-root tags timestamp title] :as ent}]
+(defn embedded-entry
+  "Creates an HTML article representing a summarized `entry` that will be embedded within another `ent`ity."
+  [{:keys [path-to-root] :as ent} {:keys [author contents path tags timestamp title] :as entry}]
   (article
    (header
     (panel
@@ -63,7 +63,7 @@
        (h1 (a {:href (pathcat path-to-root path)}
               title))
        (p "Posted on " (time (format-time "YYYY-MM-dd HH:mm" timestamp))
-          " by " author)
+          " by " (or author (:author ent))) ;; KLUDGE :(
        (entry-tags ent)))))
    contents)) ;; FIXME This should be shortened somehow.

@@ -71,12 +71,12 @@
   "Creates an HTML page containing a list of [[entry-summary]]'ies of `n` most recent `entries` and a link to the `archives`."
   [n {:keys [archives entries path-to-root] :as ent}]
   (page (fn [_]
-          [(map (juxt entry-summary (constantly (hr)))
+          [(map (juxt (partial embedded-entry ent)
+                      (constantly (hr)))
                 (->> entries
                      (sort-by :timestamp)
                      reverse
-                     (take n)
-                     (map (partial merge ent))))
+                     (take n)))
            (-> (a {:href (pathcat path-to-root (:path archives))}
                   "Further reading...")
                h1
@@ -89,15 +89,15 @@
   [{:keys [archives entries id path-to-root] :as ent}]
   (page (fn [_]
           [(panel (text-centered (h1 (format "Tagged %s" id))))
-           (map (juxt entry-summary (constantly (hr)))
+           (map (juxt (partial embedded-entry ent)
+                      (constantly (hr)))
                 (->> entries
                      (filter (fn [{:keys [tags]}]
                                (contains? (into #{}
                                                 (map :id tags))
                                           id)))
                      (sort-by :timestamp)
-                     reverse
-                     (map (partial merge ent))))
+                     reverse))
            (-> (a {:href (pathcat path-to-root (:path archives))}
                   "Archives")
                h1


add failed tests file support (#893)

add failed tests file support (#893)

--- waiter/test/waiter/test_helpers.clj
+++ waiter/test/waiter/test_helpers.clj
@@ -30,7 +30,7 @@
             [waiter.util.client-tools :as ct]
             [waiter.util.date-utils :as du])
   (:import (com.codahale.metrics MetricFilter MetricRegistry)
-           (java.io ByteArrayOutputStream)
+           (java.io ByteArrayOutputStream File)
            (java.net InetAddress URL)
            (javax.servlet ServletOutputStream ServletResponse)))

@@ -69,13 +69,23 @@

 (defonce ^:private test-metrics-run-description
          (System/getenv "TEST_METRICS_RUN_DESCRIPTION"))
+
+(defonce ^:private test-metrics-run-attempt
+         (System/getenv "TEST_METRICS_RUN_ATTEMPT"))
+
+(defonce ^:private test-metrics-failed-tests-file
+         (if-let [given-path (System/getenv "TEST_METRICS_FAILED_TESTS_FILE")]
+           given-path
+           (do
+             (.mkdirs (File. ".test_metrics"))
+             ".test_metrics/last_failed_tests")))

 (defonce ^:private git-repo
          (when test-metrics-url
            (try
              (jgit/load-repo (str (System/getProperty "user.dir") "/.."))
              (catch Throwable _
-               (log/warn "Could not get git repo when trying to report test metrics.")))))
+               (log/info "Could not get git repo when trying to report test metrics.")))))

 (defonce ^:private current-git-branch
          (when git-repo
@@ -103,7 +113,7 @@
   (let [test-meta (meta testing-var)
         namespace (ns-name (:ns test-meta))
         name (:name test-meta)]
-    {:full-name (str name "/" namespace)
+    {:full-name (str namespace "/" name)
      :name name
      :namespace namespace}))

@@ -131,12 +141,14 @@
                  (.setRequestMethod "POST")
                  (.setRequestProperty "content-type" "application/json")
                  (.setUseCaches false)
+                 (.setReadTimeout 10000)
+                 (.setConnectTimeout 10000)
                  (.connect))]
       (with-open [writer (io/writer (.getOutputStream conn))]
         (.write writer json))
       (.getResponseCode conn))
     (catch Throwable e
-      (log/error "Failed to post test metrics json " e url json)
+      (log/error e "Failed to post test metrics json " url json)
       (throw e))))

 (defn blue [message] (str ANSI-BLUE message ANSI-RESET))
@@ -162,7 +174,8 @@

 (let [running-tests (atom {})
       start-millis (atom {})
-      test-durations (atom {})]
+      test-durations (atom {})
+      failed-tests (atom #{})]
   (defn- log-running-tests []
     (let [tests @running-tests]
       (log/debug (count tests) "running test(s):" tests))
@@ -195,6 +208,8 @@
                   test-failed? (> (+ num-fails num-errors) 0)
                   result (if test-failed? "failed" (if test-skipped? "skipped" "passed"))
                   es-index (str "waiter-tests-" (du/date-to-str (t/now) (f/formatters :basic-date)))]
+              (when test-failed?
+                (swap! failed-tests conj full-name))
               ;TODO: can check for outstanding commits: (println (jgit/git-status git-repo))
               (post-json (str test-metrics-url "/" es-index "/test-result")
                          (json/write-str {:build-id test-metrics-build-id
@@ -206,6 +221,7 @@
                                           :host hostname
                                           :project "waiter"
                                           :result result
+                                          :run-attempt test-metrics-run-attempt
                                           :run-description test-metrics-run-description
                                           :run-id test-metrics-run-id
                                           :runtime-milliseconds elapsed-millis
@@ -214,7 +230,7 @@
                                           :timestamp (du/date-to-str (t/now))
                                           :user username})))
             (catch Throwable e
-              (log/error "Failed to post test metrics " e test-metrics-url)))))
+              (log/error e "Failed to post test metrics " test-metrics-url)))))
       (log-running-tests)))

   (defmethod report :summary [m]
@@ -228,6 +244,10 @@
       (println "\nRan" (:test m) "tests containing"
                (+ (:pass m) (:fail m) (:error m)) "assertions.")
       (println (:fail m) "failures," (:error m) "errors.")
+      (try
+        (spit test-metrics-failed-tests-file (json/write-str {:failed-tests @failed-tests}))
+        (catch Exception e
+          (log/error e "Failed to write out failed tests " test-metrics-failed-tests-file @failed-tests)))
       (when http-client (http/stop-client! http-client)))))

 ;; Overrides the default reporter for :error so that the ex-data of


Update clj-semver

Update clj-semver

--- build.boot
+++ build.boot
@@ -9,7 +9,7 @@
    [cheshire "5.6.1"]
    [throttler "1.0.0"]
    [org.slf4j/slf4j-nop "1.7.21"]
-   [grimradical/clj-semver "0.3.0-20130920.191002-3" :exclusions [org.clojure/clojure]]
+   [grimradical/clj-semver "0.3.0" :exclusions [org.clojure/clojure]]
    ; testing
    [org.clojure/test.check "0.9.0" :scope "test"]
    [clj-http-fake "1.0.2" :scope "test"]


Update several dependencies

Update several dependencies

--- build.boot
+++ build.boot
@@ -1,7 +1,7 @@
 (set-env!
  :source-paths #{"src/clj" "src/cljs"}
- :dependencies '[[adzerk/boot-cljs "1.7.228-1"]
-                 [adzerk/boot-reload "0.4.12"]
+ :dependencies '[[adzerk/boot-cljs "2.0.0"]
+                 [adzerk/boot-reload "0.5.1"]
                  [pandeiro/boot-http "0.7.3"]
                  [ring "1.5.0"]
                  [amalloy/ring-gzip-middleware "0.1.3"]


Re-enable the cljs repl

Re-enable the cljs repl

--- build.boot
+++ build.boot
@@ -32,6 +32,7 @@
                          (:test
                            [plumula/mimolette "0.2.0"])))

+(require '[adzerk.boot-cljs-repl :refer [start-repl]])
 (task-options!
   pom #(assoc % :description "A library for representing documents and changes to documents."
                 :url "https://github.com/plumula/delta"


kick-it on reload

kick-it on reload

--- clojure/src/dnd/core.cljs
+++ clojure/src/dnd/core.cljs
@@ -128,4 +128,4 @@

 (set! *main-cli-fn* -main)

-
+(when term (kick-it term))


attempt to work around resolve issues in CLJS 1.10.439

https://dev.clojure.org/jira/browse/CLJS-712
https://dev.clojure.org/jira/browse/CLJS-2957

--- src/main/shadow/build/cljs_hacks.cljc
+++ src/main/shadow/build/cljs_hacks.cljc
@@ -193,28 +193,6 @@
                (confirm env full-ns sym))
              (resolve-ns-var full-ns sym current-ns))

-           ;; FIXME: would this not be better handled if checked before calling resolve-var
-           ;; and analyzing this properly?
-           (ana/dotted-symbol? sym)
-           (let [idx (.indexOf s ".")
-                 prefix (symbol (subs s 0 idx))
-                 suffix (subs s (inc idx))]
-             (if-some [lb (handle-symbol-local prefix (get locals prefix))]
-               {:op :local
-                :name (symbol (str (:name lb)) suffix)}
-               (if-some [full-ns (ana/gets current-ns-info :imports prefix)]
-                 {:op :local
-                  :name (symbol (str full-ns) suffix)}
-                 (if-some [info (ana/gets current-ns-info :defs prefix)]
-                   (merge info
-                     {:op :local
-                      :name (symbol (str current-ns) (str sym))
-                      :ns current-ns})
-                   (merge (ana/gets @env/*compiler* ::ana/namespaces prefix :defs (symbol suffix))
-                     {:op :local
-                      :name (if (= "" prefix) (symbol suffix) (symbol (str prefix) suffix))
-                      :ns prefix})))))
-
            (some? (ana/gets current-ns-info :uses sym))
            (let [full-ns (ana/gets current-ns-info :uses sym)]
              (resolve-ns-var full-ns sym current-ns))
@@ -248,6 +226,77 @@

            (invokeable-ns? s env)
            (resolve-invokeable-ns s current-ns env)
+
+           ;; any symbol with a dot but no namespace, already checked all renames/imports/requires
+           ;; so that (:require ["some-js" :as foo.bar]) (foo.bar)
+           ;; works properly and isn't desugared into anything else
+           (ana/dotted-symbol? sym)
+           (let [idx (.indexOf s ".")
+                 prefix (subs s 0 idx)
+                 prefix-sym (symbol prefix)
+                 suffix (subs s (inc idx))]
+             (if-some [lb (handle-symbol-local prefix-sym (get locals prefix-sym))]
+               {:op :local
+                :name (symbol (str (:name lb) "." suffix))}
+               (if-some [full-ns (ana/gets current-ns-info :imports prefix-sym)]
+                 {:op :local
+                  :name (symbol (str full-ns) suffix)}
+                 (if-some [info (ana/gets current-ns-info :defs prefix-sym)]
+                   (merge info
+                     {:op :local
+                      :name (symbol (str current-ns) (str sym))
+                      :ns current-ns})
+
+                   ;; attempt to fix
+                   ;; https://dev.clojure.org/jira/browse/CLJS-712
+                   ;; https://dev.clojure.org/jira/browse/CLJS-2957
+                   ;; FIXME: patch this properly in clojurescript so we don't need this hackery
+
+                   ;; CLJS defaults to just resolving everything with a dot in it and is completely broken
+                   ;; process.env.FOO ends up as process/env.FOO and never warns
+                   ;; cljs.core.-invoke ends up as cljs/core.-invoke
+                   ;; ANY symbol with a dot should not automatically resolve magically without any further checks
+
+                   ;; I don't see how this could ever resolve something useful but this is what CLJS does
+                   (if-let [last-hope (ana/gets @env/*compiler* ::ana/namespaces prefix-sym :defs (symbol suffix))]
+                     (merge last-hope
+                       {:op :local
+                        :name (if (= "" prefix-sym) (symbol suffix) (symbol (str prefix-sym) suffix))
+                        :ns prefix-sym})
+
+                     ;; cljs.core.-invoke was split into cljs | core.-invoke
+                     ;; if the prefix is a known namespace root at least try to turn it into a valid symbol
+                     ;; by using the last dot instead of first. cljs.core.-invoke -> cljs.core/-invoke
+                     (let [ns-roots (:shadow/ns-roots @env/*compiler*)]
+                       (if (contains? ns-roots prefix)
+                         (let [last-dot (str/last-index-of s ".")
+                               guessed-ns (symbol (subs s 0 last-dot))
+                               guessed-sym (symbol (subs s (inc last-dot)))]
+
+                           ;; this path happens way too often and should be fixed properly
+                           #_(log/debug ::autofix-symbol
+                               {:sym sym
+                                :prefix prefix
+                                :suffix suffix
+                                :guessed-ns guessed-ns
+                                :guessed-sym guessed-sym})
+
+                           (merge (ana/gets @env/*compiler* ::ana/namespaces guessed-ns :defs guessed-sym)
+                             {:op :var
+                              :name (symbol (str guessed-ns) (str guessed-sym))
+                              :ns guessed-ns}))
+
+                         ;; not known namespace root, resolve as js/ as a last ditch effort
+                         ;; this should probably hard fail instead but that would break too many builds
+                         ;; resolving as js/* is closer to the default behavior
+                         ;; and will most likely be for cases where we are actually accessing a global
+                         ;; ala process.env.FOO which will then warn properly
+                         (do (when (some? confirm)
+                               (confirm env current-ns sym))
+                             {:op :js-var
+                              :name (symbol "js" s)
+                              :ns 'js}
+                             ))))))))

            :else
            (do (when (some? confirm)


fix docstring.

fix docstring.

--- src/metabase/models/pulse_channel.clj
+++ src/metabase/models/pulse_channel.clj
@@ -131,15 +131,17 @@
 ;; ## Persistence Functions

 (defn retrieve-scheduled-channels
-  "Fetch all `PulseChannels` that are scheduled to run given the current hour and day.
-
-   Example:
-       (retrieve-scheduled-channels 14 \"mon\")
+  "Fetch all `PulseChannels` that are scheduled to run at a given time described by HOUR, WEEKDAY, MONTHDAY, and MONTHWEEK.
+
+   Examples:
+       (retrieve-scheduled-channels 14 \"mon\" :first :first)  -  2pm on the first Monday of the month
+       (retrieve-scheduled-channels 8 \"wed\" :other :last)    -  8am on Wednesday of the last week of the month

    Based on the given input the appropriate `PulseChannels` are returned:
-     * no input returns any channel scheduled for HOURLY delivery only.
-     * just `hour` input returns any HOURLY scheduled channels + DAILY channels for the chosen hour.
-     * when `hour` and `day` are supplied we return HOURLY channels + DAILY channels + WEEKLY channels."
+     * HOURLY scheduled channels are always included.
+     * DAILY scheduled channels are included if the HOUR matches.
+     * WEEKLY scheduled channels are included if the WEEKDAY & HOUR match.
+     * MONTHLY scheduled channels are included if the MONTHDAY, MONTHWEEK, WEEKDAY, & HOUR all match."
   [hour weekday monthday monthweek]
   [:pre [(integer? hour)
          (day-of-week? weekday)


Add documentation

Add documentation

--- src/oxcart.clj
+++ src/oxcart.clj
@@ -27,12 +27,34 @@
   @#'clojure.core/root-directory)

 (def ^:dynamic *load-configuration*
+  "Dynamic var that oxcart/load uses to stash its configuration.
+
+  Because load invocations may be recursive thanks to use, require and
+  literal load uses in order for a load to capture all the compilation
+  requested into a configuration containing AST atoms the AST atoms
+  must be made visible to subsequent invocations of oxcart/load. This
+  var combined with the single arity case of oxcart/load provides the
+  required configuration persistance.
+
+  nil by default, may be a valid configuration map for oxcart/load."
   nil)
+

 (defn atom? [x]
   (instance? clojure.lang.Atom x))

+
 (defn eval
+  "λ form → value
+   λ form → config-map → value
+
+  Form is any Clojure sexpr, config map is a load configuration and
+  value is an arbitrary Clojure value or class.
+
+  Analyzes the form argument via tools.analyzer.jvm, emits the
+  appropriate bytecode and returns a computed result side effecting
+  the invoking Clojure runtime."
+
   ([form]
      (eval form {:debug? false}))

@@ -93,6 +115,27 @@

 (defn load
+  "λ String → nil
+   λ String → config-map → nil
+
+  Loads a resource on the classpath identified by a string path as
+  clojure code via eval for side-effects against the invoking Clojure
+  runtime.
+
+  config-map:
+    If config-map is not provided, it will default to the value of
+    *load-configuration* or {:debug? false}.
+
+    If config contains a :debug? key, then printing of the generated
+    class bytecode and other development information is enabled.
+
+    If config contains an atom at [:ast :defs] the ASTs of all def
+    symbols will be assoc'd into that atom keyed on the symbol they
+    define. Multiple definitions will overwrite each other.
+
+    If config contains an atom at [:ast :forms] the ASTs of all read
+    forms will be conj'd to it in reading & evaluation order."
+
   ([res]
      (load res
            (or *load-configuration*
@@ -108,7 +151,8 @@
            reader (readers/indexing-push-back-reader file 1 p)]
        (binding [*ns*                 *ns*
                  *file*               p
-                 *load-configuration* options]
+                 *load-configuration* options
+                 clojure.core/load    oxcart/load]
          (loop []
            (let [form (r/read reader false eof)]
              (when (not= eof form)


change nrepl-select to only allow select when a JS runtime is connected

--- src/main/shadow/cljs/devtools/api.clj
+++ src/main/shadow/cljs/devtools/api.clj
@@ -247,10 +247,19 @@
      (catch Exception e
        (e/user-friendly-error e)))))

+(defn repl-client-connected? [worker]
+  (not (empty? (-> worker :state-ref deref :eval-clients))))
+
 (defn nrepl-select [id]
   (let [worker (get-worker id)]
-    (if-not worker
+    (cond
+      (nil? worker)
       [:no-worker id]
+
+      (not (repl-client-connected? worker))
+      [:no-client id "Please load your JS to connect to the REPL."]
+
+      :else
       (do (set! *nrepl-cljs* id)

           ;; doing this to make cider prompt not show "user" as prompt after calling this


Add per-query tunable consistency-level and retry policy

--- src/clojure/clojurewerkz/cassaforte/client.clj
+++ src/clojure/clojurewerkz/cassaforte/client.clj
@@ -2,18 +2,105 @@
   (:require [clojurewerkz.cassaforte.debug-utils :as debug-utils]
             [clojurewerkz.cassaforte.conversion :as conv])
   (:import [com.datastax.driver.core Query ResultSet ResultSetFuture Host Session Cluster
-            Cluster$Builder SimpleStatement PreparedStatement Query HostDistance PoolingOptions]
+            Cluster$Builder SimpleStatement PreparedStatement Query HostDistance PoolingOptions
+            ConsistencyLevel]
            [com.google.common.util.concurrent Futures FutureCallback]
            [com.datastax.driver.core.policies
             LoadBalancingPolicy DCAwareRoundRobinPolicy RoundRobinPolicy TokenAwarePolicy
             LoggingRetryPolicy DefaultRetryPolicy DowngradingConsistencyRetryPolicy FallthroughRetryPolicy
             RetryPolicy ConstantReconnectionPolicy ExponentialReconnectionPolicy]))

+;;
+;; Load Balancing policies
+;;
+
+(defn round-robin-policy
+  "Round-robin load balancing policy. Each next query is ran on the node that was contacted
+  least recently."
+  []
+  (RoundRobinPolicy.))
+
+(defn dc-aware-round-robin-policy
+  "Datacenter aware load balancing policy. Each next query is ran on the node that was contacted
+  least recently, over the nodes located in current datacenter. Nodes from other datacenters will
+  be tried only after the local nodes."
+  [^String local-dc]
+  (DCAwareRoundRobinPolicy. local-dc))
+
+(defn token-aware-policy
+  "Wrapper to add token-awareness to the underlying policy."
+  [^LoadBalancingPolicy underlying-policy]
+  (TokenAwarePolicy. underlying-policy))
+
+;;
+;; Retry policies
+;;
+
+(def retry-policies {:default                 (constantly DefaultRetryPolicy/INSTANCE)
+                     :downgrading-consistency (constantly DowngradingConsistencyRetryPolicy/INSTANCE)
+                     :fallthrough             (constantly FallthroughRetryPolicy/INSTANCE)})
+
+(defn retry-policy
+  [rp]
+  ((rp retry-policies)))
+
+(defn logging-retry-policy
+  "A retry policy that wraps another policy, logging the decision made by its sub-policy."
+  [^RetryPolicy policy]
+  (LoggingRetryPolicy. policy))
+
+;;
+;; Reconnection policies
+;;
+
+(defn exponential-reconnection-policy
+  "Reconnection policy that waits exponentially longer between each
+reconnection attempt (but keeps a constant delay once a maximum delay is
+reached).
+
+   Delays should be given in milliseconds"
+  [base-delay-ms max-delay-ms]
+  (ExponentialReconnectionPolicy. base-delay-ms max-delay-ms))
+
+(defn constant-reconnection-policy
+  "Reconnection policy that waits constantly longer between each
+reconnection attempt (but keeps a constant delay once a maximum delay is
+reached).
+
+   Delay should be given in milliseconds"
+  [delay-ms]
+  (ConstantReconnectionPolicy. delay-ms))
+
+;;
+;; Consistency Level
+;;
+
+(def consistency-levels
+  {:any ConsistencyLevel/ANY
+   :one ConsistencyLevel/ONE
+   :two ConsistencyLevel/TWO
+   :three ConsistencyLevel/THREE
+   :quorum ConsistencyLevel/QUORUM
+   :all ConsistencyLevel/ALL
+   :local-quorum ConsistencyLevel/LOCAL_QUORUM
+   :each-quorum ConsistencyLevel/EACH_QUORUM})
+
+(defn consistency-level
+  [kl]
+  (kl consistency-levels))
+
+;;
+;; Client-related
+;;
+
 (def ^:dynamic *default-cluster*)
 (def ^:dynamic *default-session*)
 (def ^:dynamic *async* false)
 (def ^:dynamic *debug* false)

+(def ^:dynamic *consistency-level* (consistency-level :one))
+(def ^:dynamic *retry-policy* (retry-policy :default))
+
 (defmacro with-session
   "Executes query with given session"
   [session & body]
@@ -24,6 +111,18 @@
   "Executes query with debug output"
   [& body]
   `(binding [*async* true]
+     ~@body))
+
+(defmacro with-consistency-level
+  "Executes query given consistency level"
+  [consistency-level & body]
+  `(binding [*consistency-level* consistency-level]
+     ~@body))
+
+(defmacro with-retry-policy
+  "Executes query given retry policy"
+  [retry-policy & body]
+  `(binding [*retry-policy* retry-policy]
      ~@body))

 (defmacro with-debug
@@ -32,11 +131,19 @@
   `(binding [*debug* true]
      (debug-utils/catch-exceptions ~@body)))

+(defn- set-statement-options-
+  [^Query statement]
+  (when *retry-policy*
+    (.setRetryPolicy statement *retry-policy*))
+  (when *consistency-level*
+    (.setConsistencyLevel statement *consistency-level*))
+  statement)
+
 (defn build-statement
   ([^PreparedStatement query args]
-     (.bind query (to-array args)))
+     (set-statement-options- (.bind query (to-array args))))
   ([^String string-query]
-     (SimpleStatement. string-query)))
+     (set-statement-options- (SimpleStatement. string-query))))

 (defn ^PreparedStatement prepare
   [^String query]
@@ -46,7 +153,16 @@
   [{:keys [contact-points
            port
            connections-per-host
-           max-connections-per-host]}]
+           max-connections-per-host
+
+           consistency-level
+           retry-policy]}]
+  (when consistency-level
+    (alter-var-root (var *consistency-level*) (constantly consistency-level)))
+
+  (when retry-policy
+    (alter-var-root (var *retry-policy*) (constantly retry-policy)))
+
   (let [^Cluster$Builder builder        (Cluster/builder)
         ^PoolingOptions pooling-options (.poolingOptions builder)]
     (when port
@@ -121,64 +237,6 @@
 ;; defn rebuild-schema

 ;;
-;; Round-robin policies
-;;
-
-(defn round-robin-policy
-  "Round-robin load balancing policy. Each next query is ran on the node that was contacted
-  least recently."
-  []
-  (RoundRobinPolicy.))
-
-(defn dc-aware-round-robin-policy
-  "Datacenter aware load balancing policy. Each next query is ran on the node that was contacted
-  least recently, over the nodes located in current datacenter. Nodes from other datacenters will
-  be tried only after the local nodes."
-  [^String local-dc]
-  (DCAwareRoundRobinPolicy. local-dc))
-
-(defn token-aware-policy
-  "Wrapper to add token-awareness to the underlying policy."
-  [^LoadBalancingPolicy underlying-policy]
-  (TokenAwarePolicy. underlying-policy))
-
-;;
-;; Retry policies
-;;
-
-(def retry-policies {:default                 DefaultRetryPolicy/INSTANCE
-                     :downgrading-consistency DowngradingConsistencyRetryPolicy/INSTANCE
-                     :fallthrough             FallthroughRetryPolicy/INSTANCE})
-
-(defn logging-retry-policy
-  "A retry policy that wraps another policy, logging the decision made by its sub-policy."
-  [^RetryPolicy policy]
-  (LoggingRetryPolicy. policy))
-
-;;
-;; Reconnection policies
-;;
-
-(defn exponential-reconnection-policy
-  "Reconnection policy that waits exponentially longer between each
-reconnection attempt (but keeps a constant delay once a maximum delay is
-reached).
-
-   Delays should be given in milliseconds"
-  [base-delay-ms max-delay-ms]
-  (ExponentialReconnectionPolicy. base-delay-ms max-delay-ms))
-
-(defn constant-reconnection-policy
-  "Reconnection policy that waits constantly longer between each
-reconnection attempt (but keeps a constant delay once a maximum delay is
-reached).
-
-   Delay should be given in milliseconds"
-  [delay-ms]
-  (ConstantReconnectionPolicy. delay-ms))
-
-
-;;
 ;;
 ;;


Show multiples

Show multiples

--- src/om_animation_playground/core.cljs
+++ src/om_animation_playground/core.cljs
@@ -7,9 +7,19 @@

 (def app-state (atom {:tick 0}))

+(defn multiples
+  [upper-limit]
+  (reduce (fn [acc n]
+            (if (= (mod upper-limit n) 0)
+              (conj acc n)
+              acc))
+          []
+          (range 2 (inc upper-limit))))
+
 (defcomponent app
   (render
-   (dom/div nil (:tick data))))
+   (let [{:keys [tick]} data]
+     (dom/div nil (str (multiples tick))))))

 (defn app-loop-tick
   []
@@ -25,6 +35,6 @@
    app
    app-state
    {:target (. js/document (getElementById "my-app"))})
-  (init-app-loop 300))
+  (init-app-loop 500))

 (init!)


No need to write out the lyrics because we have them embedded in clojure itself (including the accent).

--- src/overtunes/songs/frere_jacques.clj
+++ src/overtunes/songs/frere_jacques.clj
@@ -3,18 +3,13 @@
   (:use [overtunes.core])
   (:use [overtunes.instruments.foo]))

-;; Frère Jacques, frère Jacques,
-;; Dormez-vous? Dormez-vous?
-;; Sonnez les matines! Sonnez les matines!
-;; Din, dan, don. Din, dan, don.
-
-(def frere-jacques [:C4 :D4 :E4 :C4])
+(def frère-jacques [:C4 :D4 :E4 :C4])
 (def dormez-vous [:E4 :F4 :G4 :rest])
 (def sonnez-les-matines [:G4 :G4 :E4 :C4])
 (def din-dan-don [:C4 :G3 :C4 :rest])

 (def melody (concat
-  frere-jacques frere-jacques
+  frère-jacques frère-jacques
   dormez-vous dormez-vous
   sonnez-les-matines sonnez-les-matines
   din-dan-don din-dan-don


defaults do not work that way

defaults do not work that way

--- src/buyme_aggregation_backend/sources.clj
+++ src/buyme_aggregation_backend/sources.clj
@@ -25,11 +25,11 @@
               :stopped (let [command (<! command-ch)]
                          (condp = command
                            :start :running
-                           :default :stopped))
+                           :stopped))
               :running (alt!
                          command-ch ([command] (condp = command
                                                  :stop :shutdown
-                                                 :default :running))
+                                                 :running))
                          fetch-timer-ch (do
                                           (println "got a chime")
                                           :running)))]


Sync JUnit XML from Go

Sync JUnit XML from Go

--- scripts/gosync.clj
+++ scripts/gosync.clj
@@ -93,22 +93,62 @@
         pipelines (:pipelines pipelineGroup)]
     (mapcat stages-for-pipeline pipelines)))

+;; /files/%pipeline/%run/%stage/%run/job.json
+
+(defn looks-like-xml? [file-name]
+  (.endsWith file-name "xml"))
+
+(defn filter-xml-files [file-node]
+  (if (= "folder" (:type file-node))
+    (mapcat filter-xml-files (:files file-node))
+    (if (looks-like-xml? (:name file-node))
+      (list (:url file-node))
+      [])))
+
+(defn xml-artifacts-for-job-run [{pipeline-name :pipelineName
+                                  pipeline-run :pipelineRun
+                                  stage-name :stageName
+                                  stage-run :stageRun
+                                  job-name :jobName}]
+  (let [artifacts-url (format "/files/%s/%s/%s/%s/%s.json" pipeline-name pipeline-run stage-name stage-run job-name)
+        file-tree (get-json artifacts-url)]
+    (mapcat filter-xml-files file-tree)))
+
+(defn augment-job-instance-with-junit-xml [job-instance]
+  (if-let [xml-file-url (first (xml-artifacts-for-job-run job-instance))]
+    (assoc job-instance
+           :junit-xml-func
+           (fn []
+             (println xml-file-url)
+             (:body (client/get xml-file-url))))
+    job-instance))

 ;; upload

 (defn make-build-instance [{jobName :jobName stageName :stageName pipelineName :pipelineName
                             stageRun :stageRun pipelineRun :pipelineRun
+                            junit-xml-func :junit-xml-func
                             inputs :inputs build :build}]
   {:jobName (format "%s %s %s" pipelineName stageName jobName)
    :buildNo (format "%s %s" pipelineRun stageRun)
+   :junit-xml-func junit-xml-func
    :build (assoc build :inputs inputs)})

+(defn put-build [job-name build-no build]
+  (client/put (format "http://localhost:3000/builds/%s/%s" job-name build-no)
+              {:content-type :json
+               :body (j/generate-string build)}))
+
+(defn put-junit-xml [job-name build-no xml-content]
+  (client/put (format "http://localhost:3000/builds/%s/%s/testresults" job-name build-no)
+              {:body xml-content}))
+
 (defn put-to-buildviz [builds]
-  (doseq [{jobName :jobName buildNo :buildNo build :build} builds]
+  (doseq [{jobName :jobName buildNo :buildNo build :build junit-xml-func :junit-xml-func} builds]
     (println jobName buildNo build)
-    (client/put (format "http://localhost:3000/builds/%s/%s" jobName buildNo)
-                {:content-type :json
-                 :body (j/generate-string build)})))
+    (put-build jobName buildNo  build)
+    (when (some? junit-xml-func)
+      (put-junit-xml jobName buildNo (junit-xml-func)))))

 (def job-instances
   (->> (concat (stages-for-pipeline-group "Development")
@@ -116,6 +156,7 @@
                (stages-for-pipeline-group "Production"))
        (mapcat job-instances-for-stage)
        (map augment-job-with-inputs)
-       (map job-data-for-instance)))
+       (map job-data-for-instance)
+       (map augment-job-instance-with-junit-xml)))

 (put-to-buildviz (map make-build-instance job-instances))


Fix tab fade in being instant

Fix tab fade in being instant

--- src/cljs/gtfve/components/side_panel.cljs
+++ src/cljs/gtfve/components/side_panel.cljs
@@ -93,15 +93,23 @@
     om/IDidMount
     (did-mount [_]
       (let [{:keys [toggle-ch kill-ch]} (om/get-state owner)
-            transition-ch (utils/listen
-                           (om/get-node owner)
-                           EventType.TRANSITIONEND
-                           (chan 1 (comp
-                                    (filter #(and (= "opacity" (.. % -event_ -propertyName))
-                                                  (let [classList (.. % -target -classList)]
-                                                    (and
-                                                     (.contains classList "tab-pane")
-                                                     (.contains classList "fade"))))))))
+            tab-pane-filter   (filter #(.. % -target -classList (contains "tab-pane")))
+            fade-filter       (filter #(.. % -target -classList (contains "fade")))
+            not-active-filter (filter #(not (.. % -target -classList (contains "active"))))
+            opacity-filter    (filter #(= "opacity" (.. % -event_ -propertyName)))
+            mutations-ch      (utils/mutation-listen (om/get-node owner)
+                                                     #js {:subtree true
+                                                          :attributes true
+                                                          :attributeFilter #js ["class"]}
+                                                     (chan 1 (comp
+                                                              tab-pane-filter
+                                                              not-active-filter)))
+            transition-ch     (utils/listen (om/get-node owner)
+                                            EventType.TRANSITIONEND
+                                            (chan 1 (comp
+                                                     opacity-filter
+                                                     fade-filter
+                                                     tab-pane-filter)))
             active-in-ch (chan 1)]
         (go-loop []
           (let [[v c] (alts! [active-in-ch toggle-ch kill-ch])]
@@ -114,7 +122,9 @@
                               (<! transition-ch)
                               (om/set-state! owner :active v)
                               (>! active-in-ch v))
-                  active-in-ch (om/set-state! owner :in v))
+                  active-in-ch (do
+                                 (<! mutations-ch)
+                                 (om/set-state! owner :in v)))
                 (recur)))))))
     om/IWillUnmount
     (will-unmount [_]


Add request helper on http

Add request helper on http

--- src/com/wsscode/pathom/diplomat/http.cljc
+++ src/com/wsscode/pathom/diplomat/http.cljc
@@ -22,7 +22,13 @@

 (s/def ::response (s/keys :req [::headers]))

-(defn request [req])
+(defn request
+  ([{::keys [driver] :as request}]
+   (driver request))
+  ([{::keys [driver] :as request} url]
+   (driver (assoc request ::url url)))
+  ([{::keys [driver] :as request} url config]
+   (driver (merge request {::url url} config))))

 (s/fdef request
   :args (s/cat :req ::request)


Fix a test broken by a previous change to the list of non-escaped markup characters

--- src/test/clojure/cascade/test_dom.clj
+++ src/test/clojure/cascade/test_dom.clj
@@ -93,4 +93,4 @@
     "one < 2" "one < 2"
     "two > one" "two > one"
     "Calvin & Hobbes" "Calvin & Hobbes"
-    (str "What's this: " (char 128) (char 31)) "What's this: €"))+    (str "What's this: " (char 128) (char 31)) "What's this: €"))


refactoring of selection code

refactoring of selection code

--- cljs/src/main/plastic/cogs/editor/ops/selection.cljs
+++ cljs/src/main/plastic/cogs/editor/ops/selection.cljs
@@ -27,56 +27,53 @@
     (if-let [result-id (op (get structural-web selected-id))]
       (editor/set-selection editor #{result-id}))))

-(defn find-first-non-empty-line [spatial-web line op]
+(defn find-first-non-empty-line-in-given-direction [spatial-web line op]
   (first (drop-while #(and (not (nil? %)) (empty? %)) (map spatial-web (iterate op (op line))))))
+
+(defn spatial-movement-up-down [editor dir-fun]
+  (let [selected-id (get-selected-node-id editor)
+        render-info (editor/get-focused-render-info editor)
+        {:keys [spatial-web all-selections]} render-info
+        sel-node (get all-selections selected-id)
+        line-selectables (find-first-non-empty-line-in-given-direction spatial-web (:line sel-node) dir-fun)
+        line-selections (map #(get all-selections (:id %)) line-selectables)]
+    (if-let [result (find-best-spatial-match sel-node line-selections)]
+      (editor/set-selection editor #{(:id result)}))))
+
+(defn spatial-movement-left-right [editor dir-fun]
+  (let [selected-id (get-selected-node-id editor)
+        render-info (editor/get-focused-render-info editor)
+        {:keys [spatial-web all-selections]} render-info
+        sel-node (get all-selections selected-id)
+        line-selectables (get spatial-web (:line sel-node))]
+    (if-let [result (dir-fun #(= (:id %) selected-id) line-selectables)]
+      (editor/set-selection editor #{(:id result)}))))
+
+(defn move-to-form [editor dir-fun next-sel-fun]
+  (let [focused-form-id (editor/get-focused-form-id editor)
+        top-level-ids (editor/get-top-level-form-ids editor)
+        next-focused-form-id (dir-fun #(= % focused-form-id) top-level-ids)]
+    (if next-focused-form-id
+      (let [next-selection (next-sel-fun editor next-focused-form-id)]
+        (-> editor
+          (editor/set-focused-form-id next-focused-form-id)
+          (editor/set-selection #{next-selection}))))))

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

 (defmulti op (fn [op-type & _] op-type))

 (defmethod op :spatial-down [_ editor]
-  (let [selected-id (get-selected-node-id editor)
-        render-info (editor/get-focused-render-info editor)
-        {:keys [spatial-web all-selections]} render-info
-        sel-node (get all-selections selected-id)
-        line-selectables (find-first-non-empty-line spatial-web (:line sel-node) inc)
-        line-selections (map #(get all-selections (:id %)) line-selectables)
-        result (find-best-spatial-match sel-node line-selections)]
-    (if result
-      (editor/set-selection editor #{(:id result)}))))
+  (spatial-movement-up-down editor inc))

 (defmethod op :spatial-up [_ editor]
-  (let [selected-id (get-selected-node-id editor)
-        render-info (editor/get-focused-render-info editor)
-        {:keys [spatial-web all-selections]} render-info
-        sel-node (get all-selections selected-id)
-        line-selectables (find-first-non-empty-line spatial-web (:line sel-node) dec)
-        line-selections (map #(get all-selections (:id %)) line-selectables)
-        result (find-best-spatial-match sel-node line-selections)]
-    (if result
-      (editor/set-selection editor #{(:id result)}))))
+  (spatial-movement-up-down editor dec))

 (defmethod op :spatial-right [_ editor]
-  (let [selected-id (get-selected-node-id editor)
-        render-info (editor/get-focused-render-info editor)
-        {:keys [spatial-web all-selections]} render-info
-        sel-node (get all-selections selected-id)
-        sel-line (:line sel-node)
-        line-selectables (get spatial-web sel-line)
-        result (helpers/next-item #(= (:id %) selected-id) line-selectables)]
-    (if result
-      (editor/set-selection editor #{(:id result)}))))
+  (spatial-movement-left-right editor helpers/next-item))

 (defmethod op :spatial-left [_ editor]
-  (let [selected-id (get-selected-node-id editor)
-        render-info (editor/get-focused-render-info editor)
-        {:keys [spatial-web all-selections]} render-info
-        sel-node (get all-selections selected-id)
-        sel-line (:line sel-node)
-        line-selectables (get spatial-web sel-line)
-        result (helpers/prev-item #(= (:id %) selected-id) line-selectables)]
-    (if result
-      (editor/set-selection editor #{(:id result)}))))
+  (spatial-movement-left-right editor helpers/prev-item))

 (defmethod op :structural-up [_ editor]
   (structural-movemement editor :up))
@@ -91,24 +88,10 @@
   (structural-movemement editor :right))

 (defmethod op :move-prev-form [_ editor]
-  (let [focused-form-id (editor/get-focused-form-id editor)
-        top-level-ids (editor/get-top-level-form-ids editor)
-        next-focused-form-id (helpers/prev-item #(= % focused-form-id) top-level-ids)]
-    (if next-focused-form-id
-      (let [next-selection (editor/get-last-selectable-token-id-for-form editor next-focused-form-id)]
-        (-> editor
-          (editor/set-focused-form-id next-focused-form-id)
-          (editor/set-selection #{next-selection}))))))
+  (move-to-form editor helpers/prev-item editor/get-last-selectable-token-id-for-form))

 (defmethod op :move-next-form [_ editor]
-  (let [focused-form-id (editor/get-focused-form-id editor)
-        top-level-ids (editor/get-top-level-form-ids editor)
-        next-focused-form-id (helpers/next-item #(= % focused-form-id) top-level-ids)]
-    (if next-focused-form-id
-      (let [next-selection (editor/get-first-selectable-token-id-for-form editor next-focused-form-id)]
-        (-> editor
-          (editor/set-focused-form-id next-focused-form-id)
-          (editor/set-selection #{next-selection}))))))
+  (move-to-form editor helpers/next-item editor/get-first-selectable-token-id-for-form))

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


Add tests for adadelta-clojure and adam-clojure

--- cortex/test/cljc/cortex/optimise/optimisers_test.clj
+++ cortex/test/cljc/cortex/optimise/optimisers_test.clj
@@ -4,7 +4,7 @@
             [clojure.test :refer :all]
             [cortex.optimise.optimisers :refer :all]
             [cortex.nn.protocols :as cp]
-            [cortex.util :refer [def-]]))
+            [cortex.util :refer [approx= def-]]))

 ;;;; Protocol extensions

@@ -53,3 +53,35 @@
            (cp/compute-parameters [2 4 8] [1 2 3])
            ((juxt cp/parameters cp/get-state)))
          [[-9 -18 -37] {}])))
+
+(deftest adadelta-clojure-test
+  (is (approx= 1e-8
+               (-> (adadelta-clojure :decay-rate 0.5
+                                     :conditioning 1)
+                 (assoc-in [:state :acc-gradient] [6 3 9])
+                 (assoc-in [:state :acc-step] [7 8 7])
+                 (dissoc :initialize)
+                 (cp/compute-parameters [2 4 8] [1 2 3])
+                 ((juxt cp/parameters cp/get-state)))
+               ;; The following was computed manually using a calculator.
+               [[-1.309401077 -1.703280399 -0.6950417228]
+                {:acc-gradient [5.0 9.5 36.5]
+                 :acc-step [6.166666667 10.85714286 10.32666667]}])))
+
+(deftest adam-clojure-test
+  (is (approx= 1e-8
+               (-> (adam-clojure :step-size 5
+                                 :first-moment-decay 0.75
+                                 :second-moment-decay 0.3
+                                 :conditioning 0.2)
+                 (assoc-in [:state :first-moment] [5 2 -3])
+                 (assoc-in [:state :second-moment] [-1 -3 -8])
+                 (assoc-in [:state :num-steps] 2)
+                 (dissoc :initialize)
+                 (cp/compute-parameters [5 3 7] [1 2 -5])
+                 ((juxt cp/parameters cp/get-state)))
+               ;; The following was computed manually using a calculator.
+               [[-8.81811015 -5.613809809 -4.270259223]
+                {:first-moment [5.0 2.25 -0.5]
+                 :second-moment [17.2 5.4 31.9]
+                 :num-steps 3}])))


Added three more sponsors

Added three more sponsors

Signed-off-by: Tom Marble <b248307e886b80bf9cb4014595572a835b049bf4@info9.net>

--- src/main/cljs/clojurebridgemn/client.cljs
+++ src/main/cljs/clojurebridgemn/client.cljs
@@ -734,11 +734,27 @@
     [:div "ClojureBridge has been made possible locally through the generous support of our sponsors and individual donors"
      [:ul
       [:li
-       "November 4-5, 2016: Object Partners, PurelyFunctional.tv" [:br]
+       "November 4-5, 2016: "
+       [:a {:href "https://objectpartners.com/"} "Object Partners"]
+       ", "
+       [:a {:href "https://purelyfunctional.tv/"} "PurelyFunctional.tv"]
+       ", "
+       [:a {:href "http://worldsingles.com/"} "World Singles"]
+       ", "
+       [:a {:href "http://tech.puredanger.com"} "Alex Miller"]
+       ", "
+       [:a {:href "https://lambdaisland.com"} "Lambda Island"]
+       [:br]
        [:img {:alt "Object Partners"
               :src "images/sponsors/ObjectPartners_400x400.png"}]
        [:img {:alt "PurelyFunctional.tv"
-              :src "images/sponsors/Lispcast.png"}]]
+              :src "images/sponsors/Lispcast.png"}]
+       [:img {:alt "World Singles"
+              :src "images/sponsors/world-singles.svg"}]
+       [:img {:alt "Alex Miller"
+              :src "images/sponsors/puredanger.jpg"}]
+       [:img {:alt "Lambda Island"
+              :src "images/sponsors/lambdaisland.png"}]]
       [:li "November 13-14 2015: Vidku, Harbinger Partners" [:br]
        [:img {:alt "Vidku"
               :src "images/sponsors/vidku_400x400.png"}]


reader: call char only when non-nil instead of calling everytime and catching NPEs

--- src/main/clojure/clojure/tools/reader.clj
+++ src/main/clojure/clojure/tools/reader.clj
@@ -15,8 +15,8 @@
   (list 'set! what (list f what)))

 (defn- char [x]
-  (try (clojure.core/char x)
-       (catch NullPointerException e)))
+  (when x
+    (clojure.core/char x)))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; reader protocols


last query doesn't quite want to work - perhaps because pivotted row would be left with no keys ?

--- src/main/clojure/org/dada/demo/whales.clj
+++ src/main/clojure/org/dada/demo/whales.clj
@@ -453,6 +453,8 @@
 (def #^Collection some-years (map #(Date. % 0 1) (range num-years)))
 (def #^NavigableSet years (TreeSet. some-years))

+(defn by-year [time] (list (or (.lower years time) time)))
+
 ;; (?2 [] all-whales)

 ;; (?2 [(union)] all-whales)
@@ -481,9 +483,9 @@
 ;; (?2 [(split :type nil [(ccount)(split :time)])] all-whales)
 ;; (?2 [(split :type nil [(split :time nil)(split :length)])] all-whales)

-;; (?2 [(split :type nil [(pivot :time years (keyword (count-value-key nil)))(ccount)(split :time (fn [time] (list (or (.lower years time) time))))])] all-whales)
-
-;; (?2 [(union "count/type/year")(split :type nil [(pivot :time years (keyword (count-value-key nil)))(ccount)(split :time (fn [time] (list (or (.lower years time) time))))])] all-whales)
+;; (?2 [(split :type nil [(pivot :time years (keyword (count-value-key nil)))(ccount)(split :time by-year)])] all-whales)
+
+;; (?2 [(union "count/type/year")(split :type nil [(pivot :time years (keyword (count-value-key nil)))(ccount)(split :time by-year)])] all-whales)

 ;; (?2 [(union "count/type/ocean")(split :type nil [(pivot :ocean oceans (keyword (count-value-key nil)))(ccount)(split :ocean )])] all-whales)

@@ -493,11 +495,13 @@

 ;; (?2 [(union "sum(weight)/ocean/type")(split :ocean nil [(pivot :type types (keyword (sum-value-key :weight)))(sum :weight)(split :type )])] all-whales)

-(def subquery [(pivot :time years (keyword (count-value-key nil)))(ccount)(split :time (fn [time] (list (or (.lower years time) time))))])
+(def subquery [(pivot :time years (keyword (count-value-key nil)))(ccount)(split :time by-year)])

 (?2 [(split :ocean nil [(union)(split :type nil subquery)])] all-whales)

 (?2 [(union)(split :ocean nil subquery)] all-whales)
+
+;;(?2 [(pivot :time years (keyword (count-value-key nil)))(split :time by-year [(ccount)])] all-whales)
 ;;--------------------------------------------------------------------------------

 ;; create some whales...
@@ -513,7 +517,7 @@
 	#(.create creator (into-array Object %))
 	(list
 	 [0 0 (Date. 0 1 1) "blue whale" "arctic" 100 100]
-	 [1 0 (Date. 0 1 1) "blue whale" "indian" 200 100]
+	 ;;[1 0 (Date. 0 1 1) "blue whale" "indian" 200 100]
 	 ;; [2 0 (Date. 0 1 1) "gray whale" "arctic" 100 100]
 	 ;; [3 0 (Date. 0 1 1) "gray whale" "indian" 200 100]
 	 ;; [4 0 (Date. 1 1 1) "blue whale" "arctic" 100 100]