Support all races and all name types.

Support all races and all name types.

--- src/hxgm30/language/app/handler/core.clj
+++ src/hxgm30/language/app/handler/core.clj
@@ -14,6 +14,7 @@
     [clojure.java.io :as io]
     [clojusc.twig :as twig]
     [hxgm30.httpd.kit.response :as response]
+    [hxgm30.language.common :as common]
     [hxgm30.language.gen.core :as gen]
     [hxgm30.language.gen.corpus :as corpus]
     [hxgm30.language.gen.name :as name]
@@ -49,6 +50,37 @@
   (when-let [sylls (get-in request [:params :syllables])]
     (Integer/parseInt sylls)))

+(defn -gen-name
+  [generator race name-type sylls]
+  (if-not (nil? sylls)
+    (name/gen-name generator race name-type sylls)
+    (name/gen-name generator race name-type)))
+
+(defn gen-one-name
+  [generator race name-type sylls]
+  [{:race race
+    :name-type name-type
+    :name (-gen-name generator race name-type sylls)}])
+
+(defn gen-all-names
+  [generator race sylls]
+  [{:race race
+    :name {:female (-gen-name generator race :female sylls)
+           :male (-gen-name generator race :male sylls)
+           :surname (-gen-name generator race :surname sylls)}}])
+
+(defn gen-one-name-all-races
+  [generator name-type sylls]
+  (->> common/supported-names
+       (mapcat #(gen-one-name generator % name-type sylls))
+       vec))
+
+(defn gen-all-names-all-races
+  [generator sylls]
+  (->> common/supported-names
+       (mapcat #(gen-all-names generator % sylls))
+       vec))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;   Generic Handlers   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -76,12 +108,19 @@
           ;;       a generator in the component so that it doesn't have to be
           ;;       done on every request.
           generator (gen/create-content-generator component gen-type)]
-      (response/json request
-                     [{:race race
-                       :name-type name-type
-                       :name (if-not (nil? sylls)
-                               (name/gen-name generator race name-type sylls)
-                               (name/gen-name generator race name-type))}]))))
+      (response/json
+        request
+        (cond (and (not= :all race) (not= :all name-type))
+              (gen-one-name generator race name-type sylls)
+
+              (and (not= :all race) (= :all name-type))
+              (gen-all-names generator race sylls)
+
+              (and (= :all race) (not= :all name-type))
+              (gen-one-name-all-races generator name-type sylls)
+
+              (and (= :all race) (= :all name-type))
+              (gen-all-names-all-races generator sylls))))))

 (defn read-lang-stats
   [component]


implement partial project file upgrading. (see #51)

--- src/leiningen/ancient/artifact/check.clj
+++ src/leiningen/ancient/artifact/check.clj
@@ -5,13 +5,18 @@

 ;; ## Artifact Map

+(defn- check-artifact?
+  [[_ _ & {:keys [upgrade?] :or {upgrade? true}}]]
+  (boolean upgrade?))
+
 (defn read-artifact
   "Combine artifact path and artifact vector to a map of `:path`/`:artifact`."
   [path artifact-vector]
   (when (and (vector? artifact-vector)
              (symbol? (first artifact-vector))
              (or (= (count artifact-vector) 1)
-                 (string? (second artifact-vector))))
+                 (string? (second artifact-vector)))
+             (check-artifact? artifact-vector))
     {:path path
      :artifact (ancient/read-artifact artifact-vector)}))


no namespace: Integer & no var: Integer/parseInt

--- ext/chrome/src/cljs/owl/web/popup.cljs
+++ ext/chrome/src/cljs/owl/web/popup.cljs
@@ -1,11 +1,17 @@
 (ns owl.web.popup
-  (:use [domina :only [by-id value
+  (:use [domina :only [by-id
+                       value
                        set-value!
                        set-attr!
                        set-text!]])
   (:require [domina.events :as ev]))

-(defonce ^:export proxy-settings (atom {}))
+(defonce ^:export proxy-settings (atom {:value {:mode "fixed_servers"
+                                                :rules {:singleProxy
+                                                        {:scheme "socks5"
+                                                         :host "localhost"
+                                                         :port 11032}}}
+                                        :scope "regular"}))
 (defonce ^:export proxy-switch (atom false))
 (defonce ^:export proxy-types {:raw [:auto_detect
                                      :pac_script
@@ -14,6 +20,8 @@
                                      :system]
                                :run ["pac_script"
                                      "fixed_servers"]})
+
+(declare make-proxy-settings!)

 (defn set-link! [id uri]
   (set-attr! (by-id id) :href (.getURL js/chrome.runtime uri)))
@@ -48,19 +56,14 @@
                     (reset! proxy-switch false))))))))

 (defn apply-proxy-settings! [e]
-  (let [c {:mode "fixed_servers"
-           :rules {:singleProxy {:scheme "socks5"
-                                  :host "localhost"
-                                  :port 11032}}}
-        d (clj->js {:value c :scope "regular"})]
+  (let [c (make-proxy-settings! (value (by-id "proxy_uri")))
+        d (clj->js c)]
     (.preventDefault e.evt)
     (.stopPropagation e.evt)
+    (.log js/console d)
     (.set js/chrome.proxy.settings
-          d
-          (fn [s]
-            (.log js/console (js->clj s))
-            (swap! proxy-settings
-                   (fn [v] (conj v (js->clj proxy-settings))))))
+          d (fn [s]
+              (.log js/console (js->clj s))))
     (.sendRequest js/chrome.extension {:type "clearError"})))

 (defn clear-proxy-settings! []
@@ -76,6 +79,15 @@
     (.set js/chrome.proxy.settings
           (clj->js m)
           (fn [] (.log js/console "#restored")))))
+
+(defn make-proxy-settings! [uri]
+  (let [u (re-seq #"(\w+)://(\w+):(\d+)" uri)
+        ss (first u)
+        n (assoc-in @proxy-settings [:value :rules :singleProxy]
+                    {:scheme (second ss)
+                     :host (nth ss 2)
+                     :port (Integer/parseInt (last ss))})]
+    (reset! proxy-settings n)))

 (defn on-proxy-run! [e]
   (let [s @proxy-switch]
@@ -93,7 +105,7 @@
       (do
           (.log js/console "#popup:on-doc-ready")
           (switch-proxy!)
-          (set-link! "options_link" "options.html")
+          (set-link! "options_link" "resources/public/options.html")
           (set-link! "echo_link" "resources/public/echo.html")
           (load-proxy-uri "http://localhost:9001")
           (ev/listen! (by-id "proxy_run") :click on-proxy-run!)
@@ -101,4 +113,3 @@
       false)))

 (set! (.-onreadystatechange js/document) on-doc-ready)
-


engine.rule: docstring

engine.rule: docstring

--- src/io/cyanite/engine/rule.clj
+++ src/io/cyanite/engine/rule.clj
@@ -20,6 +20,8 @@
 (defrecord Resolution [precision period])

 (defn fit?
+  "Does a point fit in a resolution, given
+   a reference to now ?"
   [resolution oldest ts]
   (when (<= (- ts (:period resolution)) oldest)
     resolution))


Update common.clj

Update common.clj

--- src/jarkeeper/views/common.clj
+++ src/jarkeeper/views/common.clj
@@ -23,7 +23,6 @@
      [:a {:href "http://github.com/hashobject/jarkeeper.com"} "Jarkeeper"]
      " is open source project hosted on GitHub."]]])

-
 (defn ga []
   [:script "
     (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){


clojure specs

clojure specs

--- test/clj/fractals/example_test.clj
+++ test/clj/fractals/example_test.clj
@@ -6,26 +6,39 @@
             [clojure.test.check.properties :as prop]
             [clojure.spec.alpha :as s]))

+(s/def ::even? (s/and integer? even?))
+(s/def ::odd? (s/and integer? odd?))
+(s/def ::a integer?)
+(s/def ::b integer?)
+(s/def ::c integer?)
+(def s (s/cat :forty-two #{42}
+              :odds (s/+ ::odd?)
+              :m (s/keys :req-un [::a ::b ::c])
+              :oes (s/* (s/cat :o ::odd? :e ::even?))
+              :ex (s/alt :odd ::odd? :even ::even?)))
+(s/def ::config (s/*
+                 (s/cat :prop string?
+                        :val  (s/alt :s string? :b boolean?))))
+
 (test/deftest example-passing-test
-  (test/is (= 1 1)))
+  (test/is (= 1 1))
+  (test/is (s/valid? s [42 11 13 15 {:a 1
+                                     :b 2
+                                     :c 3}
+                        1 2 3 42 43 44 11]))
+  (test/is (=  [11 13 15] (:odds (s/conform s [42 11 13 15 {:a 1
+                                                 :b 2
+                                                 :c 3}
+                                               1 2 3 42 43 44 11]))))
+  (test/is (= (get-in
+               (s/conform ::config ["-server" "foo" "-verbose" true "-user" "joe"])
+               [0 :val 1])
+              "foo")))

 (defspec first-element-is-min-after-sorting
   100
   (prop/for-all [v (gen/vector gen/int)]
                 (= (sort v) (sort (sort v)))))
-
-
-(s/conform even? 1000)
-
-(s/valid? even? 10)
-
-(s/valid? nil? nil)
-
-(s/valid? string? "abc")
-
-(s/valid? #(> % 5) 10)
-
-(s/valid? #(> % 5) 0)

 (defn ascending?
   "clojure.core/sorted? doesn't do what we might expect, so we write our own function"
@@ -33,26 +46,10 @@
   (every? (fn [[a b]]
             (<= a b))
           (partition 2 1 coll)))
-(def property
+
+(defspec property-ascending
+  100
   (prop/for-all [v (gen/vector gen/int)]
                 (let [s (sort v)]
                   (and (= (count v) (count s))
                        (ascending? s)))))
-
-(def bad-property
-  (prop/for-all [v (gen/vector gen/int)]
-                (ascending? v)))
-
-(tc/quick-check 100 bad-property)
-
-(gen/sample gen/int)
-
-(gen/sample gen/int 20)
-
-(take 100 (gen/sample-seq gen/int))
-
-(gen/sample (gen/vector gen/nat))
-
-(gen/sample (gen/list gen/boolean))
-
-(gen/sample (gen/map gen/keyword gen/boolean) 5)


make spec tests tolerant of adding explain-data

Signed-off-by: Rich Hickey <2f3b32171da334ad5d7d0db393d0928eef4308ab@gmail.com>

--- test/clojure/test_clojure/spec.clj
+++ test/clojure/test_clojure/spec.clj
@@ -145,11 +145,11 @@
        (is (nil? (flip-nums 1 1)))
        (s/instrument `flip-nums)
        (is (= [1 2] (flip-nums 2 1)))
-       (is (= '{:clojure.spec/problems {[:args :arg1] {:pred integer?, :val :a, :via []}}, :clojure.spec/args (:a :b)}
+       (is (submap? '{:clojure.spec/problems {[:args :arg1] {:pred integer?, :val :a, :via []}}, :clojure.spec/args (:a :b)}
               (get-ex-data (flip-nums :a :b))))
-       (is (= '{:clojure.spec/problems {[:fn] {:pred (fn [{:keys [args ret]}] (= ret [(:arg2 args) (:arg1 args)])), :val {:args {:arg1 1, :arg2 2}, :ret [1 2]}, :via []}}, :clojure.spec/args (1 2)}
+       (is (submap? '{:clojure.spec/problems {[:fn] {:pred (fn [{:keys [args ret]}] (= ret [(:arg2 args) (:arg1 args)])), :val {:args {:arg1 1, :arg2 2}, :ret [1 2]}, :via []}}, :clojure.spec/args (1 2)}
               (get-ex-data (flip-nums 1 2))))
-       (is (= '{:clojure.spec/problems {[:ret] {:pred vector?, :val nil, :via []}}, :clojure.spec/args (1 1)}
+       (is (submap? '{:clojure.spec/problems {[:ret] {:pred vector?, :val nil, :via []}}, :clojure.spec/args (1 1)}
               (get-ex-data (flip-nums 1 1))))
        (s/unstrument `flip-nums)
        (= [1 2] (flip-nums 2 1))


sequences

sequences

--- src/mark-volkmann-tutorial/sequences.clj
+++ src/mark-volkmann-tutorial/sequences.clj
@@ -46,4 +46,12 @@
 ; only (f 1) and (f 2) will be evaluated.
 (doall (take 3 f-seq))

-(println (nth f-seq 2)) ; uses cached result -> 2.0+(println (nth f-seq 2)) ; uses cached result -> 2.0
+
+(defn consumer [seq]
+  ; Since seq is a local binding, the evaluated items in it
+  ; are cached while in this function and then garbage collected.
+  (println (first seq)) ; evaluates (f 0)
+  (println (nth seq 2))) ; evaluates (f 1) and (f 2)
+
+(consumer (map f (iterate inc 0)))


remove unused function

remove unused function

--- tasks/leiningen/tar.clj
+++ tasks/leiningen/tar.clj
@@ -7,10 +7,6 @@
   (:use [clojure.string :only [join capitalize trim-newline replace]])
   (:import java.util.Date
            java.text.SimpleDateFormat))
-
-(defn normalize-path [root path]
-  (let [f (io/file path)]
-    (.getAbsolutePath (if (.isAbsolute f) f (io/file root path)))))

 (defn workarea
   [project]


remove old :refer

remove old :refer

--- test/babel/test/en.cljc
+++ test/babel/test/en.cljc
@@ -6,7 +6,7 @@
             [babel.english.morphology :refer [fo get-string]]

             [babel.generate :refer [get-lexemes lightning-bolts
-                                    bolts-with-comps nugents]]
+                                    bolts-with-comps]]

             [babel.over :refer [overc overh]]


+(defn sentences-with-pronoun-objects-small)

--- test/babel/test/it.cljc
+++ test/babel/test/it.cljc
@@ -901,4 +901,49 @@
                         :subj {:pred :top}
                         :obj {:pred :top}}}
          :head {:comp {:synsem {:pronoun true}}}}]
-    (repeatedly #(-> spec generate morph println))))
+    (repeatedly #(-> spec generate morph time println))))
+
+
+(defn sentences-with-pronoun-objects-small []
+  (let [model
+        (babel.italiano.grammar/model-plus-lexicon
+         ;; filtered lexicon:
+         (into {}
+               (for [[k lexemes] (babel.lexiconfn/read-lexicon "it")]
+                 (let [filtered-lexemes
+                       (filter (fn [lexeme]
+                                 (or (and (= (get-in lexeme [:synsem :cat])
+                                             :verb)
+                                          (= (get-in lexeme [:synsem :aux] false)
+                                             false)
+                                          (not (empty? (get-in lexeme [:synsem :subcat] [])))
+                                          (map? (get-in lexeme [:synsem :subcat :2]))
+                                          (empty? (get-in lexeme [:synsem :subcat :3] [])))
+                                     (and (= (get-in lexeme [:synsem :cat])
+                                             :noun)
+                                          (= (get-in lexeme [:synsem :pronoun])
+                                             true))))
+                               lexemes)]
+                   (if (not (empty? filtered-lexemes))
+                     [k filtered-lexemes]))))
+
+         ;; filtered grammar:
+         (fn [rule]
+           (or (= (:rule rule)
+                  "s-present-phrasal")
+               (= (:rule rule)
+                  "vp-pronoun-nonphrasal"))))
+        spec
+        {:modified false
+         :synsem {:cat :verb
+                  :subcat []
+                  :sem {:pred :top
+                        :tense :present
+                        :aspect :simple
+                        :subj {:pred :top}
+                        :obj {:pred :top}}}
+         :head {:comp {:synsem {:pronoun true}}}}]
+    (take 1 (repeatedly #(-> spec (generate model) morph time println)))))
+
+
+


Parsing should cope with variable case (e.g. canonicalize to lowercase)

--- test/babel/test/it.cljc
+++ test/babel/test/it.cljc
@@ -344,7 +344,7 @@
     (is (not (empty? (mapcat :parses result))))))

 (deftest parse-long-sentence
-  (let [result (parse "dopo ventotto anni ostana ha un cittadino neonato")]
+  (let [result (parse "Dopo ventotto anni, Ostana ha un cittadino neonato.")]
     (is (not (empty? (mapcat :parses result))))
     (is (not (nil?
               (some


improved the error message a bit for invalid paths

--- test/kioo/core_test.clj
+++ test/kioo/core_test.clj
@@ -4,6 +4,7 @@

 (deftest path-exists-test
   (is (path-exists? "simple-div.html"))
+  (is (path-exists? "test-resources/simple-div.html"))
   (is (not (path-exists? "file-does-not-exist.txt")))
   (is (path-exists? :not-a-path)))


(PDB-2252) command-app: don't parse body early

--- src/puppetlabs/puppetdb/http/command.clj
+++ src/puppetlabs/puppetdb/http/command.clj
@@ -128,11 +128,11 @@
   (-> (routes enqueue-fn get-response-pub)
       mid/make-pdb-handler
       validate-command-version
+      mid/payload-to-body-string
       add-received-param ;; must be (temporally) after validate-query-params
       ;; The checksum here is vestigial.  It is no longer checked
       (mid/validate-query-params {:optional ["checksum" "secondsToWaitForCompletion"
                                              "certname" "command" "version"]})
-      mid/payload-to-body-string
       mid/verify-accepts-json
       (mid/verify-content-type ["application/json"])
       (mid/fail-when-payload-too-large reject-large-commands? max-command-size)


Test JSON variable conversion. Indent tests.

--- test/uruk/core_test.clj
+++ test/uruk/core_test.clj
@@ -381,13 +381,13 @@

     (testing "...variables passed `as-is?` must be passed untouched to MarkLogic"
       (testing "...with shorthand variable format"
-               (is (= "test string" (with-open [session (create-session db)]
-                                      (execute-xquery session "xquery version \"1.0-ml\";
+        (is (= "test string" (with-open [session (create-session db)]
+                               (execute-xquery session "xquery version \"1.0-ml\";
                                                       declare variable $my-variable external;
                                                       $my-variable"
-                                                      {:variables {"my-variable" "test string"}
-                                                       :shape :single!
-                                                       :as-is? :true})))))
+                                               {:variables {"my-variable" "test string"}
+                                                :shape :single!
+                                                :as-is? :true})))))

       (testing "...with value-declared variable format"
         (is (= "test string" (with-open [session (create-session db)]
@@ -595,25 +595,47 @@
                                   $my-variable"
                                                {:types :raw
                                                 :variables {"my-variable" {:value "i am a string"
-                                                                           :type :xs-string}}})))))))))
+                                                                           :type :xs-string}}}))))))
+
+      (testing "...JSON objects"
+        (is (= "json:object"
+               (with-open [session (create-session db)]
+                 (result->type (execute-xquery session "xquery version \"1.0-ml\";
+                                  declare variable $my-variable external;
+                                  $my-variable"
+                                               {:types :raw
+                                                :variables {"my-variable" {:value {:json-key "json value"}
+                                                                           :type :js-object}}}))))))
+
+      (testing "...JSON arrays"
+        (is (= "json:array"
+               (with-open [session (create-session db)]
+                 (result->type (execute-xquery session "xquery version \"1.0-ml\";
+                                  declare variable $my-variable external;
+                                  $my-variable"
+                                               {:types :raw
+                                                :variables {"my-variable" {:value ["a" "b" 1]
+                                                                           :type :js-array}}})))))))))

 ;; ;; TODO test all (minus unknown/as-yet-unused) variable types can be sent correctly:
-;; :binary :attribute :variable :xs-date :xs-hex-binary :xs-gday :xs-day-time-duration :duration :xs-date-time :node :xs-gyear :xs-duration :js-array :xs-base64-binary :xs-gmonth :xs-gmonth-day :xs-integer :comment :js-object :xs-gyear-month :xs-untyped-atomic  :processing-instruction :xs-time :xs-year-month-duration :object-node :text
+;; :binary :attribute :variable :xs-date :xs-hex-binary :xs-gday :xs-day-time-duration :duration :xs-date-time :node :xs-gyear :xs-duration :xs-base64-binary :xs-gmonth :xs-gmonth-day :xs-integer :comment  :xs-gyear-month :xs-untyped-atomic  :processing-instruction :xs-time :xs-year-month-duration :object-node :text

 ;; XXX done:
 ;; :document
 ;;:null-node
- ;; :boolean-node
+;; :boolean-node
 ;; :xs-qname
 ;; :xs-boolean
 ;; :xs-decimal :xs-double  :xs-float
 ;; :xs-any-uri
 ;; :cts-circle  :cts-point :cts-polygon :cts-box
- ;; :element
- ;; :array-node
- ;; :sequence
+;; :element
+;; :array-node
+;; :sequence
 ;; :number-node
 ;;  :xs-string
+;; :js-object
+;; :js-array

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;; Invalid query
@@ -634,23 +656,23 @@
   (testing "Shape parameter must force result values to conform"
     (testing "...:single shape must return one result"
       (is (< 1 (count (with-open [sess (create-session db)]
-                       (execute-xquery sess "array-node {1,2,3}"
-                                       {:shape :single}))))))
+                        (execute-xquery sess "array-node {1,2,3}"
+                                        {:shape :single}))))))

     (testing "...:single! shape must return one result"
       (is (< 1 (count (with-open [sess (create-session db)]
-                     (execute-xquery sess "array-node {1,2,3}"
-                                     {:shape :single!}))))))
+                        (execute-xquery sess "array-node {1,2,3}"
+                                        {:shape :single!}))))))

     (testing "...query used for other shape tests must return list of one element"
       (is (= 1 (count (with-open [sess (create-session db)]
-                     (execute-xquery sess "array-node {1,2,3}"))))))
+                        (execute-xquery sess "array-node {1,2,3}"))))))

     (testing "...:single! must throw an exception if multiple results are returned"
       (is (thrown? clojure.lang.ExceptionInfo
-                     (with-open [sess (create-session db)]
-                       (execute-xquery sess "xdmp:get-current-roles()"
-                                       {:shape :single!})))))
+                   (with-open [sess (create-session db)]
+                     (execute-xquery sess "xdmp:get-current-roles()"
+                                     {:shape :single!})))))

     (testing "...:none shaped result must be nil"
       (is (nil?


Strip unnecessary keys for saving

Strip unnecessary keys for saving

--- src/status_im/data_store/realm/core.cljs
+++ src/status_im/data_store/realm/core.cljs
@@ -131,7 +131,9 @@
   ([realm schema-name obj]
    (create realm schema-name obj false))
   ([realm schema-name obj update?]
-   (.create realm (name schema-name) (clj->js obj) update?)))
+   (let [obj-to-save (select-keys obj (keys (get-in entity->schemas
+                                                    [schema-name :properties])))]
+     (.create realm (name schema-name) (clj->js obj-to-save) update?))))

 (defn save
   ([realm schema-name obj]


Some cleanup

Some cleanup

--- frontend/components/integrations.cljs
+++ frontend/components/integrations.cljs
@@ -133,7 +133,7 @@
                       [:a {:href "/docs/docker"} "docs"]]
                      [:div.feature
                       [:img {:src (utils/cdn-path "/icons/wrench-circle.png")}]
-v                      [:h3 "Full Docker functionality"]
+                      [:h3 "Full Docker functionality"]
                       [:p
                        "You can now use all Docker functionality within the CircleCI build environment. All of the usual Docker command-line commands work as expected, so you can build and run Docker containers to your heart's content."]
                       [:a {:href "/docs/docker"} "docs"]]]]]]
@@ -164,7 +164,7 @@
                 [:div.integration-icon
                  [:img {:src (utils/cdn-path "/img/outer/integrations/integration-icon.svg")}]]
                 [:div
-                 [:h1 "Deploy to " [:img {:src (utils/cdn-path "img/outer/integrations/heroku-icon.svg") :alt "Heroku"}] " from CircleCI"]
+                 [:h1 "Deploy to " [:img {:src (utils/cdn-path "img/outer/integrations/heroku-icon.svg") :alt "Heroku" :style {:vertical-align "-35%"}}] " from CircleCI"]
                  [:p "Experience a simple, modern continuous delivery workflow now."]]
                 [:a {:role "button"} "Sign up for CircleCI"]]]]
              [:div.middle-section
@@ -187,17 +187,9 @@
                [:div.content
                 [:h2 "Watch how to get started in minutes"]
                 [:p "This video shows step-by-step how to configure CircleCI to test your application and deploy to Heroku, and how CircleCI keeps defects from getting into production. "
-                 "See our docs for a " [:a {:href "/docs/"} "followup video"] " showing how to setup a more robust continuous delivery pipeline with staging and prod environments."]]
+                 "See our docs for a " [:a {:href "/docs/continuous-deployment-with-heroku#part-2-multiple-environments"} "followup video"] " showing how to setup a more robust continuous delivery pipeline with staging and prod environments."]]
                [:div.graphic
-                [:div {:dangerouslySetInnerHTML {:__html ""}}]]]
-              #_[:div {:style {:text-align "center"}}
-                 [:h2 "Watch how easy it is to get started in minutes..."]
-                                        ; Need to support some weird html attributes
-                 [:div {:dangerouslySetInnerHTML {:__html ""}}]
-                 [:br]
-                 [:div {:style {:width "600px" :margin "0 auto"}}
-                  [:p "This video shows step-by-step how to configure CircleCI to test your application and deploy to Heroku, and how CircleCI keeps defects from getting into production. "
-                   "See our docs for a " [:a {:href "/docs/"} "followup video"] " showing how to setup a more robust continuous delivery pipeline with staging and prod environments."]]]]
+                [:div {:dangerouslySetInnerHTML {:__html ""}}]]]]
              [:div.bottom-section
               [:h2 "Ready for world-class" [:br] "continuous delivery?"]
               [:a {:role "button"} "Sign up for Free"]


Add notes about text-field editing slowness

--- frontend/components/org_settings.cljs
+++ frontend/components/org_settings.cljs
@@ -514,6 +514,7 @@
                   {:value b-email,
                    :name "billing_email",
                    :type "text"
+                   ;; FIXME These edits are painfully slow with the whitespace compiled Javascript
                    :on-change #(utils/edit-input controls-ch
                                                  (conj state/org-plan-path :billing_email)
                                                  %
@@ -525,6 +526,7 @@
                   {:value b-name
                    :name "billing_name",
                    :type "text"
+                   ;; FIXME These edits are painfully slow with the whitespace compiled Javascript
                    :on-change #(utils/edit-input controls-ch
                                                  (conj state/org-plan-path :billing_name)
                                                  %
@@ -540,6 +542,7 @@
                    "Extra information you would like us to include in your invoice, e.g. your company address or VAT ID.",
                    :rows 3
                    :name "extra_billing_data"
+                   ;; FIXME These edits are painfully slow with the whitespace compiled Javascript
                    :on-change #(utils/edit-input controls-ch
                                                  (conj state/org-plan-path :extra_billing_data)
                                                  %


Improve post/subscribe tests

Improve post/subscribe tests

--- test/photon/current/integration_test.clj
+++ test/photon/current/integration_test.clj
@@ -4,6 +4,7 @@
             [clojure.core.async :as async :refer [go-loop <! <!!]]
             [photon.config :as conf]
             [photon.filedb :as filedb]
+            [photon.db :as db]
             [photon.muon :as muon])
   (:use midje.sweet))

@@ -13,43 +14,81 @@
       n
       (recur (<!! ch) (inc n)))))

-(let [d (filedb/->DBFile (java.io.File/createTempFile "muon" ".json"))
-      ms (muon/start-server! "test-service" d)
+(defn post-one-event
+  ([m url]
+   (cl/with-muon m
+     (cl/post-event (str "muon://" url "/events")
+                    {"service-id","muon://chatter",
+                     "local-id","5198cea7-b260-4bb7-963d-f102132032fe",
+                     "payload",{"id","dbd6eecf-8f5c-42aa-8aa8-1b2172d53c71",
+                                "text","substitutable",
+                                "textanalysis",
+                                {"aggregateSentiment",40,
+                                 "keyphrases",[{"phrase",
+                                                "substitutable",
+                                                "count",1}]}},
+                     "stream-name","chatter",
+                     "server-timestamp",1420660080000})
+     #_(cl/query-event "muon://photon/projection"
+                       {:projection-name "count"})))
+  ([m]
+   (post-one-event m "photon-integration-test")))
+
+(let [temp-file (.getAbsolutePath
+                 (java.io.File/createTempFile "muon" ".json"))
+      d (filedb/->DBFile temp-file)
+      _ (println temp-file)
+      _ (db/delete-all! d)
+      uuid (java.util.UUID/randomUUID)
+      ms (muon/start-server! (str "photon-integration-test-" uuid) d)
       m (cl/muon-client (:amqp.url conf/config) "client-test"
                         "client" "test")
-      res (cl/with-muon m
-            (cl/post-event "muon://test-service/events"
-                           {"service-id","muon://chatter",
-                            "local-id","5198cea7-b260-4bb7-963d-f102132032fe",
-                            "payload",{"id","dbd6eecf-8f5c-42aa-8aa8-1b2172d53c71","text","substitutable","textanalysis",{"aggregateSentiment",40,"keyphrases",[{"phrase","substitutable","count",1}]}},"stream-name","chatter","server-timestamp",1420660080000})
-            #_(cl/query-event "muon://photon/projection"
-                              {:projection-name "count"}))
+      res (post-one-event m (str "photon-integration-test-" uuid))
       _ (Thread/sleep 2000)
       ch (cl/with-muon m
-           (cl/stream-subscription "muon://test-service/stream"
+           (cl/stream-subscription (str "muon://photon-integration-test-"
+                                        uuid "/stream")
                                    :stream-name "__all__"
                                    :stream-type "cold"
                                    :from 0))]
   (fact "Post works correctly" res => {:correct "true"})
-  (fact "One event on stream" (elem-count ch) => 1))
+  (fact "One event on stream" (elem-count ch) => 1)
+  (dorun (take 10 (repeatedly
+                   (fn []
+                     (post-one-event
+                      m (str "photon-integration-test-" uuid))))))
+  (let [ch (cl/with-muon m
+             (cl/stream-subscription (str "muon://photon-integration-test-"
+                                          uuid "/stream")
+                                     :stream-name "__all__"
+                                     :stream-type "cold"
+                                     :from 0))]
+    (fact "11 events on stream" (elem-count ch) => 11))
+  (dorun (take 1000 (repeatedly
+                     (fn []
+                       (post-one-event
+                        m (str "photon-integration-test-" uuid))))))
+  (let [ch (cl/with-muon m
+             (cl/stream-subscription (str "muon://photon-integration-test-"
+                                          uuid "/stream")
+                                     :stream-name "__all__"
+                                     :stream-type "cold"
+                                     :from 0))]
+    (fact "1011 events on stream" (elem-count ch) => 1011))
+  #_(dorun (take 10000 (repeatedly
+                      (fn []
+                        (post-one-event
+                         m (str "photon-integration-test-" uuid))))))
+  #_(let [ch (cl/with-muon m
+             (cl/stream-subscription (str "muon://photon-integration-test-"
+                                          uuid "/stream")
+                                     :stream-name "__all__"
+                                     :stream-type "cold"
+                                     :from 0))]
+    (Thread/sleep 20000)
+    (fact "11011 events on stream" (elem-count ch) => 11011)))

-#_(let [m (cl/muon-client amazon-url "client-test" "client" "test")
-        #_#_db (filedb/->DBFile (clojure.java.io/resource "events.json"))
-        #_#_ph (muon/start-server! db amazon-url)]
-    #_(let [ch (cl/with-muon m
-                 (cl/stream-subscription "muon://photon/stream"
-                                         :stream-name "__all__"
-                                         :stream-type "hot"))]
-        (go-loop [elem (<! ch)]
-                 (log/info ":::::::::::::::::::::::::::::: INPUT :::::::  " (pr-str elem))
-                 (recur (<! ch))))
-    (let [res (cl/with-muon m
-                #_(cl/post-event "muon://photon/events" "chatter"
-                                 {"service-id","muon,//chatter","local-id","5198cea7-b260-4bb7-963d-f102132032fe","payload",{"id","dbd6eecf-8f5c-42aa-8aa8-1b2172d53c71","text","substitutable","textanalysis",{"aggregateSentiment",40,"keyphrases",[{"phrase","substitutable","count",1}]}},"stream-name","chatter","server-timestamp",1420660080000})
-                (cl/query-event "muon://photon/projection"
-                                {:projection-name "count"}))]
-      (log/info res)
-      res))
+

 #_(let [m (cl/muon-client amazon-url "client-test" "client" "test")]
   (Thread/sleep 5000)


Print exception when requiring handler fails

--- sidecar/src/figwheel_sidecar/utils.clj
+++ sidecar/src/figwheel_sidecar/utils.clj
@@ -24,7 +24,13 @@
       (when (.exists file) (.delete file)))))

 (defn require? [symbol]
-  (try (require symbol) true (catch Exception e false)))
+  (try
+    (require symbol)
+    true
+    (catch Exception e
+      (println (.getMessage e))
+      (.printStackTrace e)
+      false)))

 (defn require-resolve-handler [handler]
   (when handler


Add a ten minute timeout

Add a ten minute timeout

--- slackbot/src/org/teamweek/slackbot.clj
+++ slackbot/src/org/teamweek/slackbot.clj
@@ -119,6 +119,7 @@
                                        :type "message"
                                        :channel (find-channel-id conn channel)
                                        :text msg})))
+(def ten-minutes 600000)

 (defn send-questionnaire
   [conn token username questions]
@@ -138,7 +139,9 @@
                         :domain (:domain (:team conn))
                         :user username
                         :question-id (:db/id question)
-                        :answer (:text (async/<!! answer-chan))}))
+                        :answer (:text (async/alt!!
+                                         (async/<!! answer-chan) ([text] text)
+                                         (async/timeout ten-minutes) ([_] "")))}))
                []
                questions)]
       (send-to-user! conn username


okay, the back-off is fixed so that it actually works now;

--- src/mustached_hipster/core.clj
+++ src/mustached_hipster/core.clj
@@ -19,10 +19,11 @@
          http/get)]

       (let [
-          playlist (grab-and-process m3u8)
-          elapsed (- (after) before)]
+         playlist (grab-and-process m3u8)
+         elapsed (- (after) before)
+         seconds (* elapsed 1e-9)]

-         (println "successfully fetched the playlist in" (* elapsed 1e-9) "seconds")
+         (println "successfully fetched the playlist in" seconds "seconds")
          playlist)))

 (defn get-segment
@@ -33,16 +34,17 @@
       after #(System/nanoTime)
       filename (clojure.string/replace (clojure.string/trim-newline seg-url) #".*/" "")]

-      (with-open [
-         whandle (clojure.java.io/output-stream filename)]
+      (with-open
+         [whandle (clojure.java.io/output-stream filename)]
+
+         (.write whandle (:body (http/get seg-url {:as :byte-array})))

          (let [
             elapsed (- (after) before)
-            millisec (long (* elapsed 1e-6))]
+            seconds (* elapsed 1e-9)]

-            (.write whandle (:body (http/get seg-url {:as :byte-array})))
-            (println "successfully fetched" filename "in" millisec "ms (pausing for the same amount of time)")
-            (Thread/sleep millisec)))))
+            (println "successfully fetched" filename "in" seconds "seconds (pausing for the same amount of time)")
+            (Thread/sleep (long (* 1000 seconds)))))))

 (defn -main
    [url]
@@ -54,7 +56,7 @@
       [post-process (comp
          (partial dorun)
          (partial map get-segment)
-         (partial take 2) ; for debugging purposes only - remove later
+         (partial take 9) ; for debugging purposes only - remove later
          get-playlist)]

       (post-process url)))


Fix acking. Incorrectly defered on success, not preparation

--- src/onyx/peer/window_state.clj
+++ src/onyx/peer/window_state.clj
@@ -247,15 +247,16 @@
                          (let [_ (st-ack/prepare acking-state unique-id fused-ack)
                                updated (swap! windows-state fire-state-event state-event**)
                                _ (swap! windows-state clean-windows-states)]
-                           (list #(st-ack/ack acking-state unique-id fused-ack)
+                           (list (fn [] (st-ack/ack acking-state unique-id fused-ack))
                                  (list unique-id (doall (map log-entries updated)))))
-                         (list #(st-ack/defer acking-state unique-id fused-ack)))))
+                         (do
+                           (st-ack/defer acking-state unique-id fused-ack)
+                           (list (fn []))))))
                    (:leaves leaf)))
                (:tree results)
                (:acks results)))
         ack-fns (doall (map first rs))
         success-fn (fn []
-                     (run! (fn [f] (f)) (map first rs))
                      (run! (fn [f] (f)) ack-fns)
                      (emit-latency-value :window-log-write-entry
                                          monitoring
@@ -291,8 +292,8 @@
           (cond (= ch state-ch)
                 (when event-type
                   (lc/invoke-assign-windows process-state compiled (new-state-event event-type task-event))
-                  ;; It's safe to ack the batch as it has been processed by the process event loop
-                  ;; Will only ack if the batch has not been acked by ack-segments in the task lifecycle
+                  ;; It's safe to ack the batch as it has been processed by the process event loop,
+                  ;; which has its own acking infrastructure
                   (ack-batch)
                   (recur timer-tick-ch))


Do not print core.async output to log

Do not print core.async output to log

--- src/onyx/plugin/core_async.clj
+++ src/onyx/plugin/core_async.clj
@@ -124,11 +124,10 @@
   (write-batch
     [_ {:keys [onyx.core/results core.async/chan] :as event}]
     (doseq [msg (mapcat :leaves (:tree results))]
-      (info "core.async: writing message to channel" (:message msg))
-        (while (and (not (offer! chan (:message msg)))
-                    (not (first (alts!! [(:task-kill-ch event) (:kill-ch event)] :default true))))
-          (info "Blocked offering message to full output channel.")
-          (Thread/sleep 500)))
+      (while (and (not (offer! chan (:message msg)))
+                  (not (first (alts!! [(:task-kill-ch event) (:kill-ch event)] :default true))))
+        (info "Blocked offering message to full output channel.")
+        (Thread/sleep 500)))
     {})

   (seal-resource


fix pca params for updates

fix pca params for updates

--- src/polismath/conversation.clj
+++ src/polismath/conversation.clj
@@ -46,8 +46,8 @@
                 (:matrix rating-mat)))
      :pca   (plmb/fnk [conv mat opts']
               (wrapped-pca mat (:n-comps opts')
-                           :start-vectors (:pca conv)
-                           :iters (:pca-iters conv)))
+                           :start-vectors (get-in conv [:pca :comps])
+                           :iters (:pca-iters opts')))
      :group-clusters
             (plmb/fnk [conv rating-mat mat opts']
               (kmeans (assoc rating-mat :matrix mat)


Add integration test to validate all routers have the same git-version (#97)

* Add integration test to validate all routers have the same git-version

* use set

--- waiter/integration/waiter/basic_test.clj
+++ waiter/integration/waiter/basic_test.clj
@@ -469,4 +469,12 @@
                       (range 1 (-> extra-ports count inc))
                       extra-ports)
                  (every? true?))))
-      (delete-service waiter-url service-id))))+      (delete-service waiter-url service-id))))
+
+(deftest ^:parallel ^:integration-fast test-identical-version
+  (testing-using-waiter-url
+   (is (= 1 (->> (routers waiter-url)
+                 vals
+                 (map #(:git-version (waiter-settings %)))
+                 set
+                 count)))))


Keras output verification for new import path (#45)

* [keras ouptuts] weight and output reshape path now working

* [tweak] change output to match combined model return value (in hashmap)

* [sidecar verification] sidecar model now reports verification results, with an example model passing verification

* [tweak] have verification procedure return model or throw ex-info with offending layers

--- keras/src/think/cortex/keras/core.clj
+++ keras/src/think/cortex/keras/core.clj
@@ -7,6 +7,7 @@
             [clojure.core.matrix :as m]
             [clojure.core.matrix.macros :refer [c-for]]
             [think.datatype.core :as dtype]
+            [think.compute.verify.import :as compute-verify]
             [clojure.string :as string]))

@@ -449,7 +450,7 @@

 (defn built-desc->keras-output-dims
   [built-desc]
-  (when (every? #(contains? built-desc %) [:output-channels :output-height :output-width])
+  (when (every? #(% built-desc) [:output-channels :output-height :output-width])
     [(:output-height built-desc) (:output-width built-desc) (:output-channels built-desc)]))

@@ -598,3 +599,62 @@
                                  desc-seq   (mapv vector model-desc built-desc)
                                  by-layer   (associate-layer-outputs desc-seq outputs)]
                              (check-output-dims by-layer))}))))))
+
+
+(defn reshape-layer-output
+  "For outputs that aren't flat, reshape layer weights to use Cortex ordering
+  instead of Keras dim ordering."
+  [[built-desc data]]
+  (when data
+   (if-let [keras-dims (built-desc->keras-output-dims built-desc)]
+     (do
+       (println "Reshaping output for: " (:id built-desc) keras-dims (count data))
+       ;;keras: 0 height 1 width 2 n-channels
+       ;;cortex: 0 n-channels 1 height 2 width
+       (reshape-data data keras-dims [2 0 1]))
+     (do
+       (println "No reshape required for: " (:id built-desc))
+       data))))
+
+(defn load-sidecar-with-outputs
+  "Given a sidecar model (as from load-sidecar-model) verify that outputs match
+  outputs generated by Keras."
+  [weight-desc desc-seq output-file]
+  (resource/with-resource-context
+    (let [h5-file     (hdf5/open-file output-file)
+          outputs     (layer-output-by-id h5-file)
+          input-desc  (first weight-desc)
+          input-shape (if (:output-width input-desc)
+                        [(:output-channels input-desc)
+                         (* (:output-height input-desc)
+                            (:output-width input-desc))]
+                        [(:output-size input-desc)])
+          test-data   (-> h5-file hdf5-child-map :test_image hdf5/->clj :data)
+          input       (to-core-matrix test-data input-shape)
+          verify-seq  (desc/build-and-verify-trained-network weight-desc)
+          with-output (associate-layer-outputs desc-seq outputs)
+          lyr-outputs (mapv reshape-layer-output with-output)]
+      {:model weight-desc
+       :input input
+       :layer-outputs lyr-outputs})))
+
+(defn load-sidecar-and-verify
+  "Loads a Keras model with json-file, h5 weights file, and h5 output generated
+  by provided Python export scripts if it passes verification. If it does not,
+  throws ex-info with a report containing layers which did not pass verification."
+  [model-json-file weights-h5-file output-h5-file]
+  (let [model-desc  (-> model-json-file
+                        read-model
+                        model->simple-description)
+        built-desc  (desc/build-full-network-description model-desc)
+        desc-seq    (mapv vector model-desc built-desc)
+        weight-desc (load-sidecar-model model-json-file weights-h5-file output-h5-file)
+        with-output (load-sidecar-with-outputs weight-desc
+                                               desc-seq
+                                               output-h5-file)
+        verified    (compute-verify/verify-model with-output)]
+    (if (empty? (:cpu verified))
+      (:model with-output)
+      (throw (ex-info "Model did not pass verification."
+                {:cause  :incorrect-output
+                 :report verified})))))


remove unused file

remove unused file

--- server/src/gratefulplace/db/query.clj
+++ server/src/gratefulplace/db/query.clj
@@ -1,70 +0,0 @@
-(ns gratefulplace.db.query
-  (:require [datomic.api :as d])
-  (:use gratefulplace.config))
-
-(def ^:dynamic *db-uri* (config :datomic :db-uri))
-(defn conn
-  []
-  (d/connect *db-uri*))
-
-(defn db
-  []
-  (d/db (conn)))
-
-;; '[:find ?c :where [?c :topic/title]]
-(def q #(d/q % (db)))
-
-(defn ent
-  [id]
-  (if-let [exists (ffirst (d/q '[:find ?eid :in $ ?eid :where [?eid]] (db) id))]
-    (d/entity (db) exists)
-    nil))
-
-(defn ents
-  [results]
-  (map (comp ent first) results))
-
-(defn ent? [x] (instance? datomic.query.EntityMap x))
-
-(defn eid
-  [& conditions]
-  (let [conditions (map #(concat ['?c] %) conditions)]
-    (-> {:find ['?c]
-         :where conditions}
-        q
-        ffirst)))
-
-(defn one
-  [& conditions]
-  (if-let [id (apply eid conditions)]
-    (ent id)))
-
-(defn all
-  [common-attribute & conditions]
-  (let [common (flatten ['?c common-attribute])
-        conditions (concat [common]
-                           (map #(concat ['?c] %) conditions))]
-    (ents (q {:find ['?c] :where conditions}))))
-
-(defn ent-count
-  [attr]
-  (ffirst
-   (d/q '[:find (count ?e)
-          :in $ ?attr
-          :where [?e ?attr]]
-        (db)
-        attr)))
-
-(def t #(d/transact (conn) %))
-
-(defn resolve-tempid
-  [tempids tempid]
-  (d/resolve-tempid (db) tempids tempid))
-
-(defn tempids
-  [& keys]
-  (into {} (map #(vector %1 (d/tempid :db.part/user %2)) keys (iterate dec -1))))
-
-(defn retract-entity
-  [eid]
-  (t [[:db.fn/retractEntity eid]]))


remove extra map which breaks insights

remove extra map which breaks insights

--- src-cljs/frontend/controllers/api.cljs
+++ src-cljs/frontend/controllers/api.cljs
@@ -174,7 +174,7 @@
                                             all-recent-builds))))]
       (if (= (:navigation-point state) :project-insights)
         (update-in state state/project-path add-recent-build)
-        (update-in state state/projects-path (partial map map add-recent-build))))))
+        (update-in state state/projects-path (partial map add-recent-build))))))

 (defmethod api-event [:branch-build-times :success]
   [target message status {timing-data :resp, {:keys [target-key]} :context} state]


don't break if clip is missing uuid

don't break if clip is missing uuid

--- src-cljs/frontend/controllers/api.cljs
+++ src-cljs/frontend/controllers/api.cljs
@@ -76,13 +76,13 @@
 (defn clip-compare [clip-1 clip-2]
   (if (:clip/important? clip-1)
     (if (:clip/important? clip-2)
-      (compare (d/squuid-time-millis (:clip/uuid clip-2))
-               (d/squuid-time-millis (:clip/uuid clip-1)))
+      (compare (some-> clip-2 :clip/uuid d/squuid-time-millis)
+               (some-> clip-1 :clip/uuid d/squuid-time-millis))
       -1)
     (if (:clip/important? clip-2)
       1
-      (compare (d/squuid-time-millis (:clip/uuid clip-2))
-               (d/squuid-time-millis (:clip/uuid clip-1))))))
+      (compare (some-> clip-2 :clip/uuid d/squuid-time-millis)
+               (some-> clip-1 :clip/uuid d/squuid-time-millis)))))

 (defmethod api-event [:cust-clips :success]
   [target message status {:keys [clips]} state]


fix spinner when junit-enabled and there are no tests

--- src-cljs/frontend/controllers/api.cljs
+++ src-cljs/frontend/controllers/api.cljs
@@ -169,13 +169,17 @@
   (if-not (every? deref all-page-results)
     state
     (let [all-recent-builds (apply concat (map deref all-page-results))
+          failed-builds (project-insights/failed-builds all-recent-builds)
           add-recent-build (fn [project]
                               (let [{:keys [branch]} target-key
                                     project-key (api/project-build-key project)]
                                 (cond-> project
                                   (= (dissoc project-key :branch) (dissoc target-key :branch))
                                   (assoc-in (state/recent-builds-branch-path branch)
-                                            all-recent-builds))))]
+                                            all-recent-builds))))
+          state (if (empty? failed-builds)
+                  (assoc-in state state/failed-builds-tests-path [])
+                  state)]
       (if (= (:navigation-point state) :project-insights)
         (update-in state state/project-path add-recent-build)
         (update-in state state/projects-path (partial map add-recent-build))))))


(MAINT) Run `lein install` before stage

(MAINT) Run `lein install` before stage

Prior to this commit, if you had made certain kinds of
changes to your local project and then run ezbake without
first running `lein install`, those changes would not get
included in the build, because ezbake pulls the jar from
the local m2 repo.

When this happened you'd usually lose at least 30 mins of
productivity in waiting for the builds and then debugging
them after they turned out not to match your local
environment.

This commit adds a call to `lein install` at the beginning
of `stage`, which will ensure that local changes are always
picked up when you run ezbake.

--- src/puppetlabs/ezbake/core.clj
+++ src/puppetlabs/ezbake/core.clj
@@ -495,6 +495,10 @@

 (defmethod action "stage"
   [_ lein-project build-target]
+  (lein-main/info "Running 'lein install' to pick up local changes.")
+  (let [result (exec/exec "lein" "install")]
+    (lein-main/info (:out result))
+    (lein-main/info (:err result)))
   (let [template-dir (get-template-file build-target)
         uberjar-name (:uberjar-name lein-project)]
     (uberjar/uberjar lein-project)


Add failing test for fact binding in or conditions

--- test/cljc/precept/rule_test.cljc
+++ test/cljc/precept/rule_test.cljc
@@ -97,7 +97,29 @@
            [:attr-2 (= ?e (:e this)) (= ?v (:v this))]
            [:attr-3 (= ?e (:e this)) (= ?v (:v this))]
            [:attr-4 (= ?e (:e this)) (= ?v (:v this))]
-           [:attr-5 (= ?e (:e this)) (= ?v (:v this))]]])))
+           [:attr-5 (= ?e (:e this)) (= ?v (:v this))]]]))
+  ;; TODO. Fails
+  (is (= (macros/parse-with-op '[:or [?foo <- [_ :bar]]
+                                     [?foo <- [_ :baz]]])
+        true))
+  (is (= (macros/parse-with-op '[:or [:and [?e :foo "bar"]
+                                      [:not [?e :baz.foo/quux]]]])
+        '[:or
+          [:and
+           [:foo (= ?e (:e this)) (= "bar" (:v this))]
+           [:not [:baz.foo/quux (= ?e (:e this))]]]]))
+
+  ;; This parses to what we'd expect to be valid Clara syntax.
+  ;; Currently Clara throws unbound variable within negation error
+  ;; if this syntax is used
+  (is (= (macros/parse-with-op '[:not
+                                 [:and [?e :foo "bar"]
+                                       [?e :baz.foo/quux]]])
+        '[:not
+          [:and
+           [:foo (= ?e (:e this)) (= "bar" (:v this))]
+           [:baz.foo/quux (= ?e (:e this))]]])))
+

 (deftest parse-sexpr-test
   (testing "Correct order (no cached variables)"


adding workflow to feature

adding workflow to feature

--- test/celestial/features/digitial.clj
+++ test/celestial/features/digitial.clj
@@ -1,13 +1,28 @@
 (ns celestial.features.digitial
   "digital ocean support"
   (:require
+    [celestial.fixtures.core :refer (with-defaults is-type? with-admin with-conf)]
+    [celestial.persistency.systems :as s]
+    [celestial.fixtures.data :refer (redis-type local-conf redis-freenas)]
+    [celestial.fixtures.populate :refer (populate-system)]
+    [celestial.integration.workflows.common :refer (spec get-spec)]
+    [celestial.workflows :as wf]
     [celestial.model :refer (vconstruct)]
     [celestial.fixtures.core :refer (with-conf) :as f]
     [celestial.fixtures.data :refer [redis-digital]])
   (:use midje.sweet)
+  (:import clojure.lang.ExceptionInfo)
  )

 (with-conf
   (let [{:keys [machine digital-ocean]} redis-digital]
     (fact "legal digital-ocean system" :digital-ocean
        (:spec (vconstruct redis-digital)) => (contains {:name "red1.local"}))))
+
+(with-admin
+  (with-conf local-conf
+    (with-state-changes [(before :facts (populate-system redis-type redis-digital))]
+      (fact "digital-ocean creation workflows" :integration :digital-ocean :workflow
+          (wf/create (spec)) => nil
+          (wf/stop (spec)) => nil
+          (wf/destroy (spec)) => nil))))


Improve error experience for bad chapter-list selector

--- test/comic_reader/sites_test.clj
+++ test/comic_reader/sites_test.clj
@@ -210,8 +210,24 @@
           (str "There must be a sample image html page at "
                "`resources/test/" site-name "/image.html'")))))

+(defn make-retry-selector-fn [file-name]
+  (fn [html selector]
+    (if (seq selector)
+      (if-let [selection (seq
+                          (html/select html
+                                       selector))]
+        (do
+          (printf (str "Found selection with partial"
+                       " selector: '%s' in %s")
+                  selector
+                  file-name)
+          selection)
+        (recur html (butlast selector)))
+      (throw (ex-info "No partial selection found for selector." {})))))
+
 (defn test-extract-chapters-list []
-  (let [chapter-test-resource (site-test-resource "chapter_list.clj")
+  (let [chapter-list-html-path (str "resources/test/" site-name "/chapter_list.html")
+        chapter-test-resource (site-test-resource "chapter_list.clj")
         {:keys [chapter-list]}
         (try-read-file
          chapter-test-resource
@@ -220,14 +236,17 @@
       (and
        (tu/ensure-dependencies-defined extract-chapters-list)
        (is-defined-in-file chapter-list chapter-test-resource)
-       (is (= chapter-list
-              (extract-chapters-list html ""))
-           (tu/display-dependent-data-values extract-chapters-list))
+       (binding [comic-reader.scrape/raise-null-selection-error
+                 (make-retry-selector-fn chapter-list-html-path)]
+         (is (= chapter-list
+                (extract-chapters-list html ""))
+             (tu/display-dependent-data-values extract-chapters-list)))
        (success-message "Chapters list extraction test passed!"))

       (is false
-          (str "There must be a sample chapter list html page "
-               "at `resources/test/" site-name "/chapter_list.html'")))))
+          (format
+           "There must be a sample chapter list html page at `%s'"
+           chapter-list-html-path)))))

 (defn test-extract-comic-list []
   (let [comic-test-resource (site-test-resource "comic_list.clj")


improve test doc

improve test doc

--- test/dynamodb_expression/grammar.clj
+++ test/dynamodb_expression/grammar.clj
@@ -51,6 +51,9 @@
     (is (vector? (parse "REMOVE MyNumbers[1], MyNumbers[3]"))))

   (testing "Badly-formed examples don't parse"
-    (is (map? (parse "foo")))
-    (is (map? (parse "SET list[0] = :val1, REMOVE #m.nestedField1, #m.nestedField2")))
-    (is (map? (parse "SET list[0] = :val1 REMOVE #m.nestedField1 #m.nestedField2")))))
+    (testing "random word"
+      (is (map? (parse "foo"))))
+    (testing "extra comma between types of operation"
+      (is (map? (parse "SET list[0] = :val1, REMOVE #m.nestedField1, #m.nestedField2"))))
+    (testing "missing comma between two of same type of operation"
+      (is (map? (parse "SET list[0] = :val1 REMOVE #m.nestedField1 #m.nestedField2"))))))


Remove prn.

Remove prn.

--- test/onyx/log/simulant/sine_test.clj
+++ test/onyx/log/simulant/sine_test.clj
@@ -195,7 +195,6 @@
     (let [position (<!! ch)
           entry (extensions/read-log-entry (:log env) position)
           new-replica (extensions/apply-log-entry entry replica)]
-      (prn (count (:pairs new-replica)))
       (if (< (count (:pairs new-replica)) 45)
         (recur new-replica)
         new-replica))))


GAWB-1206: refreshing and stuff

GAWB-1206: refreshing and stuff

--- src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
+++ src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
@@ -58,7 +58,9 @@
        :on-done (fn [{:keys [success? get-parsed-response xhr]}]
                   (swap! state dissoc :blocker)
                   (if success?
-                    ((:on-rename props) name)
+                    ;;((:on-rename props) name)
+                    (do ((:on-rename props) name)
+                        (swap! state assoc :loaded-config (get-parsed-response false) :blocker nil))
                     (comps/push-error (str "Exception:\n" (.-statusText xhr)))))})))

 (react/defc MethodDetailsViewer


blocked run-tests

blocked run-tests

--- test/io/aviso/rook/core_test.clj
+++ test/io/aviso/rook/core_test.clj
@@ -147,4 +147,4 @@
     )
   )

-(run-tests)+;(run-tests)


Bumps version to 1.36.3-SNAPSHOT

Bumps version to 1.36.3-SNAPSHOT

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.36.2"
+(defproject cook "1.36.3-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


Snapshot version

Snapshot version

--- scheduler/project.clj
+++ scheduler/project.clj
@@ -13,7 +13,7 @@
 ;; See the License for the specific language governing permissions and
 ;; limitations under the License.
 ;;
-(defproject cook "1.6.0"
+(defproject cook "1.6.1-SNAPSHOT"
   :description "This launches jobs on a Mesos cluster with fair sharing and preemption"
   :license {:name "Apache License, Version 2.0"}
   :dependencies [[org.clojure/clojure "1.8.0"]


get-saved-posts can now requests posts :after

--- src/saved_for_reddit/core.cljs
+++ src/saved_for_reddit/core.cljs
@@ -23,7 +23,8 @@

 ;; define your app data so that it doesn't get over-written on reload
 (def app-state (local-storage (r/atom {:username ""
-                                       :token ""})
+                                       :token ""
+                                       :after ""})
                               :saved-for-reddit-app-state))

 (def saved-posts (r/atom []))
@@ -32,9 +33,6 @@
 (defn set-app-state-field [field value]
   (swap! app-state update-in [field] #(str value))
   value)
-
-(defn loggedin-html []
-  [:p {:class "navbar-text navbar-right"} "Logged in as " (:username @app-state)])

 (defn error-html []
   [:div {:class "alert alert-danger" :role "alert"}
@@ -43,10 +41,45 @@
             :on-click (fn [] (alandipert.storage-atom/remove-local-storage! :saved-for-reddit-app-state)
                         (set! (.-location js/window) "/"))}]])

+(defn handle-error [error]
+  (swap! error-msg #(str error))
+  (r/render-component [error-html] (dommy/sel1 :#error)))
+
+
+(defn get-saved-posts [& after]
+  (let [saved-post-get-chan (if (nil? after)
+                              (http/get (str "https://oauth.reddit.com/user/" (:username @app-state) "/saved")
+                                        {:with-credentials? false
+                                         :oauth-token (:token @app-state)})
+                              (http/get (str "https://oauth.reddit.com/user/" (:username @app-state) "/saved")
+                                        {:with-credentials? false
+                                         :oauth-token (:token @app-state)
+                                         :query-params {"after" (first after)}}))]
+    (js/console.log "Retreiving saved posts..." after)
+    (go (let [response (<! saved-post-get-chan )
+              posts (-> response :body :data :children)
+              error (-> response :body :error)
+              after (-> response :body :data :after) ]
+          (println "received response")
+          #_(println response)
+          (if (clojure.string/blank? error)
+            (do
+              (set-app-state-field :after after)
+              (if (clojure.string/blank? after)
+                (set! (.-disabled (dommy/sel1 :#btn-get-posts)) true))
+              (doseq [p posts]
+                #_(println (process-json-post p))
+                (swap! saved-posts #(conj % %2) (assoc (:data p) :key (str (-> p :data :name) (-> p :data :subreddit_id) (-> p :data :link_id))))))
+            (handle-error (str error " " (:error-text response) "\nYour API token might've expired")))))))
+
+(defn loggedin-html []
+  [:p {:class "navbar-text navbar-right"} "Logged in as " (:username @app-state)])
+
 (defn post-html [p]
   (let [link? (nil? (:title p))
+        key (:key p)
         title (unescapeEntities (if link? (:link_title p) (:title p)))
-        url (if link? (str (:link_url p) (:key p)) (:url p))
+        url (if link? (str (:link_url p) key) (:url p))
         body (if (not (nil? (:body_html p))) (unescapeEntities (:body_html p)))
         subreddit (:subreddit p)
         author (:author p)
@@ -60,7 +93,9 @@
       [:small "submitted by " [:a {:href (str "https://www.reddit.com/user/" author)} [:small author]]
        " on " created-on-str]]
      [:div {:class "panel-body"}
-      [:div {:dangerouslySetInnerHTML {:__html body}}]]]))
+      [:div {:dangerouslySetInnerHTML {:__html body}}]
+      [:div {:class "btn-group btn-group-xs" :role= "group" :aria-label key}
+       [:button {:type "button" :class "btn btn-default"} "Unsave"]]]]))

 (defn main-html [posts]
   [:div {:class "col-md-12"}
@@ -71,14 +106,11 @@
    [:div {:class "row"}
     [:div {:class "col-md-12"}
      [:input {:type "button" :value "moar!"
-              :on-click (fn [] (println "get more posts"))}]]]
+              :id "btn-get-posts" :name "btn-get-posts"
+              :on-click (fn [] (println "get more posts") (get-saved-posts (:after @app-state)) )}]]]
    [:p "Reddit API Token: "
     [:input {:type "text" :id "token" :name "token"
              :value (:token @app-state) :readOnly "true"}]]])
-
-(defn handle-error [error]
-  (swap! error-msg #(str error))
-  (r/render-component [error-html] (dommy/sel1 :#error)))

 (defn process-json-post [post]
   (let [p (:data post)
@@ -90,21 +122,6 @@
         over_i8 (:over_i8 p)
         author (:author p)]
     (println id ": " title " by " author " (" url ")")))
-
-(defn get-saved-posts []
-  (js/console.log "Retreiving saved posts...")
-  (go (let [response (<! (http/get (str "https://oauth.reddit.com/user/" (:username @app-state) "/saved")
-                                   {:with-credentials? false
-                                    :oauth-token (:token @app-state)}))
-            posts (-> response :body :data :children)
-            error (-> response :body :error)]
-        (println "received response")
-        (println response)
-        (if (clojure.string/blank? error)
-          (doseq [p posts]
-            #_(println (process-json-post p))
-            (swap! saved-posts #(conj % %2) (assoc (:data p) :key (-> p :data :id))))
-          (handle-error (str error " " (:error-text response) "\nYour API token might've expired"))))))

 (defn process-after-token-acquire []
   (js/console.log "Token acquired...")


Invoke encode-or-split from the encode queue

--- src/mdr2/main.clj
+++ src/mdr2/main.clj
@@ -18,8 +18,8 @@
   (msg/listen (queues/encode)
               (fn [{:keys [production bitrate sample-rate]}]
                 (if (and bitrate sample-rate)
-                  (encode/encode production bitrate sample-rate)
-                  (encode/encode production))))
+                  (encode/encode-or-split production bitrate sample-rate)
+                  (encode/encode-or-split production))))
   (msg/listen (queues/archive) #(archive/archive %))
   (msg/listen (queues/notify-abacus) #(abacus/export-file %))
   (msg/listen (queues/metadata-update) #(production/update-or-create! %))


resource state #134

resource state
#134

--- src/cljs/swarmpit/component/state.cljs
+++ src/cljs/swarmpit/component/state.cljs
@@ -28,6 +28,7 @@
                                                :secrets    []
                                                :variables  []
                                                :mounts     []
+                                               :resources  {}
                                                :deployment {}}}
                           :task      {:list {}}
                           :registry  {:list {}


spelling mistake

spelling mistake

--- src/clojure/zensols/nlparse/locale.clj
+++ src/clojure/zensols/nlparse/locale.clj
@@ -249,7 +249,7 @@
        (map (fn [{:keys [cnt urec]}]
               (assoc urec :count cnt)))))

-(defn locale-count
+(defn locale-counts
   "Return counts that are a member of a language mapping (locale) of all
   characters in **text**.  See [[unicode-for-char]].


don't upload css files

don't upload css files

--- src/pc/assets.clj
+++ src/pc/assets.clj
@@ -157,7 +157,9 @@
 (defn public-files []
   (remove #(.isDirectory %)
           (tree-seq (fn [f] (and (.isDirectory f)
-                                 (not= f (io/file "resources/public/cljs"))))
+                                 (not= f (io/file "resources/public/cljs"))
+                                 ;; css gets assetified and uploaded separately
+                                 (not= f (io/file "resources/public/css"))))
                     (fn [f] (seq (.listFiles f)))
                     (io/file "resources/public"))))


ENTER when no result selected in auto-complete now closes autocomplete

--- src/chat/client/views/new_message.cljs
+++ src/chat/client/views/new_message.cljs
@@ -93,12 +93,20 @@
             highlight-clear!
             (fn []
               (om/set-state! owner :highlighted-result-index -1))
-            clear-text!
-            (fn []
-              (om/set-state! owner :text ""))
             close-autocomplete!
             (fn []
               (highlight-clear!))
+            reset-state!
+            (fn []
+              (om/set-state! owner
+                             {:text ""
+                              :force-close? false
+                              :highlighted-result-index -1}))
+            send-message!
+            (fn []
+              (dispatch! :new-message {:thread-id (config :thread-id)
+                                       :content text})
+              (reset-state!))
             choose-result!
             (fn [result]
               ((result :action) (config :thread-id))
@@ -119,19 +127,20 @@
                                  (condp = e.keyCode
                                    KeyCodes.ENTER
                                    (cond
-                                     ; ENTER when autocomplete -> trigger chosen result's action
+                                     ; ENTER when autocomplete -> trigger chosen result's action (or exit autocomplete if no result chosen)
                                      autocomplete-open?
                                      (do
                                        (.preventDefault e)
-                                       (when-let [result (nth results highlighted-result-index nil)]
-                                         (choose-result! result)))
+                                       (if-let [result (nth results highlighted-result-index nil)]
+                                         (choose-result! result)
+                                         (do
+                                           (close-autocomplete!)
+                                           (om/set-state! owner :force-close? true))))
                                      ; ENTER otherwise -> send message
                                      (not e.shiftKey)
                                      (do
                                        (.preventDefault e)
-                                       (dispatch! :new-message {:thread-id (config :thread-id)
-                                                                :content text})
-                                       (clear-text!)))
+                                       (send-message!)))

                                    KeyCodes.ESC (do
                                                   (om/set-state! owner :force-close? true)


Length validation for registration password

--- src/clj/food/handlers/registration.clj
+++ src/clj/food/handlers/registration.clj
@@ -16,6 +16,12 @@
     (assoc validity name (conj (vec (name validity)) :empty))
     validity))

+(defn !length [validity name val shortest longest]
+  (let [l (count val)]
+    (if (or (< l shortest) (> l longest))
+      (assoc validity name (conj (vec (name validity)) :length))
+      validity)))
+
 (defn validate-user-registration
   [{:keys [username confirm-username password confirm-password]}]
   (-> {}
@@ -23,15 +29,17 @@
       (!empty :confirm-username confirm-username)
       (!equal :confirm-username username confirm-username)
       (!empty :password password)
+      (!length :password password 4 20)
       (!empty :confirm-password confirm-password)
       (!equal :confirm-password password confirm-password)))

 (def messages {:username         {:empty "Enter a username"}
                :confirm-username {:empty "Enter username confimation"
-                                  :equal "Username confirmation doesn't match."}
-               :password         {:empty "Enter a password"}
+                                  :equal "Username confirmation doesn't match"}
+               :password         {:empty "Enter a password"
+                                  :length "Password must have 4 to 20 characters"}
                :confirm-password {:empty "Enter password confirmation"
-                                  :equal "Password confirmation doesn't match."}})
+                                  :equal "Password confirmation doesn't match"}})

 (defn field-messages [field errors]
   (for [msg-key (field errors)]


Tweak the home page text.

Tweak the home page text.

--- src/clj/hatnik/web/server/renderer.clj
+++ src/clj/hatnik/web/server/renderer.clj
@@ -28,7 +28,7 @@
     [:div.modal-dialog
      [:div.modal-content
       [:div.modal-header
-       [:h4.modal-title "Creating a new project"]]
+       [:h4.modal-title "Create a new project"]]
       [:div.modal-body
        [:form
         [:input#project-name-input.form-control
@@ -94,27 +94,27 @@
   [:div.about
    [:div.page-header
     [:h1 "Hatnik " [:small "Don't miss a release"]]
-    [:p "Hatnik is a web app that helps you to track library releases. Choose a library to track and setup an action that sends emails or creates github issues once library released."]]
+    [:p "Hatnik is a web app that helps you to track library releases. Choose a library to track and setup an action that sends emails or creates Github issues when a new release of the library is published."]]

    [:div.row
     [:div.col-md-6.col-xs-12.use-cases
      [:h3 "When to use"]
      [:p "Use cases might be different. Here is some of them:"]
      [:ul
-      [:li "You want to stay on the edge and use latest ClojureScript."]
+      [:li "You want to stay on the cutting edge and use the latest release of ClojureScript."]
       [:li "You keep forgetting to update wiki tutorials and examples "
-       "to use new version when you release a library."]
-      [:li "You want to have some place shows latest version of your favourite "
+       "to use the new version when you release your library."]
+      [:li "You want to have a place shows the latest version of your favourite "
        "libraries."]
-      [:li "You want your project to automatically switch to newer dependencies."]]]
+      [:li "You want your project to automatically update to the latest version of its dependencies."]]]
     [:div.col-md-6.col-xs-12.how-to
      [:h3 "How to start"]
      [:ol
       [:li "Login via GitHub. Sorry can't do without it."]
       [:li "Create and setup an action"
        [:ol
-        [:li "Choose library, for example " [:code "org.clojure/clojurescript"] "."]
-        [:li "Fill in action settings. For example send email with custom text."]]]]
+        [:li "Choose a library, for example " [:code "org.clojure/clojurescript"] "."]
+        [:li "Fill in the action settings. For example send an email with custom text."]]]]
      [:p "That's all! Now you forget about Hatnik until the library you're tracking is released. "
       "You'll get an email with your text. You can create multiple actions and group them by projects. "
       "A project is simply a group of actions related to each other."]]]
@@ -126,16 +126,16 @@
     "limited only to sending emails, but we're working on it! Here's the initial set of actions:"]
    [:ul.actions
     [:li.available [:strong  "Email"]
-     " - send email with custom text. You can use template variables to substitute library name or version."]
+     " - send an email with custom text. You can use template variables to substitute the library name or the version."]
     [:li.unavailable {:title "Work in progress"} [:strong "GitHub Issue"]
-     " - create an issue in selected repo. Text can be customized just like in email."]
+     " - create an issue in the selected repo. The text can be customized just like in email."]
     [:li.unavailable {:title "Work in progress"} [:strong "GitHub Pull Request"]
      " - create a pull request in selected repo using simple find-and-replace-in-file operations."]
     [:li.unavailable {:title "Work in progress"} [:strong "GitHub Wiki"]
-     " - change a wiki page using same find-and-replace operations."]
+     " - update a wiki page using the same find-and-replace operations."]
     [:li.unavailable {:title "Work in progress"} [:strong "Noop"]
      " - does nothing. Useful if you want to "
-     "have a place that shows latest versions for selected libraries."]]
+     "have a place that lists the latest versions for selected libraries."]]
    ])

 (defn core-page [req]


zero-vec? fn

zero-vec? fn

--- src/cljs/infinitelives/utils/vec2.cljs
+++ src/cljs/infinitelives/utils/vec2.cljs
@@ -289,6 +289,11 @@
         (> x (- y)) :down
         :default :left))))

+(defn zero-vec? [v]
+  (and
+   (zero? (get-x v))
+   (zero? (get-y v))))
+
 ;; make the underlying type of the vec2 sequable and countable
 (extend-type js/Float64Array
   ICounted


GAWB-2387: changing put to post for method configuration edit (#910)

--- src/cljs/main/broadfcui/endpoints.cljs
+++ src/cljs/main/broadfcui/endpoints.cljs
@@ -154,7 +154,7 @@
 (defn update-workspace-method-config [workspace-id config-id]
   {:path (str "/workspaces/" (id-path workspace-id)
               "/method_configs/" (id-path config-id))
-   :method :put})
+   :method :post})

 (defn delete-workspace-method-config [workspace-id config-id]
   {:path (str "/workspaces/" (id-path workspace-id)


Expanding documentation during #33

Expanding documentation during #33

--- src/cljs/memento/handlers/routing.cljs
+++ src/cljs/memento/handlers/routing.cljs
@@ -16,7 +16,13 @@
                   "thread/"  {[:id] #(dispatch [:thread-display (:id %)])}
                   ""         :record}])

-(defn set-page! [match]
+(defn set-page!
+  "Sets a page to the handler matching a parameter. The handler can be either
+  a keyword or a function.
+
+  In case the match is a keyword, it'll assume it's a UI section we need to
+  switch to. If it's a function, it will invoke it with the route-params."
+  [match]
   (let [{:keys [handler route-params]} match]
     (timbre/trace "Setting" match)
     (if (fn? handler)
@@ -31,8 +37,6 @@
   (pushy/pushy set-page! bidi-matcher))

-
-
 ;; Handler for changing the browser token from a keyword, so that
 ;; :record leads to /record. The handler is expected to apply any
 ;; necessary changes to the ui state, or dispatch the relevant


Allow specify one unique undex instead of coll for :assets route directive.

--- src/clojure/catacumba/impl/routing.clj
+++ src/clojure/catacumba/impl/routing.clj
@@ -50,13 +50,17 @@
     method))

 (defmethod attach-route :assets
-  [^Chain chain [_ ^String path {:keys [dir indexes]}]]
+  [^Chain chain [_ ^String path {:keys [dir indexes index]}]]
   (.files chain (hp/fn->action
                  (fn [^FileHandlerSpec spec]
                    (when-not (empty? path)
                      (.path spec path))
-                   (when indexes (.indexFiles spec (into-array String indexes)))
-                   (when dir (.dir spec dir))))))
+                   (when index
+                     (.indexFiles spec (into-array String [index])))
+                   (when indexes
+                     (.indexFiles spec (into-array String indexes)))
+                   (when dir
+                     (.dir spec dir))))))

 (defmethod attach-route :prefix
   [^Chain chain [_ ^String path & handlers]]


move init fcalls inside the fact

move init fcalls inside the fact

--- test/greybear/model_test.clj
+++ test/greybear/model_test.clj
@@ -26,9 +26,9 @@
     (select players (aggregate (count :*) :cnt)) => [{:cnt 1}]))

 (facts "about read-game"
-  (create-user "user1" "foo")
-  (create-user "user2" "foo")
   (fact "reads a game initialized to an empty board"
+    (create-user "user1" "foo")
+    (create-user "user2" "foo")
     (insert games
             (values {:white_id (subselect players
                                           (fields :id)


removing nulls from category list

removing nulls from category list

--- src/spcr/core.clj
+++ src/spcr/core.clj
@@ -31,11 +31,12 @@
                       :default (fn [_] :true)})

 (defn get-matching-rules [record rules]
-  (map (fn [[key pred-fn]]
-         (if (pred-fn record)
-           key
-           nil))
-       rules))
+  (remove nil?
+          (map (fn [[key pred-fn]]
+                 (if (pred-fn record)
+                   key
+                   nil))
+               rules)))

 (defn rule-engine [data rules]
   (map


deleted fact covering :Description in the report that was not needed

--- test/midje/util/t_report.clj
+++ test/midje/util/t_report.clj
@@ -204,20 +204,4 @@
                      :expected "s"}
         raw-report (with-identity-renderer (clojure.test/old-report failure-map))]
     (nth raw-report 0) => #"FAIL.*some description.* at .*foo.clj:3"
-    (nth raw-report 1) => #"a note"))
-
-(fact "shows doc string if present in failure-map"
-  (let [failure-map {:type :mock-expected-result-functional-failure
-                     :description "some description"
-                     :actual 2
-                     :intermediate-results [ ['(f 1) 33] ]
-                     :position ["foo.clj" 3]
-                     :expected '(test-checker 33)}
-        raw-report (with-identity-renderer (clojure.test/old-report failure-map))]
-
-    (nth raw-report 0) => #"FAIL.*some description.*foo.clj:3"
-    (nth raw-report 1) => #"Actual.*did not agree"
-    (nth raw-report 2) => #"Actual.*2"
-    (nth raw-report 3) => #"Checking function.*test-checker 33"
-    (nth raw-report 4) => #"intermediate values"
-    (nth raw-report 5) => #"\(f 1\) => 33"))+    (nth raw-report 1) => #"a note"))


add `defcomponent` devcards example that reads constants

--- src/devcards/om_css/devcards/bugs.cljs
+++ src/devcards/om_css/devcards/bugs.cljs
@@ -126,7 +126,7 @@
 ;;====================
 ;; OMCSS-12

-(defui ^:once Foo
+(defui ^:once OMCSS-12-Defui
    static oc/Style
    (style [_]
      [[:.root {:background-color "tomato"}]
@@ -137,5 +137,15 @@
      (dom/div {:class :root} "div with class :root"
        (dom/section {:class :section} "section with class :section"))))

-(defcard-om-next omcss-12-card
-   Foo)
+(defcard-om-next omcss-12-defui-card
+   OMCSS-12-Defui)
+
+(defcomponent OMCSS-12-Defcomponent [props children]
+  [[:.root {:background-color "tomato"}]
+   [:.section (merge c/some-style
+                {:background-color :green})]]
+  (dom/div {:class :root} "div with class :root"
+    (dom/section {:class :section} "section with class :section")))
+
+(defcard omcss-12-defcomponent-card
+   OMCSS-12-Defcomponent)


Remove line key attributes from search results

--- src/clj/cglossa/search/cwb/speech.clj
+++ src/clj/cglossa/search/cwb/speech.clj
@@ -92,7 +92,12 @@
               ;; so just find the first one. Note that corpora are only marked with line
               ;; keys if they do in fact have media files, so line-key might be nil.
               line-key          (second (re-find #"<who_line_key\s+(\d+)>" result*))
-              segments          (map second (re-seq #"<sync_end.+?>(.+)</sync_end" result*))
+              segments          (->> result*
+                                     (re-seq #"<sync_end.+?>(.+)</sync_end")
+                                     (map second)
+                                     ;; Remove line key attribute tags, since they would only
+                                     ;; confuse the client code
+                                     (map #(str/replace % #"</?who_line_key.*?>" "")))
               ;; We asked for a context of several segments to the left and right of the one
               ;; containing the matching word or phrase in order to be able to show them in the
               ;; media player display. However, only the segment with the match (marked by braces)


extra check

extra check

--- src/clj/morpheus/models/edge/base.clj
+++ src/clj/morpheus/models/edge/base.clj
@@ -111,7 +111,7 @@

 (def-cid-append-op
   append-cids-to-list* [target-cids]
-  (if (< list-length max-list-size)
+  (if (and (not (empty? target-cids)) (< list-length max-list-size))
     (let [cids-num-to-go (- max-list-size list-length)
           cids-to-go (take cids-num-to-go target-cids)]
       (neb-cell/update-cell*


add pending endorsements to stream

add pending endorsements to stream

--- src/cljs/salava/social/ui/stream.cljs
+++ src/cljs/salava/social/ui/stream.cljs
@@ -15,7 +15,8 @@
             [salava.core.ui.notactivated :refer [not-activated-banner]]
             [salava.badge.ui.pending :refer [pending-badge-content]]
             [salava.core.ui.helper :refer [path-for plugin-fun not-activated?]]
-            [salava.badge.ui.modal :as bm]))
+            [salava.badge.ui.modal :as bm]
+            [salava.badge.ui.endorsement :refer [pending-endorsements]]))

 (defn init-data [state]
@@ -421,6 +422,7 @@
      [m/modal-window]
      [badge-alert state]
      [pending-connections reload-fn]
+     [pending-endorsements]
      [badges-pending state]
      (if (not-activated?)
        (not-activated-banner))


Adding more logging to bulk indexing.

Adding more logging to bulk indexing.

--- src/cmr/bootstrap/data/bulk_index.clj
+++ src/cmr/bootstrap/data/bulk_index.clj
@@ -48,16 +48,15 @@
         num-granules (index/bulk-index {:system (:indexer system)} concept-batches)]
         (info "Indexed" num-granules "granule(s) for provider" provider-id)))

-
 (defn- index-provider-collections
   "Index all the collections concepts for a given provider."
   [system provider-id]
   (let [db (get-in system [:metadata-db :db])
         params {:concept-type :collection
                 :provider-id provider-id}
-        concept-batches (db/find-concepts-in-batches db params (:db-batch-size system))]
-    (index/bulk-index {:system (:indexer system)} concept-batches)))
-
+        concept-batches (db/find-concepts-in-batches db params (:db-batch-size system))
+        num-collections (index/bulk-index {:system (:indexer system)} concept-batches)]
+    (info "Indexed" num-collections "collection(s) for provider" provider-id)))

 (defn- unindex-provider
   "Remove all records from elastic related to the given provider including indexes."


Fleshed out first servlet unit test

Fleshed out first servlet unit test

--- ring-servlet/test/ring/util/servlet_test.clj
+++ ring-servlet/test/ring/util/servlet_test.clj
@@ -15,8 +15,8 @@
     (getRemoteAddr [] (request :remote-addr))
     (getRequestURI [] (request :uri))
     (getQueryString [] (request :query-string))
-    (getScheme [] (str (request :scheme)))
-    (getMethod [] (-> request :request-method str .toUpperCase))
+    (getScheme [] (name (request :scheme)))
+    (getMethod [] (-> request :request-method name .toUpperCase))
     (getHeaderNames [] (enumeration (keys (request :headers))))
     (getHeader [name] (get-in request [:headers name]))
     (getContentType [] (request :content-type))
@@ -53,7 +53,19 @@
                 :body           nil}
           resp (atom {})
           svlt (servlet (fn [r]
-                          (is (= (:uri r) (:uri req)))
+                          (are [k v] (= (r k) v)
+                            :server-port    8080
+                            :server-name    "foobar"
+                            :remote-addr    "127.0.0.1"
+                            :uri            "/foo"
+                            :query-string   "a=b"
+                            :scheme         :http
+                            :request-method :get
+                            :headers        {"x-server" "Foo"}
+                            :content-type   "text/plain"
+                            :content-length 10
+                            :character-encoding "UTF-8"
+                            :body           nil)
                           {:status 200, :headers {}}))]
       (doto svlt
         (.init (servlet-config))


Optimize GPU constraint (#1684)

Optimize GPU constraint (#1684)

Co-authored-by: Daniel Posada <d0b0a3e4ff9ddf9df0a9e6f1184e5e15381eae45@gmail.com>
Co-authored-by: Kathryn Zhou <ce465ee26e1aa017c64eebc8207bbaa34d699e55@college.harvard.edu>

--- scheduler/src/cook/scheduler/constraints.clj
+++ scheduler/src/cook/scheduler/constraints.clj
@@ -99,20 +99,17 @@
           ; lookup the GPU model from the pool defaults defined in config.edn
           (util/match-based-on-pool-name (config/valid-gpu-models) pool-name :default-model)))))

-(defrecord gpu-host-constraint [job]
+(defrecord gpu-host-constraint [job-gpu-count-requested job-gpu-model-requested]
   JobConstraint
   (job-constraint-name [this] (get-class-name this))
   (job-constraint-evaluate
     [this _ vm-attributes]
     (job-constraint-evaluate this nil vm-attributes []))
   (job-constraint-evaluate
-    [{:keys [job]} _ vm-attributes vm-tasks-assigned]
-    (let [k8s-vm? (= (get vm-attributes "compute-cluster-type") "kubernetes")
-          job-gpu-count-requested (-> job util/job-ent->resources :gpus (or 0))]
+    [_ _ vm-attributes vm-tasks-assigned]
+    (let [k8s-vm? (= (get vm-attributes "compute-cluster-type") "kubernetes")]
           (if k8s-vm?
-            (let [job-gpu-model-requested (job->gpu-model-requested
-                                            job-gpu-count-requested job (util/job->pool-name job))
-                  vm-gpu-model->count-available (get vm-attributes "gpus")
+            (let [vm-gpu-model->count-available (get vm-attributes "gpus")
                   vm-satisfies-constraint? (if (pos? job-gpu-count-requested)
                                              ; If job requests GPUs, require that the VM has the same number of gpus available in the same model as the job requested.
                                              (and (== (get vm-gpu-model->count-available job-gpu-model-requested 0) job-gpu-count-requested)
@@ -134,7 +131,9 @@
   The constraint prevents a gpu job from running on a host that does not have the correct number and model of gpus
   and a non-gpu job from running on a gpu host because we consider gpus scarce resources."
   [job]
-  (->gpu-host-constraint job))
+  (let [job-gpu-count-requested (-> job util/job-ent->resources :gpus (or 0))
+        job-gpu-model-requested (when (pos? job-gpu-count-requested) (job->gpu-model-requested job-gpu-count-requested job (util/job->pool-name job)))]
+    (->gpu-host-constraint job-gpu-count-requested job-gpu-model-requested)))

 (defrecord rebalancer-reservation-constraint [reserved-hosts]
   JobConstraint


Follow expected page structure in group settings page


fix hours editing

fix hours editing


Found new bug in fractal tree layer, added test to verify

--- test/tree/messaging_test.clj
+++ test/tree/messaging_test.clj
@@ -62,15 +62,18 @@
                                       [del-freq (gen/tuple (gen/return :del)
                                                            (gen/no-shrink gen/int))]])
                                    num-ops)]
-                  (let [b-tree (reduce (fn [t [op x]]
+                  (let [[b-tree s] (reduce (fn [[t s] [op x]]
                                          (let [x-reduced (mod x universe-size)]
                                            (condp = op
-                                             :add (msg/insert t x-reduced)
-                                             :del (msg/delete t x-reduced))))
-                                       (core/b-tree (core/->Config 3 3 2))
+                                             :add [(msg/insert t x-reduced)
+                                                   (conj s x-reduced)]
+                                             :del [(msg/delete t x-reduced)
+                                                   (disj s x-reduced)])))
+                                       [(core/b-tree (core/->Config 3 3 2)) #{}]
                                        ops)]
   ;                  (println ops)
-                    (tree.core-test/check-node-is-balanced b-tree)))))
+                    (and (= (msg/lookup-fwd-iter b-tree -1) (sort s))
+                         (tree.core-test/check-node-is-balanced b-tree))))))

 (defspec test-few-keys-many-ops
   50


Bump minimum Leiningen version to 2.5.3

Bump minimum Leiningen version to 2.5.3

--- src/leiningen/new/chestnut/project.clj
+++ src/leiningen/new/chestnut/project.clj
@@ -24,7 +24,7 @@
   :plugins [[lein-cljsbuild "1.0.5"]
             [lein-environ "1.0.1"]{{{project-plugins}}}]

-  :min-lein-version "2.5.0"
+  :min-lein-version "2.5.3"

   :uberjar-name "{{{name}}}.jar"


Recur so that it runs indefinitely.

Recur so that it runs indefinitely.

--- src/xbxnotify.clj
+++ src/xbxnotify.clj
@@ -89,4 +89,5 @@
                      (concat
                       (map params [:sms-address :gmail-address :gmail-password])
                       [msg])))))
-        (Thread/sleep (* 1000 500))))))
+        (Thread/sleep (* 1000 500))
+        (recur new-friends)))))


Add note

Add note

--- src/yada/core.clj
+++ src/yada/core.clj
@@ -431,6 +431,16 @@
                      ;; case almost invariably nowadays. We could
                      ;; support charset-negotiation in the future, if
                      ;; someone needs it.
+                     ;;
+                     ;; There could still be a case for asking the
+                     ;; resource to tell us which charsets it supports,
+                     ;; because then we could augment a content-type
+                     ;; declaration. For example, a resource may tell us
+                     ;; it produces text/html. The resource by deliver a
+                     ;; string, which we know (on the Java platform) can
+                     ;; be encoded as utf-8. We can add the charset
+                     ;; parameter to the content-type (if one doesn't
+                     ;; already exist).
                      ["utf-8"])
                   (d/error-deferred
                    (ex-info ""


wip - about to make the first incision

wip - about to make the first incision

--- src/yada/core.clj
+++ src/yada/core.clj
@@ -418,7 +418,7 @@
                        (let [vary (negotiation/vary method representations)]
                          (cond-> ctx
                            negotiated (update-in [:response] merge negotiated)
-                           negotiated (assoc-in [:response :representation] negotiated)
+                           negotiated (assoc-in [:response :representation] negotiated) ;; TODO: remove - duplication!
                            vary (assoc-in [:response :vary] vary)
                            ))
                        ))))
@@ -506,6 +506,10 @@
                                     200)
                         :headers (merge
                                   (get-in ctx [:response :headers])
+                                  ;; TODO: The context and its response
+                                  ;; map must be documented so users are
+                                  ;; clear what they can change and the
+                                  ;; effect of this change.
                                   (when-let [ct (get-in ctx [:response :content-type])]
                                     {"content-type" (mime/media-type->string ct)})
                                   (when-let [cl (get-in ctx [:response :content-length])]


Fix aleph setting for retry?

Fix aleph setting for retry?

--- src/engulf/formulas/http_benchmark.clj
+++ src/engulf/formulas/http_benchmark.clj
@@ -28,7 +28,10 @@
   (run-repeatedly
     [this ch runner]
     (let [reqs (:req-seq params)
+          ;; Note, retry does not retry requests, but retries if
+          ;; the server connection is severed in between reqs
           client (http-client {:url (:url (first reqs))
+                               :retry? true
                                :keep-alive? (:keep-alive? (first reqs))})]
       (run-repeatedly this ch runner client reqs)))
   (run-repeatedly


found one more fn to make a letfn

found one more fn to make a letfn

--- src/midje/checkers/collection_util.clj
+++ src/midje/checkers/collection_util.clj
@@ -16,14 +16,14 @@
   (= (count (:expected-found comparison))
      (count (:expected comparison))))

-(defn closer-match?
-  "Did the candidate match more expected elements than before?"
-  [candidate best-so-far]
-  (> (count (:actual-found candidate))
-     (count (:actual-found best-so-far))))
+(letfn [(closer-match?
+         ;; Did the candidate match more expected elements than before?
+         [candidate best-so-far]
+         (> (count (:actual-found candidate))
+            (count (:actual-found best-so-far)))) ]

-(defn better-of [candidate best-so-far]
-  (if (closer-match? candidate best-so-far) candidate best-so-far))
+  (defn better-of [candidate best-so-far]
+    (if (closer-match? candidate best-so-far) candidate best-so-far)))

 (defn collection-like?
   "Extend coll? to include strings."


protect against nil server names

protect against nil server names

--- src/pc/http/handlers/custom_domain.clj
+++ src/pc/http/handlers/custom_domain.clj
@@ -24,17 +24,19 @@
    :body ""})

 (defn handle-custom-domains [handler req]
-  (let [subdomain (parse-subdomain req)]
-    (if-not subdomain
-      (if (not= (:server-name req)
-                (profile/hostname))
-        (redirect-to-main req)
-        (handler req))
-      (if (contains? blacklist subdomain)
-        (redirect-to-main subdomain)
-        (handler (assoc req
-                        :subdomain subdomain
-                        :team (team-model/find-by-subdomain (pcd/default-db) subdomain)))))))
+  (if-not (:server-name req)
+    (handler req)
+    (let [subdomain (parse-subdomain req)]
+      (if-not subdomain
+        (if (not= (:server-name req)
+                  (profile/hostname))
+          (redirect-to-main req)
+          (handler req))
+        (if (contains? blacklist subdomain)
+          (redirect-to-main subdomain)
+          (handler (assoc req
+                          :subdomain subdomain
+                          :team (team-model/find-by-subdomain (pcd/default-db) subdomain))))))))

 (defn wrap-custom-domains [handler]
   (fn [req]


c.t.n.track: docstrings

c.t.n.track: docstrings

--- src/main/clojure/clojure/tools/namespace/track.clj
+++ src/main/clojure/clojure/tools/namespace/track.clj
@@ -10,8 +10,9 @@
       :doc "Dependency tracker which can compute which namespaces need to be
   reloaded after files have changed. This is the low-level
   implementation that requires you to find the namespace dependencies
-  yourself: most users will interact with the wrappers in
-  clojure.tools.namespace.file and clojure.tools.namespace.dir."}
+  yourself: most uses will interact with the wrappers in
+  clojure.tools.namespace.file and clojure.tools.namespace.dir or the
+  public API in clojure.tools.namespace.repl."}
   clojure.tools.namespace.track
   (:refer-clojure :exclude (remove))
   (:require [clojure.set :as set]
@@ -62,8 +63,9 @@
           is the list of namespaces that need to be reloaded

   To reload namespaces in the correct order, first remove/unload all
-  namespaces in the 'unload' list, then (re)load all namespaces in
-  the 'load' list."
+  namespaces in the 'unload' list, then (re)load all namespaces in the
+  'load' list. The clojure.tools.namespace.reload namespace has
+  functions to do this."
   [tracker depmap]
   (let [{load ::load
          unload ::unload
@@ -82,9 +84,8 @@

 (defn remove
   "Returns an updated dependency tracker from which the namespaces
-  (symbols) have been removed. The :unload and :load lists indicate
-  the order in which namespaces should be un/reloaded to reflect this
-  change, as with add."
+  (symbols) have been removed. The ::unload and ::load lists are
+  populated as with 'add'."
   [tracker names]
   (let [{load ::load
          unload ::unload


Fix no-op regexp

Fix no-op regexp

Misread the docs. \B is just the complement of \b.  \b alone seems to be
what's needed here.

--- src/refactor_nrepl/ns/dependencies.clj
+++ src/refactor_nrepl/ns/dependencies.clj
@@ -202,7 +202,7 @@

 (defn- macro-in-use? [file-content macro]
   (when (-> macro
-            (str "(\\b|\\B)")
+            (str "\\b")
             re-pattern
             (re-find file-content)
             empty?