More on type hints.

More on type hints.

--- test/com/nomistech/clojure_the_language/type_hints_test.clj
+++ test/com/nomistech/clojure_the_language/type_hints_test.clj
@@ -2,28 +2,78 @@
   (:require [midje.sweet :refer :all]))

 ;;;; ___________________________________________________________________________
+;;;; What type hints are not.
+
+;;; Type hints are not constraints on the value of a variable:

 (defn f [^String s]
   (identity s))

-(f 42)
+(fact
+  (f 42)
+  => 42 ; even though not a String
+  )
+
+;;;; ---------------------------------------------------------------------------
+
+;; clojure.core/*warn-on-reflection*
+;;   When set to true, the compiler will emit warnings when reflection is
+;;   needed to resolve Java method calls or field accesses.
+;;
+;;   Defaults to false.

 ;;;; ___________________________________________________________________________

-*warn-on-reflection*
-;; => nil
+(fact
+  *warn-on-reflection*
+  => nil)

-(defn uppify [s]
+(defn uppify-v1 [s]
   (.toUpperCase s))
+;; No reflection warning.

-(uppify "abcd")
-;; => "ABCD"
+;;;; ---------------------------------------------------------------------------

-#_ ; comment out to avoid setting a global
-(do
-  (set! *warn-on-reflection* true)
+(set! *warn-on-reflection* true)

-  (defn uppify [s]
-    (.toUpperCase s))
-  ;; Reflection warning - reference to field toUpperCase can't be resolved.
-  )
+(defn uppify-v2 [s]
+  (.toUpperCase s))
+;; Reflection warning - reference to field toUpperCase can't be resolved.
+
+(defn uppify-v3 [^String s]
+  (.toUpperCase s))
+;; No reflection warning.
+
+(set! *warn-on-reflection* nil)
+
+;;;; ---------------------------------------------------------------------------
+
+(fact
+  (= (uppify-v1 "abcd")
+     (uppify-v2 "abcd")
+     (uppify-v3 "abcd")
+     "ABCD")
+  => truthy)
+
+(fact "Calling `uppify` with a non-string throws an exception"
+
+  (fact "`uppify-v1` throws an IllegalArgumentException"
+    (uppify-v1 42)
+    => (throws IllegalArgumentException
+               "No matching field found: toUpperCase for class java.lang.Long"))
+
+  (fact "`uppify-v2` throws an IllegalArgumentException"
+    (uppify-v2 42)
+    => (throws IllegalArgumentException
+               "No matching field found: toUpperCase for class java.lang.Long"))
+
+  (fact "`uppify-v3` throws a ClassCastException"
+    (uppify-v3 42)
+    => (throws java.lang.ClassCastException
+               "java.lang.Long cannot be cast to java.lang.String")))
+
+;;;; ---------------------------------------------------------------------------
+
+;;; `lein check`
+;;; $ lein check --help
+;;; Check syntax and warn on reflection.


some commits were deleted; added logic back

--- src-cljs/frontend/components/build_head.cljs
+++ src-cljs/frontend/components/build_head.cljs
@@ -485,7 +485,7 @@
               (when-not (empty? bottom-map)
                 (list
                  [:hr]
-                 [:li
+                 [:span
                   [:a.build-tests-toggle {:on-click #(om/update-state! owner [:is-open?] not)}
                    [:span
                     [:i.fa.build-tests-toggle-icon {:class (if (om/get-state owner :is-open?) "expanded")}]
@@ -494,7 +494,7 @@
                       "More")]]]
                  (when (om/get-state owner :is-open?)
                    (om/build-all build-tests-file-block bottom-map))))))
-           [:div.link-to-insights
+           [:div.bottom-right-cta
             (button/link {:fixed? true
                           :kind :primary
                           :target "_blank"


support ‘re’ verbs in present-tense in French

--- src/babel/francais/morphology.clj
+++ src/babel/francais/morphology.clj
@@ -136,7 +136,11 @@
                                 (throw (Exception. (str "Can't regex-find on non-string: " infinitive " from word: " word)))))
                  er-type (re-find #"er$" infinitive)
                  ir-type (re-find #"ir$" infinitive)
+                 re-type (re-find #"re$" infinitive)
                  stem (string/replace infinitive #"[iae]r$" "")
+                 stem (if re-type
+                        (string/replace infinitive #"re$" "")
+                        stem)
                  last-stem-char-is-i (re-find #"ir$" infinitive)
                  last-stem-char-is-e (re-find #"er$" infinitive)
                  person (get-in word '(:agr :person))
@@ -151,12 +155,18 @@

               (and (= person :1st) (= number :sing) ir-type)
               (str stem "is")
+
+              (and (= person :1st) (= number :sing) re-type)
+              (str stem "")

               (and (= person :2nd) (= number :sing) er-type)
               (str stem "es")

               (and (= person :2nd) (= number :sing) ir-type)
               (str stem "is")
+
+              (and (= person :2nd) (= number :sing) re-type)
+              (str stem "s")

               (and (= person :3rd) (= number :sing) er-type)
               (str stem "e")
@@ -164,6 +174,9 @@
               (and (= person :3rd) (= number :sing) ir-type)
               (str stem "it")

+              (and (= person :3rd) (= number :sing) re-type)
+              (str stem "")
+
               (and (= person :1st) (= number :plur) er-type g-stem)
               (str stem "eons")

@@ -172,7 +185,11 @@

               (and (= person :1st) (= number :plur) ir-type)
               (str stem "issons")
-
+
+              (and (= person :1st) (= number :plur) re-type)
+              (let [stem (string/replace stem #"d$" "")]
+                (str stem "ons"))
+
               ;; <second person plural present>

               (and (= person :2nd) (= number :plur) er-type)
@@ -180,7 +197,9 @@

               (and (= person :2nd) (= number :plur) ir-type)
               (str stem "issez")
-
+
+              (and (= person :2nd) (= number :plur) re-type)
+              (str stem "ez")

               ;; </second person plural present>

@@ -191,6 +210,10 @@
               (and (= person :3rd) (= number :plur)
                    ir-type)
               (str stem "issent")
+              (and (= person :3rd) (= number :plur)
+                   re-type)
+              (let [stem (string/replace stem #"d$" "")]
+                (str stem "nent"))

               ;; </third person plural present>

@@ -200,8 +223,7 @@
               (get-in word [:français])

               :else
-              (throw (Exception. (str "get-string: present regular inflection: don't know what to do with input argument: " (strip-refs word))))))
-
+              (throw (Exception. (str "get-string: present regular inflection: don't know what to do with input argument: " (strip-refs word) " (er-type: " er-type "; ir-type: " ir-type "; re-type: " re-type)))))
            (and
             (= (get-in word '(:infl)) :futuro)
             (string? (get-in word '(:français))))


STORM-527: update worker.clj -- delete "missing-tasks" checking

--- storm-core/src/clj/backtype/storm/daemon/worker.clj
+++ storm-core/src/clj/backtype/storm/daemon/worker.clj
@@ -312,11 +312,7 @@
                      #(HashMap. (apply dissoc (into {} %1) %&))
                      remove-connections)

-              (let [missing-tasks (->> needed-tasks
-                                       (filter (complement my-assignment)))]
-                (when-not (empty? missing-tasks)
-                  (log-warn "Missing assignment for following tasks: " (pr-str missing-tasks))
-                  )))))))
+           )))))

 (defn refresh-storm-active
   ([worker]


Remove unused trait select algorithm

Remove unused trait select algorithm

--- src/search/algorithms/select.clj
+++ src/search/algorithms/select.clj
@@ -1,12 +0,0 @@
-(ns search.algorithms.select
-  (:require [schema.core :as s]
-
-            [search.schemas :as schema]
-            [search.algorithms.base.step :refer [Select]]))
-
-(s/defn trait->select :- Select
-  "Select the individual with the highest of one traits"
-  [trait :- s/Keyword]
-  (s/fn trait->select-inner :- schema/Individual
-    [individuals :- [schema/Individual]]
-    (apply max-key (comp trait :traits) individuals)))


add 'space' key to go to next slide

add 'space' key to go to next slide

--- src/solar_system_of_js/core.cljs
+++ src/solar_system_of_js/core.cljs
@@ -938,6 +938,9 @@
   (let [kname (key-name e)
         shift (.-shiftKey e)]
     (case kname
+      :space (do
+               (next-slide!)
+               (.preventDefault e))
       :left  (do
                (prev-slide!)
                (.preventDefault e))


Cosmetic changes on token backends.

Cosmetic changes on token backends.

--- src/buddy/auth/backends/token.clj
+++ src/buddy/auth/backends/token.clj
@@ -81,8 +81,9 @@
       (parse-authorization-header request token-name))
     (authenticate [_ request token]
       (let [rsq (authfn request token)]
-        (if (response? rsq) rsq
-            (assoc request :identity rsq))))
+        (if (response? rsq)
+          rsq
+          (assoc request :identity rsq))))

     proto/IAuthorization
     (handle-unauthorized [_ request metadata]


fix integration test with distribution scheme simple (#1607)

--- waiter/integration/waiter/metrics_sync_integration_test.clj
+++ waiter/integration/waiter/metrics_sync_integration_test.clj
@@ -499,9 +499,11 @@
           routers (routers waiter-url)]

       (let [extra-headers {:content-type "application/json"
+                           ; this must be simple distribution because we rely on x-kitchen-delay-ms to cause queue build up
+                           :x-waiter-distribution-scheme "simple"
+                           :x-waiter-concurrency-level 1
                            ; make sure raven doesn't send external metrics for these services
                            :x-waiter-env-raven_export_metrics "false"
-                           :x-waiter-concurrency-level 1
                            ; force outstanding metrics to use external metrics for outstanding metrics calculation
                            :x-waiter-metadata-waiter-proxy-bypass-opt-in "true"
                            :x-waiter-min-instances 1


CMR-4661: Added more tests.

CMR-4661: Added more tests.

--- system-int-test/test/cmr/system_int_test/search/service/service_search_test.clj
+++ system-int-test/test/cmr/system_int_test/search/service/service_search_test.clj
@@ -2,6 +2,7 @@
   "This tests searching services."
   (:require
    [clojure.test :refer :all]
+   [cmr.common.mime-types :as mt]
    [cmr.common.util :refer [are3]]
    [cmr.mock-echo.client.echo-util :as e]
    [cmr.system-int-test.data2.core :as d]
@@ -333,6 +334,32 @@

       ;; verify service search UMM JSON response is correct and does not have
       ;; collection associations like variable search response does
-      (du/assert-service-umm-jsons-match
-       umm-version/current-service-version [expected-service1 expected-service2]
-       (search/find-concepts-umm-json :service {})))))
+      (are3 [umm-version options]
+        (du/assert-service-umm-jsons-match
+         umm-version [expected-service1 expected-service2]
+         (search/find-concepts-umm-json :service {} options))
+
+        "without specifying UMM JSON version"
+        umm-version/current-service-version
+        {}
+
+        "explicit UMM JSON version through accept header"
+        umm-version/current-service-version
+        {:accept (mt/with-version mt/umm-json umm-version/current-service-version)}
+
+        "explicit UMM JSON version through suffix"
+        "1.0"
+        {:url-extension "umm_json_v1_0"})))
+
+  (testing "Searching with non-existent UMM JSON version"
+    (are3 [options]
+      (let [{:keys [status errors]} (search/find-concepts-umm-json :service {} options)]
+        (is (= 400 status))
+        (is (= ["The mime type [application/vnd.nasa.cmr.umm_results+json] with version [0.1] is not supported for services."]
+               errors)))
+
+      "explicit UMM JSON version through suffix"
+      {:url-extension "umm_json_v0_1"}
+
+      "explicit UMM JSON version through accept header"
+      {:accept (mt/with-version mt/umm-json "0.1")})))


3 column var meta

3 column var meta

--- src/clj/clojuredocs/site/vars.clj
+++ src/clj/clojuredocs/site/vars.clj
@@ -42,9 +42,9 @@
        (when (> (count users) 10)
          [:div.contributors
           (count users) " contributors total."])
-       [:div.created
+       #_[:div.created
         "Created " (util/timeago created-at) " ago."]
-       (when-not (= created-at updated-at)
+       #_(when-not (= created-at updated-at)
          [:div.last-updated
           "Updated " (util/timeago updated-at) " ago."])
        [:div.links
@@ -57,20 +57,30 @@
 (defn source-url [{:keys [file line]}]
   (str "https://github.com/clojure/clojure/blob/clojure-1.5.1/src/clj/" file "#L" line))

-(defn $see-also [{:keys [ns name created-at doc] :as sa}]
-  [:div.see-also
+(defn $see-also [{:keys [ns name created-at doc user] :as sa}]
+  [:div.col-sm-6.see-also
    [:div
-    ns "/" name]
-   [:div
+    (util/$var-link ns name
+      [:span.ns ns "/"]
+      [:span.name name])]
+   [:p
     (->> doc
-         (take 50)
-         (apply str))]])
+         (take 100)
+         (apply str))
+    (when (> (count doc) 100)
+      "...")]
+   [:div.meta
+    "Added by " [:a {:href (str "/u/" (:login user))} (:login user)]]])
+
+(defn lookup-var [ns name]
+  (or (mon/fetch-one :vars :where {:name name :ns ns})
+      (search/lookup (str ns "/" name))))

 (defn var-page [ns name]
   (fn [{:keys [user]}]
     (let [name (util/unmunge-name name)
           {:keys [arglists name ns doc runtimes added file] :as v}
-          (mon/fetch-one :vars :where {:name name :ns ns})
+          (lookup-var ns name)
           examples (examples-for v)
           see-alsos (see-alsos-for v)]
       (common/$main
@@ -79,7 +89,7 @@
          :content [:div
                    [:div.row
                     [:div.col-sm-4
-                     [:section
+                     [:section.var-data
                       [:h1 name]
                       [:h2 ns]]]
                     [:div.col-sm-4
@@ -97,18 +107,34 @@
                          [:a {:href (source-url v)} "Source"]])]]]
                    [:div.row
                     [:div.col-sm-12
-                     [:div.docstring
-                      [:pre (-> doc
-                                (str/replace #"\n\s\s" "\n"))]
-                      [:div.copyright
-                       "© Rich Hickey. All rights reserved."
-                       " "
-                       [:a {:href "http://www.eclipse.org/legal/epl-v10.html"}
-                        "Eclipse Public License 1.0"]]]
-                     [:h3 (count examples) " Examples"]
-                     (map $example examples)
-                     [:h3 "See Alsos"]
-                     (map $see-also see-alsos)]]]}))))
+                     [:section
+                      [:div.docstring
+                       (when doc
+                         [:pre (-> doc
+                                   (str/replace #"\n\s\s" "\n"))])
+                       [:div.copyright
+                        "© Rich Hickey. All rights reserved."
+                        " "
+                        [:a {:href "http://www.eclipse.org/legal/epl-v10.html"}
+                         "Eclipse Public License 1.0"]]]]
+                     [:section
+                      [:h3 (util/pluralize (count examples) "Example" "Examples")]
+                      (if (empty? examples)
+                        [:div.null-state
+                         "No examples for " name ", "
+                         [:a {:href "#"} "add one"]
+                         "?"]
+                        (map $example examples))]
+                     [:section
+                      [:h3 "See Also"]
+                      (if (empty? see-alsos)
+                        [:div.null-state
+                         "No see-alsos for " [:code name] ", "
+                         [:a
+                          {:href "#"} "add one"]
+                         "?"]
+                        [:div.row
+                         (map $see-also see-alsos)])]]]]}))))

 (defn $example-history-point [{:keys [user body created-at updated-at] :as ex}]
   [:div.row


Better to check if spdy is used

Better to check if spdy is used

--- src/clj/fortress/ring/writers.clj
+++ src/clj/fortress/ring/writers.clj
@@ -40,7 +40,7 @@
                                                   (log/error (.cause f) "Error when handling stream response"))
                                                 (.close stream)))]
     (.addListener future listener)
-    (.addListener future ChannelFutureListener/CLOSE)))
+    #_(.addListener future ChannelFutureListener/CLOSE)))

 (defn- write-response [^HttpResponse response ^Channel channel]
   (-> (.write channel response)
@@ -73,6 +73,7 @@
 (extend-type InputStream
   ResponseWriter
   (write [body headers version status ^Channel channel]
+    (println headers)
     (let [response (DefaultHttpResponse. version status)]
       (set-headers response headers)
       (.write channel response)


moved game-list to separate function

moved game-list to separate function

--- src/cljs/netrunner/gamelobby.cljs
+++ src/cljs/netrunner/gamelobby.cljs
@@ -180,6 +180,25 @@
           [:input {:ref "msg-input" :placeholder "Say something" :accessKey "l"}]
           [:button "Send"]]]]))))

+(defn game-list [{:keys [games gameid] :as cursor} owner]
+  [:div.game-list
+   (if (empty? games)
+     [:h4 "No game"]
+     (for [game games]
+       [:div.gameline {:class (when (= gameid (:gameid game)) "active")}
+        (when-not (or gameid (= (count (:players game)) 2) (:started game))
+          (let [id (:gameid game)]
+            [:button {:on-click #(join-game id owner)} "Join"]))
+        (when (and (:allowspectator game) (not gameid))
+          (let [id (:gameid game)]
+            [:button {:on-click #(watch-game id owner)} "Watch"]))
+        (let [c (count (:spectators game))]
+          [:h4 (str (:title game)
+                    (when (pos? c)
+                      (str  " (" c " spectator" (when (> c 1) "s") ")")))])
+        [:div
+         (om/build-all player-view (:players game))]]))])
+
 (defn game-lobby [{:keys [games gameid messages user] :as cursor} owner]
   (reify
     om/IRenderState
@@ -191,23 +210,7 @@
           (if gameid
             [:button {:class "disabled"} "New game"]
             [:button {:on-click #(new-game cursor owner)} "New game"])]
-         [:div.game-list
-          (if (empty? games)
-            [:h4 "No game"]
-            (for [game games]
-              [:div.gameline {:class (when (= gameid (:gameid game)) "active")}
-               (when-not (or gameid (= (count (:players game)) 2) (:started game))
-                 (let [id (:gameid game)]
-                   [:button {:on-click #(join-game id owner)} "Join"]))
-               (when (and (:allowspectator game) (not gameid))
-                 (let [id (:gameid game)]
-                  [:button {:on-click #(watch-game id owner)} "Watch"]))
-               (let [c (count (:spectators game))]
-                 [:h4 (str (:title game)
-                           (when (pos? c)
-                             (str  " (" c " spectator" (when (> c 1) "s") ")")))])
-               [:div
-                (om/build-all player-view (:players game))]]))]]
+         (game-list cursor owner)]

         [:div.game-panel
          (if (:editing state)


fix ui controller dispatch

fix ui controller dispatch

--- src/cljs/swarmpit/controller.cljs
+++ src/cljs/swarmpit/controller.cljs
@@ -18,11 +18,12 @@
   []
   (let [router (br/start-router! handler
                                  {:on-navigate
-                                  (fn [loc] (do (dispatch loc)
-                                                (reset! location loc)))})
+                                  (fn [loc]
+                                    (dispatch loc)
+                                    (reset! location loc))})
         route (:handler @location)]
     (if (some? route)
-      (br/set-location! router {:handler route}))))
+      (br/set-location! router @location))))

 (defmethod dispatch :index
   [_]
@@ -30,18 +31,21 @@

 (defmethod dispatch :service-list
   [_]
+  (print "list")
   (GET "/services"
        {:handler (fn [response]
                    (slist/mount! response))}))

 (defmethod dispatch :service-info
   [{:keys [route-params]}]
+  (print "info")
   (GET (str "/services/" (:id route-params))
        {:handler (fn [response]
                    (sinfo/mount! response))}))

 (defmethod dispatch :service-create
   [_]
+  (print "create")
   (screate/mount!))

 (defmethod dispatch nil


Remove aluemeri.

Remove aluemeri.

--- src/cljs/town_client/control.cljs
+++ src/cljs/town_client/control.cljs
@@ -52,9 +52,11 @@
       ; no id, got all neighborhoods
       (let [neighborhoods
             (sort-by #(:name %)
-                     (map
-                      (fn [n] {:name ((n "name") "fi") :id (n "id")})
-                      (:results data)))
+                     (filter
+                      #(not (= "Aluemeri" (:name %)))
+                      (map
+                       (fn [n] {:name ((n "name") "fi") :id (n "id")})
+                       (:results data))))

             neighborhood-map
             (apply hash-map (flatten


Start cursor at beginning of document

Start cursor at beginning of document

--- src/clojure/nightcode/editors.clj
+++ src/clojure/nightcode/editors.clj
@@ -324,7 +324,7 @@
   (if (contains? utils/clojure-exts extension)
     (let [old-text (.getText text-area)]
       ; use paren mode to preprocess the code
-      (let [state (get-state text-area true)]
+      (let [state (assoc (get-state text-area true) :cursor-position 0)]
         (mwm/update-edit-history! edit-history state)
         (refresh-content! text-area state))
       (.discardAllEdits text-area)


(PDB-5484) event-counts-test: test include_total as intended

The count? parameter which was supposed to test include_total in one
of the loop iterations wasn't actually being used.  Use it, and when
it's true, check for the expected X-Records header.

--- test/puppetlabs/puppetdb/http/event_counts_test.clj
+++ test/puppetlabs/puppetdb/http/event_counts_test.clj
@@ -4,6 +4,7 @@
             [clojure.test :refer :all]
             [clojure.walk :refer [keywordize-keys]]
             [puppetlabs.puppetdb.examples.reports :refer [reports]]
+            [puppetlabs.puppetdb.testutils :as tu]
             [puppetlabs.puppetdb.testutils.catalogs :as testcat]
             [puppetlabs.puppetdb.testutils.http
              :refer [are-error-response-headers
@@ -256,15 +257,19 @@
                         :successes             1
                         :noops                 0
                         :skips                 0}]
-            results (ordered-query-result
-                      method
-                      endpoint
-                      [">" "timestamp" 0]
-                      {:summarize_by "resource"
-                       :order_by (vector-param method [{"field" "resource_title"}])
-                       :include_total true})]
-        (is (= (count expected) (count results)))
-        (is (= expected results)))))))
+            {:keys [headers body] :as res}
+            (query-response method
+                            endpoint
+                            [">" "timestamp" 0]
+                            {:summarize_by "resource"
+                             :order_by (vector-param method [{"field" "resource_title"}])
+                             :include_total count?})
+            _ (tu/assert-success! res)
+            body (tu/parse-result body)]
+        (when count?
+          (is (= "3" (get headers "X-Records"))))
+        (is (= (count expected) (count body)))
+        (is (= expected body)))))))

 (deftest-http-app query-distinct-event-counts
   [[_version endpoint] endpoints
@@ -860,15 +865,19 @@
                         :intentional_noops     0
                         :corrective_noops      0
                         :skips                 0}]
-            results (ordered-query-result
-                      method
-                      endpoint
-                      [">" "timestamp" 0]
-                      {:summarize_by "resource"
-                       :order_by (vector-param method [{"field" "resource_title"}])
-                       :include_total true})]
-        (is (= (count expected) (count results)))
-        (is (= expected results)))))))
+            {:keys [headers body] :as res}
+            (query-response method
+                            endpoint
+                            [">" "timestamp" 0]
+                            {:summarize_by "resource"
+                             :order_by (vector-param method [{"field" "resource_title"}])
+                             :include_total count?})
+            _ (tu/assert-success! res)
+            body (tu/parse-result body)]
+        (when count?
+          (is (= "3" (get headers "X-Records"))))
+        (is (= (count expected) (count body)))
+        (is (= expected body)))))))

 (deftest-http-app query-distinct-event-counts-with-corrective-changes
   [[_version endpoint] endpoints


Fix misc. syntax issues.

Fix misc. syntax issues.

--- src/lexemic/sentiment/simple.cljs
+++ src/lexemic/sentiment/simple.cljs
@@ -3,16 +3,15 @@
   (:require [lexemic.data.sentiment :as data]))

 (defn- collect-matches [tokens lexicon]
-  (vec
-   (for [token tokens
-         :when (contains? lexicon token)]
-     token)))
+  (for [token tokens
+        :when (contains? lexicon token)]
+    token))

 (defn- rate [phrase lexicon]
   (let [tokens (split (lower-case phrase) #"\s+")
         matches (collect-matches tokens lexicon)
-        hits (count matches)])
-  {:score hits :comparative (/ hits (count tokens)) :words words})
+        hits (count matches)]
+    {:score hits :comparative (/ hits (count tokens)) :words matches}))

 (defn negative-rating [phrase]
   (rate phrase data/negative-words))
@@ -23,7 +22,7 @@
 (defn analyse [phrase]
   (let [negative (negative-rating phrase)
         positive (positive-rating phrase)]
-    {:score (- (positive :score) (negative :score))
-     :comparative (- (positive :comparative) (negative :comparative))
+    {:score (- (get positive :score) (get negative :score))
+     :comparative (- (get positive :comparative) (get negative :comparative))
      :positive positive
      :negative negative}))


Remove extra arg from watcher fns

Remove extra arg from watcher fns

--- src/angelic/search/implicit/dash_astar.clj
+++ src/angelic/search/implicit/dash_astar.clj
@@ -135,20 +135,20 @@
   (evaluate!           [s] (eval!-fn s))

   (get-output-set      [s] @out-set-atom)
-  (add-output-watcher! [s w] (if @out-set-atom (w s) (.add output-watchers w)))
+  (add-output-watcher! [s w] (if @out-set-atom (w) (.add output-watchers w)))
   (set-output-set!    [s o]
     (assert (nil? @out-set-atom))
     (reset! out-set-atom o)
     (summaries/summary-changed-local! s)
     (when (canonical? s)
       (summaries/summary-changed! (sp-ts s)))
-    (doseq [w output-watchers] (w s))
-    (doseq [c (get-children s), w (doall (seq child-watchers))] (w s c)))
+    (doseq [w output-watchers] (w))
+    (doseq [c (get-children s), w (doall (seq child-watchers))] (w c)))

   (get-children        [s] (doall (seq child-list)))
   (add-child-watcher!  [s w]
     (.add child-watchers w)
-    (when (get-output-set s)) (doseq [c (get-children s)] (swap! *out-count* inc) (w s c)))
+    (when (get-output-set s)) (doseq [c (get-children s)] (swap! *out-count* inc) (w c)))
   (add-sp-child!*      [s c] ;; TODO: wait if output not set yet, send them above?
     (util/assert-is (and (not (identical? s c)) (get-output-set c)))
     (.add child-list c)
@@ -156,10 +156,12 @@
     (when (canonical? s)
       (summaries/connect! (sp-ts s) (sp-ts c))
       (when (get-output-set s) (summaries/summary-changed! (sp-ts s)))) ;; TODO: remove this overhead from atomic.
-    (when (get-output-set s) (doseq [w (doall (seq child-watchers))] (swap! *out-count* inc) (w s c))))
+    (when (get-output-set s) (doseq [w (doall (seq child-watchers))] (swap! *out-count* inc) (w c))))

   (subsuming-sps [s] (keys subsuming-sp-set))
   (add-subsuming-sp! [s subsuming-sp]
+    (util/assert-is (canonical? s))
+    (util/assert-is (canonical? subsuming-sp))
     (util/assert-is (= nm (sp-name subsuming-sp)))
     (when-not (.containsKey subsuming-sp-set subsuming-sp)
       (.put subsuming-sp-set subsuming-sp true)
@@ -178,7 +180,7 @@
 (defn- connect-and-watch-ts! [p c out-f]
   (summaries/connect! p (sp-ts c))
   (if (get-output-set c)
-    (do (out-f c) false)
+    (do (out-f) false)
     (do (add-output-watcher! c out-f) true)))

 (defn- add-sp-child! [sp child-sp up?]
@@ -191,7 +193,7 @@
     (add-sp-child!* sp child-sp)
     (do (summaries/connect! sp child-sp)
         (add-output-watcher! child-sp
-          (fn [child-sp]
+          (fn []
             (summaries/disconnect! sp child-sp)
             (add-sp-child!* sp child-sp)))
         (when up? (summaries/summary-changed! sp)))))
@@ -201,13 +203,13 @@
 (defn noeval [s] (throw (RuntimeException. (print-str s "not evaluable!"))))

 (defn make-wrapped-subproblem [nm inp-set prefix-set inner-sp output-wrap child-watch ri-fn]
-  (assert (prefix-set (first (sp-name inner-sp))))
+  (util/assert-is (contains? prefix-set (first (sp-name inner-sp))))
   (let [ret (traits/reify-traits
              [summaries/or-summarizable
               (simple-subproblem nm inp-set (sp-ts inner-sp) noeval ri-fn)])]
     (connect-and-watch! ret inner-sp
-      (fn [inner-sp] (set-output-set! ret (output-wrap (get-output-set! inner-sp))))
-      (fn [inner-sp inner-child] (child-watch ret inner-child)))
+      (fn [] (set-output-set! ret (output-wrap (get-output-set! inner-sp))))
+      (fn [inner-child] (child-watch ret inner-child)))
     ret))

@@ -254,8 +256,8 @@
            (reset! state :go)
            (if-let [subsuming-sps (seq (filter #(not (terminal? %)) (subsuming-sps s)))]
              (connect-and-watch! s (apply min-key (comp summaries/get-bound sp-ts) subsuming-sps)
-               (fn ignore-output [sub] nil)
-               (fn [sub sub-out] (add-sp-child! s (refine-input sub-out inp-set) true)))
+               (fn ignore-output [] nil)
+               (fn [sub-out] (add-sp-child! s (refine-input sub-out inp-set) true)))
              (doseq [ref-name (refinement-names fs inp-set)] #_ (println fs ref-name)
                (add-sp-child! s (get-subproblem ref-name inp-set) false))) ;; TODO: watch ?
            (reset! sm-fn summaries/or-summary)
@@ -298,21 +300,21 @@
                               (get-output-set @right-sp))
                      (reset! right?-atom true)
                      (summaries/disconnect! ss (sp-ts @right-sp))
-                     (add-child-watcher! left-sp (fn [o c] (throw (RuntimeException. "Solved and children."))))
+                     (add-child-watcher! left-sp (fn [c] (throw (RuntimeException. "Solved and children."))))
                      (connect-and-watch! ss @right-sp
-                       (fn ignore-output [o] nil)
-                       (fn right-child [right-sp right-child]
+                       (fn ignore-output [] nil)
+                       (fn right-child [right-child]
                          (summaries/summary-changed-local! ss)
                          (add-sp-child! s (make-pair-subproblem left-sp right-child) true))))
                    (summaries/or-summary s)))]
        (summaries/connect! ret ss)
        (connect-and-watch! ss left-sp
-         (fn left-output [left-sp]
+         (fn left-output []
            (summaries/summary-changed-local! ss)
-           (when (connect-and-watch-ts! ss @right-sp ;; TODO: too eager/
-                   (fn [right-sp] (summaries/summary-changed-local! ss) (set-output-set! ret (get-output-set! right-sp))))
+           (when (connect-and-watch-ts! ss @right-sp ;; TODO: too eager?
+                   (fn [] (summaries/summary-changed-local! ss) (set-output-set! ret (get-output-set! @right-sp))))
              (summaries/summary-changed! ret)))
-         (fn left-child [left-sp left-child]
+         (fn left-child [left-child]
            (summaries/summary-changed-local! ss)
            (add-sp-child! ret (make-pair-subproblem left-child right-name #(refine-input @right-sp %)) true)))
        ret)))
@@ -335,7 +337,11 @@
   (util/assert-is (= (state/current-context s1) (state/current-context s2)) "%s" [s1 s2])
   (= s1 s2))

-(defn wrapper? [sp] (#{:OC :SA} (first (sp-name sp))))
+;; Note: must always wrap (at least with SA), or we lose context.
+;; TODO: only :Atomic or :Pair inside, when SA off
+;;(defn wrapper? [sp] (#{:OC :SA} (first (sp-name sp))))
+;; (comment  (if (wrapper? child-sp) child-sp (make-output-collecting-subproblem fs child-sp)))
+

 (defn atomic-name-fs [n] (util/match [[:Atomic ~fs] n] fs))
 (defn log-input [fs inp-set] (if *state-abstraction* (fs/get-logger fs inp-set) inp-set))
@@ -346,15 +352,13 @@

 (defn- make-output-collecting-subproblem [fs inner-sp]
   (make-wrapped-subproblem
-   (oc-name (sp-name inner-sp)) (input-set inner-sp) #{:Atomic :Pair} inner-sp
+   (oc-name (sp-name inner-sp)) (input-set inner-sp) #{:Atomic :Pair #_ ::TODO??? :SA :OC} inner-sp
    identity
    (fn child-watch [sp child-sp] #_ (println inner-sp sp child-sp)
      (if (=-state-sets (get-output-set! inner-sp) (get-output-set! child-sp))
-       (do (connect-and-watch! sp child-sp nil #(child-watch sp %2))
+       (do (connect-and-watch! sp child-sp nil #(child-watch sp %))
            (summaries/summary-changed! sp))
-       (add-sp-child! sp
-         (if (wrapper? child-sp) child-sp (make-output-collecting-subproblem fs child-sp))
-         false)))
+       (add-sp-child! sp (make-output-collecting-subproblem fs child-sp) false)))
    (fn refine-input [s ni]
      (if (= (input-set s) ni)
        s


Properly sort players.

Properly sort players.

--- src/cljs/wombats_web_client/utils/games.cljs
+++ src/cljs/wombats_web_client/utils/games.cljs
@@ -99,8 +99,8 @@

 (defn sort-players
   [players-map]
-  (sort #(compare (get-player-score %1)
-                  (get-player-score %2))
+  (sort #(compare (get-player-score %2)
+                  (get-player-score %1))
         (vals players-map)))

 (defn get-arena-from-game


Don't print stacktraces for reader / analysis errors

--- planck-cljs/src/planck/repl.cljs
+++ planck-cljs/src/planck/repl.cljs
@@ -583,30 +583,21 @@
     e))

 (defn- is-reader-or-analysis?
-  "Indicates if an ExceptionInfo data map pertains to
-  a reader or analysis issue."
-  [data]
-  {:pre [(map? data)]}
-  (some #{[:type :reader-exception] [:tag :cljs/analysis-error]} data))
-
-(defn- strip-if-reader-analysis
-  "Takes an ex-info and returns just the message
-  if the data indicates a reader or analysis issue."
+  "Indicates if an exception is a reader or analysis exception."
   [e]
-  {:pre [(instance? ExceptionInfo e)]}
-  (if (is-reader-or-analysis? (ex-data e))
-    (ex-message e)
-    e))
+  (and (instance? ExceptionInfo e)
+       (some #{[:type :reader-exception] [:tag :cljs/analysis-error]} (ex-data e))))

 (defn print-error
   ([error]
    (print-error error true))
   ([error include-stacktrace?]
    (let [cause (get-root-cause error)]
-     (println (if (instance? ExceptionInfo cause)
-                (strip-if-reader-analysis cause)
+     (println (if (is-reader-or-analysis? cause)
+                (ex-message cause)
                 (.-message cause)))
-     (when include-stacktrace?
+     (when (and (not (is-reader-or-analysis? cause))
+                include-stacktrace?)
        (load-core-source-maps!)
        (let [canonical-stacktrace (st/parse-stacktrace
                                     {}


Added the implementation of a blobstore upload hack.

--- src/appengine_magic/services/blobstore.clj
+++ src/appengine_magic/services/blobstore.clj
@@ -1,9 +1,11 @@
 (ns appengine-magic.services.blobstore
   (:require [appengine-magic.core :as core]
-            [appengine-magic.services.datastore :as ds])
+            [appengine-magic.services.datastore :as ds]
+            [appengine-magic.services.url-fetch :as url])
   (:import [com.google.appengine.api.blobstore ByteRange BlobKey
             BlobstoreService BlobstoreServiceFactory]
-           [javax.servlet.http HttpServletRequest HttpServletResponse]))
+           [javax.servlet.http HttpServletRequest HttpServletResponse]
+           org.apache.commons.io.IOUtils))

 (defonce *blobstore-service* (atom nil))
@@ -51,6 +53,39 @@
   {:commit? false})

+(defn upload-hack [contents success-path & {:keys [headers] :or {headers {}}}]
+  "This allows uploading arbitrary data to the Blobstore. This is a temporary workaround,
+   meant to last only until the App Engine SDK provides a cleaner
+   implementation."
+  (let [contents (if (sequential? contents) contents [contents])
+        boundary (str (java.util.UUID/randomUUID))
+        payload-content-type (str "multipart/form-data; boundary=" boundary)
+        payload (with-open [output-stream (java.io.ByteArrayOutputStream.)]
+                  (doseq [{:keys [field filename content-type bytes]} contents]
+                    (IOUtils/write (format "--%s\r\n" boundary) output-stream)
+                    (IOUtils/write
+                     (format "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n"
+                             field filename)
+                     output-stream)
+                    (IOUtils/write
+                     (format "Content-Type: %s\r\n\r\n" content-type)
+                     output-stream)
+                    (IOUtils/write bytes output-stream)
+                    (IOUtils/write "\r\n" output-stream))
+                  (IOUtils/write (format "--%s--\r\n" boundary) output-stream)
+                  (.toByteArray output-stream))
+        upload-target (upload-url success-path)]
+    (url/fetch (condp = (core/appengine-environment-type)
+                   :production upload-target
+                   :interactive (str (core/appengine-base-url) upload-target)
+                   :dev-appserver (throw (RuntimeException.
+                                          "upload-hack not supported in dev_appserver.sh")))
+               :method :post
+               :follow-redirects false
+               :headers (merge headers {"Content-Type" payload-content-type})
+               :payload payload)))
+
+
 (if (core/in-appengine-interactive-mode?)
     (load "blobstore_local")
     (load "blobstore_google"))


added serveral new observable types

added serveral new observable types

--- src/ctia/schemas/vocabularies.clj
+++ src/ctia/schemas/vocabularies.clj
@@ -265,7 +265,14 @@
           "sha256"
           "md5"
           "sha1"
-          "url"))
+          "url"
+          ;; PKI Certificate serial numbers for revoked
+          ;; code signing or server certificates
+          "pki-serial"
+          "email"
+          "imei"
+          "imsi"
+          "amp-device"))

 (s/defschema OwnershipClass
   (s/enum "Internally-Owned"


Add Task Count to the node view #363

Add Task Count to the node view
#363

--- src/cljs/swarmpit/component/node/info.cljs
+++ src/cljs/swarmpit/component/node/info.cljs
@@ -134,7 +134,8 @@
       {:className "Swarmpit-card"}
       (comp/card-header
         {:className "Swarmpit-table-card-header"
-         :title     (comp/typography {:variant "h6"} "Tasks")})
+         :title     (comp/typography {:variant "h6"} "Tasks")
+         :subheader (str "Running: " (count tasks))})
       (if (empty? tasks)
         (comp/card-content
           {}


Remove debugging println.

Remove debugging println.

--- src/clojure/catacumba/handlers/session.clj
+++ src/clojure/catacumba/handlers/session.clj
@@ -169,7 +169,6 @@
            (if (nil? dkey)
              (deliver [(jws/sign {} pkey opts) {}])
              (try
-               (println 2222 dkey)
                (deliver [dkey (jws/unsign dkey pkey opts)])
                (catch clojure.lang.ExceptionInfo e
                  (deliver [(jws/sign {} pkey opts) {}])))))))


More experiments with the way data is enqueued.

--- src/dsbdp/local_data_processing_pipeline.clj
+++ src/dsbdp/local_data_processing_pipeline.clj
@@ -30,10 +30,10 @@
                   (println file-name "not found. Using default.")
 ;                  "ArrayBlockingQueue_put"))]
 ;                  "ArrayBlockingQueue_put-counted-yield"))]
-;                  "ArrayBlockingQueue_add-counted-yield"))]
+                  "ArrayBlockingQueue_add-counted-yield"))]
 ;                  "ArrayBlockingQueue_add-counted-yield_remove-yield"))]
-                  "OneToOneConcurrentArrayQueue3_add-counted-yield_remove-yield"))]
-;                  "ArrayBlockingQueue_offer"))]
+;                  "OneToOneConcurrentArrayQueue3_add-counted-yield_remove-yield"))]
+;                  "ArrayBlockingQueue_offer-counted"))]
 ;                  "ArrayBlockingQueue_offer-counted-yield"))]
 ;                  "LinkedTransferQueue_transfer"))]
 ;                  "LinkedTransferQueue_transfer-counted-yield"))]
@@ -73,6 +73,9 @@
                                         (.inc ~dropped-counter)
                                         (Thread/yield)))
                "offer" `(.offer ~queue ~data)
+               "offer-counted" `(if (.offer ~queue ~data)
+                                  (.inc ~enqueued-counter)
+                                  (.inc ~dropped-counter))
                "offer-counted-yield" `(if (< (.size ~queue) queue-size)
                                         (do
                                           (.offer ~queue ~data)


--- src/dsbdp/local_data_processing_pipeline.clj
+++ src/dsbdp/local_data_processing_pipeline.clj
@@ -34,8 +34,8 @@
 ;                  "ArrayBlockingQueue_add-counted-yield"))]
 ;                  "ArrayBlockingQueue_add-counted-yield_remove-yield"))]
 ;                  "ArrayBlockingQueue_add-counted_remove"))]
-                  "LinkedBlockingQueue_add-counted_remove"))]
-;                  "OneToOneConcurrentArrayQueue3_add-counted-yield_remove-yield"))]
+;                  "LinkedBlockingQueue_add-counted_remove"))]
+                  "OneToOneConcurrentArrayQueue3_add-counted-yield_remove-yield"))]
 ;                  "OneToOneConcurrentArrayQueue3_add-counted_remove-yield"))]
 ;                  "OneToOneConcurrentArrayQueue3_add-counted_remove"))]
 ;                  "ArrayBlockingQueue_offer-counted"))]


fix some tests for older clojure versions

--- test/clj_http/test/conn_mgr.clj
+++ test/clj_http/test/conn_mgr.clj
@@ -1,8 +1,8 @@
 (ns clj-http.test.conn-mgr
-  (:use [clojure.test])
+  (:use [clojure.test]
+        [clj-http.test.core :only [run-server]])
   (:require [clj-http.conn-mgr :as conn-mgr]
             [clj-http.core :as core]
-            [clj-http.test.core :refer [run-server]]
             [ring.adapter.jetty :as ring])
   (:import (java.security KeyStore)
            (org.apache.http.conn.ssl SSLSocketFactory)


Added unit test for removing sessions

Added unit test for removing sessions

--- test/compojure/http/session.clj
+++ test/compojure/http/session.clj
@@ -100,3 +100,17 @@
   (binding [mock-store {:foo "bar"}]
     (mock-session-update {:cookies {:compojure-session "mock-id"}} {})
     (is (= mock-store {:foo "bar"}))))
+
+(declare deleted-mock)
+
+(derive ::mock-delete ::mock)
+
+(defmethod destroy-session ::mock-delete [session]
+  (set! deleted-mock session))
+
+(deftest session-destroy-existing
+  (binding [deleted-mock nil]
+    (let [handler (-> (constantly {:session nil})
+                      (with-session ::mock-delete))]
+      (handler {})
+      (is (= deleted-mock {:id ::mock-id})))))


more reorg

more reorg

--- src/frontend/cljs/alibi/post_entry_form.cljs
+++ src/frontend/cljs/alibi/post_entry_form.cljs
@@ -10,6 +10,20 @@
     [alibi.entry-page-state :as state :refer [validate-form]]))

 (defn parse-float [v] (js/parseFloat v))
+
+(defn active-errors
+  [for-state]
+  (let [{:keys [input-entry]} for-state
+        {:keys [formWasSubmitted]} input-entry]
+    (seq (when formWasSubmitted
+           (validate-form input-entry)))))
+
+(defn summary-errors
+  [for-state]
+  (let [{:keys [input-entry]} for-state
+        {:keys [formWasSubmitted submit-time-state]} input-entry]
+    (seq (when formWasSubmitted
+           (validate-form submit-time-state)))))

 (defn on-form-submit [entry on-error event]
   (log "submit")
@@ -37,8 +51,13 @@
                                             :autoclose true })
           (.. $input-element datepicker
               (on "changeDate"
-                  #((or (:onChangeDate data)
-                        identity) %)))
+                  (fn [event]
+                    (let [instant (js/JSJoda.Instant.ofEpochMilli
+                                    (.. event -date getTime))
+
+                          new-date
+                          (.toString (js/JSJoda.LocalDate.ofInstant instant))]
+                      ((:onChangeDate data identity) new-date)))))
           (. $show-btn on "click" #(.datepicker $input-element "show"))))

       om/IWillUnmount
@@ -63,8 +82,148 @@
             (dom/i
               #js {:className "glyphicon glyphicon-calendar"})))))))

-(defn render-state
+(defn validation-summary
   [for-state]
+  (let [summary-errors (summary-errors for-state)]
+    (dom/div
+      #js {:className
+           (str "alert entry-form-errors"
+                (if (active-errors for-state) " alert-danger" " alert-success")
+                (when summary-errors " entry-form-errors-has-errors"))}
+      "There is a problem with one or more fields in the form, please correct them:"
+      (dom/ul
+        #js {:className "entry-form-errors-list-container"}
+        (map #(-> (dom/li #js {:key (get % 0)}
+                          (dom/strong nil (get % 0))
+                          (str " "(get % 1))))
+             summary-errors)))))
+
+(defn time-input [id value on-change]
+  (dom/input
+    #js {:id id
+         :className "form-control time-entry-input"
+         :type "text"
+         :name id
+         :value value
+         :size "5"
+         :maxLength "5"
+         :autoComplete "off"
+         :placeholder "Time"
+         :onFocus #(.. % -target select)
+         :onChange #(on-change (.. % -target -value))
+         :onBlur #(on-change (expand-time (.. % -target -value)))
+         :onKeyDown #(when (= (.-keyCode %) 13)
+                       (on-change (expand-time (.. % -target -value))))}))
+
+(defn date-time-entry-row [for-state]
+  (let [{:keys [input-entry
+                dispatch!
+                ]} for-state
+        {:keys [startTime endTime selected-date comment isBillable
+                formWasSubmitted submit-time-state selected-item
+                entry-id]} input-entry
+        {:keys [project-id task-id]} selected-item
+        editing? (integer? (parse-float entry-id))
+        failed-fields (into {} (active-errors for-state))
+        start-time-error? (failed-fields "Start time")
+        end-time-error? (failed-fields "End time")
+        on-change-start-time (fn [start-time]
+                               (dispatch! {:action :change-start-time
+                                           :start-time start-time}))
+        on-change-end-time (fn [end-time]
+                             (dispatch! {:action :change-end-time
+                                         :end-time end-time}))
+        time-errors? (or start-time-error? end-time-error?)]
+    (dom/div
+      #js {:className "form-group"}
+      (dom/label
+        #js {:className "control-label col-md-2"}
+        "Date:")
+      (dom/div
+        #js {:className "col-md-10"}
+        (dom/div
+          #js {:className "form-inline form-inline-no-horz-margin"}
+          (dom/div
+            #js {:className "form-group"}
+            (om/build datepicker
+                      {:input-name "for-date"
+                       :selected-date selected-date
+                       :onChangeDate #(dispatch!
+                                        (actions/change-entry-page-date %))}))
+          " "
+          (dom/div
+            #js {:className (str "form-group"
+                                 (when start-time-error?  " has-error"))}
+            (dom/label #js {:htmlFor "start-time"} "From:")
+            " "
+            (time-input "start-time" startTime on-change-start-time))
+          " "
+          (dom/div
+            #js {:className (str "form-group"
+                                 (when end-time-error? " has-error"))}
+            (dom/label #js {:htmlFor "end-time"} "To:")
+            " "
+            (time-input "end-time" endTime on-change-end-time))
+          " "
+          (dom/div #js {:className "form-group help-block"} "Use format 13:37")
+          (dom/div
+            #js {:className (when time-errors? "has-error")}
+            (dom/span
+              #js {:className "help-block entry-forms-errors-date-time-errors"}
+              (when start-time-error?
+                (dom/span nil (str "Start time: " start-time-error?)
+                          (dom/br nil)))
+              (when end-time-error?
+                (dom/span nil (str "End time: " end-time-error?))))))))))
+
+(defn comment-row [for-state]
+  (let [{:keys [input-entry
+                dispatch!]} for-state
+        {:keys [comment]} input-entry]
+
+    (dom/div
+      #js {:className "form-group"}
+      (dom/label
+        #js {:className "col-md-2 control-label"
+             :htmlFor "opmerking"}
+        "Comment:")
+      (dom/div
+        #js {:className "col-md-10"}
+        (dom/input
+          #js {:type "text"
+               :name "comment"
+               :value comment
+               :onChange #(dispatch! {:action :change-comment
+                                      :comment (.. % -target -value)})
+               :id "comment"
+               :className "form-control"})
+        (dom/span
+          #js {:className "help-block"}
+          "Provide any details that can help the customer understand what you've worked on.")))))
+
+(defn billable?-row [for-state]
+  (let [{:keys [input-entry
+                dispatch!]} for-state
+        {:keys [isBillable]} input-entry]
+    (dom/div
+      #js {:className "form-group"}
+      (dom/div
+        #js {:className "col-md-offset-2 col-md-10"}
+        (dom/div
+          #js {:className "checkbox"}
+          nil
+          (dom/label
+            nil
+            (dom/input
+              #js {:type "checkbox"
+                   :id "billable"
+                   :name "billable?"
+                   :checked isBillable
+                   :onChange #(dispatch! {:action :change-billable?
+                                          :billable? (.. % -target -checked)})})
+            "This entry is billable"))))))
+
+(defn btn-row [for-state]
   (let [{:keys [input-entry
                 dispatch!
                 ]} for-state
@@ -73,213 +232,73 @@
                 entry-id]} input-entry
         {:keys [project-id task-id]} selected-item
         editing? (integer? (parse-float entry-id))]
+    (dom/div
+      #js {:className "form-group"}
+      (dom/div
+        #js {:className "col-md-offset-2 col-md-10 form-actions"}
+        (dom/button
+          #js {:className "btn btn-success save-hours"
+               :type "submit"}
+          (if editing? " Save changes" " Post entry"))
+        " "
+        (if editing?
+          (dom/button
+            #js {:className "btn btn-danger delete-entry"
+                 :name "delete-entry"}
+            "Delete entry"))
+        " "
+        (dom/button
+          #js {:className "btn btn-link"
+               :name "cancel"
+               :onClick #(do
+                           (.preventDefault %)
+                           (dispatch! {:action :cancel-entry}))}
+          "Cancel")))))
+
+(defn render-state
+  [for-state]
+  (let [{:keys [input-entry dispatch!]} for-state
+        {:keys [selected-date selected-item entry-id]} input-entry
+        {:keys [project-id task-id]} selected-item]
     (when input-entry
       ;(log "render-state" comment)
-      (let [on-change-start-time (fn [start-time]
-                                   (dispatch! {:action :change-start-time
-                                               :start-time start-time}))
-            on-change-end-time (fn [end-time]
-                                 (dispatch! {:action :change-end-time
-                                             :end-time end-time}))
-            summary-errors (seq (when formWasSubmitted
-                                  (validate-form submit-time-state)))
-            active-errors (seq (when formWasSubmitted
-                                 (validate-form input-entry)))
-            failed-fields (into {} active-errors)
-            start-time-error? (failed-fields "Start time")
-            end-time-error? (failed-fields "End time")
-            time-errors? (or start-time-error? end-time-error?)]
-        (dom/form
-          #js {:method "post"
-               :action (str "/entry/" selected-date)
-               :className "form-horizontal entry-form"
-               :onSubmit (partial on-form-submit input-entry
-                                  #(dispatch! {:action :entry-form-show-errors
-                                               :for-entry %}))}
-          (dom/div
-            #js {:className (string/join
-                              " "
-                              [(when summary-errors "has-errors")
-                               (when (seq selected-item) "entry-form-visible")])
-                 :id "entry-form-container"}
-            (dom/input #js {:type "hidden"
-                            :name "selected-project-id"
-                            :value (or project-id "")})
-            (dom/input #js {:type "hidden"
-                            :name "selected-task-id"
-                            :value (or task-id "")})
-            (dom/input #js {:type "hidden"
-                            :name "entry-id"
-                            :value (or entry-id "")})
+      (dom/form
+        #js {:method "post"
+             :action (str "/entry/" selected-date)
+             :className "form-horizontal entry-form"
+             :onSubmit (partial on-form-submit input-entry
+                                #(dispatch! {:action :entry-form-show-errors
+                                             :for-entry %}))}
+        (dom/div
+          #js {:className (string/join
+                            " "
+                            [(when (summary-errors for-state) "has-errors")
+                             (when (seq selected-item) "entry-form-visible")])
+               :id "entry-form-container"}
+          (dom/input #js {:type "hidden"
+                          :name "selected-project-id"
+                          :value (or project-id "")})
+          (dom/input #js {:type "hidden"
+                          :name "selected-task-id"
+                          :value (or task-id "")})
+          (dom/input #js {:type "hidden"
+                          :name "entry-id"
+                          :value (or entry-id "")})
+          (dom/div
+            #js {:className "row"}
             (dom/div
-              #js {:className "row"}
+              #js {:className "col-md-12"}
+              (validation-summary for-state)
               (dom/div
-                #js {:className "col-md-12"}
+                #js {:className "panel panel-default"}
                 (dom/div
-                  #js {:className
-                       (str "alert entry-form-errors"
-                            (if active-errors " alert-danger" " alert-success")
-                            (when summary-errors " entry-form-errors-has-errors"))}
-                  "There is a problem with one or more fields in the form, please correct them:"
-                  (dom/ul
-                    #js {:className "entry-form-errors-list-container"}
-                    (map #(-> (dom/li #js {:key (get % 0)}
-                                      (dom/strong nil (get % 0))
-                                      (str " "(get % 1))))
-                         summary-errors)))
-                (dom/div
-                  #js {:className "panel panel-default"}
-                  (dom/div
-                    #js {:className "panel-body"}
-                    (dom/fieldset
-                      nil
-                      (dom/div
-                        #js {:className "form-group"}
-                        (dom/label
-                          #js {:className "control-label col-md-2"}
-                          "Date:")
-                        (dom/div
-                          #js {:className "col-md-10"}
-                          (dom/div
-                            #js {:className "form-inline form-inline-no-horz-margin"}
-                            (dom/div
-                              #js {:className "form-group"}
-                              (om/build datepicker {:input-name "for-date"
-                                                    :selected-date selected-date
-                                                    :onChangeDate
-                                                    (fn [event]
-                                                      (let [instant
-                                                            (..
-                                                              js/JSJoda -Instant
-                                                              (ofEpochMilli
-                                                                (.. event -date getTime)))
-
-                                                            new-date
-                                                            (.. js/JSJoda -LocalDate
-                                                                (ofInstant instant) toString)]
-                                                        (dispatch! (actions/change-entry-page-date new-date))))}))
-                            " "
-                            (dom/div
-                              #js {:className (str "form-group"
-                                                   (when start-time-error?
-                                                     " has-error"))}
-                              (dom/label
-                                #js {:htmlFor "start-time"}
-                                "From:")
-                              " "
-                              (dom/input
-                                #js {:id "start-time"
-                                     :className "form-control time-entry-input"
-                                     :type "text"
-                                     :name "start-time"
-                                     :value startTime
-                                     :size "5"
-                                     :maxLength "5"
-                                     :autoComplete "off"
-                                     :placeholder "Time"
-                                     :onFocus #(.. % -target select)
-                                     :onChange #(on-change-start-time (.. % -target -value))
-                                     :onBlur #(on-change-start-time (expand-time
-                                                                      (.. % -target -value)))
-                                     :onKeyDown #(when (= (.-keyCode %) 13)
-                                                   (on-change-start-time
-                                                     (expand-time (.. % -target -value))))
-                                     }))
-                            " "
-                            (dom/div
-                              #js {:className (str "form-group"
-                                                   (when end-time-error? " has-error"))}
-                              (dom/label
-                                #js {:htmlFor "end-time"} "To:")
-                              " "
-                              (dom/input
-                                #js {:type "text"
-                                     :className "form-control time-entry-input"
-                                     :id "end-time"
-                                     :name "end-time"
-                                     :value endTime
-                                     :size "5"
-                                     :maxLength "5"
-                                     :autoComplete "off"
-                                     :placeholder "Time"
-                                     :onFocus #(.. % -target select)
-                                     :onChange #(on-change-end-time (.. % -target -value))
-                                     :onBlur #(on-change-end-time (expand-time
-                                                                    (.. % -target -value)))
-                                     :onKeyDown #(when (= (.-keyCode %) 13)
-                                                   (on-change-end-time (expand-time
-                                                                         (.. % -target -value))))}))
-                            " "
-                            (dom/div
-                              #js {:className "form-group help-block"}
-                              "Use format 13:37")
-                            (dom/div
-                              #js {:className (when time-errors? "has-error")}
-                              (dom/span
-                                #js {:className "help-block entry-forms-errors-date-time-errors"}
-                                (when start-time-error?
-                                  (dom/span nil (str "Start time: " start-time-error?)
-                                            (dom/br nil)))
-                                (when end-time-error?
-                                  (dom/span nil (str "End time: " end-time-error?))))))))
-                      (dom/div
-                        #js {:className "form-group"}
-                        (dom/label
-                          #js {:className "col-md-2 control-label"
-                               :htmlFor "opmerking"}
-                          "Comment:")
-                        (dom/div
-                          #js {:className "col-md-10"}
-                          (dom/input
-                            #js {:type "text"
-                                 :name "comment"
-                                 :value comment
-                                 :onChange #(dispatch! {:action :change-comment
-                                                        :comment (.. % -target -value)})
-                                 :id "comment"
-                                 :className "form-control"})
-                          (dom/span
-                            #js {:className "help-block"}
-                            "Provide any details that can help the customer understand what you've worked on.")))
-                      (dom/div
-                        #js {:className "form-group"}
-                        (dom/div
-                          #js {:className "col-md-offset-2 col-md-10"}
-                          (dom/div
-                            #js {:className "checkbox"}
-                            nil
-                            (dom/label
-                              nil
-                              (dom/input
-                                #js {:type "checkbox"
-                                     :id "billable"
-                                     :name "billable?"
-                                     :checked isBillable
-                                     :onChange #(dispatch! {:action :change-billable?
-                                                            :billable? (.. % -target -checked)})})
-                              "This entry is billable"))))
-                      (dom/div
-                        #js {:className "form-group"}
-                        (dom/div
-                          #js {:className "col-md-offset-2 col-md-10 form-actions"}
-                          (dom/button
-                            #js {:className "btn btn-success save-hours"
-                                 :type "submit"}
-                            (if editing? " Save changes" " Post entry"))
-                          " "
-                          (if editing?
-                            (dom/button
-                              #js {:className "btn btn-danger delete-entry"
-                                   :name "delete-entry"}
-                              "Delete entry"))
-                          " "
-                          (dom/button
-                            #js {:className "btn btn-link"
-                                 :name "cancel"
-                                 :onClick #(do
-                                             (.preventDefault %)
-                                             (dispatch! {:action :cancel-entry}))}
-                            "Cancel"))))))))))))))
+                  #js {:className "panel-body"}
+                  (dom/fieldset
+                    nil
+                    (date-time-entry-row for-state)
+                    (comment-row for-state)
+                    (billable?-row for-state)
+                    (btn-row for-state)))))))))))

 (defn om-component [for-state owner]
   (reify


forgot to change namespace

forgot to change namespace

--- test/midje/util/t_one_seven.clj
+++ test/midje/util/t_one_seven.clj
@@ -1,4 +1,4 @@
-(ns midje.util.t-laziness
+(ns midje.util.t-one-seven
   (:use [midje.sweet]
         [midje.util laziness thread-safe-var-nesting]
         [midje.test-util]))


Print results out as README describes

Print results out as README describes

--- test/workshop/jobs/test_2_3.clj
+++ test/workshop/jobs/test_2_3.clj
@@ -72,6 +72,7 @@
                 (onyx.api/submit-job peer-config job)
                 (let [[results] (u/collect-outputs! lifecycles [:write-segments])]
                   (u/segments-equal? expected-output results)))))
+          _ (println results)
           lines (butlast (rest (clojure.string/split results #"\n")))
           groups (group-by #(last (re-find #":user-id (\d+).*" %)) lines)]
       (doseq [k (keys groups)]


Added *print-with-dl-type*

Added *print-with-dl-type*

which is only used by DL-expression's print-method.

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/contrib/dl/framework/syntax.clj
+++ src/conexp/contrib/dl/framework/syntax.clj
@@ -14,6 +14,11 @@

 ;;;

+(defvar *print-with-dl-type* false
+  "If true, prints DL data structures with type tag.")
+
+;;;
+
 (deftype DL [name concept-names role-names constructors])

 (defn language-name
@@ -66,7 +71,9 @@

 (defmethod print-method ::DL-expression [dl-exp out]
   (let [#^String output (with-out-str
-			  (pprint (list 'DL-expr (expression dl-exp))))]
+			  (if *print-with-dl-type*
+			    (pprint (list 'DL-expr (expression dl-exp)))
+			    (pprint (expression dl-exp))))]
     (.write out (.trim output))))

 ;;;


rethinking autoload toggling

rethinking autoload toggling

--- support/src/figwheel/client.cljs
+++ support/src/figwheel/client.cljs
@@ -22,10 +22,15 @@
                  :content args})
   args)

-(defonce autoload (atom true))
-
-(defn ^:export toggle_autoload []
-  (swap! autoload not))
+(defn autoload? []
+  (condp = (or (.getItem js/localStorage "figwheel_autoload") "true")
+    "true" true
+    "false" false))
+
+(defn ^:export toggle-autoload []
+  (.setItem js/localStorage "figwheel_autoload" (not (autoload?)))
+  (utils/log :info
+             (str "Figwheel autoloading " (if (autoload?) "ON" "OFF"))))

 (defn console-print [args]
   (.apply (.-log js/console) js/console (into-array args))
@@ -39,6 +44,7 @@
             console-print
             figwheel-repl-print))))

+
 (defn get-essential-messages [ed]
   (when ed
     (cons (select-keys ed [:message :class])
@@ -90,14 +96,17 @@
                (let [msg-hist (focus-msgs #{:files-changed :compile-warning} msg-hist')
                      msg-names (map :msg-name msg-hist)
                      msg (first msg-hist)]
-                 (when @autoload
-                     #_(.log js/console (prn-str msg))
+                 #_(.log js/console (prn-str msg))
+                 (if (autoload?)
                      (cond
                        (reload-file-state? msg-names opts)
                        (alts! [(reloading/reload-js-files opts msg) (timeout 1000)])

                        (block-reload-file-state? msg-names opts)
-                       (.warn js/console "Figwheel: Not loading code with warnings - " (-> msg :files first :file))))
+                       (utils/log :warn (str "Figwheel: Not loading code with warnings - " (-> msg :files first :file))))
+                     (do
+                       (utils/log :warn "Figwheel: code autoloading is OFF")
+                       (utils/log :info (str "Not loading: " (map :file (:files msg))))))
                  (recur))))
     (fn [msg-hist] (put! ch msg-hist) msg-hist)))

@@ -177,7 +186,6 @@
           :compile-failed  (on-compile-fail msg)
           nil)))

-
 ;; this is seperate for live dev only
 (defn heads-up-plugin-msg-handler [opts msg-hist']
   (let [msg-hist (focus-msgs #{:files-changed :compile-warning :compile-failed} msg-hist')
@@ -186,7 +194,8 @@
     (go
      (cond
       (reload-file-state? msg-names opts)
-      (if (and @autoload (:autoload opts))
+      (if (and (autoload?)
+               (:autoload opts))
         (<! (heads-up/flash-loaded))
         (<! (heads-up/clear)))


move integer-id-params and model wrappers earlier

--- src/clj/clj_money/web/server.clj
+++ src/clj/clj_money/web/server.clj
@@ -48,124 +48,130 @@
             [clj-money.web.users :as users]
             [clj-money.web.grants :as grants]))

+(defmacro model-route
+  [method path handler]
+  `(~method ~path req# (-> ~handler
+                           wrap-models
+                           wrap-integer-id-params)))
+
 (defroutes all-routes
   ; Entities
-  (GET "/entities" req entities/index)
-  (GET "/entities/new" req entities/new-entity)
-  (POST "/entities" req entities/create-entity)
-  (GET "/entities/:id/edit" req entities/edit-entity)
-  (POST "/entities/:id" req entities/update)
-  (POST "/entities/:id/delete" req entities/delete)
+  (model-route GET "/entities" entities/index)
+  (model-route GET "/entities/new" entities/new-entity)
+  (model-route POST "/entities" entities/create-entity)
+  (model-route GET "/entities/:id/edit" entities/edit-entity)
+  (model-route POST "/entities/:id" entities/update)
+  (model-route POST "/entities/:id/delete" entities/delete)

   ; User grants
-  (GET "/entities/:entity-id/grants" req grants/index)
-  (GET "/entities/:entity-id/grants/new" req grants/new-grant)
-  (POST "/entities/:entity-id/grants" req grants/create)
-  (GET "/grants/:id/edit" req grants/edit)
-  (POST "/grants/:id" req grants/update)
-  (POST "/grants/:id/delete" req grants/delete)
+  (model-route GET "/entities/:entity-id/grants" grants/index)
+  (model-route GET "/entities/:entity-id/grants/new" grants/new-grant)
+  (model-route POST "/entities/:entity-id/grants" grants/create)
+  (model-route GET "/grants/:id/edit" grants/edit)
+  (model-route POST "/grants/:id" grants/update)
+  (model-route POST "/grants/:id/delete" grants/delete)

   ; Accounts
-  (GET "/entities/:entity-id/accounts" req accounts/index)
-  (GET "/entities/:entity-id/accounts/new" req accounts/new-account)
-  (POST "/entities/:entity-id/accounts" req accounts/create)
-  (GET "/accounts/:id" req accounts/show)
-  (GET "/accounts/:id/edit" req accounts/edit)
-  (POST "/accounts/:id" req accounts/update)
-  (POST "/accounts/:id/delete" req accounts/delete)
+  (model-route GET "/entities/:entity-id/accounts" accounts/index)
+  (model-route GET "/entities/:entity-id/accounts/new" accounts/new-account)
+  (model-route POST "/entities/:entity-id/accounts" accounts/create)
+  (model-route GET "/accounts/:id" accounts/show)
+  (model-route GET "/accounts/:id/edit" accounts/edit)
+  (model-route POST "/accounts/:id" accounts/update)
+  (model-route POST "/accounts/:id/delete" accounts/delete)

   ; Budgets
-  (GET "/entities/:entity-id/budgets" req budgets/index)
-  (GET "/entities/:entity-id/budgets/new" req budgets/new-budget)
-  (POST "/entities/:entity-id/budgets" req budgets/create)
-  (GET "/budgets/:id/edit" req budgets/edit)
-  (POST "/budgets/:id" req budgets/update)
-  (POST "/budgets/:id/delete" req budgets/delete)
-  (GET "/budgets/:id" req budgets/show)
+  (model-route GET "/entities/:entity-id/budgets" budgets/index)
+  (model-route GET "/entities/:entity-id/budgets/new" budgets/new-budget)
+  (model-route POST "/entities/:entity-id/budgets" budgets/create)
+  (model-route GET "/budgets/:id/edit" budgets/edit)
+  (model-route POST "/budgets/:id" budgets/update)
+  (model-route POST "/budgets/:id/delete" budgets/delete)
+  (model-route GET "/budgets/:id" budgets/show)

   ; Budget items
-  (GET "/budgets/:budget-id/items/new/:method" req budgets/new-item)
-  (POST "/budgets/:budget-id/items" req budgets/create-item)
-  (GET "/budget-items/:id/edit/:method" req budgets/edit-item)
-  (POST "/budget-items/:id" req budgets/update-item)
-  (POST "/budget-items/:id/delete" req budgets/delete-item)
+  (model-route GET "/budgets/:budget-id/items/new/:method" budgets/new-item)
+  (model-route POST "/budgets/:budget-id/items" budgets/create-item)
+  (model-route GET "/budget-items/:id/edit/:method" budgets/edit-item)
+  (model-route POST "/budget-items/:id" budgets/update-item)
+  (model-route POST "/budget-items/:id/delete" budgets/delete-item)

   ; Budget monitors
-  (GET "/entities/:entity-id/monitors" req entities/monitors)
-  (POST "/entities/:entity-id/monitors" req entities/create-monitor)
-  (POST "/entities/:entity-id/monitors/:account-id/delete" req entities/delete-monitor)
+  (model-route GET "/entities/:entity-id/monitors" entities/monitors)
+  (model-route POST "/entities/:entity-id/monitors" entities/create-monitor)
+  (model-route POST "/entities/:entity-id/monitors/:account-id/delete" entities/delete-monitor)

   ; Commodities
-  (GET "/entities/:entity-id/commodities" req commodities/index)
-  (GET "/entities/:entity-id/commodities/new" req commodities/new-commodity)
-  (POST "/entities/:entity-id/commodities" req commodities/create)
-  (GET "/commodities/:id/edit" req commodities/edit)
-  (POST "/commodities/:id" req commodities/update)
-  (POST "/commodities/:id/delete" req commodities/delete)
+  (model-route GET "/entities/:entity-id/commodities" commodities/index)
+  (model-route GET "/entities/:entity-id/commodities/new" commodities/new-commodity)
+  (model-route POST "/entities/:entity-id/commodities" commodities/create)
+  (model-route GET "/commodities/:id/edit" commodities/edit)
+  (model-route POST "/commodities/:id" commodities/update)
+  (model-route POST "/commodities/:id/delete" commodities/delete)

   ; Prices
-  (GET "/commodities/:commodity-id/prices" req prices/index)
-  (GET "/commodities/:commodity-id/prices/new" req prices/new-price)
-  (POST "/commodities/:commodity-id/prices" req prices/create)
-  (POST "/commodities/:commodity-id/prices/fetch" req prices/fetch)
-  (POST "/entities/:entity-id/prices/fetch" req prices/fetch-all)
-  (POST "/prices/:id/delete" req prices/delete)
+  (model-route GET "/commodities/:commodity-id/prices" prices/index)
+  (model-route GET "/commodities/:commodity-id/prices/new" prices/new-price)
+  (model-route POST "/commodities/:commodity-id/prices" prices/create)
+  (model-route POST "/commodities/:commodity-id/prices/fetch" prices/fetch)
+  (model-route POST "/entities/:entity-id/prices/fetch" prices/fetch-all)
+  (model-route POST "/prices/:id/delete" prices/delete)

   ; Transactions
-  (GET "/entities/:entity-id/transactions" req transactions/index)
-  (GET "/entities/:entity-id/transactions/new" req transactions/new-transaction)
-  (POST "/entities/:entity-id/transactions" req transactions/create)
-  (GET "/transactions/:transaction-date/:id/edit" req transactions/edit)
-  (POST "/transactions/:transaction-date/:id" req transactions/update)
-  (POST "/transactions/:transaction-date/:id/delete" req transactions/delete)
+  (model-route GET "/entities/:entity-id/transactions" transactions/index)
+  (model-route GET "/entities/:entity-id/transactions/new" transactions/new-transaction)
+  (model-route POST "/entities/:entity-id/transactions" transactions/create)
+  (model-route GET "/transactions/:transaction-date/:id/edit" transactions/edit)
+  (model-route POST "/transactions/:transaction-date/:id" transactions/update)
+  (model-route POST "/transactions/:transaction-date/:id/delete" transactions/delete)

   ; Attachments
-  (GET "/transactions/:transaction-id/attachments" req attachments/index)
-  (GET "/transactions/:transaction-id/attachments" req attachments/index)
-  (GET "/transactions/:transaction-id/attachments/new" req attachments/new-attachment)
-  (POST "/transactions/:transaction-id/attachments" req attachments/create)
-  (GET "/attachments/:id/edit" req attachments/edit)
-  (POST "/attachments/:id" req attachments/update)
-  (POST "/attachments/:id/delete" req attachments/delete)
+  (model-route GET "/transactions/:transaction-id/attachments" attachments/index)
+  (model-route GET "/transactions/:transaction-id/attachments" attachments/index)
+  (model-route GET "/transactions/:transaction-id/attachments/new" attachments/new-attachment)
+  (model-route POST "/transactions/:transaction-id/attachments" attachments/create)
+  (model-route GET "/attachments/:id/edit" attachments/edit)
+  (model-route POST "/attachments/:id" attachments/update)
+  (model-route POST "/attachments/:id/delete" attachments/delete)

   ; Images
-  (GET "/images/:image-id" req images/show)
+  (model-route GET "/images/:image-id" images/show)

   ; Trading
-  (GET "/accounts/:account-id/purchases/new" req trading/new-purchase)
-  (POST "/accounts/:account-id/purchases" req trading/purchase)
-  (GET "/accounts/:account-id/sales/new" req trading/new-sale)
-  (POST "/accounts/:account-id/sales" req trading/sell)
-  (POST "/transactions/:transaction-id/unbuy" req trading/unbuy)
+  (model-route GET "/accounts/:account-id/purchases/new" trading/new-purchase)
+  (model-route POST "/accounts/:account-id/purchases" trading/purchase)
+  (model-route GET "/accounts/:account-id/sales/new" trading/new-sale)
+  (model-route POST "/accounts/:account-id/sales" trading/sell)
+  (model-route POST "/transactions/:transaction-id/unbuy" trading/unbuy)

   ; Lots
-  (GET "/accounts/:account-id/lots" req lots/index)
+  (model-route GET "/accounts/:account-id/lots" lots/index)

   ; Reconciliations
-  (GET "/accounts/:account-id/reconciliations/new" req reconciliations/new-reconciliation)
-  (POST "/accounts/:account-id/reconciliations" req reconciliations/create)
-  (GET "/reconciliations/:id" req reconciliations/show)
-  (GET "/reconciliations/:id/edit" req reconciliations/edit)
-  (POST "/reconciliations/:id" req reconciliations/update)
-  (POST "/reconciliations/:id/delete" req reconciliations/delete)
+  (model-route GET "/accounts/:account-id/reconciliations/new" reconciliations/new-reconciliation)
+  (model-route POST "/accounts/:account-id/reconciliations" reconciliations/create)
+  (model-route GET "/reconciliations/:id" reconciliations/show)
+  (model-route GET "/reconciliations/:id/edit" reconciliations/edit)
+  (model-route POST "/reconciliations/:id" reconciliations/update)
+  (model-route POST "/reconciliations/:id/delete" reconciliations/delete)

   ; Imports
   (GET "/imports/new" req imports/new-import)

   ; Reports
-  (GET "/entities/:entity-id/reports" req reports/render)
-  (GET "/entities/:entity-id/reports/:type" req reports/render)
+  (model-route GET "/entities/:entity-id/reports" reports/render)
+  (model-route GET "/entities/:entity-id/reports/:type" reports/render)

   ; Single page apps
   (GET "/apps" req apps/index)
   (GET "/apps/:id" req apps/show)

-  (GET "/api/entities" req entities-api/index)
-  (DELETE "/api/entities/:id" req entities-api/delete)
+  (model-route GET "/api/entities" entities-api/index)
+  (model-route DELETE "/api/entities/:id" entities-api/delete)

   ; Imports
   (POST "/api/imports" req imports-api/create)
-  (GET "/api/imports/:id" req imports-api/show)
+  (model-route GET "/api/imports/:id" imports-api/show)

   (GET "/" req pages/home)
   (GET "/login" req pages/login)
@@ -244,8 +250,6 @@

 (def wrapped-routes
   (wrap-routes all-routes
-               [wrap-models                         "models"]
-               [wrap-integer-id-params              "multipart params"]
                [wrap-multipart-params               "multipart params" (complement api?)]
                [wrap-keyword-params                 "keyword params"   (complement api?)]
                [wrap-json-params                    "json params"      api?]


Expand search queries and add some for sanity checking

--- src/clj/freestuffly/notifier.clj
+++ src/clj/freestuffly/notifier.clj
@@ -8,7 +8,7 @@
   (:require [hickory.select :as s]))

 (def interesting-keywords
-  #"(?i)paint|playstation|camping|emulsion|lamp|ladder|roller|xbox|mac")
+  #"(?i)paint|playstation|camping|emulsion|lamp|ladder|roller|xbox|mac|fish|marine|kitchen")

 (defn interesting-finds
   [results]


The created response needs to contain an empty map as body

otherwise we run into problems with transit

--- src/clj/mdr2/routes/services.clj
+++ src/clj/mdr2/routes/services.clj
@@ -107,7 +107,7 @@
              :handler (fn [{{p :body} :parameters}]
                         (try
                           (let [p (prod/create! p)]
-                            (created (str (:id p))))
+                            (created (str "productions/" (:id p)) {}))
                           (catch clojure.lang.ExceptionInfo e
                             (let [{:keys [error-id errors]} (ex-data e)]
                               (case error-id
@@ -254,7 +254,7 @@
                         (try
                           (let [tempfile (:tempfile file)
                                 p (abacus/import-new-production tempfile)]
-                            (created (str (:id p))))
+                            (created (str "productions/" (:id p)) {}))
                           (catch clojure.lang.ExceptionInfo e
                             (let [{:keys [error-id errors]} (ex-data e)]
                               (case error-id


extract calculations for balance sheet transform

--- src/clj_money/models/reports.clj
+++ src/clj_money/models/reports.clj
@@ -109,10 +109,10 @@

 (defn- set-balances-in-account-groups
   [storage-spec as-of groups]
-  (map #(set-balances-in-account-group
-          %
-          (partial set-balances storage-spec as-of))
-       groups))
+  (mapv #(set-balances-in-account-group
+           %
+           (partial set-balances storage-spec as-of))
+        groups))

 (defn- transform-account
   [account depth]
@@ -160,36 +160,48 @@

 (defn- transform-balance-sheet
   "Accepts group accounts and returns a report structure"
-  [storage-spec entity-id groups]
+  [groups]
   (let [summary (->> groups
                      (map (juxt :type :value))
                      (into {}))
         retained (- (:income summary) (:expense summary))
-         ; I think I want to rework this and calculate unrealized gains
-         ; and maybe also retained earnings before passing data into this function.
-         ; Then this function can focus on rearranging nested data into report records
-        unrealized-gains (lots/unrealized-gains storage-spec entity-id)
-        unrealized-caption (if (< unrealized-gains 0)
-                             "Unrealized Losses"
-                             "Unrealized Gains")
         records (->> groups
-                     (map (fn [entry]
-                            (if (= :equity (:type entry))
-                              (-> entry
-                                  (update-in [:accounts] #(conj %
-                                                                {:name unrealized-caption
-                                                                 :balance unrealized-gains
-                                                                 :children-balance 0}
-                                                                {:name "Retained Earnings"
-                                                                 :balance retained
-                                                                 :children-balance 0}))
-                                  (update-in [:value] #(+ %1 retained)))
-                              entry)))
                      (remove #(#{:income :expense} (:type %)))
                      (mapcat transform-account-group))]
     (concat records [{:caption "Liabilities + Equity"
-                      :value (+ retained (:equity summary) (:liability summary))
+                      :value (+ (:equity summary) (:liability summary))
                       :style :summary}])))
+
+(defn- append-retained-earnings
+  [account-groups]
+  (let [summary (->> account-groups
+                     (map (juxt :type :value))
+                     (into {}))
+        retained (- (:income summary) (:expense summary))]
+    (update-in account-groups
+               [2]
+               (fn [entry]
+                 (-> entry
+                     (update-in [:accounts] #(conj %
+                                                   {:name "Retained Earnings"
+                                                    :balance retained
+                                                    :children-balance 0}))
+                     (update-in [:value] #(+ % retained)))))))
+
+(defn- append-unrealized-gains
+  [account-groups storage-spec entity-id as-of]
+  account-groups
+  #_(let [unrealized-gains (lots/unrealized-gains storage-spec entity-id as-of)
+        unrealized-caption (if (< unrealized-gains 0)
+                             "Unrealized Losses"
+                             "Unrealized Gains")]
+    account-groups))
+
+(defn- append-calculated-values
+  [storage-spec entity-id as-of account-groups]
+  (-> account-groups
+      append-retained-earnings
+      (append-unrealized-gains storage-spec entity-id as-of)))

 (defn balance-sheet
   "Returns the data used to populate a balance sheet report"
@@ -201,9 +213,9 @@
    (->> (accounts/select-nested-by-entity-id
           storage-spec
           entity-id)
-        (into [])
         (set-balances-in-account-groups storage-spec as-of)
-        (transform-balance-sheet storage-spec entity-id))))
+        (append-calculated-values storage-spec entity-id as-of)
+        transform-balance-sheet)))

 (defn- ->budget-report-record
   [storage budget period-count as-of account]


first and last name have been replaced with name

--- src/freecoin/handlers/sign_in.clj
+++ src/freecoin/handlers/sign_in.clj
@@ -109,8 +109,7 @@
                          (if (:activated account)
                            (if (account/correct-password? account-store email (-> ctx :request :params :sign-in-password) hashers/check)
                              {:email email
-                              :first-name (:first-name account)
-                              :last-name (:last-name account)}
+                              :name (:name account)}
                              [false  (fh/form-problem (conj problems
                                                             {:keys [:sign-in-password] :msg (str "Wrong password for account " email)}))])
                            [false  (fh/form-problem (conj problems
@@ -129,7 +128,7 @@
   :post! (fn [ctx]
            ;; the wallet exists already
            (let [email (:email ctx)
-                 name (str (:first-name ctx) " " (:last-name ctx))]
+                 name (:name ctx)]
              (if-let [wallet (wallet/fetch wallet-store email)]
                (do
                  (log/trace "The wallet for email " email " already exists")


Implement chaincode-event

Implement chaincode-event

--- src/clojure_fabric/event_hub.clj
+++ src/clojure_fabric/event_hub.clj
@@ -188,7 +188,7 @@

 (defn deliver-block-events-to-channels
   [^Common$Block proto-block]
-  (let [clj-block (proto/proto->clj proto-block {})]
+  (let [clj-block (proto/proto->clj proto-block (proto/parse-trees :block))]
     ;; 1. Block Event on all channels
     (async/put! block-channel clj-block)
     (doseq [[data code] (map list
@@ -197,27 +197,17 @@
                                  (:metadata)
                                  (nth (block-metadata-index-map :transactions-filter))
                                  (.toByteArray)))]
-      (let [payload (-> (Common$Envelope/parseFrom ^bytes data)
-                        (proto/proto->clj {})
-                        (:payload envelope))
-            channel-header (-> payload (:header) (:channel-header))]
+      (let [payload (get data :payload)
+            channel-header (get-in payload [:header :channel-header])]
         ;; 2. Transaction Event with tx-id
         (when-let [ch (tx-id->channel tx-id)]
-          (async/put! ch
-                      (make-TxEvent (:tx-id channel-header) code)))
+          (async/put! ch (make-TxEvent (:tx-id channel-header) code)))
         ;; 3. Chaincode event
         (when (= (:type channel-header) (proto/header-types :endorser-transaction))
-          (-> (:data payload)
-              ;; FIXME use toplevel prot->clj opts
-              ;; Add record for TransactionPackage$Transaction
-              (TransactionPackage$Transaction/parseFrom)
-              ;; YOU'RE HERE
-              ))
-        ))
-
-    ))
-
-
+          (let [chaincode-event (get-in payload [:data :actions 0 :payload :action
+                                                 :proposal-response-payload :extension :events])]
+            (when-let [ch (chaincode-id->channel (:chaincode-id chaincode-event))]
+              (async/put! ch chaincode-event))))))))

 (defn transaction-observer
   [ch]


fix: generator _validity field json error

--- src/main/clojure/pdok/featured/generator.clj
+++ src/main/clojure/pdok/featured/generator.clj
@@ -135,7 +135,7 @@
 (def ^:dynamic *attribute-generators* attribute-generators)

 (defn texify-validity [validity]
-  (tf/unparse date-time-formatter validity))
+  (tf/unparse date-time-formatter (to-date-time validity)))

 (defn new-feature [collection id]
   {:_action     "new"
@@ -242,18 +242,18 @@

 (defn generate-smile [obj]
   (let [baos (ByteArrayOutputStream.)]
-    (.toByteArray (generate-smile-stream obj baos))))
+    (.toByteArray ^ByteArrayOutputStream (generate-smile-stream obj baos))))

 (defn texify-feature [feature]
-  (walk/postwalk
+  (walk/prewalk
     (fn [e]
-      (cond (instance? LocalDateTime e)
+      (cond (and (instance? MapEntry e) (= :_validity (first e)))
+            (MapEntry. :_validity (texify-validity (second e)))
+            (instance? LocalDateTime e)
             (texify-moment e)
             (instance? LocalDate e)
             (texify-date e)
-            (and (instance? MapEntry e) (= :_validity (first e)))
-            (MapEntry. :_validity (texify-validity (second e)))
             :else e))
     feature))

@@ -262,14 +262,14 @@
                (doto smile-generator
                  (.writeStartArray 2)
                  (.writeString "D")
-                 (.writeNumber (to-long c))
+                 (.writeNumber ^long (to-long c))
                  (.writeEndArray))))
 (add-encoder LocalDateTime
              (fn [c ^SmileGenerator smile-generator]
                (doto smile-generator
                  (.writeStartArray 2)
                  (.writeString "M")
-                 (.writeNumber (to-long c))
+                 (.writeNumber ^long (to-long c))
                  (.writeEndArray))))

 (defn random-json-features [out-stream dataset collection total & args]


Relax parser spec, avoid fspec

Relax parser spec, avoid fspec

--- src/com/wsscode/pathom/core.cljc
+++ src/com/wsscode/pathom/core.cljc
@@ -68,9 +68,9 @@

 (>def ::js-value-transform ::map-value-transform)

-(>def ::parser
-  (s/fspec :args (s/cat :env map? :tx ::eql/query)
-    :ret map?))
+(>def ::parser fn?
+  #_(s/fspec :args (s/cat :env map? :tx ::eql/query)
+      :ret map?))

 (>def ::wrap-read
   (s/fspec :args (s/cat :reader ::reader-fn)


fix using-latest-result? regression

fix using-latest-result? regression

--- src/main/cljs_api_gen/cljsdoc/validate.clj
+++ src/main/cljs_api_gen/cljsdoc/validate.clj
@@ -208,8 +208,9 @@
 ;;--------------------------------------------------------------------------------

 (defn using-latest-result? []
-  (= (-> *result* :release :cljs-tag)
-     (last @published-cljs-tags)))
+  (let [version (:version *result*)]
+    (= (get-in *result* [:history :details version :tag])
+       (last @published-cljs-tags))))

 (defn symbol-check-pass?
   "Determines if we should pass the symbol check."


Update comment to reflect removed std prefix

--- src/main/clojure/clojure/data/xml/name.clj
+++ src/main/clojure/clojure/data/xml/name.clj
@@ -107,7 +107,7 @@
    Similar to clojure.core/alias, but if namespace doesn't exist, it is created.

    ## Example
-   ;; (declare-ns :xml.dav \"DAV:\") ; already in stdlib
+   (declare-ns :xml.dav \"DAV:\")
    (alias-ns :D :xml.dav)
   {:tag ::D/propfind :content []}"
   {:arglists '([& {:as alias-nss}])}


fix convert empty strings (#719)

fix convert empty strings (#719)

--- src/cljs/main/broadfcui/page/workspace/summary/catalog/wizard.cljs
+++ src/cljs/main/broadfcui/page/workspace/summary/catalog/wizard.cljs
@@ -50,12 +50,13 @@
             (map option-match [:questions :enumerate])))
         [questions enumerate]))))

-(defn- convert-empty-strings [attributes]
-  (utils/map-values
+(defn- remove-empty-values [attributes]
+  (utils/filter-values
    (fn [val]
      (if (or (coll? val) (string? val))
        (not-empty val)
-       val)) attributes))
+       true))
+   attributes))

 (def ^:private ALL_USERS "All users")

@@ -103,7 +104,7 @@
             invalid-attributes)]])
    (style/create-paragraph
     [:div {}
-     (let [questions (first (get-questions-for-page (convert-empty-strings attributes) library-schema 0))]
+     (let [questions (first (get-questions-for-page (remove-empty-values attributes) library-schema 0))]
        (map (fn [attribute]
               (if (not-empty (str (attributes (keyword attribute))))
                 (library-utils/render-property library-schema attributes (keyword attribute))))
@@ -233,7 +234,7 @@
          (swap! locals update :page-attributes assoc page-num attributes-from-page)
          (doseq [page (conj pages-stack page-num)]
            (let [[questions _] (get-questions-for-page all-attributes (:library-schema props) page)
-                 {:keys [invalid]} (library-utils/validate-required (convert-empty-strings all-attributes)
+                 {:keys [invalid]} (library-utils/validate-required (remove-empty-values all-attributes)
                                                                     questions required-attributes)]
              (reset! invalid-attributes (clojure.set/union invalid @invalid-attributes))))
          (swap! state assoc :invalid-properties @invalid-attributes)
@@ -260,7 +261,7 @@
          (swap! state assoc :submitting? true :submit-error nil)
          (endpoints/call-ajax-orch
           {:endpoint (endpoints/save-library-metadata (:workspace-id props))
-           :payload  (convert-empty-strings (merge attributes-seen (:version-attributes @state)))
+           :payload  (remove-empty-values (merge attributes-seen (:version-attributes @state)))
            :headers utils/content-type=json
            :on-done (fn [{:keys [success? get-parsed-response]}]
                       (swap! state dissoc :submitting?)


Improve terminology in `invert-injection` and `invert-non-injection`

--- test/com/nomistech/clojure_the_language/c_850_utils/s_100_utils.clj
+++ test/com/nomistech/clojure_the_language/c_850_utils/s_100_utils.clj
@@ -52,25 +52,26 @@
 ;;;; ___________________________________________________________________________
 ;;;; ---- invert-injection invert-non-injection ----

-(defn invert-injection [f domain]
+(defn invert-injection [f domain-subset]
   "Return a map which, when regarded as a function, is the inverse of `f`.
-  `f` is an injective function -- it takes elements of `domain` (and possibly
-  other values, not relevant here) as argument, and returns a single value.
+  `f` is an injective function -- it takes elements of `domain-subset` (and
+  possibly other values, not relevant here) as argument, and returns a single
+  value.
   For explanations of terminology, see:
     https://www.mathsisfun.com/sets/domain-range-codomain.html
     https://www.mathsisfun.com/sets/injective-surjective-bijective.html"
-  (dissoc (group-by f domain)
+  (dissoc (group-by f domain-subset)
           nil))

-(defn invert-non-injection [f domain]
+(defn invert-non-injection [f domain-subset]
   "Return a map which, when regarded as a function, is the inverse of `f`.
-  `f` is an non-injective function -- it takes elements of `domain` (and
-  possibly other values, not relevant here) as argument, and returns acollection
-  of values.
+  `f` is an non-injective function -- it takes elements of `domain-subset` (and
+  possibly other values, not relevant here) as argument, and returns a
+  collection of values.
   For explanations of terminology, see:
     https://www.mathsisfun.com/sets/domain-range-codomain.html
     https://www.mathsisfun.com/sets/injective-surjective-bijective.html"
-  (let [range-domain-pairs (for [d domain
+  (let [range-domain-pairs (for [d domain-subset
                                  r (f d)]
                              [d r])]
     (reduce (fn [sofar [d r]]


test other arguments to get-posts

test other arguments to get-posts

--- test/start_clojure/test/core.clj
+++ test/start_clojure/test/core.clj
@@ -9,4 +9,29 @@
 		(data/make-post "text" content)
 		(let [result (data/get-mostrecent-posts 1 0)]
 			(is (= 1 (count result)))
-			(is (= content (get (first result) :content))))))
+			(is (= content (get (first result) :content)))))
+	(comment the sleep is so that sqlite can sort things)
+	(. Thread (sleep 1001)))
+
+(deftest interval-post
+	(let [content1 (str "first content " (now))
+			content2 (str "second content " (now))
+			content3 (str "third content " (now))
+			content4 (str "fourth content " (now))]
+		(. Thread (sleep 1001))
+		(data/make-post "title" content1)
+		(. Thread (sleep 1001))
+		(data/make-post "title" content2)
+		(. Thread (sleep 1001))
+		(data/make-post "title" content3)
+		(let [result (data/get-mostrecent-posts 1 0)]
+			(is (= 1 (count result)))
+			(is (= content3 (get (first result) :content))))
+		(let [result (data/get-mostrecent-posts 1 1)]
+			(is (= 1 (count result)))
+			(is (= content2 (get (first result) :content))))
+		(let [result (data/get-mostrecent-posts 2 1)]
+			(is (= 2 (count result)))
+			(is (= content2 (get (first result) :content)))
+			(is (= content1 (get (second result) :content)))))
+	(. Thread (sleep 1001)))