Rough draft of an implementation for issue #6. Very hacked-together at the moment: 'application' logic mingling with presentation logic and all that mess. It works, but I don't want to mark the feature completed until I've finished it up

--- src/foreclojure/problems.clj
+++ src/foreclojure/problems.clj
@@ -4,7 +4,8 @@
 	[somnium.congomongo]
         [hiccup form-helpers])
   (:require [sandbar.stateful-session :as session]
-            [clojure.string :as s]))
+            [clojure.string :as s]
+            [clj-github.gists :as gist]))

 (defn get-solved [user]
   (set
@@ -23,14 +24,43 @@
           :only [:_id :title :tags :times-solved]
           :sort {:id 1})))

-(defn mark-completed [id]
-  (if-let [user (session/session-get :user)]
-    (do
-      (when (not-any? #{id} (get-solved user))
-        (update! :users {:user user} {:$push {:solved id}})
-        (update! :problems {:_id id} {:$inc {:times-solved 1}}))
-      (flash-msg "Congratulations, you've solved the problem!" "/problems"))
-    (flash-msg "You've solved the problem! If you log in we can track your progress." "/problems")))
+(defn gist!
+  "Create a new gist containing a user's solution to a problem and
+  return its url."
+  [user-name problem-num solution]
+  (let [user-name (or user-name "anonymous")
+        filename (str user-name "-4clojure-solution" problem-num ".clj")
+        text (str ";; " user-name
+                  "'s solution to http://4clojure.com/problem/" problem-num
+                  "\n\n"
+                  solution)]
+    (try
+      (->> (gist/new-gist {} filename text)
+           :repo
+           (str "https://gist.github.com/"))
+      (catch Throwable _ nil))))
+
+(defn mark-completed [id code & [user]]
+  (let [user (or user (session/session-get :user))
+        gist-url (gist! user id code)
+        gist-link (if gist-url
+                    (str "
"
+                         "Share this "
+                         "solution"
+                         " on Twitter!"
+                         "
")
+                    (str "
Failed to create gist of "
+                         "your solution
"))
+
+        message
+        (if user
+          (do
+            (when (not-any? #{id} (get-solved user))
+              (update! :users {:user user} {:$push {:solved id}})
+              (update! :problems {:_id id} {:$inc {:times-solved 1}}))
+            "Congratulations, you've solved the problem!")
+          "You've solved the problem! If you log in we can track your progress.")]
+    (flash-msg (str message " " gist-link) "/problems")))

 (defn get-tester [restricted]
   (into secure-tester (map symbol restricted)))
@@ -51,7 +81,7 @@
       (try
 	(loop [[test & more] tests]
 	  (if-not test
-	    (mark-completed id)
+	    (mark-completed id code)
 	    (let [testcase (s/replace test "__" (str code))]
 	      (if (sb sb-tester (read-string testcase))
 		(recur more)


add gangway schema to applications, pass db-conn to helmsman-definition

--- src/galleon/applications.clj
+++ src/galleon/applications.clj
@@ -3,6 +3,7 @@
             [helmsman.uri :as h-uri]
             [helmsman.navigation :as h-nav]
             [gangway.util :as gw-util]
+            [gangway.schema :as gw-schema]
             [gangway.web]
             [navigator.schema :as n-schema]
             [navigator]
@@ -32,7 +33,9 @@
     :helmsman-definition navigator/helmsman-def}
    {:app-name "Gangway"
     :start-fn! gw-util/start-queues!
+    :schema gw-schema/gangway-schema
     :helmsman-context "gangway"
+    :helmsman-definition-db-conn true
     :helmsman-definition gangway.web/helmsman-definition}
    #_
    {:app-name "Flare: Notifier"


Skip hidden files.

Skip hidden files.

--- src/cavm/core.clj
+++ src/cavm/core.clj
@@ -101,10 +101,19 @@
   [cgdata/detect-cgdata
    cgdata/detect-tsv])

+(defn filter-hidden
+  [s]
+  (filter #(not (.isHidden %)) s))
+
 ; Full reload metadata. The loader will skip
 ; data files with unchanged hashes.
 (defn file-changed [loader docroot kind file]
-  (doseq [f (rest (file-seq (io/file docroot)))] ; skip docroot (the first element)
+  (doseq [f (-> docroot
+                (io/file)
+                (file-seq)
+                (rest) ; skip docroot (the first element)
+                (filter-hidden))]
+    (println "Loading " f)
     (try (loader f)
       (catch Exception e (println (str "caught exception: " (.getMessage e))))))) ; XXX this is unhelpful. Log it somewhere.


removed project.clj

removed project.clj

--- games/spirograph/project.clj
+++ games/spirograph/project.clj
@@ -1,20 +0,0 @@
-(defproject spirograph "0.1.0"
-  :description "Spirograph Maker"
-  :url "http://pirosuke.github.io/spirograph"
-  :license {:name "Eclipse Public License"
-            :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[org.clojure/clojure "1.8.0"]
-                 [quil "2.6.0"]
-                 [org.clojure/clojurescript "1.9.473"]]
-
-  :plugins [[lein-cljsbuild "1.1.5"]]
-  :hooks [leiningen.cljsbuild]
-
-  :cljsbuild
-  {:builds [{:source-paths ["src"]
-             :compiler
-             {:output-to "js/main.js"
-              :output-dir "out"
-              :main "spirograph.core"
-              :optimizations :none
-              :pretty-print true}}]})


Scratch changes.

Scratch changes.

--- dev-system/scratch.clj
+++ dev-system/scratch.clj
@@ -38,18 +38,20 @@
                   [_ num-granules] concept-id-map]
               num-granules)))

+(defn remove-zero-collections
+  "Removes collections from the nested map that have counts of 0"
+  [nested-map]
+  (reduce (fn [holdings provider-id]
+            (update-in holdings [provider-id] #(into {} (filter (complement (comp zero? second)) %))))
+          nested-map
+          (keys nested-map)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; SIT
+
+
 (def testbed-holdings
   (->> (decode (slurp "testbed_holdings.json") true)
-       (map #(update-in % [:granule_count] (fn [v] (Long. v))))
-       (map (fn [{:keys [dataset_id echo_collection_id granule_count provider_id]}]
-              {:granule-count granule_count
-               :provider-id provider_id
-               :entry-title dataset_id
-               :concept-id echo_collection_id}))
-       holdings->nested-map))
-
-(def ptest-holdings
-  (->> (decode (slurp "ptest_holdings.json") true)
        (map #(update-in % [:granule_count] (fn [v] (Long. v))))
        (map (fn [{:keys [dataset_id echo_collection_id granule_count provider_id]}]
               {:granule-count granule_count
@@ -62,9 +64,6 @@
 (def sit-holdings
   (holdings->nested-map (decode (slurp "sit_holdings.json") true)))

-(def uat-holdings
-  (holdings->nested-map (decode (slurp "uat_mdb_holdings.json") true)))
-
 (holdings-map->total sit-holdings)
 (holdings-map->total testbed-holdings)

@@ -72,15 +71,51 @@
   {:sit-extra sit-extra
    :tb-extra tb-extra})

-(let [[uat-extra ptest-extra _] (clojure.data/diff uat-holdings ptest-holdings)]
+(get-in sit-holdings ["EDF_OPS" "C1000000261-EDF_OPS"])
+(get-in testbed-holdings ["EDF_OPS" "C1000000261-EDF_OPS"])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; UAT
+
+(def ptest-holdings
+  (->> (decode (slurp "ptest_holdings.json") true)
+       (map #(update-in % [:granule_count] (fn [v] (Long. v))))
+       (map (fn [{:keys [dataset_id echo_collection_id granule_count provider_id]}]
+              {:granule-count granule_count
+               :provider-id provider_id
+               :entry-title dataset_id
+               :concept-id echo_collection_id}))
+       holdings->nested-map))
+
+(def uat-mdb-holdings
+  (holdings->nested-map (decode (slurp "uat_mdb_holdings.json") true)))
+
+(def uat-search-holdings
+  (holdings->nested-map (decode (slurp "uat_holdings.json") true)))
+
+
+
+(let [[uat-extra ptest-extra _] (clojure.data/diff
+                                  uat-mdb-holdings
+                                  (remove-zero-collections ptest-holdings))]
   {:uat-extra uat-extra
    :ptest-extra ptest-extra})

-(get-in sit-holdings ["EDF_OPS" "C1000000261-EDF_OPS"])
-(get-in testbed-holdings ["EDF_OPS" "C1000000261-EDF_OPS"])
+(let [[uat-extra ptest-extra _] (clojure.data/diff
+                                  uat-mdb-holdings
+                                  (remove-zero-collections uat-search-holdings))]
+  {:uat-mdb-extra uat-extra
+   :uat-search-extra ptest-extra})

-(get-in sit-holdings ["EDF_OPS" "C1000000104-EDF_OPS"])
-(get-in testbed-holdings ["EDF_OPS" "C1000000104-EDF_OPS"])
+(let [[uat-extra ptest-extra _] (clojure.data/diff
+                                  uat-mdb-holdings
+                                  (remove-zero-collections ptest-holdings))]
+  (set (concat (mapcat (comp keys second) uat-extra)
+               (mapcat (comp keys second) ptest-extra))))
+
+
+(get-in uat-holdings   ["ECHO10_PT" "C40624-ECHO10_PT"])
+(get-in ptest-holdings ["ECHO10_PT" "C40624-ECHO10_PT"])


Update nimbus.clj

Update nimbus.clj

Adding check to disallow topology submission if the topology name is blank. In one of the scenarios, we had pushed a topology with an empty name, and it showed up on the ui with only the uid. Also since it did not have any name we could not go into "Topology Details" to kill it, and hence had to clean up the state on the disk so that Nimbus kills the topology.

--- storm-core/src/clj/backtype/storm/daemon/nimbus.clj
+++ storm-core/src/clj/backtype/storm/daemon/nimbus.clj
@@ -855,7 +855,8 @@
 (defn validate-topology-name! [name]
   (if (some #(.contains name %) DISALLOWED-TOPOLOGY-NAME-STRS)
     (throw (InvalidTopologyException.
-            (str "Topology name cannot contain any of the following: " (pr-str DISALLOWED-TOPOLOGY-NAME-STRS))))))
+            (str "Topology name cannot contain any of the following: " (pr-str DISALLOWED-TOPOLOGY-NAME-STRS))))
+              (if (clojure.string/blank? name) (throw (InvalidTopologyException. (str "Topology name cannot be blank"))))))

 (defn- try-read-storm-conf [conf storm-id]
   (try-cause


Make hack a bit more robust

Make hack a bit more robust

--- examples/repl.clj
+++ examples/repl.clj
@@ -1,7 +1,8 @@
 #!/bin/sh

-#_#_#_#_#_#_
-eval "exec $(inlein --sh-cmd "$0" "$@")"
+#_[
+   eval "exec $(inlein --sh-cmd "$0" "$@")"
+#_ 0]

 ;; Your own, self-customised repl with all the tools you'd like to use!
 ;;


Fixed minor typo in Vectors Summed ns

Fixed minor typo in Vectors Summed ns

--- src/clojush/problems/software/vectors_summed.clj
+++ src/clojush/problems/software/vectors_summed.clj
@@ -8,7 +8,7 @@
 ;;
 ;; input stack has 2 input vectors of integers

-(ns clojush.problems.software.vectors-summed-backup
+(ns clojush.problems.software.vectors-summed
   (:use clojush.pushgp.pushgp
         [clojush pushstate interpreter random util globals]
         clojush.instructions.tag


Tidy up docstrings

Tidy up docstrings

--- src/overtone/sc/machinery/ugen/metadata/unaryopugen.clj
+++ src/overtone/sc/machinery/ugen/metadata/unaryopugen.clj
@@ -5,196 +5,268 @@
   {"neg" {:summary "Signal inversion"
           :doc "Invert input signal a by changing its sign.

-i.e. 1 -> -1 and -0.5 -> 0.5"}
+                i.e. 1 -> -1 and -0.5 -> 0.5"}

    "not-pos?"    {:summary "Check for non positive signal"
-                  :doc "Determines whether the signal is negative or not. If it is less than or equal to 0 then outputs 1, otherwise outputs 0
-
-i.e. 1 -> 0,  -0.5 -> 1, 0 -> 1"}
+                  :doc "Determines whether the signal is negative or
+                        not. If it is less than or equal to 0 then
+                        outputs 1, otherwise outputs b0
+
+                        i.e. 1 -> 0,  -0.5 -> 1, 0 -> 1"}

    "abs"         {:summary "Absolute value"
-                  :doc "Outputs the value of input a without regard to its sign.
-
-i.e 1 -> 1 and -0.5 0.5"}
+                  :doc "Outputs the value of input a without regard to
+                        its sign.
+
+                        i.e 1 -> 1 and -0.5 0.5"}

    "ceil"        {:summary "Next higher integer"
                   :doc "Rounds input a up the next highest integer.

-i.e. 5.1 -> 6 and 7.0 -> 7"}
+                        i.e. 5.1 -> 6 and 7.0 -> 7"}

    "floor"       {:summary "Previous lower integer"
-                  :doc "Rounds input a down to the previous lower integer.
-
-i.e. 5.9 -> 5 and 7.0 -> 7"}
+                  :doc "Rounds input a down to the previous lower
+                       integer.
+
+                       i.e. 5.9 -> 5 and 7.0 -> 7"}

    "frac"        {:summary "Fractional part of signal"
-                  :doc "Outputs the fractional part between input a and the next higher integer. This means that negative input vals may result in a different output than positive input vals. Output is always positive.
-
-i.e. 3.5 -> 0.5, 34.2 -> 0.2, -5.2 -> 0.8"}
+                  :doc "Outputs the fractional part between input a and
+                        the next higher integer. This means that
+                        negative input vals may result in a different
+                        output than positive input vals. Output is
+                        always positive.
+
+                        i.e. 3.5 -> 0.5, 34.2 -> 0.2, -5.2 -> 0.8"}

    "sign"        {:summary "Sign of signal"
-                  :doc "Outputs -1 when a < 0, +1 when a > 0, 0 when a is 0."}
+                  :doc "Outputs -1 when a < 0, +1 when a > 0, 0 when a
+                        is 0." }

    "squared"     {:summary "Squared value"
                   :doc "Outputs the square of input a.

-i.e. 5 -> 25 and -3 -> 9"}
+                        i.e. 5 -> 25 and -3 -> 9"}

    "cubed"       {:summary "Cubed value"
                   :doc "Outputs the cube of input a.

-i.e. 2 -> 8 and -3 -> -27"}
+                        i.e. 2 -> 8 and -3 -> -27"}

    "sqrt"        {:summary "Square root"
-                  :doc "Outputs the square root of input a. The definition of square root is extended for signals so that when a is < 0 (sqrt a) returns (- (sqrt -a)).
-
-i.e. 9 -> 3 and -25 -> -5"}
+                  :doc "Outputs the square root of input a. The
+                        definition of square root is extended for
+                        signals so that when a is < 0 (sqrt a)
+                        returns (- (sqrt -a)).
+
+                        i.e. 9 -> 3 and -25 -> -5"}

    "exp"         {:summary "Exponential function"
-                  :doc "Outputs e to the power of a, where e is the mathematical constant (approximately 2.718281828) and a is the input signal.
-
-i.e. 1 -> 2.71828 and 10 -> 22026.5"}
+                  :doc "Outputs e to the power of a, where e is the
+                        mathematical constant (approximately
+                        2.718281828) and a is the input signal.
+
+                        i.e. 1 -> 2.71828 and 10 -> 22026.5"}

    "reciprocal"  {:summary "Multiplicative inverse"
-                  :doc "Outputs the multiplicative inverse of a. This is typically denoted by 1/a or a^-1.
-
-i.e. 10 -> 0.1 and -1 -> -1"}
+                  :doc "Outputs the multiplicative inverse of a. This is
+                        typically denoted by 1/a or a^-1.
+
+                        i.e. 10 -> 0.1 and -1 -> -1"}

    "midicps"     {:args [{:name "midi-note" :doc "MIDI note to convert"}]
-                  :summary "convert MIDI note to cycles per second"
-                  :doc "Outputs the corresponding Hz or cycles per second for input a representing a MIDI note. Inverse of cpsmidi.
-
-i.e 69 -> 440 and 80 -> 830.609"}
+                  :summary "Convert MIDI note to cycles per second"
+                  :doc "Outputs the corresponding Hz or cycles per
+                        second for input a representing a MIDI note. Inverse
+                        of cpsmidi.
+
+                        i.e 69 -> 440 and 80 -> 830.609"}

    "cpsmidi"     {:args [{:name "cps" :doc "Cycles per second"}]
                   :summary "convert cycles per second to MIDI note"
-                  :doc "Outputs the corresponding MIDI note for input a representing cycles per second or Hz. Doesn't always return a discrete integer. Inverse of midicps.
-
-i.e. 440 -> 69 and 500 -> 71.2131"}
+                  :doc "Outputs the corresponding MIDI note for input a
+                        representing cycles per second or Hz. Doesn't
+                        always return a discrete integer. Inverse of
+                        midicps.
+
+                        i.e. 440 -> 69 and 500 -> 71.2131"}

    "midiratio"   {:args [{:name "num-semitones" :doc "Interval in MIDI notes"}]
                   :summary "Convert an interval in MIDI notes into a frequency ratio"
-                  :doc "Outputs a frequency ratio that corresponds to the interval in MIDI notes represented by num-semitones. In other words, outputs the amount to multiply a frequency by in order to alter it by num-semitones. Inverse of ratiomidi.
-
-i.e. 12 -> 2, -2 -> 0.890899"}
+                  :doc "Outputs a frequency ratio that corresponds to
+                        the interval in MIDI notes represented by
+                        num-semitones. In other words, outputs the
+                        amount to multiply a frequency by in order to
+                        alter it by num-semitones. Inverse of ratiomidi.
+
+                        i.e. 12 -> 2, -2 -> 0.890899"}

    "ratiomidi"   {:args [{:name "freq-ratio" :doc "Cycles per second"}]
                   :summary "Convert a frequency ratio to an interval in MIDI notes"
-                  :doc "Outputs the number of semitones difference created when multiplying a given frequency by freq-ratio. Inverse of midiratio.
-
-i.e. 0.890899 -> -1.99999 and 2 -> 12 "}
+                  :doc "Outputs the number of semitones difference
+                        created when multiplying a given frequency by
+                        freq-ratio. Inverse of midiratio.
+
+                        i.e. 0.890899 -> -1.99999 and 2 -> 12 "}

    "dbamp"       {:args [{:name "decibels" :doc "Volume in decibels"}]
                   :summary "convert decibels to linear amplitude"
-                  :doc "Convert decibels to the linear amplitude. For example, to raise the amplitude by 20db, you should multiply the signal by 10. Inverse of ampdb.
-
-i.e. 20 -> 10 and 50 -> 316.228"}
+                  :doc "Convert decibels to the linear amplitude. For
+                        example, to raise the amplitude by 20db, you
+                        should multiply the signal by 10. Inverse of
+                        ampdb.
+
+                        i.e. 20 -> 10 and 50 -> 316.228"}

    "ampdb"       {:args [{:name "amplitude" :doc "Linear amplitude"}]
                   :summary "Convert linear amplitude to decibels"
-                  :doc "Convert a linear amplitude to number of decibels. For example, a 20db raise in amplitude is equivalent to multiplying a signal by 10. Inverse of dbamp.
-
-i.e. 10 -> 20 and 316.228 -> 50"}
+                  :doc "Convert a linear amplitude to number of
+                        decibels. For example, a 20db raise in amplitude
+                        is equivalent to multiplying a signal by
+                        10. Inverse of dbamp.
+
+                        i.e. 10 -> 20 and 316.228 -> 50"}

    "octcps"      {:args [{:name "dec-octaves" :doc "Decimal octaves"}]
                   :summary "Convert decimal octaves to cycles per second"
-                  :doc "Outputs the number of cycles per second represented by dec-octaves.
-
-i.e. 1 -> 32.7031 -4 -> 1.02197"}
+                  :doc "Outputs the number of cycles per second
+                        represented by dec-octaves.
+
+                        i.e. 1 -> 32.7031 -4 -> 1.02197"}

    "cpsoct"      {:args [{:name "cps" :doc "Cycles per second"}]
                   :summary "Convert cycles per second to decimal octaves"
-                  :doc "Outputs the number of decimal octaves represented by cps
-
-i.e. 32.7031 -> 0.99999 and 500 -> 4.93442"}
+                  :doc "Outputs the number of decimal octaves
+                        represented by cps
+
+                        i.e. 32.7031 -> 0.99999 and 500 -> 4.93442"}

    "log"         {:summary "Natural logarithm"
                   :doc "Outputs the natural log of input a

-i.e. 2.71828 -> 0.99999 and 10 -> 2.30259"}
+                        i.e. 2.71828 -> 0.99999 and 10 -> 2.30259"}

    "log2"        {:summary "Base 2 logarithm"
                   :doc "Outputs the base 2 log of input a

-i.e. 8 -> 3 and 256 -> 8"}
+                        i.e. 8 -> 3 and 256 -> 8"}

    "log10"       {:summary "Base 10 logarithm"
                   :doc "Outputs the base 10 log of input a

-i.e. 10 -> 1 and 200 -> 2.30103"}
+                        i.e. 10 -> 1 and 200 -> 2.30103"}

    "sin"         {:summary "Sine function"
                   :doc "Outputs the sine of input a

-i.e. 1.5707986 -> 1 and 3.14159265 -> ~0"}
+                        i.e. 1.5707986 -> 1 and 3.14159265 -> ~0"}

    "cos"         {:summary "Cosine function"
                   :doc "Outputs the cosine of input a

-i.e. 0 -> 1 and 3.14159265 -> -1"}
+                        i.e. 0 -> 1 and 3.14159265 -> -1"}

    "tan"         {:summary "Tangent function"
                   :doc "Outputs the tangent of input a

-i.e. 0 -> 0 and 1.570 -> 1255.85"}
+                        i.e. 0 -> 0 and 1.570 -> 1255.85"}

    "asin"        {:summary "Arcsine function"
                   :doc "Outputs the arcsine of input a

-i.e. 1 -> 1.5708 and 3.14159265 -> nan"}
+                        i.e. 1 -> 1.5708 and 3.14159265 -> nan"}

    "acos"        {:summary "Arccosine function"
                   :doc "Outputs the arccosine of input a

-i.e. 1 -> 0 and 3.14159265 -> nan"}
+                        i.e. 1 -> 0 and 3.14159265 -> nan"}

    "atan"        {:summary "Arctangent function"
                   :doc "Outputs the arctangent of input a

-i.e. 0 -> 0 and 1 -> 0.785398"}
+                        i.e. 0 -> 0 and 1 -> 0.785398"}

    "sinh"        {:summary "Hyperbolic sine function"
                   :doc "Outputs the hyperbolic sine of input a

-i.e. 0 -> 0 and 1 -> 1.1752"}
+                        i.e. 0 -> 0 and 1 -> 1.1752"}

    "cosh"        {:summary "Hyperbolic cosine function"
                   :doc "Outputs the hyperbolic cosine of input a

-i.e. 0 -> 1 and 1 -> 1.54308"}
+                        i.e. 0 -> 1 and 1 -> 1.54308"}

    "tanh"        {:summary "Hyperbolic tangent function"
                   :doc "Outputs the hyperbolic tangent of input a

-i.e. 0 -> 0 and 1 -> 0.761594"}
+                        i.e. 0 -> 0 and 1 -> 0.761594"}

    "distort"     {:summary "Nonlinear distortion"
-                  :doc "Maps input a to a value between 0 and 1 if a is positive and between 0 and -1 if a is negative. Slope of mapping is initially steep, then the gradient reduces as it tends towards 1. Negative part is a mirror image. Always returns a value between -1 and 1. See softclip if you require a linear region.
-
-i.e. 0 -> 0, 1 -> 0.5, 10 -> 0.909091, 1000 -> 0.999001 and -1 -> 0.5"}
+                  :doc "Maps input a to a value between 0 and 1 if a is
+                        positive and between 0 and -1 if a is
+                        negative. Slope of mapping is initially steep,
+                        then the gradient reduces as it tends towards
+                        1. Negative part is a mirror image. Always
+                        returns a value between -1 and 1. See softclip
+                        if you require a linear region.
+
+                        i.e. 0 -> 0, 1 -> 0.5, 10 -> 0.909091,
+                        1000 -> 0.999001 and -1 -> 0.5"}

    "softclip"    {:summary "Nonlinear distortion with linear region"
-                  :doc "Maps input a to a value between 0 and 1 if a is positive and between 0 and -1 if a is negative. Gradient of mapping is linear between -0.5 and 0.5 and then gradually reduces as it tends towards 1. Negative part is a mirror image. Always returns a value between -1 and 1.
-
-i.e. 0 -> 0, 0.2 -> 0.2, 0.5 -> 0.5, 0.75 -> 0.666667, 10 -> 0.975 and 1000 -> 0.99975"}
+                  :doc "Maps input a to a value between 0 and 1 if a is
+                        positive and between 0 and -1 if a is
+                        negative. Gradient of mapping is linear between
+                        -0.5 and 0.5 and then gradually reduces as it
+                        tends towards 1. Negative part is a mirror
+                        image. Always returns a value between -1 and 1.
+
+                        i.e. 0 -> 0, 0.2 -> 0.2, 0.5 -> 0.5,
+                        0.75 -> 0.666667, 10 -> 0.975 and 1000 -> 0.99975"}

    "rect-window" {:summary "Rectangular window function"
-                  :doc "Maps input a onto a rectangular window which spans between 0 and 1 with height 1. If the input signal is between 0 and 1 inclusive, the output will be 1, otherwise the output will be 0. Always returns either 0 or 1.
-
-i.e. -0.1 -> 0, 0 -> 1, 0.5 -> 1, 0.99 -> 1, 1 -> 1, 1.01 -> 0 and 2000 -> 0"}
+                  :doc "Maps input a onto a rectangular window which
+                        spans between 0 and 1 with height 1. If the
+                        input signal is between 0 and 1 inclusive, the
+                        output will be 1, otherwise the output will be
+                        0. Always returns either 0 or 1.
+
+                        i.e. -0.1 -> 0, 0 -> 1, 0.5 -> 1,
+                        0.99 -> 1, 1 -> 1, 1.01 -> 0 and 2000 -> 0"}

    "han-window"  {:summary "Hanning window function"
-                  :doc "Maps input a onto a hanning window which spans between 0 and 1 with a peak at 0.5. Any input between 0 and 1 is mapped to the corresponding val in hanning window (looks like a sharp tooth - gradient quickly increases and then decreases to the top of the tooth). All other input vals map to 0. Always returns a value between 0 and 1.
-
-i.e. 0.1 -> 0.0954915, 0.3 -> 0.654509, 0.5 -> 1, 0.7 -> 0.654509 and 0.9 -> 0.0954915"}
+                  :doc "Maps input a onto a hanning window which spans
+                        between 0 and 1 with a peak at 0.5. Any input
+                        between 0 and 1 is mapped to the corresponding
+                        val in hanning window (looks like a sharp tooth
+                        - gradient quickly increases and then decreases
+                        to the top of the tooth). All other input vals
+                        map to 0. Always returns a value between 0 and
+                        1.
+
+                        i.e. 0.1 -> 0.0954915, 0.3 -> 0.654509, 0.5 -> 1,
+                        0.7 -> 0.654509 and 0.9 -> 0.0954915"}

    "wel-window"  {:summary "Welch window function"
-                  :doc "Maps input a onto a welch window which spans between 0 and 1 with a peak at 0.5. Any input between 0 and 1 is mapped to the corresponding val in welch window (looks like a rhino horn - gradient starts off high and gradually degreases to the top of the horn). All other input vals map to 0. Always returns a value between 0 and 1.
-
-i.e. 0.1 -> 0.309017, 0.3 -> 0.809017, 0.5 -> 1, 0.7 -> 0.809017 and 0.9 -> 0.309017"}
+                  :doc "Maps input a onto a welch window which spans
+                       between 0 and 1 with a peak at 0.5. Any input
+                       between 0 and 1 is mapped to the corresponding
+                       val in welch window (looks like a rhino horn -
+                       gradient starts off high and gradually degreases
+                       to the top of the horn). All other input vals map
+                       to 0. Always returns a value between 0 and 1.
+
+                       i.e. 0.1 -> 0.309017, 0.3 -> 0.809017, 0.5 -> 1,
+                       0.7 -> 0.809017 and 0.9 -> 0.309017"}

    "tri-window"  {:summary "Triangle window function"
-                  :doc "MAps input a onto a triangle window which spance between 0 and 1 with a peak at 0.5. Any input between 0 and 1 is mapped to the corresponding val in the triangle window. All other input vals map to 0. Always returns a value between 0 and 1."}
+                  :doc "Maps input a onto a triangle window which spance
+                        between 0 and 1 with a peak at 0.5. Any input
+                        between 0 and 1 is mapped to the corresponding
+                        val in the triangle window. All other input vals
+                        map to 0. Always returns a value between 0 and
+                        1." }

    })


Added svg support for nfts

Added svg support for nfts

Signed-off-by: Shivek Khurana <ae036b02ef2f3d9f073f7930137ecb248a31c067@status.im>

--- src/status_im/ui/screens/wallet/collectibles/views.cljs
+++ src/status_im/ui/screens/wallet/collectibles/views.cljs
@@ -14,12 +14,20 @@
             [quo.design-system.colors :as colors]
             [status-im.ui.components.icons.icons :as icons]
             [status-im.i18n.i18n :as i18n]
-            [status-im.ui.components.accordion :as accordion]))
+            [status-im.ui.components.accordion :as accordion]
+            ["react-native-svg" :refer (SvgUri)]
+            [reagent.core :as reagent]))
+
+(def svg-uri (reagent/adapt-react-class SvgUri))

 (defn is-image? [nft]
   (and (seq (:image_url nft))
        (not (str/ends-with? (:image_url nft) ".svg"))
        (not (str/ends-with? (:image_url nft) ".mp4"))))
+
+(defn is-vector? [nft]
+  (and (seq (:image_url nft))
+       (str/ends-with? (:image_url nft) ".svg")))

 (defn missing-image-placeholder []
   [react/view {:style {:width            "100%"
@@ -75,74 +83,6 @@
    [react/view {:style {:height 40
                         :width  40}}]])

-(defn nft-details-modal []
-  (let [nft (<sub [:wallet/selected-collectible])]
-    [react/scroll-view
-     [topbar/topbar
-      {:navigation    {:icon :main-icons/close}
-       :border-bottom false}]
-     [react/view {:padding-horizontal 16}
-      [quo/text {:size   :large
-                 :weight :bold}
-       (:name nft)]
-      [quo/text {:size  :small
-                 :color :secondary
-                 :style {:margin-top 4}}
-       (-> nft :collection :name)]
-
-      (if (is-image? nft)
-        [react/image {:source {:uri (:image_url nft)}
-                      :style  {:width         "100%"
-                               :margin-bottom 16
-                               :aspect-ratio  1
-                               :border-radius 4
-                               :border-width  1
-                               :border-color  colors/gray-lighter}}]
-        [missing-image-placeholder])
-
-      [quo/text {:style {:margin-top 12}}
-       (:description nft)]]
-
-     (when (seq (:traits nft))
-       [nft-traits-scroller (:traits nft)])
-
-     ;; seperator
-     [react/view {:style {:border-bottom-width 1
-                          :padding-top         8
-                          :border-color        colors/gray-lighter}}]
-
-     ;; TODO <shivekkhurana>: Enable txns
-     ;; [quo/list-item {:title    (i18n/label :t/wallet-send)
-     ;;                 :icon     :main-icons/send
-     ;;                 :accessibility-label
-     ;;                 :nft-send
-     ;;                 :theme    :accent
-     ;;                 :on-press #()}]
-
-     ;; TODO <shivekkhurana>: What to do with share?
-     ;; Share links or share image?
-     ;; [quo/list-item {:title    (i18n/label :t/share)
-     ;;                 :theme    :accent
-     ;;                 :accessibility-label
-     ;;                 :nft-share
-     ;;                 :on-press #()
-     ;;                 :icon     :main-icons/share}]
-     [quo/list-item {:title    (i18n/label :t/view-on-opensea)
-                     :theme    :accent
-                     :icon     :main-icons/browser
-                     :on-press #(re-frame/dispatch [:browser.ui/open-url (:permalink nft)])}]
-     (when (is-image? nft)
-       [toastable-highlight-view
-        ;; the last string is an emoji. It might not show up in all editors but its there
-        {:toast-label (str (i18n/label :profile-picture-updated)) " " "😎"}
-        [quo/list-item {:title    (i18n/label :t/use-as-profile-picture)
-                        :theme    :accent
-                        :on-press #(re-frame/dispatch
-                                    [::multiaccounts/save-profile-picture-from-url (:image_url nft)])
-                        :icon     :main-icons/profile
-                        :accessibility-label
-                        :set-nft-as-pfp}]])]))
-
 (defn no-assets-error []
   [react/view {:style {:flex            1
                        :justify-content :center
@@ -155,6 +95,38 @@
               :style {:magin-top 8}}
     (i18n/label :t/no-collectibles)]])

+(defn render-asset [{:keys [asset width clickable?]}]
+  [(if clickable? react/touchable-opacity react/view)
+   {:style
+    {:width         width
+     :border-radius 16
+     :margin-bottom 16}
+    :on-press (when clickable? #(re-frame/dispatch [::wallet/show-nft-details asset]))
+    :accessibility-label
+    :nft-asset}
+   (cond
+     ;; pngs and jpegs
+     (is-image? asset)
+     [react/image {:style  {:flex          1
+                            :aspect-ratio  1
+                            :border-width  1
+                            :border-color  colors/gray-lighter
+                            :border-radius 16}
+                   :source {:uri (:image_url asset)}}]
+
+     ;; vectors
+     (is-vector? asset)
+     [react/view {:style {:flex          1
+                          :aspect-ratio  1
+                          :border-width  1
+                          :border-color  colors/gray-lighter
+                          :border-radius 16}}
+      [svg-uri {:uri   (:image_url asset)
+                :width "100%" :height "100%"}]]
+
+     ;; ¯\_(ツ)_/¯
+     :else [missing-image-placeholder])])
+
 (defn nft-assets [{:keys [num-assets address collectible-slug]}]
   (let [assets    (<sub [:wallet/collectible-assets-by-collection-and-address address collectible-slug])
         fetching? (<sub [:wallet/fetching-assets-by-collectible-slug collectible-slug])]
@@ -175,22 +147,9 @@
        (seq assets)
        (for [asset assets]
          ^{:key (:id asset)}
-         [react/touchable-opacity
-          {:style
-           {:width         "48%"
-            :border-radius 16
-            :margin-bottom 16}
-           :on-press #(re-frame/dispatch [::wallet/show-nft-details asset])
-           :accessibility-label
-           :nft-asset}
-          (if (is-image? asset)
-            [react/image {:style  {:flex          1
-                                   :aspect-ratio  1
-                                   :border-width  1
-                                   :border-color  colors/gray-lighter
-                                   :border-radius 16}
-                          :source {:uri (:image_url asset)}}]
-            [missing-image-placeholder])]))]))
+         [render-asset {:asset      asset
+                        :clickable? true
+                        :width      "48%"}]))]))

 (defn nft-collections [address]
   (let [collection (<sub [:wallet/collectible-collection address])]
@@ -254,3 +213,65 @@
               :align :center
               :style {:margin-top 10}}
     (i18n/label :t/disable-later-in-settings)]])
+
+(defn nft-details-modal []
+  (let [nft (<sub [:wallet/selected-collectible])]
+    [react/scroll-view
+     [topbar/topbar
+      {:navigation    {:icon :main-icons/close}
+       :border-bottom false}]
+     [react/view {:padding-horizontal 16}
+      [quo/text {:size   :large
+                 :weight :bold}
+       (:name nft)]
+      [quo/text {:size  :small
+                 :color :secondary
+                 :style {:margin-top 4}}
+       (-> nft :collection :name)]
+
+      [render-asset {:asset      nft
+                     :clickable? false
+                     :width      "100%"}]
+
+      [quo/text {:style {:margin-top 12}}
+       (:description nft)]]
+
+     (when (seq (:traits nft))
+       [nft-traits-scroller (:traits nft)])
+
+     ;; seperator
+     [react/view {:style {:border-bottom-width 1
+                          :padding-top         8
+                          :border-color        colors/gray-lighter}}]
+
+     ;; TODO <shivekkhurana>: Enable txns
+     ;; [quo/list-item {:title    (i18n/label :t/wallet-send)
+     ;;                 :icon     :main-icons/send
+     ;;                 :accessibility-label
+     ;;                 :nft-send
+     ;;                 :theme    :accent
+     ;;                 :on-press #()}]
+
+     ;; TODO <shivekkhurana>: What to do with share?
+     ;; Share links or share image?
+     ;; [quo/list-item {:title    (i18n/label :t/share)
+     ;;                 :theme    :accent
+     ;;                 :accessibility-label
+     ;;                 :nft-share
+     ;;                 :on-press #()
+     ;;                 :icon     :main-icons/share}]
+     [quo/list-item {:title    (i18n/label :t/view-on-opensea)
+                     :theme    :accent
+                     :icon     :main-icons/browser
+                     :on-press #(re-frame/dispatch [:browser.ui/open-url (:permalink nft)])}]
+     (when (is-image? nft)
+       [toastable-highlight-view
+        ;; the last string is an emoji. It might not show up in all editors but its there
+        {:toast-label (str (i18n/label :profile-picture-updated)) " " "😎"}
+        [quo/list-item {:title    (i18n/label :t/use-as-profile-picture)
+                        :theme    :accent
+                        :on-press #(re-frame/dispatch
+                                    [::multiaccounts/save-profile-picture-from-url (:image_url nft)])
+                        :icon     :main-icons/profile
+                        :accessibility-label
+                        :set-nft-as-pfp}]])]))


[#3081] Remove logs

[#3081] Remove logs

--- backend/src/akvo/lumen/lib/transformation/engine.clj
+++ backend/src/akvo/lumen/lib/transformation/engine.clj
@@ -406,9 +406,6 @@
                                     {:transformation-result (:transformation-result (ex-data e))
                                      :transformation        transformation})))))
               data-groups-to-be-created (adapt data-groups-to-be-created data-groups)]
-          (log/error :data-group data-group)
-          (log/error :data-groups data-groups)
-          (log/error :data-groups-to-be-created data-groups-to-be-created)
           (recur (reduce (fn [c dg]
                            (if (= (:id dg) (:id data-group ))
                              (conj c (assoc dg :columns columns))


[#2755] Simplify error message for dataset update

--- backend/src/akvo/lumen/lib/transformation/engine.clj
+++ backend/src/akvo/lumen/lib/transformation/engine.clj
@@ -233,10 +233,19 @@
 (defn apply-transformation-log [conn caddisfly table-name imported-table-name
                                 new-columns old-columns dataset-id job-execution-id
                                 {:keys [transformations version] :as dataset-version}]
-  (db.transformation/update-dataset-version conn {:dataset-id      dataset-id
-                                :version         version
-                                :columns         new-columns
-                                :transformations []})
+  (try
+    (db.transformation/update-dataset-version conn {:dataset-id      dataset-id
+                                                   :version         version
+                                                   :columns         new-columns
+                                                    :transformations []})
+    (catch Exception e
+      (do
+        (log/error e ::db.transformation/update-dataset-version {:dataset-id      dataset-id
+                                                                 :version         version
+                                                                 :columns         new-columns
+                                                                 :transformations []})
+        (throw
+         (ex-info (format "Database problem updating dataset. (%s)" dataset-id) {})))))
   (loop [transformations transformations
          columns         new-columns
          version         (inc version)


post for environments

post for environments

--- test/puppetlabs/puppetdb/http/environments_test.clj
+++ test/puppetlabs/puppetdb/http/environments_test.clj
@@ -5,30 +5,23 @@
             [puppetlabs.puppetdb.scf.storage :as storage]
             [clojure.test :refer :all]
             [puppetlabs.puppetdb.testutils :refer [get-request deftestseq]]
+            [puppetlabs.puppetdb.testutils.http :refer [query-response
+                                                        query-result
+                                                        order-param]]
             [puppetlabs.puppetdb.testutils.nodes :as tu-nodes]))

 (use-fixtures :each fixt/with-test-db fixt/with-http-app)

 (def endpoints [[:v4 "/v4/environments"]])

-;; RETRIEVAL
-
-(defn get-response
-  ([endpoint]
-   (get-response endpoint nil))
-  ([endpoint query]
-   (let [resp (fixt/*app* (get-request endpoint query))]
-     (if (string? (:body resp))
-       resp
-       (update-in resp [:body] slurp)))))
-
 ;; TESTS

 (deftestseq test-all-environments
-  [[version endpoint] endpoints]
+  [[version endpoint] endpoints
+   method [:get :post]]

   (testing "without environments"
-    (is (empty? (json/parse-string (:body (get-response endpoint))))))
+    (is (empty? (query-result method endpoint))))

   (testing "with environments"
     (doseq [env ["foo" "bar" "baz"]]
@@ -39,24 +32,27 @@
        (is (= #{{:name "foo"}
                 {:name "bar"}
                 {:name "baz"}}
-              (set (json/parse-string (:body (get-response endpoint))
-                                      true))))))
+              (query-result method endpoint)))))
+
     (fixt/without-db-var
      (fn []
-       (let [res (get-response endpoint)]
+       (let [res (query-response method endpoint)]
          (is (= #{{:name "foo"}
                   {:name "bar"}
                   {:name "baz"}}
-                (set @(future (json/parse-string (:body res)
-                                                 true))))))))))
+                (set @(future (-> (query-response method endpoint)
+                                  :body
+                                  slurp
+                                  (json/parse-string true)))))))))))

 (deftestseq test-query-environment
-  [[version endpoint] endpoints]
+  [[version endpoint] endpoints
+   method [:get :post]]

   (testing "without environments"
     (fixt/without-db-var
      (fn []
-       (is (= 404 (:status (get-response (str endpoint "/foo"))))))))
+       (is (= 404 (:status (query-response method (str endpoint "/foo"))))))))

   (testing "with environments"
     (doseq [env ["foo" "bar" "baz"]]
@@ -64,18 +60,22 @@
     (fixt/without-db-var
      (fn []
        (is (= {:name "foo"}
-              (json/parse-string (:body (get-response (str endpoint "/foo")))
-                                 true)))))))
+              (-> (query-response method (str endpoint "/foo"))
+                  :body
+                  (json/parse-string true))))))))

 (deftestseq environment-subqueries
-  [[version endpoint] endpoints]
+  [[version endpoint] endpoints
+   method [:get :post]]

   (let [{:keys [web1 web2 db puppet]} (tu-nodes/store-example-nodes)]
     (doseq [env ["foo" "bar" "baz"]]
       (storage/ensure-environment env))

     (are [query expected] (= expected
-                             (-> (:body (get-response endpoint query))
+                             (-> (query-response method endpoint query)
+                                 :body
+                                 slurp
                                  (json/parse-string true)))

          ["in" "name"
@@ -115,8 +115,9 @@
                           [:v4 "/v4/environments/foo/resources"]])

 (deftestseq unknown-parent-handling
-  [[version endpoint] no-parent-endpoints]
+  [[version endpoint] no-parent-endpoints
+   method [:get :post]]

-  (let [{:keys [status body]} (get-response endpoint)]
+  (let [{:keys [status body]} (query-response method endpoint)]
     (is (= status http/status-not-found))
     (is (= {:error "No information is known about environment foo"} (json/parse-string body true)))))


Formatting

Formatting

--- test/clojure/clojurewerkz/cassaforte/async_cql_test.clj
+++ test/clojure/clojurewerkz/cassaforte/async_cql_test.clj
@@ -1,11 +1,11 @@
 (ns clojurewerkz.cassaforte.async-cql-test
   (:refer-clojure :exclude [update])
   (:require [clojurewerkz.cassaforte.test-helper :as th]
-            [clojurewerkz.cassaforte.client :as client]
-            [clojurewerkz.cassaforte.policies :as cp]
-            [clojurewerkz.cassaforte.cql :refer :all]
-            [clojure.test :refer :all]
-            [clojurewerkz.cassaforte.query :refer :all]))
+            [clojurewerkz.cassaforte.client      :as client]
+            [clojurewerkz.cassaforte.policies    :as cp]
+            [clojurewerkz.cassaforte.cql         :refer :all]
+            [clojure.test                        :refer :all]
+            [clojurewerkz.cassaforte.query       :refer :all]))

 (let [s (th/make-test-session)]
   (use-fixtures :each (fn [f]
@@ -93,7 +93,7 @@

   (deftest test-select-async-with-callbacks
     (th/test-combinations
-     (let [r {:name "Alex" :city "Munich" :age (int 19)}
+     (let [r       {:name "Alex" :city "Munich" :age (int 19)}
            success (fn [res]
                      (is (= r (first res)))
                      (truncate s :users))]


fix bind-attr! call typo

fix bind-attr! call typo

--- src-cljs/freactive/dom.cljs
+++ src-cljs/freactive/dom.cljs
@@ -419,7 +419,7 @@
 (defn- rebind-prop-attr! [element attr-name attr-value node-state]
   (unbind-attr!* node-state "attr" attr-name)
   (if attr-value
-    (bind-attr! element attr-name attr-value node-state)
+    (bind-attr! element nil attr-name attr-value node-state)
     (remove-attr! element attr-name)))

 (defn- rebind-attr! [element attr-name attr-value node-state]


Making some changes!

Making some changes!

--- src-cljs/tea_time/core.cljs
+++ src-cljs/tea_time/core.cljs
@@ -138,10 +138,10 @@

 (defn sync-atom-to-event
   [atom target-value]
-    (reset! atom (->
-                  target-value
-                  .-target
-                  .-value)))
+  (reset! atom (->
+                 target-value
+                 .-target
+                 .-value)))

 (def sync-new-tea (partial sync-atom-to-event new-tea))
 (def sync-edit-tea (partial sync-atom-to-event edit-tea))
@@ -149,7 +149,7 @@
 (defn tea-adder
   "A component for the tea-adder form"
   []
-  (fn []
+  (fn []
     [:div.row
      [:div.col-md-12
       [:form {:post "/api/newtea"}
@@ -161,7 +161,7 @@
 (defn tea-edit
   "The edit/delete form component"
   []
-  (fn []
+  (fn []
     [:div.form-group
      [:div.row
       [:div.col-md-12
@@ -180,16 +180,16 @@
 ;; this passes the value of the new tea atom into the post-to-teas-db function

 (defn list-page []
-    [:div.container
-     [:div.row
-      [:div.col-md-12
-       "Here is a list of teas"]]
-     [:div.row {:style {:display "flex" :align-items "flex-end"}}
-      [:div.col-md-6
-       [tealister]]
-      [:div.col-md-6
-       [tea-edit]
-       [tea-adder]]]])
+  [:div.container
+   [:div.row
+    [:div.col-md-12
+     "Here is a list of teas"]]
+   [:div.row {:style {:display "flex" :align-items "flex-end"}}
+    [:div.col-md-6
+     [tealister]]
+    [:div.col-md-6
+     [tea-edit]
+     [tea-adder]]]])

 (def pages
@@ -219,11 +219,11 @@
 ;; must be called after routes have been defined
 (defn hook-browser-navigation! []
   (doto (History.)
-        (events/listen
-          EventType/NAVIGATE
-          (fn [event]
-              (secretary/dispatch! (.-token event))))
-        (.setEnabled true)))
+    (events/listen
+      EventType/NAVIGATE
+      (fn [event]
+        (secretary/dispatch! (.-token event))))
+    (.setEnabled true)))

 ;; -------------------------
 ;; Initialize app


Eat arrow presses to prevent page scrolling

--- src/blue_salamander/keypresses.cljs
+++ src/blue_salamander/keypresses.cljs
@@ -34,6 +34,7 @@
 (defn- process-key-down [keys-pressed-atom key-event]
   (let [key (.-keyCode key-event)]
     (swap! keys-pressed-atom #(conj % key))
+    (.preventDefault key-event)
     #_(js/console.log (str "key down: " key))))

 (defn- process-key-up [keys-pressed-atom key-event]


Split sending options, depending on :host.  Add sendmail support.

--- src/clj/com/draines/postal/core.clj
+++ src/clj/com/draines/postal/core.clj
@@ -3,99 +3,76 @@
         [com.draines.postal.date :only [make-date]])
   (:import [java.util Date Properties]
            [javax.mail Session Transport Message$RecipientType]
-           [javax.mail.internet MimeMessage InternetAddress]
-           [com.sun.mail.smtp SMTPSSLTransport]))
+           [javax.mail.internet MimeMessage InternetAddress]))

-;;  Properties props = new Properties();
-;;  props.put("mail.smtp.host", "my-mail-server");
-;;  props.put("mail.from", "me@example.com");
-;;  Session session = Session.getInstance(props, null);
-;;
-;;  try {
-;;      MimeMessage msg = new MimeMessage(session);
-;;      msg.setFrom();
-;;      msg.setRecipients(Message.RecipientType.TO,
-;;                        "you@example.com");
-;;      msg.setSubject("JavaMail hello world example");
-;;      msg.setSentDate(new Date());
-;;      msg.setText("Hello, world!\n");
-;;      Transport.send(msg);
-;;  } catch (MessagingException mex) {
-;;      System.out.println("send failed, exception: " + mex);
-;;  }
+(defn add-recipient [jmsg rtype addr]
+  (doto jmsg (.addRecipient rtype (InternetAddress. addr))))

-;; Session.getTransport() and Transport.connect()
+(defn add-recipients [jmsg rtype addrs]
+  (if (string? addrs)
+    (add-recipient jmsg rtype addrs)
+    (doseq [addr addrs]
+      (add-recipient jmsg rtype addr)))
+  jmsg)

-(defn get-message [msg]
-  (get msg :MimeMessage msg))
+(defn make-jmessage [msg]
+  (let [{:keys [from to cc bcc date subject body host]} msg
+        props (doto (java.util.Properties.)
+                (.put "mail.smtp.host" (or host "not.provided"))
+                (.put "mail.from" from))
+        session (Session/getInstance props)
+        jmsg (MimeMessage. (:Session msg))]
+    (add-recipients jmsg Message$RecipientType/TO to)
+    (add-recipients jmsg Message$RecipientType/CC cc)
+    (add-recipients jmsg Message$RecipientType/BCC bcc)
+    (.setFrom jmsg (InternetAddress. from))
+    (.setSubject jmsg subject)
+    (.setText jmsg body)
+    (.setSentDate jmsg (or date (make-date)))
+    jmsg))

-(defn get-recipients [msg]
-  (map (comp str
-             #(.getAddress %))
-       (.getAllRecipients (get-message msg))))
+(defn recipients [msg]
+  (let [jmsg (make-jmessage msg)]
+    (map str (.getAllRecipients jmsg))))

-(defn add-recipient [msg rtype addr]
-  (doto (get-message msg) (.addRecipient rtype (InternetAddress. addr))))
+(defn sender [msg]
+  (or (:sender msg) (:from msg)))

-(defn add-recipients [msg rtype addrs]
-  (if (string? addrs)
-    (add-recipient msg rtype addrs)
-    (doseq [addr addrs]
-      (add-recipient msg rtype addr)))
-  msg)
+(defn message->str [msg]
+  (let [out (java.io.ByteArrayOutputStream.)]
+    (.writeTo (make-jmessage msg) out)
+    (str out)))

-(defn set-from [msg from]
-  (.setFrom (get-message msg) (InternetAddress. from)))
+(defn smtp-send [msg]
+  (let [jmsg (make-jmessage msg)]
+    (Transport/send jmsg)))

-(defn set-subject [msg subj]
-  (.setSubject (get-message msg) subj))
+(defn sendmail-send [msg]
+  (let [mail (message->str msg)
+        cmd (concat
+             ["/usr/sbin/sendmail" (format "-f %s" (sender msg))]
+             (recipients msg))
+        pb (ProcessBuilder. cmd)
+        p (.start pb)
+        smtp (java.io.PrintStream. (.getOutputStream p))]
+    (.print smtp mail)
+    (.close smtp)
+    (.waitFor p)
+    (condp = (.exitValue p)
+      0 :success
+      [:error (.exitValue p)])))

-(defn set-body [msg body]
-  (.setText (get-message msg) body))
+(defn send-message [msg]
+  (if (:host msg)
+    (smtp-send msg)
+    (sendmail-send msg)))

-(defn set-date [msg date]
-  (.setSentDate (get-message msg) date))
+(comment
+  (send-message {:from "fee@bar.dom"
+                 :to "Foo Bar <foo@bar.dom>"
+                 :cc ["baz@bar.dom" "quux@bar.dom"]
+                 :date (make-date "yyyy-MM-dd" "2009-01-01")
+                 :subject "Test"
+                 :body "Test!"})

-(defn get-from [msg]
-  (.getFrom (get-message msg)))
-
-(defn get-subject [msg]
-  (.getSubject (get-message msg)))
-
-(defn get-body [msg]
-  (.getContent (get-message msg)))
-
-(defn get-date [msg]
-  (.getSentDate (get-message msg)))
-
-(defn make-message [attrs]
-  (let [{:keys [from to cc bcc date subject body host]} attrs
-        props (doto (java.util.Properties.)
-                (.put "mail.smtp.host" host)
-                (.put "mail.from" from))
-        msg (merge attrs {:Session (Session/getInstance props)})
-        msg (merge msg {:MimeMessage (MimeMessage. (:Session msg))})]
-    (add-recipients msg Message$RecipientType/TO to)
-    (add-recipients msg Message$RecipientType/CC cc)
-    (add-recipients msg Message$RecipientType/BCC bcc)
-    (set-from msg from)
-    (set-subject msg subject)
-    (set-body msg body)
-    (set-date msg date)
-    msg))
-
-(deftest all
-  (let [date (make-date "yyyy-MM-dd" "2009-01-01")
-        msg (make-message {:host "smtp.comcast.net"
-                           :from "fee@bar.dom"
-                           :to "Foo Bar <foo@bar.dom>"
-                           :cc ["baz@bar.dom" "quux@bar.dom"]
-                           :date date
-                           :subject "Test"
-                           :body "Test!"})]
-    (is (= '("foo@bar.dom" "baz@bar.dom" "quux@bar.dom") (get-recipients msg)))
-    (is (= "Test" (get-subject msg)))
-    (is (= "Test!" (get-body msg)))
-    (is (= date (get-date msg)))))
-
-(run-tests)
+)


Make the list of provided hyphenators stateful

And provide some API to reload this list. Also provide some API to
hyphenate against a base line of hyphenators (which is needed for
export).

--- src/clj/hyphen_keeper/hyphenate.clj
+++ src/clj/hyphen_keeper/hyphenate.clj
@@ -1,4 +1,9 @@
 (ns hyphen-keeper.hyphenate
+  "Functionality to hyphenate words for a given spelling.
+
+  The list of provided hyphenators is stateful. After a change of the
+  hyphenation dictionaries in the file system the hyphenators list
+  needs to be reloaded."
   (:require [clojure.java.io :as io]
             [clojure.string :as string])
   (:import ch.sbs.jhyphen.Hyphenator))
@@ -7,22 +12,52 @@
   {0 "/usr/share/hyphen/hyph_de_DE_OLDSPELL.dic"
    1 "/usr/share/hyphen/hyph_de_DE.dic"})

+(def base-hyphen-dictionaries
+  {0 (io/resource "dicts/hyph_de_DE_OLDSPELL.dic")
+   1 (io/resource "dicts/hyph_de_DE.dic")})
+
+(defn- load-hyphenators
+  "Given a map of keys for spelling and paths to hyphenation
+  dictionaries return a map of keys and materialized Hyphenators
+  constructed from the dictionaries in the paths."
+  [dics]
+  (zipmap
+    (keys dics)
+    (map #(new Hyphenator (io/file %)) (vals dics))))
+
 (def hyphenators
-  (zipmap
-   (keys hyphen-dictionaries)
-   (map #(new Hyphenator (io/file %)) (vals hyphen-dictionaries))))
+  "A stateful map of Hyphenators"
+  (atom (load-hyphenators hyphen-dictionaries)))
+
+(def base-hyphenators
+  "The \"base hyphenators\" that use the hyphen tables as they are
+  provided by upstream without the exceptions from the database"
+  (load-hyphenators base-hyphen-dictionaries))
+
+(defn reload!
+  "Reload the hyphenator map. Typically this is needed when the
+  hyphenation dicts are re-generated."
+  []
+  (reset! hyphenators (load-hyphenators)))
+
+(defn- hyphenate*
+  "Hyphenate given `text` using a given `hyphenator`"
+  [text hyphenator]
+  (if (string/blank? text)
+    ""
+    (.hyphenate hyphenator text \- nil)))

 (defn hyphenate
-  "Hyphenate the given `text` for given `spelling` by inserting the
-  given `hyphen` char"
-  ([text spelling]
-   (hyphenate text spelling \-))
-  ([text spelling hyphen]
-   (if (string/blank? text)
-     ""
-     (let [hyphenator
-           (get hyphenators
-                ;; if a valid spelling was provided use it, otherwise
-                ;; just use new spelling
-                (if (contains? hyphen-dictionaries spelling) spelling 1))]
-       (.hyphenate hyphenator text hyphen nil)))))
+  "Hyphenate the given `text` for given `spelling`"
+  [text spelling]
+  (let [default (get @hyphenators 1) ;; new spelling
+        hyphenator (get @hyphenators spelling default)]
+    (hyphenate* text hyphenator)))
+
+(defn hyphenate-against-base
+  "Hyphenate the given `text` for given `spelling` against the base
+  upstream dictionaries which contain no exceptions"
+  [text spelling]
+  (let [default (get base-hyphenators 1) ;; new spelling
+        hyphenator (get base-hyphenators spelling default)]
+    (hyphenate* text hyphenator)))


add user-faces in emacs theme export and refactor

--- src/cljs/koeeoadi/themebuilder.cljs
+++ src/cljs/koeeoadi/themebuilder.cljs
@@ -1,6 +1,5 @@
 (ns koeeoadi.themebuilder
   (:require [koeeoadi.reconciler :refer [reconciler]]
-            [cljs.pprint :as pprint]
             [cljs.reader :as reader]))

 (defn face-to-emacs [face-name]
@@ -9,54 +8,18 @@
         :else
         (str "font-lock-" face-name "-face")))

-(defn emacs-theme [name faces-by-name colors-by-id]
-  (let [doc    (pr-str "A theme created with Koeeoadi")
-        bg-rgb (pr-str (let [[_ color-id] (get-in faces-by-name ["background" :face/color])]
-                         (get-in colors-by-id [color-id :color/rgb])))]
-    (letfn [(spec
-              ([face-name]
-               (spec face-name :foreground))
+(defn emacs-theme [face-specs]
+  (let [rec           @reconciler
+        name           (:theme/name rec)
+        name-sym       (reader/read-string name)
+        name-sym-quote (reader/read-string (str "'" name))
+        doc      "A theme created with Koeeoadi"]
+    `(~'progn
+      (~'deftheme ~name-sym ~doc)
+      (~'put ~name-sym-quote (~'quote ~'theme-immediate) ~'t)
+      (~'custom-theme-set-faces ~name-sym-quote ~@face-specs)
+      (~'provide-theme ~name-sym-quote))))

-              ([face-name property]
-               (let [face-name-emacs (face-to-emacs face-name)
-                     face            (get faces-by-name face-name)
-                     fg-color-id     (last (:face/color-fg face))
-                     bg-color-id     (last (:face/color-bg face))
-                     fg-rgb          (pr-str (get-in colors-by-id [fg-color-id :color/rgb]))
-                     bg-rgb          (pr-str (get-in colors-by-id [bg-color-id :color/rgb]))]
-                 ;; TODO This is gross because cljs doesn't support interning
-                 ;; Need to cleanup
-                 (if (= face-name "default")
-                   `(~'read ~(str
-                               "(default  ((t (:foreground " fg-rgb " :background " bg-rgb ")))))"))
-                   `(~'read ~(str
-                               "(" face-name-emacs " ((t (" property " " fg-rgb "))))"))))))]
-
-      `(~'progn
-        (~'eval (~'read ~(str "(deftheme " name " " doc ")")))
-        ;;(~'eval (~'deftheme ~name ~doc))
-        ;; adds someproperties to that theme
-        (~'put (~'read ~(str name)) (quote ~'theme-immediate) ~'t)
-        ;; executes in color scope
-        (~'custom-theme-set-faces (~'read ~(str name))
-         ~(spec "default")
-         ~(spec "builtin")
-         ~(spec "comment-delimiter")
-         ~(spec "comment")
-         ~(spec "constant")
-         ~(spec "doc")
-         ~(spec "doc-string")
-         ~(spec "function-name")
-         ~(spec "keyword")
-         ~(spec "negation-char")
-         ~(spec "preprocessor")
-         ~(spec "string")
-         ~(spec "type")
-         ~(spec "variable-name")
-         (~'provide-theme (~'read ~(str name))))))))
-
-
-;;'(font-lock-warning-face ((t (:foreground "yellow" :background ... :italic ... :weight ... ))))
 (defn font-lock-faceify [[face-name props :as pair]]
   (let [face-name' (str "font-lock-" face-name "-face")]
     (if (= face-name "default")
@@ -77,7 +40,7 @@
 (defn xform-face-emacs [{:keys [face/name] :as face}]
   ;; TODO could use transducers here to optimize
   (let [plist (filter identity (map xform-prop-emacs face))]
-    `(~(reader/read-string name) ((~'t ~(flatten plist))))))
+    (reader/read-string (str "'" (pr-str `(~(reader/read-string name) ((~'t ~(flatten plist)))))))))

 (defn xform-faces-emacs [default-faces-map user-faces-map]
   (let [default-faces-map' (into {} (map font-lock-faceify default-faces-map))
@@ -92,18 +55,13 @@
                             ;; combine with the user defined emacs faces
                             (concat (filter #(= :emacs (:face/editor %)) (vals user-faces-map)))))))

-;; (pprint/pprint (xform-default-faces-emacs (:faces/by-name @reconciler) (:user-faces/by-name @reconciler)))
-
 ;; TODO use a multimethod here
 (defn build-emacs []
   (let [{current-theme      :theme/name
          faces-by-name      :faces/by-name
          user-faces-by-name :user-faces/by-name} @reconciler
-
-        user-faces-by-name'  (collect-user-faces-emacs user-faces-by-name)
-        xformed-faces-list   (xform-faces-emacs (merge user-faces-by-name faces-by-name))]
-    (pr-str (emacs-theme current-theme faces-by-name' colors-by-id))))
-
+        face-specs   (xform-faces-emacs faces-by-name user-faces-by-name)]
+    (emacs-theme face-specs)))

 (defn build-vim []
   "stub")


changed scheduling order

changed scheduling order

--- src/crawler/rich_char_extractor.clj
+++ src/crawler/rich_char_extractor.clj
@@ -107,8 +107,7 @@
                                                                    '()
                                                                    info)]
                                         {:xpath potential-xpath
-                                         :score (/ potential-score
-                                                   (count potential-hrefs-texts))
+                                         :score (count potential-hrefs-texts)
                                          :hrefs-and-texts potential-hrefs-texts}))
                                     xpaths-anchors-chars))]


Describe what a locality's summary looks like

--- test/vip/data_processor/validation/v5/locality_test.clj
+++ test/vip/data_processor/validation/v5/locality_test.clj
@@ -82,14 +82,49 @@
                            first)]
         (is (= 3 (:count localities)))))

-    (testing "a locality element can have a number of errors"
+    (testing "a locality has some basic info"
+      (let [localities (-> (korma/select psql/v5-dashboard-localities
+                             (korma/fields :name :type :id)
+                             (korma/where {:results_id results-id})))]
+        (is (= #{{:name "Salida"
+                  :type "city"
+                  :id "loc3"}
+                 {:name "Nathrop"
+                  :type "ghost town"
+                  :id "loc2"}
+                 {:name "Buena Vista"
+                  :type "town"
+                  :id "loc1"}}
+               (set localities)))))
+
+    (testing "in a locality, we count elements, their errors, and success rates"
       (let [salida (-> (korma/select psql/v5-dashboard-localities
                          (korma/where {:id "loc3" :results_id results-id}))
                        first)]
-        (is (= (:type salida) "city"))
-        (is (= (:street_segment_errors salida) 1))
-        (is (= (:voter_service_errors salida) 1))
-        (is (= (:hours_open_errors salida) 2))
-        (is (= (:department_errors salida) 0))
-        (is (= (:election_administration_errors salida) 0))
-        (is (= (:polling_location_errors salida) 0))))))
+        (is (= {:id "loc3"
+                :name "Salida"
+                :type "city"
+                :error_count 4
+                :precinct_errors 0
+                :precinct_count 1
+                :precinct_completion 100
+                :polling_location_errors 0
+                :polling_location_count 2
+                :polling_location_completion 100
+                :street_segment_errors 1
+                :street_segment_count 3
+                :street_segment_completion 66
+                :hours_open_errors 2
+                :hours_open_count 1
+                :hours_open_completion 0
+                :election_administration_errors 0
+                :election_administration_count 1
+                :election_administration_completion 100
+                :department_errors 0
+                :department_count 4
+                :department_completion 100
+                :voter_service_errors 1
+                :voter_service_count 1
+                :voter_service_completion 0
+                :results_id results-id}
+               salida))))))


Fix typo.

Fix typo.

--- test/com/nomistech/clojure_the_language/core_async_101_basics.clj
+++ test/com/nomistech/clojure_the_language/core_async_101_basics.clj
@@ -137,7 +137,7 @@

   ;; We can create a background thread with alts that combines inputs on
   ;; either of two channels. `alts!!` takes either a set of operations
-  ;; to perform - either a channel to take from a [channel value] to put
+  ;; to perform - either a channel to take from or a [channel value] to put
   ;; and returns the value (nil for put) and channel that succeeded:

   (let [c1 (chan)


Add debug output

Add debug output

--- src/puppeteer/infra/client/container_builder.clj
+++ src/puppeteer/infra/client/container_builder.clj
@@ -11,6 +11,7 @@

 (defn create-build
   [{:keys [project-id client access-token] :as comp} build]
+  (println access-token)
   (-> client
       .projects
       .builds


doc(handler): add refact TODO's and comments

--- clojure/compojure-bot/src/compojure_bot/facebook.clj
+++ clojure/compojure-bot/src/compojure_bot/facebook.clj
@@ -12,15 +12,26 @@
       {:status 200 :body (params "hub.challenge")}
       {:status 403})))

-(defn onMessage [event]
+; Process Received Message Event by Facebook
+(defn receivedMessage [event]
+  (println "Messaging Event:")
+  (println event)
   (let [senderID (get-in event [:sender :id]) recipientID (get-in event [:recipient :id]) timeOfMessage (get-in event [:timestamp]) message (get-in event [:message])]
     (println (str "Received message for user " senderID " and page " recipientID " at " timeOfMessage " with message:"))
     (println message)
-    ; Add rules here
+    ; TODO: Check for text (onText ?), attachments (onAttachments ?)
+    ; or quick_reply (onQuickReply) in :message tree here
+    ; TODO: Simplify function to send a message vs.
+    ; (msg/sendTextMessage (receivedMessage messagingEvent))
     (cond
-      (s/includes? (s/lower-case (:text message)) "help") [senderID "Hi there, happy to help :)"]
-      (s/includes? (s/lower-case (:text message)) "image") [senderID "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/1280px-M101_hires_STScI-PRC2006-10a.jpg"]
-      :else [senderID (:text message)])))
+      ; Check for :text
+      ; TODO: move to separate handler
+      (s/includes? (s/lower-case (:text message)) "help") (msg/sendTextMessage [senderID "Hi there, happy to help :)"])
+      (s/includes? (s/lower-case (:text message)) "image") (msg/sendImageMessage [senderID "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/1280px-M101_hires_STScI-PRC2006-10a.jpg"])
+      ; Check for :attachments
+      (contains? message :attachments) (msg/sendTextMessage [senderID "Message with attachment received"])
+      ; If no rules apply echo the user's text input
+      :else (msg/sendTextMessage [senderID (:text message)]))))

 (defn route-request [request]
   (let [data (get-in request [:params])]
@@ -29,6 +40,7 @@
     (when (= (:object data) "page")
       (doseq [pageEntry (:entry data)]
         (doseq [messagingEvent (:messaging pageEntry)]
-          ; Check for text or attachments here
-          (cond (contains? messagingEvent :message) (msg/sendTextMessage (onMessage messagingEvent))
-            :else (println (str "Webhook received unknown messagingEvent: " messagingEvent))))))))
+          ; Check for message (onMessage) or postback (onPostback) here
+          (cond (contains? messagingEvent :message) (receivedMessage messagingEvent)
+                (contains? messagingEvent :postback) (msg/sendTextMessage (receivedMessage messagingEvent))
+                :else (println (str "Webhook received unknown messagingEvent: " messagingEvent))))))))


When filestore bucket is created, set CORS policy

--- src/kixi/datastore/filestore/s3.clj
+++ src/kixi/datastore/filestore/s3.clj
@@ -17,8 +17,10 @@
 (defn ensure-bucket
   [creds bucket]
   (when-not (s3/does-bucket-exist creds bucket)
-    (s3/create-bucket creds bucket)))
-
+    (let [rules [{:max-age-seconds 3000 :allowed-origins ["*"] :allowed-methods [:PUT] :exposed-headers ["etag"] :allowed-headers ["*"]}
+                 {:max-age-seconds 3000 :allowed-origins ["*"] :allowed-methods [:GET] :allowed-headers ["*"]}]]
+      (s3/create-bucket creds bucket)
+      (s3/set-bucket-cross-origin-configuration creds bucket {:rules rules}))))

 (defn init-multi-part-upload-creator
   [creds bucket]


:bug: Add missing demo service in initialization.

--- backend/src/uxbox/services/init.clj
+++ backend/src/uxbox/services/init.clj
@@ -24,6 +24,7 @@

 (defn- load-mutation-services
   []
+  (require 'uxbox.services.mutations.demo)
   (require 'uxbox.services.mutations.icons)
   (require 'uxbox.services.mutations.images)
   (require 'uxbox.services.mutations.projects)


Compute subexpressions

Compute subexpressions

--- src/bluebell/utils/core.clj
+++ src/bluebell/utils/core.clj
@@ -390,12 +390,25 @@

 (def default-subexpr-cfg (merge default-traverse-cfg {:visit identity}))

-(defn add-subexpressions [result lookup k]
-  (assoc result k true))
+(defn insert-subexpr [result p k]
+  (update result p (fn [x] (conj (or x #{}) k))))
+
+(defn add-subexpression-to-parents-of [result lookup p k]
+  (if (= p ::parent)
+    result
+    (let [parents (keys (get-in lookup [p :parents]))]
+      (reduce
+       (fn [r x]
+         (add-subexpression-to-parents-of r lookup x k))
+       (insert-subexpr result p k)
+       parents))))
+
+(defn add-subexpression [result lookup k]
+  (add-subexpression-to-parents-of result lookup k k))

 (defn compute-subexpressions-sub [analyzed]
   (reduce (fn [r k]
-            (add-subexpressions r analyzed k))
+            (add-subexpression r analyzed k))
           {}
           (keys analyzed)))


changed users-in-group into a reaction

changed users-in-group into a reaction

--- src/braid/common/state.cljs
+++ src/braid/common/state.cljs
@@ -80,10 +80,12 @@
                                       @current-group-id))))))]
       (reaction open-threads)))

-
-(defn- users-in-group
-  [group-id state]
-  (filter (fn [u] (contains? (set (u :group-ids)) group-id)) (vals (state :users))))
+(defn get-users-in-group
+  [state [_ group-id]]
+  (reaction
+    (->> (state :users)
+         vals
+         (filter (fn [u] (contains? (set (u :group-ids)) group-id))))))

 (defn get-open-group-id
   [state _]
@@ -91,7 +93,7 @@

 (defn get-users-in-open-group
   [state _]
-  (reaction (users-in-group (@state :open-group-id) @state)))
+  (reaction @(get-users-in-group @state [nil (@state :open-group-id)])))

 (defn get-user-id
   [state _]


Avoid a name clash with core/newline

Avoid a name clash with core/newline

--- src/catalog/layout/text.clj
+++ src/catalog/layout/text.clj
@@ -10,8 +10,8 @@
              [walk :as walk]]
             [endophile.core :as endophile]))

-(def ^:private newline "\r\n")
-(def ^:private double-newline (str newline newline))
+(def ^:private dos-newline "\r\n")
+(def ^:private double-newline (str dos-newline dos-newline))

 (defmulti to-text (fn [{:keys [tag attrs content]}] tag))

@@ -22,7 +22,7 @@
 (defmethod to-text :h3 [{content :content}] (str  content double-newline))
 (defmethod to-text :ul [{content :content}] [:list {:type "ul"} content])
 (defmethod to-text :li [{content :content}] [:li content])
-(defmethod to-text :br [_] newline)
+(defmethod to-text :br [_] dos-newline)
 (defmethod to-text :default [{content :content}] content) ; just assume :p

 (defn- node? [node]
@@ -45,7 +45,7 @@

 (defn wrap-line [text]
   ;; see http://rosettacode.org/wiki/Word_wrap#Clojure
-  (string/join newline (re-seq (re-pattern (str ".{1," line-length "}(?:\\s|\\z)")) text)))
+  (string/join dos-newline (re-seq (re-pattern (str ".{1," line-length "}(?:\\s|\\z)")) text)))

 (defn- entry-heading-str
   [{:keys [creator title subtitles name-of-part source-publisher source-date]}]
@@ -95,7 +95,7 @@
 (defn- join [& more]
   (->> more
    (remove empty-or-blank?)
-   (string/join newline)))
+   (string/join dos-newline)))

 (defmethod entry-str :braille
   [{:keys [creator title subtitles name-of-part source-publisher
@@ -220,7 +220,7 @@
 (defn- impressum []
   (let [creator (layout/translations :sbs)]
     (string/join
-     newline
+     dos-newline
      ["Herausgeber:"
       creator
       "Grubenstrasse 12"


remove unused imports

remove unused imports

--- src/chessground/common.cljs
+++ src/chessground/common.cljs
@@ -1,8 +1,5 @@
 (ns chessground.common
-  "Shared utilities for the library"
-  (:require [cljs.core.async :as a]
-            [chessground.klass :as klass])
-  (:require-macros [cljs.core.async.macros :as am]))
+  "Shared utilities for the library")

 (enable-console-print!)


Init board

Init board

--- src/cljs/triboard/core.cljs
+++ src/cljs/triboard/core.cljs
@@ -57,7 +57,7 @@
 ;; -----------------------------------------

 (defn rect-cell
-  [x y color & options]
+  [x y color options]
   [:rect
    (merge
      {:width 0.9
@@ -65,14 +65,13 @@
       :x (+ 0.05 x)
       :y (+ 0.05 y)
       :fill color}
-     #_(into {} options)
-     )
+     options)
    ])

 (defn empty-cell
   [x y]
   (rect-cell x y "lightgray"
-    :on-click #(js/alert (str "Got click on " [x y]))
+    {:on-click #(prn [x y])}
     ))

 (defn greeting []


removed some old notes

removed some old notes

--- src/flax/main.clj
+++ src/flax/main.clj
@@ -118,20 +118,6 @@
 (defn assoc-flags
   [c m]
   (merge c (select-keys m [:throw :skip])))
-
-
-;;(defn do-groups
-;;  [fun m c]
-;;  (let [groups (-> m :groups)]
-;;    ;; run all groups sequentially
-;;    (doall (for [group groups]
-;;      (let [c (assoc-flags c group)]
-;;        ;; run all x in (:group group) in parallel, passing x and the config object as args
-;;        ;; TODO map for now, pmap or core.async later
-;;        (doall (map #(apply fun %)
-;;                    (map (fn [x] [x c])
-;;                         (:group group))))
-;;        )))))

 (defn do-groups
@@ -208,13 +194,6 @@
         ;; for each checkpoint.
         report (run-module module (assoc-flags config patch))]
     ;; here we want to deal with each patch, determining whether it should be isolated or not.
-    ;; If so, then the clusters it should use should be a snapshot of the current clusters. It should, in effect,
-    ;; branch away from the current clusters as if it were its own path. And the way to do this is to have every clone/snapshot/whatever
-    ;; have its own name. With ctool this is going to be awful. But with lxc, we can really make this awesome. But what exactly
-    ;; needs to happen? We need to have a list of clusters at any particular point (that follows this path) and when you come across
-    ;; a directive to isolate it, you have to clone all of these clusters before running any concurrent tests.
-    ;;(doseq [patch (-> p :next)]
-    ;;  (run-patch patch dc cc))
     ))


Update dep to hyde 1.1-SNAPSHOT

Update dep to hyde 1.1-SNAPSHOT

--- hyde-pallet-core/project.clj
+++ hyde-pallet-core/project.clj
@@ -5,4 +5,4 @@
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :plugins [[lein-modules "0.3.1"]]
   :dependencies [[org.clojure/clojure "1.6.0"]
-                 [com.palletops/hyde "0.1.0"]])
+                 [com.palletops/hyde "0.1.1-SNAPSHOT"]])


use full component to query remote

use full component to query remote

--- src/cljs/daveconservatoire/site/ui/exercises.cljs
+++ src/cljs/daveconservatoire/site/ui/exercises.cljs
@@ -72,12 +72,12 @@

 (defn play-sound [c] (play-notes (-> (om/props c) ::notes)))

-(def ModelIdent
-  (reify
-    om/Ident
-    (ident [_ props] (u/model-ident props))))
-
-(defn with-ident [query] (with-meta query {:component ModelIdent}))
+(om/defui UserScore
+  static om/IQuery
+  (query [_] [:db/table :db/id :user/score])
+
+  static om/Ident
+  (ident [_ props] (u/model-ident props)))

 (defmethod um/mutate 'dcex/check-answer
   [{:keys [state ref]} _ _]
@@ -143,7 +143,7 @@
           [opt-type _] (s/conform ::options options)
           check-answer #(do
                          (om/transact! this `[(dcex/check-answer)
-                                              (untangled/load {:query [{:app/me ~(with-ident [:db/table :db/id :user/score])}] :marker false})]))]
+                                              (untangled/load {:query [{:app/me ~(om/get-query UserScore)}] :marker false})]))]
       (s/assert ::ex-props props)
       (dom/div #js {:className "lesson-content"}
         (dom/div #js {:className "single-exercise visited-no-recolor"


add mobile menu foldout

add mobile menu foldout

--- src/cljs/daveconservatoire/site/ui/exercises.cljs
+++ src/cljs/daveconservatoire/site/ui/exercises.cljs
@@ -668,22 +668,38 @@
 (defmethod slug->exercise "pitch-1" [name]
   {::name  name
    ::class PitchDetection
-   ::props {::variation [12 ".." 24]}})
+   ::props {::variation [12 ".." 24]}
+   ::hints (fn [props]
+     ["Pitch is the sensation of a note being higher or lower"
+      "Does the second note sound higher or lower than the first?"
+      (str "The second note is " (answer-label props))])})

 (defmethod slug->exercise "pitch-2" [name]
   {::name  name
    ::class PitchDetection
-   ::props {::variation [8 ".." 16]}})
+   ::props {::variation [8 ".." 16]}
+   ::hints (fn [props]
+             ["Here the distance in pitch is getting smaller, but the same idea applies."
+              "Does the second note sound higher or lower than the first?"
+              (str "The second note is " (answer-label props))])})

 (defmethod slug->exercise "pitch-3" [name]
   {::name  name
    ::class PitchDetection
-   ::props {::variation [1 ".." 9]}})
+   ::props {::variation [1 ".." 9]}
+   ::hints (fn [props]
+             ["Even smaller steps in pitch now."
+              "Sometimes the eyebrows test is a good approach. Does the second note make your eyebrows want to go up or down?  I'm not joking!"
+              (str "The second note is " (answer-label props))])})

 (defmethod slug->exercise "identifying-octaves" [name]
   {::name  name
    ::class IdentifyOctaves
-   ::props {}})
+   ::props {}
+   ::hints (fn [props]
+             ["An octave is a very special sound in music.  What does it sound like?"
+              "An octave sounds like two flavours of the same sound.  Is that the case here?"
+              (str "Are these notes an octave apart? " (answer-label props) ".")])})

 (defmethod slug->exercise "treble-clef-reading" [name]
   {::name  name


Clean up logging calls in corr mat compute


cleanup

cleanup

git-svn-id: 03a8048b5ee8463be5048a3801110fb50f378627@7351 d0ab736e-dc22-4aeb-8dc9-08def0aa14fd

--- acqEngine/src/org/micromanager/acq_engine.clj
+++ acqEngine/src/org/micromanager/acq_engine.clj
@@ -296,99 +296,12 @@
     (core enableContinuousFocus true))
   (return-config))

-;; alternative iterations
-
-(defn allowed-image? [f c s]
-  (if-let [channel (get-in @settings [:channels c])]
-    (and
-      (let [skip-n (channel :skip-frames)]
-        (zero? (mod f (inc skip-n))))
-      (or
-        (channel :use-z-stack)
-        (= s (int (/ (count (@settings :slices)) 2)))))
-    true))
-
-(defn manage-shutter [p f c s]
-  (let [[p_ f_ c_ s_] (:last-indices @state)]
-    (when (or
-            (and
-              (not (:keep-shutter-open-channels @settings))
-              (not= c c_))
-            (and
-              (not (:keep-shutter-open-slices @settings))
-              (not= s s_))
-            (not= f f_)
-            (not= p p_))
-      (core setShutterOpen false))))
-
-(defn set-position [p]
-  (let [msp (get-in @settings [:positions p])
-        m (MultiStagePosition-to-map msp)]
-    (for [[axis pos] (:axes m) :when pos]
-      [axis (apply set-stage-position axis pos)])))
-
-(defn set-channel [c]
-  (for [[d p v] (get-in @settings [:channels c :properties])]
-    (core setProperty d p v)))
-
-(defn collect-prev-image []
-  (let [pix (core getImage)]
-    (:last-indices @state)))
-
-(defn acq-wait [f]
-  (let [[_ f_ _ _] (:last-indices @state)]
-    (if (and (not= f f_) (pos? f))
-      (acq-sleep (@settings :interval-ms)))))
-
-(defn manage-autofocus [f]
-  (when (@settings :use-autofocus)
-    (let [[_ f_ _ _] (:last-indices @state)]
-      (when (and
-              (not= f f_)
-              (zero? (mod f (inc (@settings :autofocus-skip)))))
-        (run-autofocus)))))
-
-(defn set-slice [c s]
-  (if-let [z-drive (@settings :z-drive)]
-    (let [[_ _ c_ s_] (:last-indices @state)
-          z (+ (or (get-in @settings [:channels c :z-offset]) 0)
-               (or (get-in @settings [:slices s]) 0))]
-         (if (@settings :relative-slices)
-           (let [delta-z (- z (:last-relative-slice @state))]
-               (core setRelativePosition z-drive delta-z)
-               (swap! state assoc :last-relative-slice z))
-           (core setPosition z-drive z)))))
-
-(defn snap-single-image [p f c s]
-  (core snapImage)
-  (swap! state assoc :last-snap-time (elapsed-time @state)))
-
-(defn run-snap-event
-  "Run a single iteration with the specified indices:
-  position, frame, channel, slice."
-  [p f c s]
-  (when (allowed-image? f c s)
-    (manage-shutter p f c s)
-    (set-position p)
-    (set-channel c)
-    (collect-prev-image)
-    (acq-wait f)
-    (manage-autofocus f)
-    (set-slice s)
-    (snap-single-image p f c s)
-    (swap! state assoc :last-indices [p f c s])))
-
-
-
 ;; iterations

 (defn create-presnap-actions [event]
   (concat
     (for [[axis pos] (:axes (MultiStagePosition-to-map (get-msp (:position event)))) :when pos]
-      [axis #(do ;(when (= axis (core getFocusDevice))
-                 ;  (println "setting reference z position from msp")
-                 ;  (state-assoc! :reference-z-position pos))
-                 (apply set-stage-position axis pos))])
+      [axis #(apply set-stage-position axis pos)])
     (for [[d p v] (get-in event [:channel :properties])]
       [d #(core setProperty d p v)])
     (when-let [exposure (:exposure event)]
@@ -433,12 +346,12 @@
   (prepare-state this)
   (binding [state (.state this)]
     (def last-state state)
-    (let [acq-seq (generate-acq-sequence settings @attached-runnables)]
-       (def acq-sequence acq-seq)
-       (time (count acq-seq))
-       (execute (mapcat #(make-event-fns % out-queue) acq-seq))
-       (.put out-queue TaggedImageQueue/POISON)
-       (cleanup))))
+      (let [acq-seq (generate-acq-sequence settings @attached-runnables)]
+        (def acq-sequence acq-seq)
+        (time (count acq-seq))
+        (execute (mapcat #(make-event-fns % out-queue) acq-seq))
+        (.put out-queue TaggedImageQueue/POISON)
+        (cleanup))))

 ;; generic metadata


Button adds variable, doesn't save list

Button adds variable, doesn't save list

--- src-cljs/frontend/components/project_settings.cljs
+++ src-cljs/frontend/components/project_settings.cljs
@@ -452,7 +452,7 @@
                  [:input.btn.btn-primary {:data-failed-text "Failed",
                                           :data-success-text "Added",
                                           :data-loading-text "Adding...",
-                                          :value "Save variables",
+                                          :value "Add Variable",
                                           :type "submit"
                                           :on-click #(raise! owner [:created-env-var {:project-id project-id}])}])]]
              (when-let [env-vars (seq (:envvars project-data))]


:metal::joy_cat::metal:

--- src/puns/core.clj
+++ src/puns/core.clj
@@ -1,10 +1,11 @@
 (ns puns.core
   "punXcore"
   {:author "Eric Bailey"}
-  (:require [compojure.core :refer [GET POST defroutes]]
+  (:require [clojure.string :refer [join]]
+            [compojure.core :refer [GET POST defroutes]]
             [compojure.route :as route]
             [org.httpkit.server :refer [run-server]]
-            [puns.greyt :refer [pen-pun]]
+            [puns.greyt :refer [detokenize pen-pun tokenize]]
             [puns.html :as html]
             [puns.css :as css]
             [ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
@@ -18,7 +19,11 @@
     {:content-type "text/css"
      :body (css/styles)})
   (POST "/" {{q :q} :params}
-    (pen-pun q))
+    (->> (tokenize q)
+         (map pen-pun)
+         (map (fn [pun] (if (vector? pun) (join " " pun) pun)))
+         (detokenize)
+         (html/main-page)))
   (route/resources "/"))

 (defonce ^:private server (atom nil))


CMR-3680 fixes typo

CMR-3680 fixes typo

--- umm-spec-lib/src/cmr/umm_spec/test/echo10_expected_conversion.clj
+++ umm-spec-lib/src/cmr/umm_spec/test/echo10_expected_conversion.clj
@@ -85,7 +85,7 @@
         (assoc-in [:GetService :DataID] su/not-provided)
         (assoc-in [:GetService :DataType] su/not-provided)
         (assoc-in [:GetService :FullName] su/not-provided))
-    (dissoc related-rul :GetService)))
+    (dissoc related-url :GetService)))

 (defn- expected-echo10-related-urls
  [related-urls]


resettable summaries for tags

resettable summaries for tags

--- src/ontrail/sportsummary.clj
+++ src/ontrail/sportsummary.clj
@@ -94,5 +94,6 @@
   nil)

 (defn reset-memo-for [user]
-  (dosync (alter summary-memos dissoc user))
+  (dosync (alter summary-memos dissoc {:u user :f get-overall-summary-cond}))
+  (dosync (alter summary-memos dissoc {:u user :f get-overall-tags-cond}))
   (future (memoizes-after-reset user)))


Fix performance regression caused by boxed math.

--- src/onyx/peer/read_batch.clj
+++ src/onyx/peer/read_batch.clj
@@ -28,18 +28,19 @@
      (LockSupport/parkNanos (* 2 1000000))
      (advance state))))

-(defn read-input-batch [state batch-size batch-timeout-ns]
+(defn read-input-batch [state batch-size ^long batch-timeout-ns]
   (let [pipeline (get-input-pipeline state)
         event (get-event state)
+        outgoing (transient [])
         end-time (+ (System/nanoTime) batch-timeout-ns)
-        outgoing (transient [])
-        _ (loop [remaining (- end-time (System/nanoTime))]
+        _ (loop [remaining batch-timeout-ns]
             (when (and (< (count outgoing) batch-size)
                        (pos? remaining))
-              (let [segment (p/poll! pipeline event (long (ns->ms remaining)))]
+              (let [remaining-ms (unchecked-divide-int remaining 1000000)
+                    segment (p/poll! pipeline event remaining-ms)]
                 (when-not (nil? segment)
                   (conj! outgoing segment)
-                  (recur (- end-time (System/nanoTime)))))))
+                  (recur (int (unchecked-subtract end-time (System/nanoTime))))))))
         batch (persistent! outgoing)]
     (-> state
         (set-event! (assoc event :onyx.core/batch batch))


Remove prn.

Remove prn.

--- src/open_company/lib/bot.clj
+++ src/open_company/lib/bot.clj
@@ -42,7 +42,6 @@

 (defn send-trigger! [trigger]
   (s/validate BotTrigger trigger)
-  (prn trigger)
   (sqs/send-message
    {:access-key c/aws-access-key-id
     :secret-key c/aws-secret-access-key}


Compile fails under compojure 1.1.6. Roll back to 1.1.5.

--- http-kit/hello/project.clj
+++ http-kit/hello/project.clj
@@ -2,7 +2,7 @@
   :description "JSON/Database tests"
   :url "http://example.com/FIXME"
   :dependencies [[org.clojure/clojure "1.5.1"]
-                 [compojure "1.1.6"]
+                 [compojure "1.1.5"]
                  [ring/ring-json "0.2.0"]
                  [org.clojure/tools.cli "0.2.1"]
                  [http-kit/dbcp "0.1.0"]


[CS WR] add load-elections to csv-validations pipeline

--- src/vip/data_processor/validation/transforms.clj
+++ src/vip/data_processor/validation/transforms.clj
@@ -26,7 +26,8 @@
   [(fn [ctx] (assoc ctx :stop "This is an XML feed"))])

 (def csv-validations
-  [csv/remove-bad-filenames])
+  [csv/remove-bad-filenames
+   csv/load-elections])

 (defn xml-csv-branch [ctx]
   (let [file-extensions (->> ctx


removes a println

removes a println

--- scheduler/test/cook/test/mesos/sandbox.clj
+++ scheduler/test/cook/test/mesos/sandbox.clj
@@ -360,7 +360,6 @@
 (deftest test-prepare-sandbox-publisher
   (with-redefs [sandbox/retrieve-sandbox-directories-on-agent
                 (fn [_ hostname]
-                  (println "retrieve-sandbox-directories-on-agent:" hostname)
                   {(str "task." hostname) (str "/path/to/" hostname "/sandbox")})]
     (let [db-conn (tu/restore-fresh-database! "datomic:mem://test-start-sandbox-publisher")
           publish-batch-size 20


(PDB-3067) Log at debug when command is enqueued

When a command is placed on the queue, log its ID, command name, and
certname at the debug level, similar to the logging after the command is
processed.

--- src/puppetlabs/puppetdb/command.clj
+++ src/puppetlabs/puppetdb/command.clj
@@ -122,9 +122,12 @@
   (try
     (.acquire write-semaphore)
     (time! (get @metrics :message-persistence-time)
-           (async/>!! command-chan
-                      (queue/store-command
-                        q command version certname command-stream command-callback)))
+           (let [cmd (queue/store-command
+                       q command version certname command-stream command-callback)
+                 {:keys [id received]} cmd]
+             (async/>!! command-chan cmd)
+             (log/debugf (i18n/trs "[%s-%d] '%s' command enqueued for %s")
+                         id (tcoerce/to-long received) command certname)))
     (finally
       (.release write-semaphore)
       (when command-stream


Add optional pretty parameter to application/edn

--- src/yada/representation.clj
+++ src/yada/representation.clj
@@ -3,6 +3,7 @@
 (ns yada.representation
   (:require
    [clojure.tools.logging :refer :all]
+   [clojure.pprint :refer (pprint)]
    [byte-streams :as bs]
    [cheshire.core :as json]
    [clojure.java.io :as io]
@@ -143,12 +144,18 @@
 ;; application/edn

 (defmethod render-map "application/edn"
-  [m _]
-  (prn-str m))
+  [m representation]
+  (let [pretty (get-in representation [:content-type :parameters "pretty"])]
+    (if pretty
+      (with-out-str (pprint m))
+      (prn-str m))))

 (defmethod render-seq "application/edn"
-  [s _]
-  (prn-str s))
+  [s representation]
+  (let [pretty (get-in representation [:content-type :parameters "pretty"])]
+    (if pretty
+      (with-out-str (pprint s))
+      (prn-str s))))

 ;; text/event-stream


fix types given to union

fix types given to union

--- sidecar/src/figwheel_sidecar/core.clj
+++ sidecar/src/figwheel_sidecar/core.clj
@@ -289,10 +289,11 @@
   (vec (sort topo-compare ns-syms)))

 (defn mark-changed-ns [state ns-syms]
-  (mapv (fn [nm]
-          (vary-meta nm assoc :file-changed-on-disk
-                     (if (target-file-changed? state nm) true false)))
-        ns-syms))
+  (set
+   (mapv (fn [nm]
+           (vary-meta nm assoc :file-changed-on-disk
+                      (if (target-file-changed? state nm) true false)))
+         ns-syms)))

 (defn find-figwheel-always []
   (set (filter (fn [n] (-> n meta :figwheel-always)) (ana-api/all-ns))))
@@ -302,8 +303,8 @@
     (nil? cljs.env/*compiler*) changed-ns-syms'
     (false? (:recompile-dependents state))
     (topo-sort
-     (union (keep (fn [n] (:name (ana-api/find-ns n))) changed-ns-syms')
-            (find-figwheel-always)))
+     (union (set (keep (fn [n] (:name (ana-api/find-ns n))) changed-ns-syms'))
+            (set (find-figwheel-always))))

     :else
     (let [changed-ns-syms       (set (keep (fn [n] (:name (ana-api/find-ns n))) changed-ns-syms'))


delay connecting devtools in case document.body does not exist

fixes #422

--- src/main/shadow/cljs/devtools/client/browser.cljs
+++ src/main/shadow/cljs/devtools/client/browser.cljs
@@ -394,4 +394,7 @@
       (when-let [s @socket-ref]
         (.close s))))

-  (js/setTimeout ws-connect 10))
+  ;; async connect so other stuff while loading runs first
+  (if (and js/document (= "loading" js/document.readyState))
+    (js/window.addEventListener "DOMContentLoaded" ws-connect)
+    (js/setTimeout ws-connect 10)))


In key management section, the mnemonic was not being trimmed, which lead to issues

Signed-off-by: Shivek Khurana <ae036b02ef2f3d9f073f7930137ecb248a31c067@status.im>

--- src/status_im/multiaccounts/key_storage/core.cljs
+++ src/status_im/multiaccounts/key_storage/core.cljs
@@ -66,7 +66,8 @@
   "Check if the key-uid was generated with the given seed-phrase"
   [{:keys [import-mnemonic-fn on-success on-error]} {:keys [seed-phrase key-uid]}]
   (import-mnemonic-fn
-   seed-phrase nil
+   (mnemonic/sanitize-passphrase seed-phrase)
+   nil
    (fn [result]
      (let [{:keys [keyUid]} (types/json->clj result)]
        ;; if the key-uid from app-db is same as the one returned by multiaccount import,


Uncomment one more test

Uncomment one more test

--- test/clojure/clojurewerkz/cassaforte/cql_test.clj
+++ test/clojure/clojurewerkz/cassaforte/cql_test.clj
@@ -15,6 +15,7 @@
             [clojurewerkz.cassaforte.cql         :refer :all]

             [clojure.test                        :refer :all]
+            [clojurewerkz.cassaforte.new-query-api :as new-query-api]
             ))

@@ -22,13 +23,12 @@

 (let [s (th/make-test-session)]
-
   (deftest test-insert
-    (let [s (th/make-test-session)
-          r {:name "Alex" :city "Munich" :age (int 19)}]
+    (let [r {:name "Alex" :city "Munich" :age (int 19)}]
       (insert s :users r)
       (is (= r (first (select s :users))))
-      (truncate s :users)))
+      (truncate s :users)
+      ))

   (deftest test-insert-prepare
     (let [prepared (client/prepare (insert s :users
@@ -38,7 +38,10 @@
           r        {:name "Alex" :city "Munich" :age (int 19)}]
       (client/execute s
                       (client/bind prepared ["Alex" "Munich" (int 19)]))
-      (is (= r (first (select s :users))))))
+      (is (= r (first (select s :users)))))))
+
+(comment
+

   (deftest test-update
     (testing "Simple updates"


More type hints for utils

More type hints for utils

--- src/sqls/util.clj
+++ src/sqls/util.clj
@@ -32,11 +32,12 @@
   "Join arguments as path. This should be expressed as fold.
   Takes seq of path elements, returns them joined as absolute path."
   [parts]
-  (let [base (first parts)
+  (let [^String base (first parts)
         others (rest parts)]
     (if (empty? others)
       base
-      (let [new-base (.getAbsolutePath (java.io.File. base (first others)))
+      (let [^String first-other (first others)
+            ^String new-base (.getAbsolutePath (java.io.File. base first-other))
             new-others (rest others)]
         (path-join (cons new-base new-others))))))


Fix editing expired auctions

Fix editing expired auctions

--- src/name_bazaar/ui/pages/offering_create_page.cljs
+++ src/name_bazaar/ui/pages/offering_create_page.cljs
@@ -40,7 +40,9 @@
   (/ seconds 3600))

 (defn- max-extension-duration-hours [now end-time]
-  (min 24 (/ (quot (t/in-minutes (t/interval now (from-date (.toDate (js/moment end-time))))) 15) 4)))
+  (let [end-time (from-date (.toDate (js/moment end-time)))
+        now (if (<= (.getTime now) (.getTime end-time)) now end-time)]
+    (min 24 (/ (quot (t/in-minutes (t/interval now end-time)) 15) 4))))

 (defn offering-extension-duration-slider [max-value {:keys [:value] :as props}]
   (let [duration-formatted (format-time-duration-units (hours->milis value))]


Add some tests for parse-stream-strict.

Add some tests for parse-stream-strict.

--- test/cheshire/test/core.clj
+++ test/cheshire/test/core.clj
@@ -149,16 +149,23 @@
   (is (= "{\"foo\":\"a\"}" (json/encode {:foo \a}))))

 (deftest test-streams
-  (is (= {"foo" "bar"}
-         (json/parse-stream
-          (BufferedReader. (StringReader. "{\"foo\":\"bar\"}\n")))))
-  (let [sw (StringWriter.)
-        bw (BufferedWriter. sw)]
-    (json/generate-stream {"foo" "bar"} bw)
-    (is (= "{\"foo\":\"bar\"}" (.toString sw))))
-  (is (= {(keyword "foo baz") "bar"}
-         (with-open [rdr (StringReader. "{\"foo baz\":\"bar\"}\n")]
-           (json/parse-stream rdr true)))))
+  (testing "parse-stream"
+    (are [parsed parse parsee] (= parsed
+                                  (parse (BufferedReader. (StringReader. parsee))))
+      {"foo" "bar"} json/parse-stream "{\"foo\":\"bar\"}\n"
+      {"foo" "bar"} json/parse-stream-strict "{\"foo\":\"bar\"}\n")
+
+    (are [parsed parse parsee] (= parsed
+                                  (with-open [rdr (StringReader. parsee)]
+                                    (parse rdr true)))
+      {(keyword "foo baz") "bar"} json/parse-stream "{\"foo baz\":\"bar\"}\n"
+      {(keyword "foo baz") "bar"} json/parse-stream-strict "{\"foo baz\":\"bar\"}\n"))
+
+  (testing "generate-stream"
+    (let [sw (StringWriter.)
+          bw (BufferedWriter. sw)]
+      (json/generate-stream {"foo" "bar"} bw)
+      (is (= "{\"foo\":\"bar\"}" (.toString sw))))))

 (deftest serial-writing
   (is (= "[\"foo\",\"bar\"]"


Revert "Fixed circleci type"

Revert "Fixed circleci type"

This reverts commit 2dad8b5320ca05b521740f681349081262647b42.

--- src-cljs/frontend/components/security.cljs
+++ src-cljs/frontend/components/security.cljs
@@ -114,7 +114,7 @@
             [:section
              [:h3 "Disclosure"]
              [:p
-              "If you have found a vulnerability in CircleCI, please contact our security team by email at "
+              "If you have found a vulnerability in CircleCi, please contact our security team by email at "
               [:a {:href "mailto:security@circleci.com"} "security@circleci.com"] ". We will do everything in our power to respond and fix the problem immediately. If possible, please encrypt your message using "
               [:a {:target "_blank", :href "/circleci-security.pub"}
                "our security team's GPG key"]