Reimplement test all data functions

Reimplement test all data functions

Use the set of all data function keywords as a source

--- test/comic_reader/sites/test_util.clj
+++ test/comic_reader/sites/test_util.clj
@@ -4,38 +4,6 @@
             [clj-http.client :as client]
             [loom.graph :as graph]
             [loom.alg :as alg]))
-
-(defmacro test-data-functions-not-nil []
-  `(are [selector] (is (not= (selector)
-                             nil))
-     root-url
-     manga-list-format
-     manga-url-format
-     manga-pattern-match-portion
-
-     comic->url-format
-
-     chapter-list-selector
-     comic-list-selector
-     image-selector
-     page-list-selector
-
-     chapter-number-pattern
-     chapter-number-match-pattern
-
-     link-name-normalize
-     link-url-normalize
-
-     page-normalize-format
-     page-normalize-pattern))
-
-(defmacro test-url-format-strings []
-  `(are [url-fn] (is (= (:status (client/head (url-fn)))
-                        200)
-                     (str (url-fn) "does not appear to exist."))
-     root-url
-     manga-url
-     manga-list-url))

 (def dependecy-dag
   (graph/digraph
@@ -112,10 +80,27 @@
     :page-normalize-format
     :page-normalize-pattern})

+(def key->sym
+  (comp symbol name))
+
+(defmacro test-data-functions-not-nil []
+  `(are [selector] (is (not= (selector)
+                             nil))
+     ~@(->> (seq data-function?)
+            (map key->sym))))
+
+(defn test-url-format-strings []
+  (are [url-fn] (is (= (:status (client/head (url-fn)))
+                       200)
+                    (str (url-fn) "does not appear to exist."))
+    root-url
+    manga-url
+    manga-list-url))
+
 (defmacro ensure-dependencies-defined [fn-name]
   `(are [selector] (is (not= (selector)
                              nil))
      ~@(->> (keyword fn-name)
             (alg/topsort dependecy-dag)
             (filter data-function?)
-            (map (comp symbol name)))))
+            (map key->sym))))


Drop dead code.

Drop dead code.

--- src/cavm/h2.clj
+++ src/cavm/h2.clj
@@ -639,51 +639,6 @@
 (defn- insert-field-score-out [^java.io.BufferedWriter out field-id i score-id]
   (.write out (str field-id "\t" i "\t" score-id "\n")))

-(comment
-  (defn- read-from-tsv [table file & cols]
-    (-> "INSERT INTO %s DIRECT SORTED SELECT * FROM CSVREAD('%s', '%s', 'fieldSeparator=\t')"
-        (format table file (clojure.string/join "\t" cols))
-        (exec-raw))))
-
-(defn- tsv-encoder [scores]
-  (let [s (score-encode scores)]
-    {:scores s :hex (bytes->hex s)}))
-
-(comment
-  (defn- table-writer-csv [dir dataset-id matrix-fn]
-    (let [field-seq (-> "FIELD_IDS" sequence-seq seq-iterator)
-          scores-seq (-> "SCORES_IDS" sequence-seq seq-iterator)
-          ffname (fs/file dir "field.tmp") ; XXX add pid to these, or otherwise make them unique
-          sfname (fs/file dir "scores.tmp")
-          fsfname (fs/file dir "field_score.tmp")
-
-          fields (encode-fields tsv-encoder matrix-fn)]
-      (try
-        (let [field-meta (with-open
-                           [field-file (io/writer ffname)
-                            scores-file (io/writer sfname)
-                            field-score-file (io/writer fsfname)]
-                           (let [writer
-                                 {:insert-field (partial
-                                                  insert-field-out
-                                                  field-file field-seq)
-                                  :insert-score (memoize-key
-                                                  #(ahashable (:scores (first %)))
-                                                  #(insert-scores-out scores-file scores-seq %))
-                                  :insert-field-score (partial
-                                                        insert-field-score-out
-                                                        field-score-file)}]
-                             (reduce #(load-field-feature writer dataset-id %1 %2) '() fields)))]
-          (read-from-tsv "field" ffname "ID" "DATASET_ID" "NAME")
-          (read-from-tsv "scores" sfname "ID" "SCORES")
-          (read-from-tsv "field_score" fsfname "FIELD_ID" "I" "SCORES_ID")
-          (jdbcd/transaction
-            (load-probe-meta field-meta)))
-        (finally
-          (fs/delete ffname)
-          (fs/delete sfname)
-          (fs/delete fsfname))))))
-
 (def ^:private table-writer #'table-writer-default)

 (let [fmtr (formatter "yyyy-MM-dd hh:mm:ss")]


4Clojure (~62)

4Clojure (~62)


CMR-3944: Fixed a test.

CMR-3944: Fixed a test.

--- system-int-test/test/cmr/system_int_test/ingest/granule_validation_test.clj
+++ system-int-test/test/cmr/system_int_test/ingest/granule_validation_test.clj
@@ -264,7 +264,7 @@
    (assert-invalid coll-attributes gran-attributes field-path errors :echo10))
   ([coll-attributes gran-attributes field-path errors metadata-format]
    (testing "through validation api"
-     (let [coll (data-umm-c/collection coll-attributes)
+     (let [coll (data-umm-c/collection d/unique-num coll-attributes)
            coll-concept (d/umm-c-collection->concept coll metadata-format)
            granule (dg/granule-with-umm-spec-collection coll (:concept-id coll) gran-attributes)
            gran-concept (d/item->concept granule)
@@ -286,7 +286,7 @@
 (defn assert-valid
   [coll-attributes gran-attributes]
   (testing "through validation api"
-    (let [coll (data-umm-c/collection coll-attributes)
+    (let [coll (data-umm-c/collection d/unique-num coll-attributes)
           coll-concept (d/umm-c-collection->concept coll)
           granule (dg/granule-with-umm-spec-collection coll (:concept-id coll) gran-attributes)
           gran-concept (d/item->concept granule)


don't expect gnucash ids in transactions

--- test/clj_money/import/gnucash_test.clj
+++ test/clj_money/import/gnucash_test.clj
@@ -55,8 +55,7 @@
                 :symbol "USD"}}])

 (def ^:private transactions
-  [{:id "3ab51576141406703644c0a27579c057"
-    :transaction-date (t/local-date 2015 1 1)
+  [{:transaction-date (t/local-date 2015 1 1)
     :description "Paycheck"
     :items [{:action :debit
              :account-id "ed92489659ab879fb9354a3a050fb65d"
@@ -66,30 +65,27 @@
              :account-id "1b71fd298aeca1a18d35b04a7618e76e"
              :amount 1000M
              :reconciled false}]}
-   {:id "cfade80943455ccc30a80c51df065981"
-    :transaction-date (t/local-date 2015 1 4)
-    :description "Kroger"
-    :items [{:action :debit
-             :account-id "835bfe9b2728976d06e63b90aea8c090"
-             :amount 100M
-             :reconciled false}
-            {:action :credit
-             :account-id "ed92489659ab879fb9354a3a050fb65d"
-             :amount 100M
-             :reconciled false}]}
-   {:id "0cb1dcd9a02998ad09b79909d56eb8d6"
-    :transaction-date (t/local-date 2015 1 11)
-    :description "Kroger"
-    :items [{:action :debit
-             :account-id "835bfe9b2728976d06e63b90aea8c090"
-             :amount 100M
-             :reconciled false}
-            {:action :credit
-             :account-id "ed92489659ab879fb9354a3a050fb65d"
-             :amount 100M
-             :reconciled false}]}
-   {:id "58072b476715968e046a344fe37c4141"
-    :transaction-date (t/local-date 2015 1 12)
+   {:transaction-date (t/local-date 2015 1 4)
+    :description "Kroger"
+    :items [{:action :debit
+             :account-id "835bfe9b2728976d06e63b90aea8c090"
+             :amount 100M
+             :reconciled false}
+            {:action :credit
+             :account-id "ed92489659ab879fb9354a3a050fb65d"
+             :amount 100M
+             :reconciled false}]}
+   {:transaction-date (t/local-date 2015 1 11)
+    :description "Kroger"
+    :items [{:action :debit
+             :account-id "835bfe9b2728976d06e63b90aea8c090"
+             :amount 100M
+             :reconciled false}
+            {:action :credit
+             :account-id "ed92489659ab879fb9354a3a050fb65d"
+             :amount 100M
+             :reconciled false}]}
+   {:transaction-date (t/local-date 2015 1 12)
     :description "Kroger"
     :items [{:action :debit
              :account-id "ed92489659ab879fb9354a3a050fb65d"
@@ -99,8 +95,7 @@
              :account-id "835bfe9b2728976d06e63b90aea8c090"
              :amount 10M
              :reconciled false}]}
-   {:id "a253d6afada480928f2ac3c1777eb5f3"
-    :transaction-date (t/local-date 2015 1 15)
+   {:transaction-date (t/local-date 2015 1 15)
     :description "Paycheck"
     :items [{:action :debit
              :account-id "ed92489659ab879fb9354a3a050fb65d"
@@ -110,8 +105,7 @@
              :account-id "1b71fd298aeca1a18d35b04a7618e76e"
              :amount 1000M
              :reconciled false}]}
-   {:id "17161f9669b86317f9d381589b847190"
-    :transaction-date (t/local-date 2015 1 18)
+   {:transaction-date (t/local-date 2015 1 18)
     :description "Kroger"
     :items [{:action :debit
              :account-id "835bfe9b2728976d06e63b90aea8c090"
@@ -196,6 +190,10 @@
     (is (= declarations (:declaration @found)) "The correct declarations are found")
     (is (= accounts (:account @found)) "The correct accounts are found")
     (is (= budgets (:budget @found)) "The current budgets are found")
+    (when-not (= transactions (:transaction @found))
+      (pprint {:expected transactions
+               :actual (:transaction @found)
+               :diff (diff transactions (:transaction @found))}))
     (is (= transactions (:transaction @found)) "The correct transactions are found")))

 (def ^:private commodities-input


(PDB-5022) zip-test/flip-sign-zipper: add missing (is ...) calls

Fix tests that weren't actually being checked, and then fix the tests
themselves.  Once they were being checked they failed because the
candidate trees in question only change (and should only change) if
they contain a non-zero integer.

--- test/puppetlabs/puppetdb/zip_test.clj
+++ test/puppetlabs/puppetdb/zip_test.clj
@@ -80,11 +80,15 @@
   50
   (prop/for-all [tree (gen/sized (tree-generator with-maps gen/int))]
                 (let [flipped (:node (post-order-transform (tree-zipper tree)
-                                                           [flip-sign]))]
-                  (not= tree flipped)
-                  (= tree
-                     (:node (post-order-transform (tree-zipper flipped)
-                                                  [flip-sign]))))))
+                                                           [flip-sign]))
+                      nonzero-int? #(and (integer? %) (not= 0 %))]
+                  ;; Tree only changes when there are non-zero integers.
+                  (if (some nonzero-int? (tree-seq coll? seq tree))
+                    (is (not= tree flipped))
+                    (is (= tree flipped)))
+                  (is (= tree
+                         (:node (post-order-transform (tree-zipper flipped)
+                                                      [flip-sign])))))))

 (defn extract-item
   "Zipper function for putting items matching `pred` into the state of


Break matrix load into smaller transactions.

--- src/cavm/h2.clj
+++ src/cavm/h2.clj
@@ -61,6 +61,7 @@
                        `time` TIMESTAMP NOT NULL,
                        `hash` VARCHAR(40) NOT NULL,
                        `cid` INT NOT NULL,
+                        `loaded` BOOLEAN NOT NULL,
                        FOREIGN KEY (cid) REFERENCES `cohorts` (`id`))"])

 (def exp-samples-table ["CREATE TABLE IF NOT EXISTS `exp_samples` (
@@ -137,8 +138,8 @@

 ; Delete experiment data & update experiment record.
 (defn- merge-exp [file timestamp filehash cohort]
-  (exec-raw ["MERGE INTO experiments (file, time, hash, cid) KEY(file) VALUES (?, ?, ?, ?)"
-             [file timestamp filehash cohort]])
+  (exec-raw ["MERGE INTO experiments (file, time, hash, cid, loaded) KEY(file) VALUES (?, ?, ?, ?, ?)"
+             [file timestamp filehash cohort false]])
   (let [[{exp :ID}] (select experiments (where {:file file}))]
     (clear-by-exp exp)
     exp))
@@ -217,10 +218,12 @@
            (let [sid (insert-scores-fn (ahashable (score-encode block)))]
              (insert-join pid i sid))) blocks indx))))

+(def ROWS 100)
+
 ; insert matrix, updating scores, probes, and joins tables
 (defn- load-exp-matrix [exp matrix]
   (let [loadp (partial load-probe (insert-unique-scores-fn) exp)]
-    (dorun (map loadp matrix))))
+    (dorun (map #(kdb/transaction (dorun (map loadp %))) (partition ROWS ROWS nil matrix)))))

 (defn- cohort-sample-list [cid sample-list]
   (select samples (fields :id :sample)
@@ -262,13 +265,20 @@
   (defn- format-timestamp [timestamp]
     (unparse fmtr timestamp)))

+(defn lock-matrix [file func]
+  (kdb/transaction (update experiments (where {:file file}) (set-fields {:loaded false})))
+  (func)
+  (kdb/transaction (update experiments (where {:file file}) (set-fields {:loaded true}))))
+
 (defn load-exp [file timestamp filehash matrix]
-  (kdb/transaction
-    (let [cid (merge-cohort file)
-          exp (merge-exp file (format-timestamp timestamp) filehash cid)
-          sids (load-samples cid (:samples (meta matrix)))]
-      (load-exp-samples exp sids)
-      (load-exp-matrix exp matrix))))
+  (lock-matrix
+    file
+    (fn []
+      (let [cid (kdb/transaction (merge-cohort file))
+            exp (kdb/transaction (merge-exp file (format-timestamp timestamp) filehash cid))
+            sids (kdb/transaction (load-samples cid (:samples (meta matrix))))]
+        (kdb/transaction (load-exp-samples exp sids))
+        (load-exp-matrix exp matrix)))))

 ; XXX factor out common parts with merge, above?
 (defn del-exp [file]


draft cascalog implementation of classifier

--- test/forma/classify/logistic_test.clj
+++ test/forma/classify/logistic_test.clj
@@ -114,3 +114,4 @@
          (= ?eco "eco1")
          (beta-gen ?eco ?beta)
          (logistic-prob ?beta ?feat-update :> ?prob))))
+


adapt to changes in client api (#1194)

adapt to changes in client api (#1194)

--- jar-placement-lib/src/sixsq/slipstream/placement/cimi_util.clj
+++ jar-placement-lib/src/sixsq/slipstream/placement/cimi_util.clj
@@ -3,7 +3,8 @@
     [environ.core :as e]
     [clojure.tools.logging :as log]
     [sixsq.slipstream.client.api.cimi :as cimi]
-    [sixsq.slipstream.client.api.cimi.sync :as sync]))
+    [sixsq.slipstream.client.api.authn :as authn]
+    [sixsq.slipstream.client.sync :as sync]))

 (defn- mandatory-env-value
   [env-var-name]
@@ -26,9 +27,9 @@
   []
   (log/info "updating cimi server token for user" @cimi-username)
   (let [context (sync/instance @cimi-cloud-entry-point)]
-    (cimi/login context {:href "session-template/internal"
-                         :username @cimi-username
-                         :password @cimi-password})
+    (authn/login context {:href     "session-template/internal"
+                          :username @cimi-username
+                          :password @cimi-password})
     (reset! cached-cimi-context {:context   context
                                  :timestamp (System/currentTimeMillis)})))


Add tests for subst.

Add tests for subst.

--- test/little_clojurer/chapter3_test.clj
+++ test/little_clojurer/chapter3_test.clj
@@ -30,7 +30,9 @@

 (deftest subst-test
   (testing
-    (is true)))
+    (is (= '(:a :x :c) (subst :x :b '(:a :b :c))))
+    (is (= '() (subst :x :b '())))
+    (is (= '(:a :x :b :c :b) (subst :x :b '(:a :b :b :c :b))))))

 (deftest subst2-test


Fix formatting

Fix formatting

--- test/time_tracker/projects/db_test.clj
+++ test/time_tracker/projects/db_test.clj
@@ -13,7 +13,7 @@

 (deftest retrieve-project-if-authorized
   (let [gen-projects (helpers/populate-data! {"gid1" ["foo"]
-                                      "gid2" ["goo"]})]
+                                              "gid2" ["goo"]})]
     (testing "Authorized project"
       (let [project (projects.db/retrieve-project-if-authorized
                      (get gen-projects "foo")
@@ -56,7 +56,7 @@

 (deftest delete-project-if-authorized
   (let [gen-projects (helpers/populate-data! {"gid1" ["foo"]
-                                      "gid2" ["goo"]})]
+                                              "gid2" ["goo"]})]
     (testing "Authorized project"
       (let [project-id (get gen-projects "foo")
             deleted-bool (projects.db/delete-project-if-authorized! project-id "gid1")
@@ -75,7 +75,7 @@

 (deftest retrieve-authorized-projects
   (let [gen-projects (helpers/populate-data! {"gid1" ["foo" "goo"]
-                                      "gid2" ["bar" "baz"]})]
+                                              "gid2" ["bar" "baz"]})]
     (testing "The first user"
       (let [projects (projects.db/retrieve-authorized-projects "gid1")
             project-names (map :name projects)]


Suppress the original test during scan

Suppress the original test during scan

Without swapping out the :test on the var,
it will run twice: once during scan and
once during execution.

--- modules/graclj-tools/src/main/clojure/org/graclj/tools/test/clojure_test.clj
+++ modules/graclj-tools/src/main/clojure/org/graclj/tools/test/clojure_test.clj
@@ -21,14 +21,13 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Report for scanning for test vars.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 (def ^:dynamic *tests* nil)

 (defmulti scan-report :type)

 (defmethod scan-report :begin-test-var [m]
   (println m)
-  (let [test-var (:var m)
+  (let [test-var (-> m :var meta :old-var)
         description (describe-test test-var)
         test (->Test description test-var)]
     (swap! *tests* conj test)))
@@ -37,11 +36,18 @@
   (println m)
   nil)

+(defn suppress-test-var [real-test-var]
+  (fn [v]
+    (let [old-meta (meta v)
+          new-meta (assoc old-meta :test (fn [& _] nil) :old-var v)
+          suppressed (with-meta @v new-meta)]
+      (real-test-var suppressed))))
+
 (defn scan-tests []
   (let [real-test-var test/test-var]
     (binding [*tests* (atom [])
               test/report scan-report
-              test/test-var real-test-var]
+              test/test-var (suppress-test-var real-test-var)]
       (test/run-all-tests)
       @*tests*)))


CMR-4211: Remove unused require.

CMR-4211: Remove unused require.

--- system-int-test/test/cmr/system_int_test/search/humanizer/humanizer_test.clj
+++ system-int-test/test/cmr/system_int_test/search/humanizer/humanizer_test.clj
@@ -12,7 +12,6 @@
    [cmr.system-int-test.utils.ingest-util :as ingest]
    [cmr.system-int-test.utils.search-util :as search]
    [cmr.transmit.config :as transmit-config]
-   [cmr.system-int-test.utils.url-helper :as url-helper]
    [cmr.umm-spec.test.expected-conversion :as exp-conv]))

 (use-fixtures :each (ingest/reset-fixture {"provguid1" "PROV1"}))


Implement topological sorting

Implement topological sorting

or better: write a function which is named like that. It uses sort, but
I'm not quite sure whether this is correct or not.

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

Conflicts:

	src/conexp/util.clj

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

--- src/conexp/util.clj
+++ src/conexp/util.clj
@@ -484,6 +484,15 @@
    :otherwise
    (illegal-argument "Cannot generate meaningful sequence from " x ".")))

+(defn topological-sort                  ;TODO: Write Test
+  "Returns a linear extension of the given collection coll and the
+  supplied comparator comp. If the comparator is not given, < is
+  used."
+  ([coll]
+     (topological-sort < coll))
+  ([comp coll]
+     (sort comp coll)))                 ;is this correct?
+
 ;;;

 nil


load template(s) on :init

load template(s) on :init

--- src/app/cljs/one/sample/view.cljs
+++ src/app/cljs/one/sample/view.cljs
@@ -1,7 +1,9 @@
 (ns ^{:doc "Render the views for the application."}
   one.sample.view
+  (:use [domina :only [append! destroy-children!]]
+        [query  :only [$]])
   (:require-macros [one.sample.snippets :as snippets])
-  (:require [one.dispatch :as dispatch]))
+  (:require [one.dispatch               :as dispatch]))

 (def ^{:doc "A map which contains chunks of HTML which may be used
   when rendering views."}
@@ -12,7 +14,13 @@
   and renders a view based on the value of the `:state` key."
   :state)

+(defn load-templates []
+  (let [content ($ "#content")
+        login (:login snippets)]
+    (destroy-children! content)
+    (append! content login)))
+
 (defmethod render :init [_]
-  (. js/console (log "init view rendered")))
+  (load-templates))

 (dispatch/react-to #{:state-change} (fn [_ m] (render m)))


Test for verse-0

Test for verse-0

--- beer-song/beer_song_test.clj
+++ beer-song/beer_song_test.clj
@@ -14,7 +14,8 @@
 (deftest test-verse
   (is (= verse-8 (beer-song/verse 8)))
   (is (= verse-2 (beer-song/verse 2)))
-  (is (= verse-1 (beer-song/verse 1))))
+  (is (= verse-1 (beer-song/verse 1)))
+  (is (= verse-0 (beer-song/verse 0))))

 (deftest test-song
   (is (= song-8-6 (beer-song/sing 8 6)))


log/info the generated sentences

log/info the generated sentences

--- src/babel/italiano/benchmark.cljc
+++ src/babel/italiano/benchmark.cljc
@@ -56,13 +56,17 @@
         (->>
          (take do-this-many
                (repeatedly
-                #(with-out-str (time (fo (generate {:synsem {:subcat '()
-                                                             :essere true
-                                                             :sem {:pred :be-called
-                                                                   :tense :present
-                                                                   :subj :top
-                                                                   :iobj :top}}}
-                                                   :model small))))))
+                #(with-out-str (time (fo
+                                      (let [generated
+                                            (generate {:synsem {:subcat '()
+                                                                :essere true
+                                                                :sem {:pred :be-called
+                                                                      :tense :present
+                                                                      :subj :top
+                                                                      :iobj :top}}}
+                                                      :model small)
+                                            output (log/info (fo generated))]
+                                        generated))))))
          (map #(string/replace % #".*time:\s*([0-9.]+).*" "$1"))
          (map string/trim)
          (map #(Double. %))


Fix ns form to comply with cljs.core.specs.alpha

When requiring the cljs.core.specs.alpha namespace with ClojureScript
1.10, the ns form in com.rpl.specter.navs fails spec validation and
produces a compile error, because the nested :clj reader conditionals
result in an empty :use clause.

Moving the reader conditional up to enclose :use fixes this.

Relevant spec:
https://github.com/clojure/clojurescript/blob/b11cbeefa5c148b256bcc0942d714c23ab4c6c81/src/main/cljs/cljs/core/specs/alpha.cljc#L170

Additional info:
https://clojurescript.org/news/2018-03-26-release#_core_specs_alpha

--- src/clj/com/rpl/specter/navs.cljc
+++ src/clj/com/rpl/specter/navs.cljc
@@ -5,8 +5,8 @@
               [defnav defrichnav]]
             [com.rpl.specter.util-macros :refer
               [doseqres]]))
-  (:use #?(:clj [com.rpl.specter.macros :only [defnav defrichnav]])
-        #?(:clj [com.rpl.specter.util-macros :only [doseqres]]))
+  #?(:clj (:use [com.rpl.specter.macros :only [defnav defrichnav]]
+                [com.rpl.specter.util-macros :only [doseqres]]))
   (:require [com.rpl.specter.impl :as i]
             #?(:clj [clojure.core.reducers :as r])))


disable Chronos Protocol when Employee Strike is active

allows net damage to apply normally

--- src/clj/game/cards-identities.clj
+++ src/clj/game/cards-identities.clj
@@ -122,7 +122,8 @@
                                  :no-ability {:effect (req (swap! state update-in [:damage] dissoc :damage-choose-corp)
                                                            (clear-wait-prompt state :runner)
                                                            (damage state side :net (get-defer-damage state side :net nil)
-                                                                   {:unpreventable true :card card}))}}} card nil))}}}
+                                                                   {:unpreventable true :card card}))}}} card nil))}}
+    :leave-play (req (swap! state update-in [:damage] dissoc :damage-choose-corp))}

    "Cybernetics Division: Humanity Upgraded"
    {:effect (effect (lose :hand-size-modification 1)


Fix backpack import

Fix backpack import

--- src/clj/salava/badge/importer.clj
+++ src/clj/salava/badge/importer.clj
@@ -21,11 +21,8 @@

 ;;;

-(defn- badge-checksum [badge]
-  (u/map-sha256
-    (select-keys badge [:badge_content
-                        :issuer_content
-                        :criteria_content])))
+(defn- badge-checksum [user-badge]
+  (u/map-sha256 (:badge user-badge)))

 (defn- get-remote-id [email base-url]
   (try
@@ -76,21 +73,24 @@
   (let [previous-id (b/user-owns-badge-id ctx (assoc badge :user_id (:id user)))
         expired? (if (nil? (:expires_on badge)) false (< (:expires_on badge) (u/now)))
         exists? (not (nil? previous-id))
-        error (:error (meta badge))]
-    {:status      (if (or expired? exists? error) "invalid" "ok")
-     :message     (cond
-                    exists? "badge/Alreadyowned"
-                    expired? "badge/Badgeisexpired"
-                    error "badge/Invalidbadge"
-                    :else "badge/Savethisbadge")
-     :error       error
-     :name        (get-in badge [:badge_content :name])
-     :description (get-in badge [:badge_content :description])
-     :image_file  (get-in badge [:badge_content :image_file])
-     :issuer_content_name (get-in badge [:issuer_content :name])
-     :issuer_content_url  (get-in badge [:issuer_content :url])
-     :previous-id previous-id
-     :import-key  (:checksum (meta badge))}))
+        error (:error (meta badge))
+        content (first (get-in badge [:badge :content])) ;TODO check default language
+        issuer (first (get-in badge [:badge :issuer]))  ;TODO check default language
+        ]
+    {:status              (if (or expired? exists? error) "invalid" "ok")
+     :message             (cond
+                            exists?  "badge/Alreadyowned"
+                            expired? "badge/Badgeisexpired"
+                            error    "badge/Invalidbadge"
+                            :else    "badge/Savethisbadge")
+     :error               error
+     :name                (:name content)
+     :description         (:description content)
+     :image_file          (:image_file content)
+     :issuer_content_name (:name issuer)
+     :issuer_content_url  (:url issuer)
+     :previous-id         previous-id
+     :import-key          (:checksum (meta badge))}))

 (defn user-backpack-emails
   "Get list of user's email addresses"


changed regex again to handle Snare!, Shock!

and Director Haas' Pet Project in card preview

--- src/cljs/netrunner/gameboard.cljs
+++ src/cljs/netrunner/gameboard.cljs
@@ -171,7 +171,7 @@
 (def create-span (memoize create-span-impl))

 (defn add-image-codes-impl [text]
-  (reduce #(.replace %1 (js/RegExp. (str "\\b" (:title %2) "\\b" "(?!~)") "g") (str "[" (:title %2) "~"(:code %2) "]")) text (prepared-cards)))
+  (reduce #(.replace %1 (js/RegExp. (str "(^|[^\\[\\S])" (:title %2) "(?![~\\w])") "g") (str "$1" "[" (:title %2) "~" (:code %2) "]")) text (prepared-cards)))

 (def add-image-codes (memoize add-image-codes-impl))


Fix bug caused by mouse middle button. Close #15.

--- src/cljs/nonojure/puzzleview.cljs
+++ src/cljs/nonojure/puzzleview.cljs
@@ -95,13 +95,15 @@
   state)

 (defn handle-mouse-down-on-cell [state [x y button]]
-  (let [widget (:widget state)
-        style (new-cell-style-after-click widget x y button)]
-    (pw/change-region! widget [x y] [x y] (constantly style))
-    (assoc state
-      :fill-style style
-      :base-cell [x y]
-      :last-cell [x y])))
+  (if-not (= button :middle)
+    (let [widget (:widget state)
+          style (new-cell-style-after-click widget x y button)]
+      (pw/change-region! widget [x y] [x y] (constantly style))
+      (assoc state
+        :fill-style style
+        :base-cell [x y]
+        :last-cell [x y]))
+    state))

 (defn handle-mouse-enter-on-cell [{:keys [fill-style base-cell last-cell drag-type widget board] :as state}
                                   [x y]]


correct scoring with ugly code

correct scoring with ugly code

--- src/cljs/triboard/logic/move.cljs
+++ src/cljs/triboard/logic/move.cljs
@@ -16,6 +16,9 @@
 (s/def ::winner ::player/player)
 (s/def ::looser ::player/playable-cell)
 (s/def ::conversion (s/keys :req-un [::point ::taken ::winner ::looser]))
+(s/def ::conversions (s/every ::conversion))
+
+
 (s/def ::available-moves
   (s/map-of ::player/player
     (s/map-of ::board/coord
@@ -76,15 +79,9 @@
   (let [updates (map vector (:taken move) (repeat (:winner move)))]
     (board/update-cells board updates)))

-
 (defn- apply-conversions
   [board moves]
-  (if-let [move (first moves)]
-    (reduce
-      apply-conversion
-      board
-      (conj moves (empty-cell-conversion (:winner move) (:point move)))
-      )))
+  (reduce apply-conversion board moves))

 ;; -----------------------------------------
 ;; Public API
@@ -114,9 +111,11 @@
   (map-values
     (partial map-values
       (fn [moves]
-        {:transition moves                                  ;; TODO - Add empty move (or add one to score...)
-         :scores 0                                          ;; TODO - Put a score diff (more by player, less by player)
-         :board (delay (apply-conversions board moves))}
+        (if-let [move (first moves)]
+          (let [all-moves (conj moves (empty-cell-conversion (:winner move) (:point move)))]
+            {:transition all-moves                          ;; TODO - Add empty move (or add one to score...)
+             :scores 0                                      ;; TODO - Put a score diff (more by player, less by player)
+             :board (delay (apply-conversions board all-moves))}))
         ))

     (transduce


Rearrange templates

Rearrange templates

--- src/clojure/nightcode/dialogs.clj
+++ src/clojure/nightcode/dialogs.clj
@@ -101,16 +101,16 @@
                                utils/format-project-name
                                (s/text :columns 20 :text))
         types [[:console-clojure :console "Clojure"]
+               [:console-java :console "Java"]
                [:game-clojure :game "Clojure"]
+               [:game-java :game "Java"]
                [:android-clojure :android "Clojure"]
+               [:android-java :android "Java"]
                [:ios-clojure :ios "Clojure"]
+               [:ios-java :ios "Java"]
                [:desktop-clojure :desktop "Clojure"]
+               [:web-clojure :web "ClojureScript"]
                [:graphics-clojure :graphics "Clojure"]
-               [:console-java :console "Java"]
-               [:game-java :game "Java"]
-               [:android-java :android "Java"]
-               [:ios-java :ios "Java"]
-               [:web-clojure :web "ClojureScript"]
                [:sounds-clojure :sounds "Clojure"]]
         types (if (sandbox/get-dir)
                 (remove #(contains? #{:ios :android} (second %)) types)
@@ -142,8 +142,7 @@
     (-> (s/dialog
           :title (utils/get-string :specify-project-type)
           :content (s/vertical-panel
-                     :items [(s/grid-panel :columns 5
-                                           :rows 2
+                     :items [(s/grid-panel :rows (/ (count types) 4)
                                            :items buttons)
                              (s/flow-panel :items [package-name-text])])
           :options [(s/button :text (utils/get-string :create-project)


Make sure up button is large enough

Make sure up button is large enough

--- src/clojure/nightcode/editors.clj
+++ src/clojure/nightcode/editors.clj
@@ -445,7 +445,7 @@
 (defn create-widgets
   [actions]
   {:up (doto (ui/button :id :up
-                        :text "  "
+                        :text "^^"
                         :focusable? false
                         :listen [:action (:up actions)])
          (s/text! (shortcuts/wrap-hint-text "↑")))


Remove unnecessary function

Remove unnecessary function

--- src/clojure/nightcode/editors.clj
+++ src/clojure/nightcode/editors.clj
@@ -325,11 +325,6 @@
        (subs path)
        clojure.string/lower-case))

-(defn get-syntax-style
-  [path]
-  (or (get styles (get-extension path))
-      SyntaxConstants/SYNTAX_STYLE_NONE))
-
 (defn apply-settings!
   [text-area]
   ; set theme
@@ -357,7 +352,7 @@
       (doto (create-text-area)
         (.load (FileLocation/create path) nil)
         .discardAllEdits
-        (.setSyntaxEditingStyle (get-syntax-style path))
+        (.setSyntaxEditingStyle (get styles extension))
         (.setLineWrap (contains? wrap-exts extension))
         (.setMarginLineEnabled true)
         (.setMarginLinePosition 80)


Update project.clj

Update project.clj

--- frameworks/Clojure/luminus/hello/project.clj
+++ frameworks/Clojure/luminus/hello/project.clj
@@ -1,7 +1,7 @@
 (defproject hello "0.1.0-SNAPSHOT"

-  :description "FIXME: write description"
-  :url "http://example.com/FIXME"
+  :description "Luminus framework benchmarks"
+  :url "https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Clojure/luminus"

   :dependencies [[org.clojure/clojure "1.7.0"]
                  [selmer "1.0.0"]


CMR-3158 PR fixes - fix comments and map function

--- umm-spec-lib/src/cmr/umm_spec/util.clj
+++ umm-spec-lib/src/cmr/umm_spec/util.clj
@@ -63,19 +63,18 @@
   (or country "Unknown"))

 (defn map-with-default
-  "Given a map function and a value, returns the result of mapping the value. If apply-default? is
-  true, specify a default value when mapping, otherwise no default value
+  "Returns the result of applying the given map function to a list of values. Use the default value
+  when the mapped value is nil and apply-default? is true.

   map-function - function to use for mapping
   values - the values to map
   value-default - the default to use if value is not present in the map
   apply-default? - true if the default valye should be used"
   [map-function values value-default apply-default?]
-  (if apply-default?
-    (map
-      #(let [result (map-function %)] (if (some? result) result value-default))
-      values)
-    (remove nil? (map map-function values))))
+  (let [results (map map-function values)]
+   (if apply-default?
+     (map #(if (some? %) % value-default) results)
+     (remove nil? results))))

 (defn with-default
   "Returns the value if it exists or returns the default value 'Not provided'."


Define manifest file for stefon in once.

--- src/incise/once.clj
+++ src/incise/once.clj
@@ -13,11 +13,13 @@
   [& {:as config}]
   (conf/merge! config)
   (conf/avow!)
-  (let [{:keys [out-dir precompiles stefon]} (conf/get)]
+  (let [{:keys [out-dir precompiles stefon in-dir]} (conf/get)
+        manifest-file-path (.getPath (file in-dir "manifest.json"))]
     (info "Clearing out" (str \" out-dir \"))
     (delete-recursively (file out-dir))
     (with-options (merge {:mode :production
                           :serving-root out-dir
+                          :manifest-file manifest-file-path
                           :precompiles (or precompiles [])} stefon)
       (info "Precompiling assets...")
       (precompile nil)


Rewrite saving and restoring styles

Rewrite saving and restoring styles

--- src/archi/core.clj
+++ src/archi/core.clj
@@ -92,27 +92,53 @@
 var originalStyles = {};\n

 function highlightNode(id) {\n
-    document.getElementById(id).children[1].setAttribute('fill', '#000000');\n
-    document.getElementById(id).children[2].setAttribute('fill', '#ffffff');\n
-    document.getElementById(id).children[2].setAttribute('stroke', '#ffffff');\n
+    var o = originalStyles[id] || {c1: {}, c2: {}};
+    var c1 = document.getElementById(id).children[1];
+    var c2 = document.getElementById(id).children[2];
+    o.c1.fill = c1.getAttribute('fill');
+    o.c1.stroke = c1.getAttribute('stroke');
+    o.c2.fill = c2.getAttribute('fill');
+    o.c2.stroke = c2.getAttribute('stroke');
+    originalStyles[id] = o;
+    c1.setAttribute('fill', '#000000');\n
+    c1.setAttribute('stroke', '#000000');\n
+    c2.setAttribute('fill', '#ffffff');\n
+    c2.setAttribute('stroke', '#ffffff');\n
 }\n

 function highlightEdge(id) {\n
-    document.getElementById(id).children[1].setAttribute('stroke-width', '8');\n
-    document.getElementById(id).children[2].setAttribute('stroke-width', '8');\n
-    document.getElementById(id).children[2].children[0].children[0].setAttribute('font-size', '24');\n
+    var o = originalStyles[id] || {};
+    var c1 = document.getElementById(id).children[1];
+    var c2 = document.getElementById(id).children[2];
+    var l = document.getElementById(id).children[2].children[0].children[0];
+    o.strokeWidth = c1.getAttribute('stroke-width');\n
+    o.fontSize = l.getAttribute('font-size');\n
+    originalStyles[id] = o;
+    c1.setAttribute('stroke-width', '8');\n
+    c2.setAttribute('stroke-width', '8');\n
+    l.setAttribute('font-size', '24');\n
 }\n

 function restoreNode(id) {\n
-    document.getElementById(id).children[1].setAttribute('fill', originalStyles[id].fill);\n
-    document.getElementById(id).children[2].setAttribute('fill', originalStyles[id].stroke);
-    document.getElementById(id).children[2].setAttribute('stroke', originalStyles[id].stroke);
+    var o = originalStyles[id];
+    var c1 = document.getElementById(id).children[1];
+    var c2 = document.getElementById(id).children[2];
+    c1.setAttribute('fill', o.c1.fill);\n
+    c1.setAttribute('stroke', o.c1.stroke);\n
+    c2.setAttribute('fill', o.c2.fill);\n
+    c2.setAttribute('stroke', o.c2.stroke);\n
+    delete originalStyles[id]
 }\n

 function restoreEdge(id) {\n
-    document.getElementById(id).children[1].setAttribute('stroke-width', '1');\n
-    document.getElementById(id).children[2].setAttribute('stroke-width', '1');\n
-    document.getElementById(id).children[2].children[0].children[0].setAttribute('font-size', '12');\n
+    var o = originalStyles[id];
+    var c1 = document.getElementById(id).children[1];
+    var c2 = document.getElementById(id).children[2];
+    var l = document.getElementById(id).children[2].children[0].children[0];
+    c1.setAttribute('stroke-width', o.strokeWidth);\n
+    c2.setAttribute('stroke-width', o.strokeWidth);\n
+    l.setAttribute('font-size', o.fontSize);\n
+    delete originalStyles[id]
 }\n

 function enterNode(event) {\n
@@ -144,10 +170,7 @@
      (map (fn [n]
             (str "node = document.getElementById('" n "');\n
                            node.addEventListener('mouseenter', enterNode);\n
-                           node.addEventListener('mouseleave', leaveNode);\n
-                           originalStyles['" n "'] = {};
-                           originalStyles['" n "'].fill = node.children[1].getAttribute('fill');\n
-                           originalStyles['" n "'].stroke = node.children[2].getAttribute('stroke');\n"))
+                           node.addEventListener('mouseleave', leaveNode);\n"))
           (sort (distinct (mapcat #(take 2 %) edges))))

      "


The Madras Document Status is no longer used

--- src/mdr2/abacus.clj
+++ src/mdr2/abacus.clj
@@ -110,12 +110,9 @@
   (->> [(create-row 2 productNumber)
         (create-row 233 totalTime) ; in minutes
         (create-row 106 state) ; Process Status Madras
-        ;; FIXME: what exactly is the document status? In what way is
-        ;; it different than the process status? In my view there is
-        ;; only one state and that is the state of the production. Is
-        ;; the production ready for recording, is it waiting for
-        ;; volume splitting, etc?
-        (create-row 107 :FIXME) ; Document Status Madras
+        (create-row 107 "") ; the Document Status Madras is no longer
+                            ; used but ABACUS still expects it. Just
+                            ; give it an empty string to chew on
         (create-row 276 audioFormat)
         ;; FIXME: the number of CDs is only determined at the time of
         ;; archiving. Is this persisted in the db?


Update `only` and `except` single-arity parameter names.

The single-arity parameter names for the `only` and `except` functions
did not match the same parameters in the dual-arity versions of the
same functions. This makes both arities use the same name for the same
parameter.

--- src/mount/core.cljc
+++ src/mount/core.cljc
@@ -308,8 +308,8 @@
       set))

 (defn only
-  ([states]
-   (only (find-all-states) states))
+  ([these]
+   (only (find-all-states) these))
   ([states these]
    (intersection (mapset var-to-str these)
                  (mapset var-to-str states))))
@@ -322,8 +322,8 @@
     states))

 (defn except
-  ([states]
-   (except (find-all-states) states))
+  ([these]
+   (except (find-all-states) these))
   ([states these]
    (remove (mapset var-to-str these)
            (mapset var-to-str states))))


defmacro tracing only on clj

defmacro tracing only on clj

--- src/com/wsscode/pathom/trace.cljc
+++ src/com/wsscode/pathom/trace.cljc
@@ -47,13 +47,14 @@
    (trace env (assoc event ::direction ::leave ::id trace-id))
    trace-id))

-(defmacro tracing [env event & body]
-  `(if (get ~env ::trace*)
-     (let [trace-id# (trace-enter ~env ~event)
-           res#      (do ~@body)]
-       (trace-leave ~env trace-id# ~event)
-       res#)
-     (do ~@body)))
+#?(:clj
+   (defmacro tracing [env event & body]
+     `(if (get ~env ::trace*)
+        (let [trace-id# (trace-enter ~env ~event)
+              res#      (do ~@body)]
+          (trace-leave ~env trace-id# ~event)
+          res#)
+        (do ~@body))))

 (defn live-trace! [trace-atom]
   (add-watch trace-atom :live


Fixed unique array children warning with :key

--- src/bolt/core.cljs
+++ src/bolt/core.cljs
@@ -79,7 +79,8 @@
 (rum/defc search-form []
  [:form {:onSubmit #(submit-search % event-ch)
          :className "jumbotron"}
-  [:datalist#commands (map #(vector :option {:value (name %)})
+  [:datalist#commands (map #(vector :option {:value (name %)
+                                             :key (str "command-" (name %))})
                            (sort (keys (commands-index))))]
   [:input#search_term {:type "text" :autoFocus "autofocus" :list "commands"}]
   [:a {:className "btn btn-default mic" :href "#" :onClick (partial speech/toggle-speech "#search_term" "#search_submit")}


Using threading pattern for vis updates.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -41,10 +41,10 @@
 ;; ------------------------------------------------

 (defn vis-add-ch [vis ch]
-  (swap! vis #(update-in % [:chs ch]
-                         (fn [v] (if (nil? v)
-                                   {:id ((:gen-id @vis)) :msgs {}}
-                                   v)))))
+  (update-in vis [:chs ch]
+             (fn [v] (if (nil? v)
+                       {:id ((:gen-id vis)) :msgs {}}
+                       v))))

 (def vis-event-handlers
   {"ago"
@@ -67,20 +67,23 @@
    "atake"
    {:beg (fn [vis actx args]
            (let [[ch] args]
-             (swap! vis #(assoc-in % [:actxs actx :wait-chs ch] :take))
-             (vis-add-ch vis ch)))
+             (swap! vis #(-> %
+                             (vis-add-ch ch)
+                             (assoc-in [:actxs actx :wait-chs ch] :take)))))
     :end (fn [vis actx args]
            (let [[ch msg] args]
-             (swap! vis #(dissoc-in % [:actxs actx :wait-chs ch]))
-             (swap! vis #(dissoc-in % [:chs ch :msgs msg]))
+             (swap! vis #(-> %
+                             (dissoc-in [:actxs actx :wait-chs ch])
+                             (dissoc-in [:chs ch :msgs msg])))
              (when (nil? msg)
                (swap! vis #(dissoc-in % [:chs ch])))))}
    "aput"
    {:beg (fn [vis actx args]
            (let [[ch msg] args]
-             (swap! vis #(assoc-in % [:actxs actx :wait-chs ch] :put))
-             (vis-add-ch vis ch)
-             (swap! vis #(assoc-in % [:chs ch :msgs msg] true))))
+             (swap! vis #(-> %
+                             (vis-add-ch ch)
+                             (assoc-in [:actxs actx :wait-chs ch] :put)
+                             (assoc-in [:chs ch :msgs msg] true)))))
     :end (fn [vis actx args]
            (let [[ch msg result] args]
              (swap! vis #(dissoc-in % [:actxs actx :wait-chs ch]))))}


build lists in the correct order

build lists in the correct order

- using ArrayList for speed
- implementation returns a seq - should we ensure it's a list?

--- src/transit.clj
+++ src/transit.clj
@@ -93,7 +93,7 @@

 (defn default-decoders
   []
-  {":"
+  {":"
    (reify Decoder
      (decode [_ o] (keyword o)))

@@ -117,10 +117,13 @@
 (defn list-builder
   []
   (reify ListBuilder
-    (init [_] (list))
-    (init [_ ^int size] (list))
-    (add [_ lb item] (conj lb item))
-    (^java.util.List list [_ lb] lb)))
+    (init [_] (java.util.ArrayList.))
+    (init [_ ^int size] (java.util.ArrayList. size))
+    (add [_ lb item] (.add ^java.util.List lb item) lb)
+    (^java.util.List list [_ lb]
+      (or (seq lb) '())
+      #_(apply list lb)
+      )))

 (defn set-builder
   []
@@ -220,4 +223,4 @@
   (def in (ByteArrayInputStream. (.toByteArray out)))
   (def r (reader in :json {:decoders ext-decoders}))
   (read r)
-)+)


Added file support

Added file support

Former-commit-id: 3d5b1d12877cd41928f53735e4a180bc22fedc1d

--- planck-cljs/src/planck/io.cljs
+++ planck-cljs/src/planck/io.cljs
@@ -173,3 +173,18 @@
   [filename content]
   (js/PLANCK_WRITE_FILE filename content)
   nil)
+
+(defn file
+  "Returns a PLKFile, passing each arg to as-file.  Multiple-arg
+   versions treat the first argument as parent and subsequent args as
+   children relative to the parent."
+  ([arg]
+    (js/PLANCK_IO_FILE arg))
+  ([parent & more]
+     (js/PLANCK_IO_FILE (apply str parent more))))
+
+(defn delete-file
+  "Delete file f."
+  [f]
+  (.deleteFile f))
+


Fixed port determination for smtp sending.

--- src/postal/smtp.clj
+++ src/postal/smtp.clj
@@ -17,7 +17,8 @@
                    sender ssl] :or {host "localhost"}}
            auth-map
            port (if (not port)
-                  (if ssl 465 25))
+                  (if ssl 465 25)
+                  port)
            protocol (if ssl "smtps" "smtp")
            session (doto (Session/getInstance (make-props sender auth-map))
                      (.setDebug false))]


Stop swallowing stack traces in error handling middleware.

--- src/radix/error.clj
+++ src/radix/error.clj
@@ -66,7 +66,7 @@
                  log-id (str (java.util.UUID/randomUUID))
                  context-modifier (or context-modifier identity)]
              (with-logging-context (context-modifier (merge {:request-time request-time :log-id log-id} (ex-data e)))
-               (error e)
+               (error e (.getMessage e))
                (id-error-response e log-id)))))))))

 (defn wrap-client-errors


Refinements to restricted handlers

Refinements to restricted handlers

--- src/cylon/core.clj
+++ src/cylon/core.clj
@@ -20,8 +20,7 @@
    [clojure.pprint :refer (pprint)]
    [clojure.set :as set]
    [bidi.bidi :as bidi :refer (path-for resolve-handler unresolve-handler ->WrapMiddleware Matched)]
-   [modular.ring :refer (RingHandlerProvider)]
-   [modular.index :refer (Index)]
+   [modular.ring :refer (handler RingHandlerProvider)]
    [modular.bidi :as modbidi :refer (BidiRoutesProvider routes context)]
    [schema.core :as s]
    [ring.middleware.cookies :refer (wrap-cookies cookies-request)]
@@ -202,12 +201,11 @@
 that authentication fails."
   ([h authenticator failure-handler]
      (fn [req]
-       (if-let [auth (allowed-request? authenticator req)]
-         (h (merge req auth))
-         (if failure-handler
-           (failed-authentication failure-handler req)
-           (throw (ex-info {:request (select-keys req :headers :cookies)
-                            :http-request-authenticator authenticator}))))))
+       (let [auth (allowed-request? authenticator req)]
+         (cond auth (h (merge req auth))
+               failure-handler (failed-authentication failure-handler req)
+               ;; Continue without merging auth
+               :otherwise (h req)))))
   ([h authenticator]
      (wrap-authentication h authenticator nil)))

@@ -502,6 +500,27 @@

 ;; Authorization

+;; This record wraps an existing RingHandlerProvider and sets
+;; authentication entries in the incoming request, according to its
+;; protection system dependency.
+(defrecord AuthBinder []
+  RingHandlerProvider
+  (handler [this]
+    (-> (:ring-handler-provider this)
+        handler
+        ;; TODO Just use the one authenticator if possible
+        (wrap-authentication (new-session-based-request-authenticator
+                              :http-session-store
+                              (-> this :protection-system :http-session-store)
+                              :user-roles
+                              (-> this :protection-system :user-roles))))))
+
+(defn new-auth-binder
+  "Constructor for a ring handler provider that amalgamates all bidi
+  routes provided by components in the system."
+  []
+  (component/using (->AuthBinder) [:protection-system :ring-handler-provider]))
+
 ;; Bidi handlers can be subject to access restrictions. We restrict at
 ;; the level of the handler rather than the route, because it's the
 ;; handler that determines what kind of data is being returned. It is
@@ -527,11 +546,14 @@
   Matched
   (resolve-handler [this m]
     (let [handler (resolve-handler matched m)]
-      (merge handler
-             {:handler (restrict-to-authorized (:handler handler) this)})))
+      (update-in handler [:handler] restrict-to-authorized this)))
   (unresolve-handler [this m]
-    (let [res (unresolve-handler matched m)]
-      res))
+    ;; Behave as if we weren't wrapped. We need to handle both the case
+    ;; where the handler in the map is a RestrictedHandler, and where it
+    ;; isn't.
+    (if (instance? RestrictedHandler (:handler m))
+      (unresolve-handler matched (update-in m [:handler] :matched))
+      (unresolve-handler matched m)))

   HandlerAuthorizer
   (allowed-handler? [this req]


refactor/extend the state-management

refactor/extend the state-management

--- src/dalap/walk.clj
+++ src/dalap/walk.clj
@@ -8,28 +8,41 @@

   (:import [clojure.lang IFn ILookup]))

-(defprotocol IWalker
-  (get-visitor-fn [this])
+(defprotocol IWalkerState
+  (get-state [this])
+  (update-state [this update-fn])
   (update-in-state [this keys fn])
-  (get-state [this]))
+  (conj-state [this new-state]))

-(deftype Walker
-    [visitor state-map]

-    IFn
-    (invoke [this x] (visitor x this))
-    (applyTo [this args] (clojure.lang.AFn/applyToHelper this args))
+(deftype Walker [visitor state-map]

-    IWalker
-    (get-visitor-fn [this] visitor)
-    (update-in-state [this ks fn]
-      (let [keys (if (sequential? ks) ks [ks])]
-        (Walker. visitor (update-in state-map keys fn))))
-    (get-state [this] state-map)
+  IFn
+  (invoke [this x] (visitor x this))
+  (applyTo [this args] (clojure.lang.AFn/applyToHelper this args))

-    ILookup
-    (valAt [this key] (state-map key))
-    (valAt [this key not-found] (state-map key not-found)))
+
+  ;; this is main for unit-testing of the state handling
+  Object
+  (equals [this other]
+    (and (instance? Walker other)
+         (= visitor (.visitor other))
+         (= state-map (.state-map other))))
+
+  ;; the remaining methods are state-management
+  IWalkerState
+  (get-state [this] state-map)
+  (conj-state [this new-state]
+    (Walker. visitor (conj state-map new-state)))
+  (update-state [this update-fn]
+    (Walker. visitor (update-fn state-map)))
+  (update-in-state [this ks fn]
+    (let [keys (if (sequential? ks) ks [ks])]
+      (Walker. visitor (update-in state-map keys fn))))
+  ILookup                         ; for simpler lookup of state keys
+  (valAt [this key] (state-map key))
+  (valAt [this key not-found] (state-map key not-found)))
+

 (defn gen-walker
   "A constructor wrapper around the Walker type."


Initial sample project

Initial sample project

--- apoya-app/project.clj
+++ apoya-app/project.clj
@@ -21,6 +21,8 @@
                  [org.postgresql/postgresql "9.2-1003-jdbc4"]
                  [ragtime "0.3.4"]
                  [clj-time "0.6.0"]
+                 [clj-pdf "1.11.6"
+                  :exclusions [org.bouncycastle/bctsp-jdk14]]
                  [org.clojars.ato/clojure-jsr223 "1.5.1"]
                  [org.codehaus.groovy/groovy "2.1.9"]
                  [org.codehaus.groovy/groovy-xml "2.1.9"]


handle wake time properly

handle wake time properly

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

--- clojure/acq_engine.clj
+++ clojure/acq_engine.clj
@@ -52,14 +52,13 @@
       (Thread/sleep sleep-time)))
   (clock-ms))

-(defn run-task [event]
-  (let [last-wake-time (atom 0)]
+(defn run-task [event last-wake-time]
     (update-channel event)
     (update-position event)
-    (reset! last-wake-time
-      (acq-sleep event @last-wake-time))
-    (run-autofocus event)
-    (update-slice event)
-    (snap-image event)))
+    (let [new-wake-time (acq-sleep event last-wake-time)]
+      (run-autofocus event)
+      (update-slice event)
+      (snap-image event)
+      new-wake-time))


prevent an odd bug

prevent an odd bug

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

--- clojure/acq_engine.clj
+++ clojure/acq_engine.clj
@@ -86,7 +86,8 @@
       :slice                "SlicePosition"
       "ElapsedTime-ms"      "ElapsedTime-ms"
     )
-    (assoc
+    (assoc
+      "PositionIndex" 0
       "Channel" (get-in event [:channel :name])
       "PixelType" "GRAY8"
     )))


cert fix

cert fix

--- src/nossal/web.clj
+++ src/nossal/web.clj
@@ -89,16 +89,16 @@
        [:section [:div.terminal "eval " [:span.string "\"$(curl -sL noss.al/dot)\""]]]] "")))

-(defn cert [req]
-  (env :cert-value))
+(defn cert [id]
+  (str id "." (env :cert-value)))

 (defroutes app
   (GET "/" []
     (index))

-  (GET "/.well-known/acme-challenge/"(env :cert-key) request
-    (cert request))
+  (GET "/.well-known/acme-challenge/:id" [id]
+    (cert id))

   (GET "/p" request
     (str request))


Added an option to create IR in json format.

--- src/pamela/cli.clj
+++ src/pamela/cli.clj
@@ -70,14 +70,15 @@
   "Load model(s) and build intermediate representation (IR)"
   {:added "0.3.0"}
   [options]
-  (let [{:keys [input output source]} options
-        ir (parser/parse options)]
+  (let [{:keys [input output source json-ir]} options
+        ir (parser/parse options)
+        file-format (if-not json-ir "edn-mixed" "json")]
     (if (:error ir)
       (do
         (log/errorf "unable to parse: %s\nerror: %s" input (:error ir))
         1)
       (do
-        (output-file output "edn-mixed" ir)
+        (output-file output file-format ir)
         (when source
           (output-file source "raw" (unparser/unparse ir)))
         0))))
@@ -182,6 +183,7 @@
     :validate [#(contains? output-formats %)
                (str "FORMAT not supported, must be one of "
                  (vec output-formats))]]
+   [nil "--json-ir" "Generate IR in json form" :default false]
    ["-h" "--help" "Print usage"]
    ["-i" "--input INPUT" "Input file(s) (or - for STDIN)"
     :default ["-"]


Poll: Update inbox when pages are modified.

--- src/pepa/model.clj
+++ src/pepa/model.clj
@@ -444,7 +444,13 @@
                                  "SELECT DISTINCT dp.document
                                   FROM document_pages AS dp
                                   WHERE dp.page IN (%s)" pages))
-                   (mapv :document)))}))
+                   (mapv :document)))
+     :inbox (when (seq pages)
+              (->>
+               (db/query db (db/sql+placeholders
+                             "SELECT page FROM inbox
+                              WHERE page IN (%s)" pages))
+               (mapv :page)))}))

 (defmethod changed-entities* :page_images [db _ seq-num]
   (let [pages (->>


update root query introspection with args

--- src/graphql_clj/introspection.clj
+++ src/graphql_clj/introspection.clj
@@ -8,9 +8,17 @@

 (def introspection-query (slurp (io/resource "introspection.graphql")))

+;; (parser/parse "type __Schema {
+;;   __schema: __Schema!
+;;   __type(name: String!): __Type
+;; }")
 (def root-query-schema-fields
   [{:field-name "__schema" :type-name "__Schema" :node-type :type-field :required true}
-   {:field-name "__type" :type-name "__Type" :node-type :type-field}])
+   {:field-name "__type" :type-name "__Type" :node-type :type-field
+    :arguments [{:node-type :type-field-argument,
+                 :argument-name "name",
+                 :type-name "String",
+                 :required true}]}])

 (defn- default-root-query-node [root-query-name]
   {:node-type :type-definition


made the conversion test from html to markdown pass

--- src/watney/core.clj
+++ src/watney/core.clj
@@ -28,10 +28,16 @@
                  ;; if any of the children of this :li is a :ul, then return 2 spaces here
                  :li (if (contains-node? (:content node) :ul)
                        (str (if (= (type (first (:content node))) java.lang.String)
-                              (str "* " (first (:content node)))
+                              (str "*  " (first (:content node)) "\n")
                               nil)
-                            (convert-entity (:content node) "  "))
-                       (str "* " (first (:content node))))
+                            (->> (:content node)
+                                 (filter #(= (:tag %) :ul))
+                                 first
+                                 :content
+                                 (map (fn [entity]
+                                        (convert-entity (list entity) "  ")))
+                                 (str/join "\n")))
+                       (str "*  " (first (:content node))))
                  (convert-entity (:content node)))))
         (remove empty?)
         (str/join "\n")))
@@ -49,3 +55,9 @@
       (str "\n")))

+
+
+ #_(def tables (-> the-page
+                    java.io.StringReader.
+                    html/html-resource
+                    (html/select [:table :table])))


removed obsolete config/db-server value

removed obsolete config/db-server value

--- src/vix/config.clj
+++ src/vix/config.clj
@@ -17,7 +17,6 @@
 (ns vix.config)

 ;; database
-(def db-server "http://localhost:5984/")
 (def database "vix")

 (def lucene-index-path "/var/lucene/vix")


Bitbucket link on add projects page

Bitbucket link on add projects page

--- src-cljs/frontend/components/add_projects.cljs
+++ src-cljs/frontend/components/add_projects.cljs
@@ -14,6 +14,7 @@
             [frontend.state :as state]
             [frontend.utils :as utils :refer-macros [inspect]]
             [frontend.utils.github :as gh-utils]
+            [frontend.utils.bitbucket :as bitbucket]
             [frontend.utils.vcs-url :as vcs-url]
             [goog.string :as gstring]
             [goog.string.format]
@@ -401,6 +402,7 @@
          [:hr]
          [:div#project-listing.project-listing
           [:div.overview
+           [:span [:a {:href (bitbucket/auth-url)} "bitbucket"]]
            [:span.big-number "2"]
            [:div.instruction "Choose a repo, and we'll watch the repository for activity in GitHub such as pushes and pull requests. We'll kick off the first build immediately, and a new build will be initiated each time someone pushes commits."]]
           (om/build main {:user user


Bitbucket link on add projects page

Bitbucket link on add projects page


Detect attmpt to change the prompt

Detect attmpt to change the prompt

--- src/cljs/cljs_repl_web/code_mirror/editor.cljs
+++ src/cljs/cljs_repl_web/code_mirror/editor.cljs
@@ -27,6 +27,16 @@
         last-ch (count (.getLine cm last-line))]
     (.setCursor cm last-line last-ch)))

+(defn modifying-prompt?
+  [inst key]
+  (let [pos (.getCursor inst)
+        lno (.-line pos)
+        cno (.-ch pos)
+        compare-position-fn (if (= 8 key) <= <)]
+    (and ((complement #{37 38 39 40}) key)
+         (zero? lno)
+         (compare-position-fn cno (common/beginning-of-source (.getValue inst))))))
+
 (defn editor
   [value-atom {:keys [on-change
                       on-eval
@@ -53,7 +63,7 @@
                       :extraKeys #js {"Shift-Enter" "newlineAndIndent"}
                       :value (str (get-prompt) @value-atom)
                       :mode "clojure"}))]
-
+
           (dispatch [:add-console :cljs-console inst])
           (move-to-end inst)

@@ -72,31 +82,27 @@

           (.on inst "keydown"
                (fn [inst evt]
-                 (case (.-keyCode evt)
-                   ;; backspace
-                   8 (let [pos (.getCursor inst)
-                           lno (.-line pos)
-                           cno (.-ch pos)]
-                       (when (and (zero? lno) (<= cno (common/beginning-of-source (.getValue inst))))
-                         (.preventDefault evt)))
-                   ;; enter
-                   13 (let [source (common/source-without-prompt (.getValue inst))]
-                        (when (should-eval source inst evt)
-                          (.preventDefault evt)
-                          (on-eval source)))
-                   ;; up
-                   38 (let [source (common/source-without-prompt (.getValue inst))]
-                        (when (and (not (.-shiftKey evt))
-                                   (should-go-up source inst))
-                          (.preventDefault evt)
-                          (on-up)))
-                   ;; down
-                   40 (let [source (common/source-without-prompt (.getValue inst))]
-                        (when (and (not (.-shiftKey evt))
-                                   (should-go-down source inst))
-                          (.preventDefault evt)
-                          (on-down)))
-                   :none)))))
+                 (if (modifying-prompt? inst (.-keyCode evt))
+                   (.preventDefault evt)
+                   (case (.-keyCode evt)
+                     ;; enter
+                     13 (let [source (common/source-without-prompt (.getValue inst))]
+                          (when (should-eval source inst evt)
+                            (.preventDefault evt)
+                            (on-eval source)))
+                     ;; up
+                     38 (let [source (common/source-without-prompt (.getValue inst))]
+                          (when (and (not (.-shiftKey evt))
+                                     (should-go-up source inst))
+                            (.preventDefault evt)
+                            (on-up)))
+                     ;; down
+                     40 (let [source (common/source-without-prompt (.getValue inst))]
+                          (when (and (not (.-shiftKey evt))
+                                     (should-go-down source inst))
+                            (.preventDefault evt)
+                            (on-down)))
+                     :none))))))

       :component-did-update
       (fn [this old-argv]
@@ -108,4 +114,3 @@
       (fn []
         @value-atom
         [:div])})))
-


new links

new links

--- src/cljs/work_sessions/components/headers.cljs
+++ src/cljs/work_sessions/components/headers.cljs
@@ -13,7 +13,7 @@
     "EN"]
    [:p
     "Join a simultaneous work session from your computer by opening "
-    [:a {:href "https://hangouts.google.com/hangouts/_/qrx7a5fwlrhedpmm73amlkrtiye"
+    [:a {:href "http://sws.eeefff.org/session"
          :target "blank"}
      "THIS LINK"]
     " with "
@@ -28,7 +28,7 @@

    [:p
     "To join a simultaneous work session from your smartphone or tablet install the Hangouts app. For that open "
-    [:a {:href "https://hangouts.google.com/hangouts/_/qrx7a5fwlrhedpmm73amlkrtiye"
+    [:a {:href "http://sws.eeefff.org/session"
          :target "blank"}
      "THIS LINK"]
     " with "
@@ -63,8 +63,8 @@
          :target "blank"}
      "Google Chrome"]
     " "
-    [:a {:href "https://hangouts.google.com/hangouts/_/qrx7a5fwlrhedpmm73amlkrtiye"
-         :target "blank"}
+    [:a {:href "http://sws.eeefff.org/session"
+         :Target "blank"}
      "ССЫЛКУ"]
     ". Устанавливаешь расширение "
     [:a {:href "https://chrome.google.com/webstore/detail/google-hangouts/nckgahadagoaajjgafhacjanaoiihapd"
@@ -78,7 +78,7 @@
          :target "blank"}
      "Google Chrome"]
     " "
-    [:a {:href "https://hangouts.google.com/hangouts/_/qrx7a5fwlrhedpmm73amlkrtiye"
+    [:a {:href "http://sws.eeefff.org/session"
          :target "blank"}
      "ССЫЛКУ"]
     " и присоединяешься к видео звонку после установки приложения."]
@@ -138,7 +138,7 @@
                      [:div.details.schedule
                       #_[:hr]
                       [:h4.time-and-place
-                       [:a {:href "https://hangouts.google.com/hangouts/_/qrx7a5fwlrhedpmm73amlkrtiye"
+                       [:a {:href "https://hangouts.google.com/hangouts/_/ld3v6bbvfrenjdl26pkiqdamoee"
                             :target "blank"}
                         (unescapeEntities "Session #1")]
                        (gstring/unescapeEntities ": 26 May, 13:30 — 14:30 Helsinki time")]


add analyze-js-value impl

add analyze-js-value impl

--- src/main/clojure/clojure/tools/analyzer/js.clj
+++ src/main/clojure/clojure/tools/analyzer/js.clj
@@ -11,7 +11,7 @@
   (:refer-clojure :exclude [macroexpand-1 var?])
   (:require [clojure.tools.analyzer
              :as ana
-             :refer [analyze]
+             :refer [analyze analyze-in-env ctx]
              :rename {analyze -analyze}]
             [clojure.tools.analyzer.utils :refer [resolve-var]]
             cljs.tagged-literals)
@@ -85,7 +85,21 @@
 (defn var? [x]
   (instance? Var x))

-(declare analyze-js-value)
+(defn analyze-js-value
+  [form env]
+  (let [val (.val ^JSValue form)
+        items-env (ctx env :expr)
+        items (if (map? val)
+                (zipmap (keys val)
+                        (mapv (analyze-in-env items-env) (vals val)))
+                (mapv (analyze-in-env items-env) val))]
+    {:op       :js-value
+     :js-type  (if (map? val) :object :array)
+     :env      env
+     :items    items
+     :form     form
+     :children [:items]}))
+
 (defn analyze-form
   [form env]
   (if (instance? JSValue form)


Refactored the Clojure test script and added a -main function.

--- clojure/org/gavrog/clojure/identify_nets.clj
+++ clojure/org/gavrog/clojure/identify_nets.clj
@@ -1,7 +1,8 @@
 (ns org.gavrog.clojure.identify_nets
   (:import (org.gavrog.joss.pgraphs.io Net Archive)
            (java.lang ClassLoader)
-           (java.io InputStreamReader BufferedReader)))
+           (java.io InputStreamReader BufferedReader))
+  (:gen-class))

 (defn add-to-archive [archive path]
   (let [stream (ClassLoader/getSystemResourceAsStream path)]
@@ -23,5 +24,14 @@
             (.getName found)
             :unknown)))

+(defn read-nets [path]
+  (-> path Net/iterator iterator-seq))
+
 (defn identify-all-from-file [archive path]
-  (map (partial identify archive) (-> path Net/iterator iterator-seq)))
+  (map (partial identify archive) (read-nets path)))
+
+(defn -main [path]
+  (let [archive (make-archive "1.0"
+                              "org/gavrog/apps/systre/rcsr.arc"
+                              "org/gavrog/apps/systre/zeolites.arc")]
+    (identify-all-from-file archive path)))


Untabified

Untabified

--- src/net/dishevelled/mailindex.clj
+++ src/net/dishevelled/mailindex.clj
@@ -99,8 +99,8 @@
           s (str-join "\n" lines)]
       (do (.add doc (fieldpool/tokenized-unstored-field "body" s))
           (recur doc (drop 50 body)
-		 (+ line-count (count lines))
-		 (count s))))
+                 (+ line-count (count lines))
+                 (count s))))
     (doto doc
       (.add (fieldpool/stored-field "lines" (str line-count)))
       (.add (fieldpool/stored-field "chars" (str char-count))))))
@@ -217,20 +217,20 @@
       (try
        (when (zero? (mod cnt 1000))
          (.println System/err
-		   (format "\nmsgs/sec: %.2f"
-			   (float (/ cnt
-				     (inc (/ (- (System/currentTimeMillis)
-						starttime)
-					     1000)))))))
+                   (format "\nmsgs/sec: %.2f"
+                           (float (/ cnt
+                                     (inc (/ (- (System/currentTimeMillis)
+                                                starttime)
+                                             1000)))))))
        (chatty (format "[%d] Parsing message %s" (or cnt 0) (:id (first messages)))
                (index-message iw (parse-message (first messages) connection)))
        (recur connection (rest messages) iw [(inc (or cnt 0)) starttime])
        (catch Exception e
          (.println System/err (str "Agent got exception: " e))
-	 (.printStackTrace e))
+         (.printStackTrace e))
        (catch Error e
          (.println System/err (str "Agent got error: " e))
-	 (.printStackTrace e))))))
+         (.printStackTrace e))))))

@@ -369,16 +369,16 @@
 (defn -main [& args]
   (alter-var-root #'*config* (fn [_] (read (PushbackReader. (reader "config.clj")))))
   (let [{:keys [port indexfile]} *config*
-	connections (map (fn [b]
-			   (require (:backend b))
-			   (let [conn (@(ns-resolve (:backend b)
-						    'get-connection)
-				       b)]
-			     (swap! conn assoc :config b)
-			     conn))
-			 (:backends *config*))
-	searcher (agent nil)
-	indexer (agent nil)]
+        connections (map (fn [b]
+                           (require (:backend b))
+                           (let [conn (@(ns-resolve (:backend b)
+                                                    'get-connection)
+                                       b)]
+                             (swap! conn assoc :config b)
+                             conn))
+                         (:backends *config*))
+        searcher (agent nil)
+        indexer (agent nil)]

     (send-off searcher handle-searches indexfile (Integer. port))
     (send-off indexer start-indexing indexfile connections)


WIP add some stuff

WIP add some stuff

--- src/puppetlabs/jdbc-util/core.clj
+++ src/puppetlabs/jdbc-util/core.clj
@@ -1 +1,24 @@
-(ns puppetlabs.jdbc-util)
+(ns puppetlabs.jdbc-util
+  (:require [clojure.java.jdbc           :as jdbc]
+            [puppetlabs.kitchensink.core :as ks])
+(defn- convert-result-arrays
+  "Converts Java and JDBC arrays in a result set using the provided function
+   (eg. vec, set). Values which aren't arrays are unchanged."
+  ([result-set]
+     (convert-result-arrays vec result-set))
+  ([f result-set]
+     (let [convert #(cond
+                     (ks/array? %) (f %)
+                     (isa? (class %) java.sql.Array) (f (.getArray %))
+                     :else %)]
+       (map #(ks/mapvals convert %) result-set))))
+
+(defn- query
+  "An implementation of query that returns a fully evaluated result (no
+   JDBCArray objects, etc)"
+  [db sql-and-params]
+  (let [convert (fn [rs]
+                  (doall
+                   (convert-result-arrays vec
+                                          (jdbc/result-set-seq rs))))]
+    (jdbc/db-query-with-resultset db sql-and-params convert)))


Add some examples to repl.

Add some examples to repl.

--- dev/user.clj
+++ dev/user.clj
@@ -151,19 +151,9 @@
                                               :else :black)))
           :edge->descriptor viz/edge->descriptor
           :options {:dpi 64})
-        ['context
-         update-map
-         'original-root
-         root
-         'updated-root
-         root'
-         'updated-tablets
-         (mdag/get-data store (meta root') "0/base")
-         (mdag/get-data store (meta root') "0/bc")
-         (mdag/get-data store (meta root') "1/base")
-         (mdag/get-data store (meta root') "1/bc")
-         #_ (mdag/get-data store (get-in root' [::part/tablets :base]))
-         #_ (mdag/get-data store (get-in root' [::part/tablets :bc]))])
+        ['context update-map
+         'original-root (link/identify root) root
+         'updated-root (link/identify root') root'])
       (catch Exception ex
         (throw (ex-info "Error updating tree!"
                         {:context update-map
@@ -172,7 +162,18 @@
                         ex))))))

-(def promote-reuse-example
+(def example-reuse
+  {:families {:bc #{:b :c}},
+   :records {(key/create [0]) {},
+             (key/create [5]) {:a true
+                               :b :abc
+                               :c #{"g" "h" "i"}
+                               :d #uuid "348f877b-eb00-4bf2-bced-0ea47991f627"}}
+   :changes {(key/create [0]) {}
+             (key/create [2]) {}}})
+
+
+(def example-subtree
   {:families {:bc #{:b :c}}
    :records {(key/create [0]) {:a 0 :b 0 :c 0}
              (key/create [1]) {:a 1, :c 1}
@@ -180,3 +181,26 @@
    :changes {(key/create [5]) {:a 5}
              (key/create [6]) {:x 6}
              (key/create [7]) {:y 7}}})
+
+
+(def example-delete
+  {:families {:bc #{:b :c}}
+   :records {(key/create [0]) {:b true, :d "abc"}
+             (key/create [3]) {:a :t, :c "qqq"}}
+   :changes {(key/create [0]) patch/tombstone
+             (key/create [1]) {:a 123}
+             (key/create [3]) patch/tombstone,
+             (key/create [5]) patch/tombstone}})
+
+
+(def example-index-shared
+  {:families {:bc #{:b :c}},
+   :records {(key/create [0]) {},
+             (key/create [2]) {:b {:Ec -1.0}},
+             (key/create [4]) {},
+             (key/create [7]) {},
+             (key/create [8]) {},
+             (key/create [9]) {:b #{3.0}}}
+   :changes {(key/create [0]) patch/tombstone,
+             (key/create [3]) {}
+             (key/create [4]) {:a true, :x 45}}})


Snapshot version

Snapshot version

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


Bumps version to 1.50.1-SNAPSHOT

Bumps version to 1.50.1-SNAPSHOT

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


cljfmt 0.6.3

cljfmt 0.6.3

--- dot/lein/profiles.clj
+++ dot/lein/profiles.clj
@@ -6,6 +6,6 @@
             [lein-pprint "1.2.0"]
             [jonase/eastwood "0.3.4"]
             [com.billpiel/sayid "0.0.17"]
-            [lein-cljfmt "0.6.2"]]
+            [lein-cljfmt "0.6.3"]]
   :dependencies [[slamhound "1.5.5"]]
   :aliases {"slamhound" ["run" "-m" "slam.hound"]}}}


Handling close-recv-ch's.

Handling close-recv-ch's.

--- src/cbfg/net.cljs
+++ src/cbfg/net.cljs
@@ -13,7 +13,7 @@

 (defn make-net [actx request-listen-ch request-connect-ch & opts]
   (ago-loop net actx
-            [ts 0
+            [ts 0        ; A increasing event / time stamp counter.
              listens {}  ; Keyed by [addr port], value is [close-accept-ch accept-ch].
              streams {}  ; A conn is represented by dual streams, where streams
                          ; is keyed by send-ch and a value of...
@@ -24,9 +24,14 @@
                          ;  :msgs [[deliver-at msg] ...]}.
              results []] ; A result entry is [result-ch msg].
             (let [close-accept-chs (map first (vals listens))
+                  closables (mapcat (fn [send-ch stream]
+                                      (when-let [close-recv-ch (:close-recv-ch stream)]
+                                        [close-recv-ch]))
+                                    streams)
                   deliverables (mapcat (fn [send-ch stream]
                                          (when-let [[deliver-at msg] (first (:msgs stream))]
-                                           (when (>= ts deliver-at)
+                                           (when (and (:recv-ch stream)
+                                                      (>= ts deliver-at))
                                              [[(:recv-ch stream) (first (:msgs stream))]])))
                                        streams)
                   sendables (mapcat (fn [send-ch stream]
@@ -36,6 +41,7 @@
                                     streams)
                   [v ch] (aalts net (-> [request-listen-ch request-connect-ch]
                                         (into close-accept-chs)
+                                        (into closables)
                                         (into deliverables)
                                         (into sendables)
                                         (into results)))]
@@ -58,40 +64,65 @@
                    (let [end-point-buf-size (get opts :end-point-buf-size 0)
                          client-send-ch (achan-buf net end-point-buf-size)
                          client-recv-ch (achan-buf net end-point-buf-size)
+                         close-client-recv-ch (achan net)
                          server-send-ch (achan-buf net end-point-buf-size)
-                         server-recv-ch (achan-buf net end-point-buf-size)]
+                         server-recv-ch (achan-buf net end-point-buf-size)
+                         close-server-recv-ch (achan net)]
                      ; TODO: Need to model running out of ports.
                      ; TODO: Need to model closing recv-ch's.
                      (recur (inc ts)
                             listens
                             (-> streams
-                                (assoc client-send-ch {:send-ch client-send-ch :recv-ch server-recv-ch
+                                (assoc client-send-ch {:send-ch client-send-ch
+                                                       :recv-ch server-recv-ch
+                                                       :close-recv-ch close-server-recv-ch
                                                        :server-addr to-addr :server-port to-port
                                                        :side :client :msgs []})
-                                (assoc server-send-ch {:send-ch server-send-ch :recv-ch client-recv-ch
+                                (assoc server-send-ch {:send-ch server-send-ch
+                                                       :recv-ch client-recv-ch
+                                                       :close-recv-ch close-client-recv-ch
                                                        :server-addr to-addr :server-port to-port
                                                        :side :server :msgs []}))
                             (-> results
-                                (conj [result-ch [client-send-ch client-recv-ch]])
-                                (conj [accept-ch [server-send-ch server-recv-ch]]))))
+                                (conj [result-ch [client-send-ch
+                                                  client-recv-ch close-client-recv-ch]])
+                                (conj [accept-ch [server-send-ch
+                                                  server-recv-ch close-server-recv-ch]]))))
                    (do (aclose net result-ch)
                        (recur (inc ts) listens streams results)))
                  (net-clean-up net listens streams results))
                (contains? sendables ch)
-               (let [send-ch ch]
-                 (if-let [stream (get streams send-ch)]
-                   (let [[msg result-ch] v]
+               (let [send-ch ch
+                     stream (get streams send-ch)
+                     [msg result-ch] v]
+                 (if msg
+                   (if (:recv-ch stream)
                      (recur (inc ts)
                             listens
                             (update-in streams [send-ch :msgs]
-                                       conj [(+ ts (get :opts :delivery-delay 0)) msg])
+                                       conj [(+ ts (get opts :delivery-delay 0)) msg])
                             (if result-ch
                               (conj results [result-ch :ok])
-                              result-ch)))
-                   (recur (inc ts)
-                          listens
-                          (update-in streams [send-ch :send-closed] true)
-                          results)))
+                              results))
+                     (recur (inc ts)
+                            listens
+                            streams
+                            (if result-ch
+                              (conj results [result-ch :error])
+                              results)))
+                   (if (:recv-ch stream)
+                     (recur (inc ts)
+                            listens
+                            (assoc-in streams [send-ch :send-closed] true)
+                            (if result-ch
+                              (conj results [result-ch :ok])
+                              results))
+                     (recur (inc ts)
+                            listens
+                            (dissoc streams send-ch)
+                            (if result-ch
+                              (conj results [result-ch :ok])
+                              results)))))
                :else ; Test if it's a completed deliverable (recv-ch aput'ed).
                (if-let [stream (first (filter #(= (:recv-ch %) ch) (vals streams)))]
                  (let [stream2 (update-in stream [:msgs] rest)]
@@ -106,17 +137,29 @@
                             listens
                             (assoc streams (:send-ch stream2) stream2)
                             results)))
-                 (if-let [[addr-port [close-accept-ch accept-ch]]
-                          (first (filter #(= ch (first (second %))) (seq listens)))]
+                 (if-let [stream (first (filter #(= (:close-recv-ch %) ch) (vals streams)))]
                    (if v
                      (recur (inc ts) listens streams results)
-                     (do (aclose net accept-ch) ; Handle a close-accept-ch.
+                     (do (aclose net (:recv-ch stream)) ; Handle a closed close-recv-ch.
                          (recur (inc ts)
-                                (dissoc listens addr-port)
+                                listens
+                                (assoc streams (:send-ch stream)
+                                       (-> stream
+                                           (dissoc :msgs)
+                                           (dissoc :recv-ch)
+                                           (dissoc :close-recv-ch)))
+                                results)))
+                   (if-let [[addr-port [close-accept-ch accept-ch]]
+                            (first (filter #(= ch (first (second %))) (seq listens)))]
+                     (if v
+                       (recur (inc ts) listens streams results)
+                       (do (aclose net accept-ch) ; Handle a closed close-accept-ch.
+                           (recur (inc ts)
+                                  (dissoc listens addr-port)
+                                  streams
+                                  results)))
+                     (do (aclose net ch) ; Handle a completed result-ch aput.
+                         (recur (inc ts)
+                                listens
                                 streams
-                                results)))
-                   (do (aclose net ch) ; Handle a completed result-ch aput.
-                       (recur (inc ts)
-                              listens
-                              streams
-                              (remove #(= (first %) ch) results)))))))))
+                                (remove #(= (first %) ch) results))))))))))


Remove unused import

Remove unused import

--- src/zaffre/components/render.cljc
+++ src/zaffre/components/render.cljc
@@ -6,8 +6,7 @@
             [zaffre.components :as zc]
             [zaffre.components.layout :as zl]
             [zaffre.text :as ztext]
-            [zaffre.terminal :as zt])
-  (:import [java.text.AttributedString]))
+            [zaffre.terminal :as zt]))

 (def default-style
   {:color (unchecked-int 0xffffffff) #_[255 255 255 255]


added funcs

added funcs

--- src/functions.clj
+++ src/functions.clj
@@ -1,32 +1,35 @@
 (ns functions)
+
+(defn foofn [str]
+  (println "hello " str))

 (defn total
   ([price qty]
-    (* price qty))
+   (* price qty))
   ([price]
-   (* price 1)))
-(total 2 3)
-(total 2)
+   (* price 10)))
+
+;;;;;;;;;;
+;; apply
+
+(apply str ["hello" " " "world"])
+
+(max 1 2 3)
+
+(apply max [1 2 3])
+
+;;;;;;;;;
+;; partial
+
+(def hundred-times
+  (partial * 100))

 (defn total2 [price & qty]
-    (apply * price qty))
+  (apply * price qty))

 (total2 10 2 3)

-(defn countdown [n]
-  (if-not (zero? n)
-    (do
-      (if (= 0 (rem n 100))
-        (println  "countdown: " n))
-      (recur (dec n)))))
+(def books {})

-(countdown 100)
-
-(def  books {})
-
-(some (fn [b] :books > 5) books)
-
-(def ^:dynamic *evalme* 10)
-
-(binding [*evalme* 10]
-  (str "hello" *evalme*))
+(some
+ (fn [b] :books > 5) books)


Revert "Protect throws when package.json not exists"

This reverts commit ddad95f4bb519edcdc6874589e9a25ce37b7b273.

--- src/npm/boot.cljs
+++ src/npm/boot.cljs
@@ -3,12 +3,7 @@
             [cljs.analyzer.api :as analy]
             [npm.mvn :as mvn]))

-(def PACKAGE
-  (if (js/fs.existsSync (str js/process.env.PWD "/package.json"))
-    (js->clj (js/require (str js/process.env.PWD "/package.json"))
-             :keywordize-keys true)
-    {:cljs {:source-paths ["src"]}}))
-
+(def PACKAGE (js->clj (js/require (str js/process.env.PWD "/package.json"))))
 (declare *classpath*)

 (defn file-seq [root]
@@ -22,7 +17,7 @@

 (defn ^:export lumo [& opts]
   (let [process        (atom nil)
-        source-paths   (get-in PACKAGE [:cljs :source-paths])
+        source-paths   (get-in PACKAGE ["cljs" "source-paths"])
         source-pattern (re-pattern (str \( (str/join "|" source-paths) \) "/?"))
         cache-path     (or (when (some #{"-K"} opts)
                              ".lumo_cache")
@@ -89,7 +84,7 @@
                     (apply (aget NS-EXPORTS (munge t)) args))))))

 (defn -main [& argv]
-  (mvn/async-map mvn/download-dep (map mvn/parse-dep (get-in PACKAGE [:cljs :dependencies]))
+  (mvn/async-map mvn/download-dep (map mvn/parse-dep (get-in PACKAGE ["cljs" "dependencies"]))
                  (fn [paths]
                    (set! *classpath* paths)
                    (run-task (argv->task argv)))))


client updates

client updates

--- cljs-client/tourneybot_client/core.cljs
+++ cljs-client/tourneybot_client/core.cljs
@@ -1,17 +1,25 @@
 (ns tourneybot-client.core
   (:require
-    cljsjs.marked
-    cljsjs.moment
+    [cljsjs.marked]
+    [cljsjs.moment]
     [clojure.string :refer [blank? lower-case]]
     [goog.functions :refer [once]]
-    [tourneybot.data :refer [scheduled-status in-progress-status finished-status game-statuses
+    [rum.core :as rum]
+    [tourneybot.data :refer [ensure-tournament-state
+                             finished-status
+                             game-finished?
+                             game-statuses
                              games->results
-                             ensure-tournament-state
-                             game-finished?]]
-    [tourneybot.util :refer [atom-logger by-id js-log log fetch-ajax-text
-                             fetch-json-as-cljs tourney-bot-url
-                             game->date]]
-    [rum.core :as rum]))
+                             in-progress-status
+                             scheduled-status]]
+    [tourneybot.util :refer [atom-logger
+                             by-id
+                             fetch-ajax-text
+                             fetch-json-as-cljs
+                             game->date
+                             js-log
+                             log
+                             tourney-bot-url]]))

 ;;------------------------------------------------------------------------------
 ;; Constants
@@ -26,11 +34,16 @@
 (def sort-on-record "SORT-BY-RECORD")
 (def sort-on-values #{sort-on-name sort-on-record})

-(def tournament-state-url "tournament.json")
+(def in-dev-mode? (not= -1 (.indexOf js/document.location.href "devmode")))
+
 (def info-page-url "info.md")
+(def tournament-state-url
+  (if in-dev-mode?
+    "tournament.json"
+    "api/latest.php"))

 ;; TODO: allow this to be overriden with a query param
-(def refresh-rate-ms 4000)
+(def refresh-rate-ms 5000)

 ;;------------------------------------------------------------------------------
 ;; Page State Atom
@@ -436,8 +449,7 @@
 (defn- on-change-page-state
   "Render the page on every state change."
   [_kwd _the-atom _old-state new-state]
-  (rum/request-render
-    (rum/mount (IndexApp new-state) app-container-el)))
+  (rum/mount (IndexApp new-state) app-container-el))

 (add-watch page-state :main on-change-page-state)

@@ -446,10 +458,11 @@
 ;;------------------------------------------------------------------------------

 (def init-page!
-  (once (fn []
-          (fetch-tourney-state!)
-          (fetch-info-page!)
-          ;; trigger an initial render
-          (swap! page-state identity))))
+  (once
+    (fn []
+      (fetch-tourney-state!)
+      (fetch-info-page!)
+      ;; trigger an initial render
+      (swap! page-state identity))))

 (init-page!)


Whitespace

Whitespace

--- src/cake/core.clj
+++ src/cake/core.clj
@@ -87,4 +87,4 @@
   `(project/bake ~@args))

 (defn abort-task [& message]
-  (raise {:type :abort-task :message (join " " message)}))+  (raise {:type :abort-task :message (join " " message)}))


cosmetic changes

cosmetic changes

--- src/seri/html.clj
+++ src/seri/html.clj
@@ -1,11 +1,7 @@
 (ns seri.html
-
-;; Third Party ;;;;;
+  (:import [clojure.lang IPersistentVector])

   (:require [clojure.core.match :as match])
-  (:import [clojure.lang IPersistentVector])
-
-;; Local Library ;;;

   (:use [seri.escape :only [safe]]
         [seri.escape.html :only [escape-html]])
@@ -55,15 +51,14 @@

 (defn visit-vector [v w]
   (let [named? (fn [x] (instance? clojure.lang.Named x))]
-    (match/match
-     [v]
-     [([(tag :when named?) (attrs :when map?) & content] :seq)]
-     (w (DomNode. tag attrs content))
+    (match/match [v]
+      [([(tag :when named?) (attrs :when map?) & content] :seq)]
+      (w (DomNode. tag attrs content))

-     [([(tag :when named?) & content] :seq)]
-     (w (DomNode. tag {} content))
+      [([(tag :when named?) & content] :seq)]
+      (w (DomNode. tag {} content))

-     [_] (seri.defaults/visit-seq v w))))
+      [_] (seri.defaults/visit-seq v w))))

 (extend IPersistentVector HtmlSerializable {:visit visit-vector})

@@ -92,7 +87,7 @@
     contents]])

 ;;; test
-
+
 #_(to-html
    [" match tag: " [:p "Paragraph&" [1 2 "34" 'bar] " Foo"]
     " match tag: " [:p {:id "bar" :ti&tle "fo\"o"} "Paragraph" " Foo"]


adding random keys when not specified to remove warning

--- src/show/dom.cljs
+++ src/show/dom.cljs
@@ -18,7 +18,10 @@
                       [(first vs) (rest vs)]
                       [nil        vs])
         opts        (into {} (for [[k v] opts]
-                               [k (if (array-map? v) (clj->js v) v)]))]
+                               [k (if (array-map? v) (clj->js v) v)]))
+        opts        (if (contains? opts :key)
+                      opts
+                      (assoc opts :key (gensym)))]
     [(process-opts opts)
      (clojure.core/map process-body body)]))


Turns out we get a spiffy response object. Not just a string of content.

--- src/frmr/dstt.clj
+++ src/frmr/dstt.clj
@@ -27,10 +27,10 @@
   [request-invoker pause handler]
   (future (let [slept (Thread/sleep pause)
                 start (System/nanoTime)
-                content (request-invoker)
+                response (request-invoker)
                 stop (System/nanoTime)
                 elapsed-time-in-ms (int (/ (- stop start) 1000000))]
-            (handler elapsed-time-in-ms content))))
+            (handler elapsed-time-in-ms (:body response)))))

 (defn- load-test-url
   "Execute number-of-requests requests using the request-invoker with a pause-between-requests pause between


remove extra spaces

remove extra spaces

--- exercises/poker/test/poker_test.clj
+++ exercises/poker/test/poker_test.clj
@@ -20,7 +20,7 @@
           "3H 4H 5C 6C JD"]
          ["3S 4S 5D 6H JH"
           "3H 4H 5C 6C JD"])))
-
+
 (deftest multiple-hands-with-the-same-high-cards-tie-compares-next-highest-ranked-down-to-last-card
   (is (f ["3S 5H 6S 8D 7H"
           "2S 5D 6D 8C 7S"]
@@ -50,7 +50,7 @@
   (is (f ["2S QS 2C QD JH"
           "JD QH JS 8D QC"]
          ["JD QH JS 8D QC"])))
-
+
 (deftest both-hands-have-two-identically-ranked-pairs-tie-goes-to-remaining-card-kicker
   (is (f ["JD QH JS 8D QC"
           "JS QS JC 2D QD"]
@@ -145,11 +145,3 @@
   (is (f ["4H 6H 7H 8H 5H"
           "5S 7S 8S 9S 6S"]
          ["5S 7S 8S 9S 6S"])))
-
-
-
-
-
-
-
-


Badge fixes

Badge fixes

--- src/clj/salava/badge/parse.clj
+++ src/clj/salava/badge/parse.clj
@@ -99,7 +99,7 @@

 (defn- domain [url]
-  (last (re-find #"^https?://([^/]+)" url)))
+  (last (re-find #"^https?://([^/]+)" (str url))))

 (defn- badge-image [input]
   (let [image (if (map? input) (get-in input [:badge :image] "") input)]
@@ -310,9 +310,10 @@
                                                             :mtime now}) (:evidence assertion))
                    :else [])
         badge  (if (map? (:badge assertion)) (:badge assertion) (http/json-get (:badge assertion)))
-        related (filter #(keyword "@language") (cons badge (get badge :related [])))
+        related (->> (get badge :related [])
+                     (map #(http/json-get (:id %)))
+                     (remove #(nil? ((keyword "@language") %))))
         default-language (get badge (keyword "@language") "")]
-
     (assoc initial
            :badge (merge {:id ""
                           :remote_url nil
@@ -324,10 +325,11 @@
                           :published 0
                           :last_received 0
                           :recipient_count 0}
-                          (apply merge-with (cons concat (map parser related))))
+                          (apply merge-with (cons concat (map parser (cons badge related)))))
            :issued_on  (u/str->epoch (:issuedOn assertion))
            :expires_on (u/str->epoch (:expires assertion))
            :evidence evidence)))
+
 ;;;

 (defmethod badge-content :default [initial assertion]
@@ -456,13 +458,13 @@

 (defmethod verify-assertion :v2.0 [url asr]
   (let [kind (get-in asr [:verify :type] (get-in asr [:verification :type]))]
-    (when (and url (or (= kind "hosted") (= kind "HostedBadge")))
+    (when (and (not (nil? url)) (or (= kind "hosted") (= kind "HostedBadge")))
       (if (not= (:id asr) url)
         (throw (IllegalArgumentException. "invalid assertion, verify url mismatch")))
       (if (map? (:badge asr))
         (if (not= (domain (get-in asr [:badge :id])) (domain (:id asr)))
           (throw (IllegalArgumentException. "invalid assertion, verify url mismatch")))
-        (if (not= (domain (get-in asr [:verify :url])) (domain (:badge asr)))
+        (if (not= (domain (:badge asr)) (domain (:id asr)))
           (throw (IllegalArgumentException. "invalid assertion, verify url mismatch")))))))

 (defmethod verify-assertion :default [url asr]


Removed non-judicious use of Clojure's = operator.

--- src/clojure/freactive/dom.cljs
+++ src/clojure/freactive/dom.cljs
@@ -208,12 +208,12 @@
     (fn render[frame-ms]
       (reset! frame-time frame-ms)
       (when enable-fps-instrumentation
-        (if (= instrumentation-i 4)
+        (if (identical? instrumentation-i 4)
           (do
             (reset! fps (* 1000 (/ 5 (- frame-ms last-instrumentation-time))))
             (set! instrumentation-i 0))
           (set! instrumentation-i (inc instrumentation-i)))
-        (when (= 0 instrumentation-i)
+        (when (identical? 0 instrumentation-i)
           (set! last-instrumentation-time frame-ms)) )
       (let [queue render-queue
             n (alength queue)]
@@ -292,7 +292,7 @@
   ([element state]
     (let [cur-state (get-data-state element)
           state (name state)]
-      (when-not (= cur-state state)
+      (when-not (identical? cur-state state)
         (do-set-data-state! element state)
         (let [leave-transition (get-transition element (keyword (str "after-" cur-state)))]
           (if leave-transition
@@ -308,16 +308,16 @@
 (defn bind-attr! [element attr-name attr-value node-state]
   (let [attr-name (name attr-name)]
     (cond
-      (= "style" attr-name)
+      (identical? "style" attr-name)
       (do
         (assert (map? attr-value))
         (doseq [[p v] attr-value]
           (bind-style-prop! element p v node-state)))

-      (= "data-state" attr-name)
+      (identical? "data-state" attr-name)
       (bind-prop-attr! set-data-state! element attr-name attr-value node-state)

-      (= 0 (.indexOf attr-name "on-"))
+      (identical? 0 (.indexOf attr-name "on-"))
       (listen! element (.substring attr-name 3) attr-value)

       :default
@@ -334,7 +334,7 @@
   (let [node-state (get-element-state node)]
     (doseq [[k v] attrs]
       (let [k (name k)]
-        (if (= k "style")
+        (if (identical? k "style")
           (doseq [[p v] v]
             (do
               (when node-state
@@ -375,7 +375,7 @@
         [_ tag id class] (re-matches re-tag (name kw))
         node (if tag-ns
                (let [resolved-ns
-                     (if (= tag-ns "svg")
+                     (if (identical? tag-ns "svg")
                        "http://www.w3.org/2000/svg"
                        (get-xml-namespace tag-ns))]
                  (.createElementNS js/document resolved-ns tag))
@@ -389,7 +389,7 @@
 (declare build-element)

 (defn- text-node? [dom-node]
-  (= (.-nodeType dom-node) 3))
+  (identical? (.-nodeType dom-node) 3))

 (defn- replace-child [parent new-elem-spec cur-elem]
   (let [cur-dom-node cur-elem                                       ;;