Use logging system in containium.core

Use logging system in containium.core

--- src/containium/core.clj
+++ src/containium/core.clj
@@ -18,7 +18,7 @@
             [containium.systems.repl :as repl]
             [containium.systems.ring-analytics :as ring-analytics]
             [containium.systems.mail :as mail]
-            [containium.systems.logging :as logging]
+            [containium.systems.logging :as logging :refer (refer-logging)]
             [containium.exceptions :as ex]
             [containium.commands :as commands]
             [clojure.java.io :refer (resource as-file)]
@@ -26,6 +26,7 @@
   (:import [jline.console ConsoleReader]
            [java.util Timer TimerTask])
   (:gen-class))
+(refer-logging)

 ;;; Globals for REPL access. A necessary evil.
@@ -62,7 +63,7 @@
   See the documentation on the handle-command for more info on this.
   When this function returns (of which its value is of no value, pun
   intended), the `shutdown` command has been issued."
-  [systems]
+  [{:keys [logging] :as systems}]
   (let [jline (ConsoleReader. System/in @#'containium.systems.logging/stdout)]
     (loop []
       (let [[command & args] (commands/parse-quoted (.readLine jline "containium> "))]
@@ -74,8 +75,8 @@
                                          (logging/stdout-command-logger (:logging systems) command))
                 (catch Throwable t
                   (ex/exit-when-fatal t)
-                  (println "Error handling command" command ":")
-                  (.printStackTrace t)))
+                  (error logging "Error handling command" command ":")
+                  (error logging t)))
               (recur)))))))


better handling of missing args in CLI

better handling of missing args in CLI

--- src/corpusmaker/cli.clj
+++ src/corpusmaker/cli.clj
@@ -2,19 +2,23 @@
   (:gen-class)
   (:use corpusmaker.wikipedia
     corpusmaker.entities
+    clojure.contrib.str-utils
     clojure.contrib.command-line))

 (defn handle-count-incoming [args]
   (with-command-line
     args
     "Compute the incoming links count for dbpedia resources"
-    [[pagelinks-file "The input file in N-TRIPLE format"]
+    [[link-file "The link file in N-TRIPLE format"]
      [redirect-file "The redirect file in N-TRIPLE format"]
      [output-folder "The output folder" "."] ;; TODO handle HDFS URLs
      remaining]
     (try
-      ;; TODO: find a way to report progress?
-      (time (count-incoming pagelinks-file redirect-file output-folder)) 0
+      (if (or (= link-file nil) (= redirect-file nil))
+        (do (println "ERROR: missing link file or redirect file") 3)
+        ;; TODO: find a way to report progress?
+        ;; TODO: handle the stdin case
+        (do (time (count-incoming link-file redirect-file output-folder)) 0))
       (catch java.io.FileNotFoundException fnfe
         (println "ERROR:" (.getMessage fnfe)) 2))))

@@ -23,13 +27,16 @@
     args
     "Chunk a Wikipedia pages XML dump into smaller files"
     [[input-file "The input file"]
-     [sdtin? "Stream the complete uncompressed dump to STDIN" false]
+     [stdin? "Stream the complete uncompressed dump to STDIN (not implemented)" false]
      [output-folder "The output folder" "."] ;; TODO handle HDFS URLs
      [chunk-size "The maximum size of a chunk in megabytes" 128]
      remaining]
     (try
-      ;; TODO: find a way to report progress?
-      (time (chunk-dump input-file output-folder chunk-size)) 0
+      (if (and (= input-file nil) (not stdin?))
+        (do (println "ERROR: missing input file or stdin stream") 3)
+        ;; TODO: find a way to report progress?
+        ;; TODO: handle the stdin case
+        (do (time (chunk-dump input-file output-folder chunk-size)) 0))
       (catch java.io.FileNotFoundException fnfe
         (println "ERROR:" (.getMessage fnfe)) 2))))

@@ -63,6 +70,7 @@
         (if handler
           (System/exit (handler (rest args)))
           (println "ERROR:" command "is not a valid command")))))
-  (println "try one of the following commands: " (keys *commands*))
+  (println "try one of the following commands: "
+    (str-join ", " (keys *commands*)))
   (System/exit 1))


fix coder problem with cogroup

fix coder problem with cogroup

--- src/datasplash/core.clj
+++ src/datasplash/core.clj
@@ -125,16 +125,6 @@
       (.getValue elt))
     (val elt)))

-(defn make-keyed-pcollection-tuple
-  [pcolls]
-  (let [empty-kpct (KeyedPCollectionTuple/empty (.getPipeline (first pcolls)))]
-    (reduce
-     (fn [coll-tuple [idx pcoll]]
-       (let [tag (TupleTag. (str idx))
-             new-coll-tuple (.and coll-tuple tag pcoll)]
-         new-coll-tuple))
-     empty-kpct (map-indexed (fn [idx v] [idx v]) pcolls))))
-
 (def ^{:dynamic true :no-doc true} *coerce-to-clj* true)
 (def ^{:dynamic true :no-doc true} *context* nil)
 (def ^{:dynamic true :no-doc true} *side-inputs* {})
@@ -156,7 +146,7 @@
                          (fn [acc [k pview]]
                            (assoc! acc k (.sideInput context pview)))
                          (transient {}) side-inputs))]
-          (println "dofn" without-coercion-to-clj)
+
           (binding [*context* context
                     *coerce-to-clj* (not without-coercion-to-clj)
                     *side-inputs* side-ins]
@@ -185,7 +175,6 @@
   "Get element from context in ParDo while applying relevent Clojure type conversions"
   [^DoFn$ProcessContext c]
   (let [element (.element c)]
-    (println "get" *coerce-to-clj*)
     (if *coerce-to-clj*
       (if (instance? KV element)
         (kv->clj element)
@@ -286,8 +275,7 @@

 (defn apply-transform
   [pcoll ^PTransform transform schema
-   {:keys [coder coll-name] :as options
-    :or {coder (make-nippy-coder)}}]
+   {:keys [coder coll-name] :as options}]
   (let [nam (some-> options (:name) (name))
         clean-opts (dissoc options :name :coder :coll-name)
         configured-transform (with-opts schema clean-opts transform)
@@ -339,10 +327,11 @@
     :without-coercion-to-clj {:docstr "Avoids coercing Dataflow types to Clojure, like KV. Coercion will happen by default"}}))

 (defn map-op
-  [transform base-options]
+  [transform {:keys [isomorph?] :as base-options}]
   (fn make-map-op
     ([f options ^PCollection pcoll]
-     (let [opts (merge base-options options)
+     (let [default-coder (if isomorph? (.getCoder pcoll) (make-nippy-coder))
+           opts (merge (assoc base-options :coder default-coder) options)
            pardo (ParDo/of (dofn (transform f) opts))]
        (apply-transform pcoll pardo pardo-schema opts)))
     ([f pcoll] (make-map-op f {} pcoll))))
@@ -405,7 +394,7 @@
     (ds/filter even? foo)
     (ds/filter (fn [x] (even? (* x x))) foo)"
            pardo-schema)}
-  dfilter (map-op filter-fn {:label :filter}))
+  dfilter (map-op filter-fn {:label :filter :isomorph? true}))

 (defn generate-input
   {:doc (with-opts-docstr
@@ -417,7 +406,8 @@
           base-schema)
    :added "0.1.0"}
   ([coll options ^Pipeline p]
-   (let [opts (assoc options :label :generate-input)
+   (let [opts (merge {:coder (make-nippy-coder)}
+                     (assoc options :label :generate-input))
          ptrans (Create/of (seq coll))]
      (apply-transform p ptrans base-schema opts)))
   ([coll p] (generate-input coll {} p)))
@@ -595,7 +585,8 @@
   See https://cloud.google.com/dataflow/java-sdk/JavaDoc/com/google/cloud/dataflow/sdk/transforms/GroupByKey.html"
    :added "0.1.0"}
   ([{:keys [key-coder value-coder coder] :as options} ^PCollection pcoll]
-   (let [opts (assoc options :label :group-by-keys)]
+   (let [parent-coder (.getCoder pcoll)
+         opts (assoc options :label :group-by-keys)]
      (apply-transform pcoll (GroupByKey/create) base-schema opts)))
   ([pcoll] (group-by-key {} pcoll)))

@@ -817,8 +808,10 @@
           base-schema text-reader-schema)
    :added "0.1.0"}
   ([from options ^Pipeline p]
-   (let [opts (assoc options :label (str "read-edn-file-from-"
-                                         (clean-filename from)))]
+   (let [opts (assoc options
+                     :label (str "read-edn-file-from-"
+                                 (clean-filename from))
+                     :coder (or (:coder options) (make-nippy-coder)))]
      (apply-transform p (read-edn-file-transform from opts)
                       (merge base-schema text-reader-schema) opts)))
   ([from p] (read-edn-file from {} p)))
@@ -886,6 +879,20 @@

 (def write-edn-file-by (partial write-file-by write-edn-file))
 (def write-text-file-by (partial write-file-by write-text-file))
+
+;;;;;;;;;;;
+;; Joins ;;
+;;;;;;;;;;;
+
+(defn make-keyed-pcollection-tuple
+  [pcolls]
+  (let [empty-kpct (KeyedPCollectionTuple/empty (.getPipeline (first pcolls)))]
+    (reduce
+     (fn [coll-tuple [idx pcoll]]
+       (let [tag (TupleTag. (str idx))
+             new-coll-tuple (.and coll-tuple tag pcoll)]
+         new-coll-tuple))
+     empty-kpct (map-indexed (fn [idx v] [idx v]) pcolls))))

 (defn cogroup-transform
   ([options]


Function to parse boolean value read from the INI file

--- src/hurvinek/config.clj
+++ src/hurvinek/config.clj
@@ -27,6 +27,12 @@
     [^String string]
     (java.lang.Float/parseFloat string))

+(defn parse-boolean
+    "Parse the given string as a boolean value."
+    [string]
+    (or (= string "true")
+        (= string "True")))
+
 (defn load-configuration
     "Load configuration from the provided INI file."
     [^String ini-file-name]


GAWB-2189: Optional inputs

GAWB-2189: Optional inputs

--- src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
+++ src/cljs/main/broadfcui/page/workspace/method_configs/method_config_editor.cljs
@@ -41,12 +41,13 @@
              error (style/create-server-error-message error)
              :else [comps/Spinner {:text "Loading details..."}])))
    :component-did-mount
-   (fn [{:keys [this]}]
-     (this :load-agora-method))
+   (fn [{:keys [this props state]}]
+     (react/call :load-agora-method this props state))
    :load-agora-method
-   (fn [{:keys [props state]}]
+   (fn [{:keys [state]} method-ref]
+     (utils/log "get-agora-method " method-ref)
      (endpoints/call-ajax-orch
-      {:endpoint (endpoints/get-agora-method (:namespace props) (:name props) (:snapshotId props))
+      {:endpoint (endpoints/get-agora-method (:namespace method-ref) (:name method-ref) (:snapshotId method-ref))
        :headers utils/content-type=json
        :on-done (fn [{:keys [success? get-parsed-response status-text]}]
                   (if success?
@@ -69,7 +70,7 @@
                           :backgroundColor (:background-light style/colors)
                           :border style/standard-line :borderRadius 2}}
             (str name ": (" (when optional "optional ") type ")")]
-           (when (and error (not editing?))
+           (when (and error (not editing?) (not optional))
              (icons/icon {:style {:marginLeft "0.5rem" :alignSelf "center"
                                   :color (:exception-state style/colors)}}
                          :error))
@@ -80,7 +81,7 @@
                                        :style {:width 500}}))
            (when-not editing?
              (or field-value [:span {:style {:fontStyle "italic"}} "No value entered"]))]
-          (when error
+          (when (and error (not optional))
             [:div {:style {:padding "0.5em" :marginBottom "0.5rem"
                            :backgroundColor (:exception-state style/colors)
                            :display "inline-block"
@@ -130,46 +131,46 @@
        [:div {:style {:width 290 :float "left"}}
         [:div {:ref "sidebar"}]
         (style/create-unselectable
-         :div
-         {:style {:position (when-not (:sidebar-visible? @state) "fixed")
-                  :top (when-not (:sidebar-visible? @state) 4)
-                  :width 290}}
-         (let [{:keys [locked?]} @state
-               can-edit? (access-greater-than? (:access-level props) "READER")
-               snapshot-id (get-in config [:methodRepoMethod :methodVersion])
-               config-id (ws-common/config->id config)]
-           [:div {}
-            (when (and can-edit? (not editing?))
-              (list
-               [comps/SidebarButton {:style :light :color :button-primary
-                                     :text "Edit Configuration" :icon :edit
-                                     :disabled? (when locked? "The workspace is locked")
-                                     :onClick #(swap! state assoc :editing? true :prev-snapshot-id snapshot-id)}]
-               [comps/SidebarButton {:style :light :color :exception-state :margin :top
-                                     :text "Delete" :icon :delete
-                                     :disabled? (when locked? "The workspace is locked")
+          :div
+          {:style {:position (when-not (:sidebar-visible? @state) "fixed")
+                   :top (when-not (:sidebar-visible? @state) 4)
+                   :width 290}}
+          (let [{:keys [locked?]} @state
+                can-edit? (access-greater-than? (:access-level props) "READER")
+                snapshot-id (get-in config [:methodRepoMethod :methodVersion])
+                config-id (ws-common/config->id config)]
+            [:div {}
+             (when (and can-edit? (not editing?))
+               (list
+                 [comps/SidebarButton {:style :light :color :button-primary
+                                       :text "Edit Configuration" :icon :edit
+                                       :disabled? (when locked? "The workspace is locked")
+                                       :onClick #(swap! state assoc :editing? true :prev-snapshot-id snapshot-id)}]
+                 [comps/SidebarButton {:style :light :color :exception-state :margin :top
+                                       :text "Delete" :icon :delete
+                                       :disabled? (when locked? "The workspace is locked")
+                                       :onClick #(modal/push-modal
+                                                   [delete/DeleteDialog {:config-id config-id
+                                                                         :workspace-id (:workspace-id props)
+                                                                         :after-delete (:after-delete props)}])}]))
+
+             (when-not editing?
+               [comps/SidebarButton {:style :light :color :button-primary :margin (when can-edit? :top)
+                                     :text "Publish..." :icon :share
                                      :onClick #(modal/push-modal
-                                                [delete/DeleteDialog {:config-id config-id
-                                                                      :workspace-id (:workspace-id props)
-                                                                      :after-delete (:after-delete props)}])}]))
-
-            (when-not editing?
-              [comps/SidebarButton {:style :light :color :button-primary :margin (when can-edit? :top)
-                                    :text "Publish..." :icon :share
-                                    :onClick #(modal/push-modal
-                                               [publish/PublishDialog {:config-id config-id
-                                                                       :workspace-id (:workspace-id props)}])}])
-
-            (when editing?
-              (list
-               [comps/SidebarButton {:color :success-state
-                                     :text "Save" :icon :done
-                                     :onClick #(this :-commit)}]
-               [comps/SidebarButton {:color :exception-state :margin :top
-                                     :text "Cancel Editing" :icon :cancel
-                                     :onClick (fn []
-                                                (this :load-new-method-template (:prev-snapshot-id @state))
-                                                (swap! state assoc :editing? false))}]))]))]))
+                                                 [publish/PublishDialog {:config-id config-id
+                                                                         :workspace-id (:workspace-id props)}])}])
+
+             (when editing?
+               (list
+                 [comps/SidebarButton {:color :success-state
+                                       :text "Save" :icon :done
+                                       :onClick #(this :-commit)}]
+                 [comps/SidebarButton {:color :exception-state :margin :top
+                                       :text "Cancel Editing" :icon :cancel
+                                       :onClick (fn []
+                                                  (this :load-new-method-template (utils/log (:prev-snapshot-id @state)))
+                                                  (swap! state assoc :editing? false))}]))]))]))
    :-render-main
    (fn [{:keys [state this]}]
      (let [{:keys [editing? loaded-config wdl-parse-error inputs-outputs methods]} @state
@@ -178,10 +179,10 @@
        [:div {:style {:marginLeft 330}}
         (create-section-header "Method Configuration Name")
         (create-section
-         (if editing?
-           (style/create-text-field {:ref "confname" :style {:width 500}
-                                     :defaultValue (:name config)})
-           [:div {:style {:padding "0.5em 0 1em 0"}} (:name config)]))
+          (if editing?
+            (style/create-text-field {:ref "confname" :style {:width 500}
+                                      :defaultValue (:name config)})
+            [:div {:style {:padding "0.5em 0 1em 0"}} (:name config)]))
         (create-section-header "Referenced Method")
         (create-section [MethodDetailsViewer
                          (merge {:ref "methodDetailsViewer"
@@ -192,12 +193,12 @@
                                 (utils/restructure config methods editing? wdl-parse-error))])
         (create-section-header "Root Entity Type")
         (create-section
-         (if editing?
-           (style/create-identity-select {:ref "rootentitytype"
-                                          :defaultValue (:rootEntityType config)
-                                          :style {:width 500}}
-                                         root-entity-types)
-           [:div {:style {:padding "0.5em 0 1em 0"}} (:rootEntityType config)]))
+          (if editing?
+            (style/create-identity-select {:ref "rootentitytype"
+                                           :defaultValue (:rootEntityType config)
+                                           :style {:width 500}}
+                                          root-entity-types)
+            [:div {:style {:padding "0.5em 0 1em 0"}} (:rootEntityType config)]))
         [:datalist {:id "inputs-datalist"}
          [:option {:value "this."}]
          [:option {:value "workspace."}]]
@@ -217,20 +218,20 @@
    (fn [{:keys [state props refs this]}]
      (this :load-validated-method-config)
      (endpoints/call-ajax-orch
-      {:endpoint (endpoints/get-workspace (:workspace-id props))
-       :on-done (fn [{:keys [success? get-parsed-response status-text]}]
-                  (if success?
-                    (swap! state assoc :locked? (get-in (get-parsed-response) [:workspace :isLocked]))
-                    (swap! state assoc :error status-text)))})
+       {:endpoint (endpoints/get-workspace (:workspace-id props))
+        :on-done (fn [{:keys [success? get-parsed-response status-text]}]
+                   (if success?
+                     (swap! state assoc :locked? (get-in (get-parsed-response) [:workspace :isLocked]))
+                     (swap! state assoc :error status-text)))})
      (endpoints/call-ajax-orch
-      {:endpoint endpoints/list-methods
-       :on-done (fn [{:keys [success? get-parsed-response status-text]}]
-                  (if success?
-                    (swap! state assoc :methods (->> (get-parsed-response)
-                                                     (map #(select-keys % [:namespace :name :snapshotId]))
-                                                     (group-by (juxt :namespace :name))
-                                                     (utils/map-values (partial map :snapshotId))))
-                    (swap! state assoc :error-message status-text)))})
+       {:endpoint endpoints/list-methods
+        :on-done (fn [{:keys [success? get-parsed-response status-text]}]
+                   (if success?
+                     (swap! state assoc :methods (->> (get-parsed-response)
+                                                      (map #(select-keys % [:namespace :name :snapshotId]))
+                                                      (group-by (juxt :namespace :name))
+                                                      (utils/map-values (partial map :snapshotId))))
+                     (swap! state assoc :error-message status-text)))})
      (set! (.-onScrollHandler this)
            (fn []
              (when-let [sidebar (@refs "sidebar")]
@@ -250,80 +251,85 @@
                         (->> (io-key (:inputs-outputs @state))
                              (map :name)
                              (map (juxt identity #(get-text refs (str ref-prefix "_" %))))
-                             (remove (comp empty? val))
                              (into {})))]
        (swap! state assoc :blocker "Updating...")
        (endpoints/call-ajax-orch
-        {:endpoint (endpoints/update-workspace-method-config workspace-id (ws-common/config->id config))
-         :payload (assoc config
-                    :name name
-                    :rootEntityType root-entity-type
-                    :inputs (deref-vals :inputs "in")
-                    :outputs (deref-vals :outputs "out")
-                    :methodRepoMethod (merge (:methodRepoMethod config)
-                                             ((@refs "methodDetailsViewer") :get-fields))
-                    :workspaceName workspace-id)
-         :headers utils/content-type=json
-         :on-done (fn [{:keys [success? get-parsed-response]}]
-                    (swap! state dissoc :blocker :editing?)
-                    (if success?
-                      (do ((:on-rename props) name)
-                          (swap! state assoc :loaded-config (get-parsed-response) :blocker nil))
-                      (comps/push-error-response (get-parsed-response false))))})))
+         {:endpoint (endpoints/update-workspace-method-config workspace-id (ws-common/config->id config))
+          :payload (assoc config
+                     :name name
+                     :rootEntityType root-entity-type
+                     :inputs (deref-vals :inputs "in")
+                     :outputs (deref-vals :outputs "out")
+                     :methodRepoMethod (merge (:methodRepoMethod config)
+                                              ((@refs "methodDetailsViewer") :get-fields))
+                     :workspaceName workspace-id)
+          :headers utils/content-type=json
+          :on-done (fn [{:keys [success? get-parsed-response]}]
+                     (swap! state dissoc :blocker :editing?)
+                     (if success?
+                       (do ((:on-rename props) name)
+                           (swap! state assoc :loaded-config (get-parsed-response) :blocker nil)
+                           (utils/log))
+                       (comps/push-error-response (get-parsed-response false))))})))
    :load-validated-method-config
    (fn [{:keys [state props]}]
      (endpoints/call-ajax-orch
-      {:endpoint (endpoints/get-validated-workspace-method-config (:workspace-id props) (:config-id props))
-       :on-done (fn [{:keys [success? get-parsed-response status-text]}]
-                  (if success?
-                    (let [response (get-parsed-response)]
-                      (endpoints/call-ajax-orch
-                       {:endpoint endpoints/get-inputs-outputs
-                        :payload (get-in response [:methodConfiguration :methodRepoMethod])
-                        :headers utils/content-type=json
-                        :on-done (fn [{:keys [success? get-parsed-response]}]
-                                   (if success?
-                                     (swap! state assoc :loaded-config response :inputs-outputs (get-parsed-response))
-                                     (swap! state assoc :error (:message (get-parsed-response)))))}))
-                    (swap! state assoc :error status-text)))}))
+       {:endpoint (endpoints/get-validated-workspace-method-config (:workspace-id props) (:config-id props))
+        :on-done (fn [{:keys [success? get-parsed-response status-text]}]
+                   (if success?
+                     (let [response (get-parsed-response)]
+                       (endpoints/call-ajax-orch
+                         {:endpoint endpoints/get-inputs-outputs
+                          :payload (get-in response [:methodConfiguration :methodRepoMethod])
+                          :headers utils/content-type=json
+                          :on-done (fn [{:keys [success? get-parsed-response]}]
+                                     (if success?
+                                       (swap! state assoc :loaded-config (utils/log response) :inputs-outputs (get-parsed-response))
+                                       (swap! state assoc :error (:message (get-parsed-response)))))}))
+                     (swap! state assoc :error status-text)))}))
    :load-new-method-template
-   (fn [{:keys [state refs]} new-snapshot-id]
+   (fn [{:keys [state refs props]} new-snapshot-id]
      (let [[method-namespace method-name] (map (fn [key]
                                                  (get-in (:loaded-config @state)
                                                          [:methodConfiguration :methodRepoMethod key]))
                                                [:methodNamespace :methodName])
            config-namespace+name (select-keys (get-in @state [:loaded-config :methodConfiguration])
-                                              [:namespace :name])
+                                              [:namespace :name :rootEntityType])
            method-ref {:methodNamespace method-namespace
                        :methodName method-name
                        :methodVersion new-snapshot-id}]
        (swap! state assoc :blocker "Updating...")
-       ((@refs "methodDetailsViewer") :load-agora-method {:namespace method-namespace
+       (utils/log "METHOD REF")
+       (utils/log method-ref)
+       (react/call :load-agora-method (@refs "methodDetailsViewer") {:namespace method-namespace
                                                           :name method-name
                                                           :snapshotId new-snapshot-id})
        (endpoints/call-ajax-orch
-        {:endpoint (endpoints/create-template method-ref)
-         :payload method-ref
-         :headers utils/content-type=json
-         :on-done (fn [{:keys [success? get-parsed-response]}]
-                    (let [response (get-parsed-response)]
-                      (if success?
-                        (endpoints/call-ajax-orch
-                         {:endpoint endpoints/get-inputs-outputs
-                          :payload (:methodRepoMethod response)
-                          :headers utils/content-type=json
-                          :on-done (fn [{:keys [success? get-parsed-response]}]
-                                     (swap! state dissoc :blocker :wdl-parse-error)
-                                     (let [template {:methodConfiguration (merge response config-namespace+name)}]
-                                       (if success?
-                                         (swap! state assoc
-                                                :loaded-config (assoc template
-                                                                 :invalidInputs {}
-                                                                 :validInputs {}
-                                                                 :invalidOutputs {}
-                                                                 :validOutputs {})
-                                                :inputs-outputs (get-parsed-response))
-                                         (swap! state assoc :error (:message (get-parsed-response))))))})
-                        (do
-                          (swap! state assoc :blocker nil :wdl-parse-error (:message response))
-                          (comps/push-error (style/create-server-error-message (:message response)))))))})))})
+         {:endpoint (endpoints/create-template method-ref)
+          :payload method-ref
+          :headers utils/content-type=json
+          :on-done (fn [{:keys [success? get-parsed-response]}]
+                     (let [response (get-parsed-response)]
+                       (if success?
+                         (endpoints/call-ajax-orch
+                           {:endpoint (endpoints/get-validated-workspace-method-config (:workspace-id props) (:config-id props))
+                            :on-done (fn [{:keys [success? get-parsed-response status-text]}]
+                                       (let [valid-response (get-parsed-response)]
+                                         (if success?
+                                           (endpoints/call-ajax-orch
+                                             {:endpoint endpoints/get-inputs-outputs
+                                              :payload (:methodRepoMethod response)
+                                              :headers utils/content-type=json
+                                              :on-done (fn [{:keys [success? get-parsed-response]}]
+                                                         (swap! state dissoc :blocker :wdl-parse-error)
+                                                         (let [template {:methodConfiguration (merge valid-response config-namespace+name)}]
+                                                           (if success?
+                                                               (swap! state assoc
+                                                                      ;:loaded-config (utils/log (merge template (dissoc valid-response :methodConfiguration)))
+                                                                      :loaded-config valid-response
+                                                                      :inputs-outputs (get-parsed-response)))
+                                                             (swap! state assoc :error (:message (get-parsed-response)))))})
+                                           (swap! state assoc :error status-text))))})
+                         (do
+                           (swap! state assoc :blocker nil :wdl-parse-error (:message response))
+                           (comps/push-error (style/create-server-error-message (:message response)))))))})))})


dedupe when-threeten-extra

dedupe when-threeten-extra

--- src/java_time/util.cljc
+++ src/java_time/util.cljc
@@ -24,9 +24,7 @@
     `(do ~else-body)))

 (defmacro when-threeten-extra [& body]
-  (if (try (Class/forName "org.threeten.extra.Temporals")
-           (catch Throwable e))
-    `(do ~@body)))
+  `(if-threeten-extra (do ~@body) nil))

 (defmacro when-joda-time-loaded
   "Execute the `body` when Joda-Time classes are found on the classpath.


Don't validate short option when there isn't one (fixes #350)

- Also improve error messages in general.

--- boot/core/src/boot/cli.clj
+++ boot/core/src/boot/cli.clj
@@ -172,26 +172,31 @@

 (defmacro ^:private assert
   [test fmt & args]
-  `(when-not ~test (throw (Exception. (format ~fmt ~@args)))))
+  `(when-not ~test (throw (Exception. (apply format ~fmt (map pr-str [~@args]))))))

 (defn- assert-argspecs [argspecs]
   (let [split (->> argspecs (partition-by string?))
-        opts  (->> split (mapcat #(take 2 %)) (filter symbol?))
-        specs (->> split (partition 2))]
-    (when (seq opts)
-      (assert (apply distinct? opts)
-              "cli options must be unique")
-      (assert (not-any? #{'h 'help} opts)
-              "the -h/--help cli option is reserved"))
+        specs (->> split (partition 2))
+        dupes (->> (mapcat (partial take 2) split)
+                   (filter symbol?)
+                   (group-by identity)
+                   (reduce-kv #(if (< (count %3) 2) %1 (conj %1 %2)) []))]
     (doseq [[[short long optarg type & extra] [desc]] specs]
-      (assert (and (every? symbol? [short long])
-                   (nil? (seq extra)))
-              "malformed cli option: %s" long)
+      (assert (and (not= 'h short) (not= 'help long))
+              "cli: the -h/--help option is reserved")
+      (assert ((some-fn nil? (every-pred symbol? #(= 1 (count (name %))))) short)
+              "cli: expected short option, got %s" short)
+      (assert (symbol? long)
+              "cli: expected long option, got %s" long)
+      (assert (nil? (seq extra))
+              "cli: option %s: expected description, got %s" long (first extra))
       (assert (or (and type (symbol? optarg))
                   (#{'int 'bool} optarg))
-              "cli option missing optarg: %s" long)
+              "cli: option %s: expected optarg, got %s" long (or optarg desc))
       (assert (or (not type) (not= 'bool type))
-              "cli option of bool type should not have optarg: %s" long))))
+              "cli: option %s: flags should not have optargs, got %s" long optarg))
+    (assert (not (seq dupes))
+            (format "cli: options must be unique: %s" (string/join ", " dupes)))))

 (defmacro clifn [& forms]
   (let [[doc argspecs & body]


Fix routes

Fix routes

--- src/cider_ci/tm/web.clj
+++ src/cider_ci/tm/web.clj
@@ -33,19 +33,6 @@
 ;(apply update-trial @_update-trial)

-(defn build-routes []
-  (cpj/routes
-    (cpj/context "/cider-ci" []
-
-                 (cpj/PATCH "/trials/:id"
-                            {{id :id} :params json-params :json-params}
-                            (update-trial id json-params))
-
-                 (cpj/GET "/" [] "OK")
-
-                 )))
-
-
 ; /cider-ci/executors_api_v1/trials/85bcbb1e-3f15-415b-9d59-3d87ae7bdd62

@@ -61,7 +48,7 @@

 (defn build-routes [context]
   (cpj/routes
-    (cpj/context (str context "/executors_api_v1") []
+    (cpj/context context []

                  (cpj/PATCH "/trials/:id"
                             {{id :id} :params json-params :json-params}


add q3

add q3

--- q3.clj
+++ q3.clj
@@ -0,0 +1,8 @@
+(def N 100)
+(def cards (for [x (range 1 (inc N)) y [false]] [x y]))
+
+(defn reverse-cars [cards num]
+  (map #(if (= 0 (mod (first %) num))
+            [(first %) (not (second %))]
+            %)
+       cards))


Update usage example.

Update usage example.

--- src/cli4clj/example.clj
+++ src/cli4clj/example.clj
@@ -51,5 +51,6 @@
                          :help :test
                         }
                  }]
+;;;  Last but not least, the CLI is started using the options defined above.
     (start-cli cli-opts)))


macro to check for lack of ICE protecting a server

small refactor of political assets

--- src/clj/game/macros.clj
+++ src/clj/game/macros.clj
@@ -27,6 +27,9 @@
             'installed '(#{:rig :servers} (first (:zone card)))
             'remotes '(get-remote-names @state)
             'servers '(concat ["HQ" "R&D" "Archives"] remotes)
+            'unprotected '(let [server (second (:zone (if (:host card)
+                                                        (get-card state (:host card)) card)))]
+                            (empty? (get-in @state [:corp :servers server :ices])))
             'runnable-servers '(let [servers (map zone->name
                                                   (keys (get-in @state [:corp :servers])))
                                      restricted (map zone->name


Fix count for non-counted collections, remove ICounted from Cons

Since default no longer gets extended to ICounted, the original
implementation of cljs.core/count no longer works on LazySeq
instances.

This patch takes the approach of checking whether the given collection
is counted and either calling -count or a linear traversal
helper (which rolls over to -count as soon as possible).

The implementation of ICounted on Cons is now unnecessary and has been
removed, so that things for which counted? returns true really do
provide constant-time count.

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -569,11 +569,20 @@
   [coll]
   (-empty coll))

+(declare counted?)
+
+(defn- accumulating-seq-count [coll acc]
+  (if (counted? coll) ; assumes nil is counted, which it currently is
+    (+ acc (-count coll))
+    (recur (next coll) (inc acc))))
+
 (defn count
   "Returns the number of items in the collection. (count nil) returns
   0.  Also works on strings, arrays, and Maps"
   [coll]
-  (-count coll))
+  (if (counted? coll)
+    (-count coll)
+    (accumulating-seq-count coll 0)))

 (defn nth
   "Returns the value at the index. get returns nil if index out of
@@ -1428,14 +1437,7 @@
   (-hash [coll] (caching-hash coll hash-coll __hash))

   ISeqable
-  (-seq [coll] coll)
-
-  ICounted
-  (-count [coll]
-    (loop [s (seq coll) n 0]
-      (if s
-        (recur (next s) (inc n))
-        n))))
+  (-seq [coll] coll))

 (defn cons
   "Returns a new seq where x is the first element and seq is the rest."


Adding dec

Adding dec

--- src/cljs/cljs/core.cljs
+++ src/cljs/cljs/core.cljs
@@ -378,6 +378,10 @@
   "Returns a number one greater than num."
   [x] (+ x 1))

+(defn dec
+  "Returns a number one less than num."
+  [x] (- x 1))
+
 (comment
   (use 'cljs.compiler)


Dear Java: you are an asshole.

Dear Java: you are an asshole.

--- src/clojurecraft/in.clj
+++ src/clojurecraft/in.clj
@@ -30,7 +30,7 @@
 (defn- -read-bytearray-bare [conn size]
   (io!
     (let [ba (byte-array size)]
-         (.read ^DataInputStream (:in @conn) ba 0 size)
+         (.readFully ^DataInputStream (:in @conn) ba 0 size)
          ba)))

 (defn- -read-bytearray [conn size]


Calculate and subs in adjusted relative paths for assets

--- src/lt/plugins/css.cljs
+++ src/lt/plugins/css.cljs
@@ -1,11 +1,64 @@
 (ns lt.plugins.css
-  (:require [lt.object :as object]
+  (:require [clojure.string :as string]
+            [lt.object :as object]
             [lt.objs.eval :as eval]
             [lt.objs.editor :as ed]
             [lt.objs.files :as files]
             [lt.objs.clients :as clients]
             [lt.util.dom :refer [$ append]])
   (:require-macros [lt.macros :refer [behavior defui]]))
+
+; file    /home/josh/repos/
+; client: /home/josh/
+; delta:  repos/
+
+; file    /home/josh/
+; client: /home/josh/repos/
+; delta:  ../
+
+; file:   /home/josh/project/
+; client: /home/josh/LT/
+; delta:  ../project/
+
+(defn get-prefix
+  "Get the longest shared prefix of s1 and s2 and return it."
+  ([s1 s2] (get-prefix s1 s2 ""))
+  ([s1 s2 memo]
+   (if (= (first s1) (first s2))
+     (get-prefix (rest s1) (rest s2) (str memo (first s1)))
+     memo)))
+
+;; Not currently used.
+(defn ensure-end-sep [s]
+  "If s is a directory, ensure it ends in a path separator."
+  (if (or (= (last s) files/separator) (not (files/dir? s)))
+    s
+    (str s files/separator)))
+
+; @NOTE: Are the names source and dest backwards here?
+(defn diff-paths [source dest]
+  "Create a relative path which is the difference of paths source and dest."
+  (let [root (get-prefix source dest)
+        source (string/replace-first (or source "") root "")
+        dest (string/replace-first (or dest "") root "")
+        prefix (string/replace dest #"[^/]*/" "../")]
+    (str prefix source)))
+
+(defn process-urls [diff-path matches code]
+  "Recursively prefix relative URLs in CSS with the given diff-path."
+  (if-not (first matches)
+    code
+    (let [match (first matches)
+          token (first match)
+          url (second match)]
+      (process-urls diff-path (rest matches)
+                    (string/replace code token (str "url(\"" (files/join diff-path url) "\")"))))))
+
+(defn preprocess [file-path client-path code]
+  "Preprocess CSS to make it work as expected when injected."
+  ; Matches a url() function containing a possibly quoted relative path. Captures just the path in group 1.
+  (let [matches (distinct (re-seq #"(?m)[uU][rR][lL]\([\"']?([^\/\"'].+?)[\"']?\)" code))]
+    (process-urls (diff-paths file-path client-path) matches code)))

 (behavior ::on-eval
           :triggers #{:eval
@@ -25,12 +78,20 @@
 (behavior ::eval!
           :triggers #{:eval!}
           :reaction (fn [this event]
-                      (let [{:keys [info origin]} event]
-                        (clients/send (eval/get-client! {:command :editor.eval.css
-                                                         :origin origin
-                                                         :info info})
+                      (let [{:keys [info origin]} event
+                            client (eval/get-client! {:command :editor.eval.css
+                                                      :origin origin
+                                                      :info info})
+                            file-path (:path info)
+                            client-path (case (:type @client)
+                                   "LT-UI" (files/lt-home "core/")
+                                   "")
+                            code (if-not client-path
+                                   (:code info)
+                                   (preprocess (files/parent file-path) client-path (:code info)))]
+                        (clients/send client
                                       :editor.eval.css
-                                      info
+                                      (assoc info :code code)
                                       :only origin))))

 (object/object* ::css-lang


formatting

formatting

--- src/cljs/client/components/activity/core.cljs
+++ src/cljs/client/components/activity/core.cljs
@@ -7,7 +7,7 @@
             [cljs-time.core :as t]
             [cljs-time.coerce :as ct]
             [cljs-time.periodic :refer [periodic-seq]]
-            [common.util :refer [log js-log]]))
+            [common.util :refer [log js-log cljs->js]]))

 ;; todo - remove and add as parameters to the component
 (def width 900)
@@ -27,10 +27,10 @@
               (conj acc
                     (reduce (fn [acc week]
                               (let [x (* week edge)]
-                               (conj acc {:x x
-                                          :y y
-                                          :edge edge
-                                          :date (compute-date week day)})))
+                               (conj acc {"x"    x
+                                          "y"    y
+                                          "edge" edge
+                                          "date" (compute-date week day)})))
                             []
                             (range weeks)))))
            []
@@ -38,11 +38,11 @@

 (def data (cal-grid))

-
 (defn- graph [data]
   (reagent/create-class
     {:reagent-render      (fn [] [:div [:svg {:width width :height height}]])
      :component-did-mount (fn []
+                              ; @TODO: there is an issue with cljs->js and DateTime - use string instead
                               (let [d3data (clj->js data)
                                     row    (.. js/d3
                                                (select "svg")


Update core docs.

Update core docs.

--- src/clojure/uncomplicate/neanderthal/core.clj
+++ src/clojure/uncomplicate/neanderthal/core.clj
@@ -156,6 +156,9 @@

   Changes to the resulting object affect the source `x`, even the parts of data that might not
   be accessible by `x`. Use with caution!
+
+  view always creates a new instance that reuses the master's data,
+  but releasing a view never releases the master data.

       (view (buffer (vctr float-factory 1 2 3)))
   "
@@ -194,6 +197,8 @@

   Changes to the resulting object affect the source `x`, even the parts of data that might not
   be accessible by `x`. Use with caution!
+
+  view-vctr might return the master object itself, or create a new instance that reuses the master's data.

       (view-vctr (ge float-factory 2 3 (range 6)))
   "
@@ -276,6 +281,8 @@

   Changes to the resulting object affect the source `a`, even the parts of data that might not
   be accessible by a. Use with caution!
+
+  view-ge might return the master object itself, or create a new instance that reuses the master's data.

       (view-ge (tr float-factory 3 (range 6)))
   "
@@ -335,6 +342,8 @@

   Options: `:uplo` (`upper` or `:lower`), and `:diag` (`:unit` or `:non-unit`).

+  view-tr creates a new instance that reuses the master's data.
+
       (view-tr (ge float-factory 3 2 (range 6)))
   "
   ([a]
@@ -380,6 +389,8 @@
   accessible by a. Use with caution!

   Options: `:uplo` (`upper` or `:lower`)..
+
+  view-sy creates a new instance that reuses the master's data.

       (view-sy (tr float-factory 3 (range 6)))
   "


changed the para_line_break_parser for commonmark specs

--- src/markdown/parser.clj
+++ src/markdown/parser.clj
@@ -51,7 +51,7 @@

 (defn para_line_break_parser [data]
-	(if (re-find #"^ {2,}\n" data)
+	(if (re-find #"^( {2,}|\\)\n" data)
 		(let [[a b] (split data #"\n" 2)]
 			(list (hash-map :tag "linebreak",:content "<br />") b))))


Remove old code

Remove old code

--- src/databinder/core.clj
+++ src/databinder/core.clj
@@ -449,7 +449,7 @@
     (doall (map (fn [key] (.add qm (str key) (res (get vals key)))) (keys vals)))
     qm))

-(defn uni [] (. ModelFactory createRDFSModel (.union (to-model example-view) (to-model widgets))))
+
 (defn build-query [view-data widget-data uri]
   (let [inf (. ModelFactory createRDFSModel (.union view-data widget-data))
         query  (qbuild inf (parse-uri uri))
@@ -595,7 +595,7 @@
         (= type "create")
         {:uri uri :predicate pred :value (uuid) :type type}
         (= type "delete")
-        {:urd uri :predicate pred :value data :type type}))
+        {:uri uri :predicate pred :value data :type type}))

 (defn editor [inf]
   (fn [message]
@@ -607,9 +607,8 @@
           binder (.getURI (.getPredicate statement))
           predicate (.asResource (.getObject statement))
           pred (.getURI predicate)
-          resource (res uri) ;;TODO HERE make a serializer for each binding, then use them to populate action with html if this is an htmlable type thing. Consider moving to a pure update based strategy, as then we don't need javascript that's so complicated on the client side. We just regenerate any part of the view that's changed at any time. However, this means things like chat-rooms are not really viable.
+          resource (res uri)
           reverse (= binder (db :binds))
-          ;;graph-store (. GraphStoreFactory create model)
           command (commander uri pred data type)
           update (query-builder command reverse)]
       (doall (map (fn [up]
@@ -666,11 +665,12 @@
   dc:description \"A person\" ;
   data:rank 2 .

-ex:person-container data:haschild ex:person-name-container , ex:person-age , ex:pets-list ,  ex:person-deleter .
+ex:person-container data:haschild ex:person-name-container , ex:person-age ,  ex:person-deleter .

 ex:person-deleter rdf:type w:deleter ;
                   data:bindo rdf:type ;
                   dc:title \"Remove\" ;
+                  data:rank 3 ;
                   dc:description \"Permanently delete a person from the database\" .

 ex:person-name-container
@@ -680,21 +680,16 @@
   rdf:type w:h1 .

 ex:person-name rdf:type w:text-field ;
-               data:rank 5 ;
+               data:rank 1 ;
                data:bindo ont:name ;
                dc:title \"Name\" ;
                dc:description \"The name of a person\" .

 ex:person-age rdf:type w:text-field ;
-              data:rank 4 ;
+              data:rank 2 ;
               data:bindo ont:age ;
               dc:title \"Age\" ;
               dc:description \"The age of a person\".
-
-ex:pets-list rdf:type w:list ;
-             data:bindo ont:haspet ;
-             dc:title \"Pets\" ;
-             dc:description \"A list of the pets a person has\" .

 ")

@@ -723,67 +718,6 @@
 w:text-field rdfs:subClassOf data:relator .

 w:h1 rdfs:subClassOf data:container .
-")
-
-(def data-binder "
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix data: <http://logangilmour.com/data-binder#> .
-
-data:root rdf:type rdfs:property ;
-          rdfs:range data:serializer ;
-          rdfs:domain data:view .
-
-data:serializer rdf:type rdfs:class .
-
-data:view rdf:type rdfs:class .
-
-data:binds rdf:type rdfs:property .
-
-data:binds rdfs:domain data:serializer .
-
-data:label rdf:type
-
-
-")
-
-(def ontology "
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix ont: <http://logangilmour.com/example-ontology#> .
-@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
-
-ont:person rdf:type rdfs:class .
-
-ont:name rdf:type rdfs:property .
-ont:name rdfs:domain ont:person .
-ont:name rdfs:range xsd:string .
-ont:age rdfs:domain ont:person .
-ont:age rdfs:range xsd:integer .
-
-")
-
-(def data "
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix ont: <http://logangilmour.com/example-ontology#> .
-@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
-@prefix test: <http://logangilmour.com/test#> .
-
-test:logan ont:name \"Logan Gilmour\" ;
-           rdf:type ont:person ;
-           ont:age 23 .
-
-test:logan ont:haspet \"Dog\" ;
-           ont:haspet \"Tomato\" .
-
-test:dave ont:name \"Dave Davidson\" ;
-          rdf:type ont:person ;
-          ont:age 25 .
-
-test:dave ont:haspet \"Monster\" ;
-          ont:haspet \"Truck\" ;
-          ont:haspet \"Salamander\" .
 ")

@@ -810,7 +744,7 @@
     ;;(logger/init)
     ))

-(def data-model (to-model data))
+;;(def data-model (to-model data))

 (def broadcast-channel (permanent-channel))
 (def edit (editor (to-model example-view)))


Don't use a lambda when the fn itself suffices

--- src/desdemona/utils.clj
+++ src/desdemona/utils.clj
@@ -180,4 +180,4 @@
 (defn collect-outputs! [lifecycles output-tasks]
   (->> output-tasks
        (map #(get-output-channel (channel-id-for lifecycles %)))
-       (map #(take-segments! %))))
+       (map take-segments!)))


refactoring

refactoring

--- src/notehub/handler.clj
+++ src/notehub/handler.clj
@@ -19,7 +19,7 @@
   (quot (System/currentTimeMillis) 100000000))

 ; note page cache
-(def C (atom (cache/lru-cache-factory {})))
+(def page-cache (atom (cache/lru-cache-factory {})))

 ; TODO: make sure the status is really set to the response!!!!
 (defn- response
@@ -85,14 +85,14 @@
              note-id (api/build-key year month day title)
              short-url (storage/create-short-url note-id params)]
          (when (storage/note-exists? note-id)
-           (if (cache/has? @C short-url)
+           (if (cache/has? @page-cache short-url)
              (do
-               (swap! C cache/hit short-url)
+               (swap! page-cache cache/hit short-url)
                (storage/increment-note-view note-id))
-             (swap! C cache/miss short-url
+             (swap! page-cache cache/miss short-url
                     (note-page (api/get-note {:noteID note-id})
                                (api/url short-url))))
-           (cache/lookup @C short-url))))
+           (cache/lookup @page-cache short-url))))

   (GET "/:short-url" [short-url]
        (when-let [params (storage/resolve-url short-url)]
@@ -132,7 +132,7 @@
               (if (get-in resp [:status :success])
                 (do
                   (doseq [url (storage/get-short-urls noteID)]
-                    (swap! C cache/evict url))
+                    (swap! page-cache cache/evict url))
                   (redirect (:longURL resp)))
                 (response 403)))
             (response 500))))


fix spelling error

fix spelling error

--- src/overtone/sc/bus.clj
+++ src/overtone/sc/bus.clj
@@ -60,7 +60,7 @@
          {:type ::control-bus}))))

 (defn audio-bus
-  "Allocate one ore more audio busses."
+  "Allocate one or more audio busses."
   ([] (audio-bus 1))
   ([n-channels]
      (let [id (alloc-id :audio-bus n-channels)]


fix bug in doseq destructuring. Re-creation of instrument groups on :reset *still* needs to be implemented

--- src/overtone/studio.clj
+++ src/overtone/studio.clj
@@ -16,9 +16,10 @@

 (defonce _on-connect_ (on :connected create-inst-group))

-; Clear and re-create the instrument groups after a reset
+;; Clear and re-create the instrument groups after a reset
+;; TODO: re-create the instrument groups
 (defn reset-inst-groups []
-  (doseq [inst @instruments*]
+  (doseq [[name inst] @instruments*]
     (group-clear (:group inst))))

 (defonce _reset_inst (on :reset #'reset-inst-groups))


Filter empty stdout responses

Filter empty stdout responses

--- src/replme/web/repl.clj
+++ src/replme/web/repl.clj
@@ -1,5 +1,5 @@
 (ns replme.web.repl
-  (:require [clojure.core.async :refer [go <! >! <!! >!! chan close! go-loop]]
+  (:require [clojure.core.async :refer [go <! >! <!! >!! chan close! go-loop filter<]]
             [org.httpkit.server :refer [send! with-channel on-receive on-close open? websocket?]]
             [http.async.client :as http]
             [clojure.tools.logging :as log]
@@ -12,8 +12,7 @@
 (defn- docker-attach
   [client id]
   (let [output (chan)
-        url (str "http://" (:host client) "/containers/" id "/logs?stdout=1&follow=1")
-        http-client (http/create-client)]
+        url (str "http://" (:host client) "/containers/" id "/logs?stdout=1&follow=1") http-client (http/create-client)]
     (go
       (log/info "Reading logs from: " url)
       (doseq [msg (http/string (http/stream-seq http-client :get url))]
@@ -95,10 +94,24 @@
     (when (open? channel)
       (recur (<! out-chan)))))

+(defn- not-empty?
+  [{:keys [message]}]
+  (cond
+   (= "\n" message) false
+   (= "\r\n" message) false
+   (= "" message) false
+   :else true))
+
+(defn- format-msgs
+  [msg]
+  msg)
+
+(def format-out (comp (map format-msgs) (filter not-empty?)))
+
 (defn open-websocket
   [docker-client req repo]
   (let [in-chan (chan)
-        out-chan (chan)]
+        out-chan (chan 1 format-out)]
     (with-channel req channel
       (if (websocket? channel)
         (let [[docker-id http-client] (docker-repl docker-client repo in-chan out-chan)


fix misnamed function

fix misnamed function

--- src-cljs/frontend/components/canvas.cljs
+++ src-cljs/frontend/components/canvas.cljs
@@ -551,7 +551,7 @@
                                                (.preventDefault event)
                                                (.stopPropagation event)
                                                (js/clearInterval (om/get-state owner :touch-timer))
-                                               ((:handle-mouse-move! handlers) (aget touches "0")))
+                                               ((:handle-mouse-move handlers) (aget touches "0")))

                                              (= (.-length touches) 2)
                                              (do


un-reverse 'natural scroll' y axis function

--- src-cljs/frontend/components/canvas.cljs
+++ src-cljs/frontend/components/canvas.cljs
@@ -105,8 +105,8 @@
                                                 (let [dx     (- (aget event "deltaX"))
                                                       dy     (if (aget event "nativeEvent" "webkitDirectionInvertedFromDevice")
                                                                ;; Detect inverted scroll (natural scroll)
-                                                               (aget event "deltaY")
-                                                               (- (aget event "deltaY")))]
+                                                               (- (aget event "deltaY"))
+                                                               (aget event "deltaY"))]
                                                   (om/transact! payload (fn [state]
                                                                           (let [camera (cameras/camera state)
                                                                                mode   (cameras/camera-mouse-mode state)]


add instructions for the user that created the issue

--- src-cljs/frontend/components/canvas.cljs
+++ src-cljs/frontend/components/canvas.cljs
@@ -403,17 +403,32 @@
                                      (om/get-state owner :listener-key)))
     om/IRender
     (render [_]
-      (let [{:keys [cast! issue-db]} (om/get-shared owner)]
+      (let [{:keys [cast! issue-db cust]} (om/get-shared owner)
+            font-size 24]
         (dom/g nil
           (when-let [issue (issue-model/find-by-doc-id @issue-db document-id)]
-            (svg-element {:layer/type :layer.type/text
-                          :layer/text (str "Feature request -- " (:issue/title issue))
-                          :layer/start-x 100
-                          :layer/end-x 100
-                          :layer/start-y 100
-                          :layer/end-y 100
-                          :className "text-layer issue-layer"
-                          :onClick #(cast! :issue-layer-clicked {:frontend/issue-id (:frontend/issue-id issue)})})))))))
+            (dom/g nil
+              (svg-element {:layer/type :layer.type/text
+                            :layer/text (str "Feature request -- " (:issue/title issue))
+                            :layer/start-x 100
+                            :layer/end-x 100
+                            :layer/start-y 100
+                            :layer/end-y 100
+                            :layer/font-size font-size
+                            :key "issue-title"
+                            :className "text-layer issue-layer"
+                            :onClick #(cast! :issue-layer-clicked {:frontend/issue-id (:frontend/issue-id issue)})})
+              (when (= (:cust/email cust) (:issue/author issue))
+                (svg-element {:layer/type :layer.type/text
+                              :layer/text "Draw anything here to help illustrate your idea."
+                              :layer/start-x 100
+                              :layer/end-x 100
+                              :layer/start-y (+ 100 font-size)
+                              :layer/end-y (+ 100 font-size)
+                              :layer/font-size 16
+                              :key "doc-instructions"
+                              :className "text-layer issue-layer"
+                              :onClick #(cast! :issue-layer-clicked {:frontend/issue-id (:frontend/issue-id issue)})})))))))))

 (defn subscriber-cursor-icon [tool]
   (case (name tool)


Hide features link until we build that page

--- src-cljs/frontend/components/footer.cljs
+++ src-cljs/frontend/components/footer.cljs
@@ -17,7 +17,8 @@
     [:div.col-sm-3
      [:ul.list-unstyled
       [:li.header "Product"]
-      [:li [:a {:href "/features"} "Features"]]
+      ;; TODO: features page
+      ;; [:li [:a {:href "/features"} "Features"]]
       [:li [:a {:href "/mobile"} "Mobile"]]
       [:li [:a {:href "/enterprise"} "Enterprise"]]
       (when-not (config/enterprise?)


don't spellcheck names

don't spellcheck names

--- src-cljs/frontend/components/issues.cljs
+++ src-cljs/frontend/components/issues.cljs
@@ -175,6 +175,7 @@
                   :class (str "issue-name-input " (when-not (seq cust-name) "empty "))
                   :type "text"
                   :ref "name-input"
+                  :spell-check false
                   :value (or editing-name cust-name "")
                   :onBlur #(submit-form)
                   ;;:onChange #(om/set-state! owner :editing-name (.. % -target -value))


fix reflection boxed math on edn reader

fix reflection boxed math on edn reader

--- src/main/clojure/clojure/tools/reader/edn.clj
+++ src/main/clojure/clojure/tools/reader/edn.clj
@@ -80,19 +80,21 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defn- read-unicode-char
-  ([^String token offset length base]
-     (let [l (+ offset length)]
-       (when-not (== (count token) l)
-         (throw (IllegalArgumentException. (str "Invalid unicode character: \\" token))))
-       (loop [i offset uc 0]
-         (if (== i l)
-           (char uc)
-           (let [d (Character/digit (int (nth token i)) (int base))]
-             (if (== d -1)
-               (throw (IllegalArgumentException. (str "Invalid digit: " (nth token i))))
-               (recur (inc i) (long (+ d (* uc base))))))))))
+  ([^String token ^long offset ^long length ^long base]
+   (let [l (+ offset length)]
+     (when-not (== (count token) l)
+       (throw (IllegalArgumentException. (str "Invalid unicode character: \\" token))))
+     (loop [i offset uc 0]
+       (if (== i l)
+         (char uc)
+         (let [d (Character/digit (int (nth token i)) (int base))]
+           (if (== d -1)
+             (throw (IllegalArgumentException. (str "Invalid digit: " (nth token i))))
+             (recur (inc i) (long (+ d (* uc base))))))))))

   ([rdr initch base length exact?]
+   (let [length (long length)
+         base (long base)]
      (loop [i 1 uc (Character/digit (int initch) (int base))]
        (if (== uc -1)
          (throw (IllegalArgumentException. (str "Invalid digit: " initch)))
@@ -110,7 +112,7 @@
                  (if (== d -1)
                    (throw (IllegalArgumentException. (str "Invalid digit: " ch)))
                    (recur (inc i) (long (+ d (* uc base))))))))
-           (char uc))))))
+           (char uc)))))))

 (def ^:private ^:const upper-limit (int \uD7ff))
 (def ^:private ^:const lower-limit (int \uE000))


DM + RS - Define resources for generating and serving 'secrets' from an atom

--- src/freecoin/routes.clj
+++ src/freecoin/routes.clj
@@ -41,6 +41,7 @@
    [freecoin.auth :as auth]
    [freecoin.db :as db]

+   [freecoin.fxc :as fxc]
    )
   )

@@ -88,6 +89,8 @@
 (declare fake-signup)
 (declare simple-resource)
 (declare tag-session)
+(declare secret)
+(declare secrets)

 ;; routes
@@ -109,6 +112,8 @@
                                            " (" (.. System getProperties (get "os.arch")) ")")
                                       )
        )
+  (ANY "/secrets" [request] (secrets request))
+  (ANY "/secrets/:secret-id" [secret-id :as request] (secret request secret-id))

   ) ; end of routes

@@ -127,6 +132,27 @@
   :handle-ok (fn [ctx]
                (ring-response (assoc-in (as-response "Session updated." ctx)
                                         [:session :dates] (::new-dates ctx)))))
+
+(def secrets-store (atom {}))
+
+(defresource secrets [request]
+  :allowed-methods [:get :post]
+  :available-media-types ["text/plain"]
+  :handle-ok (fn [ctx] (str "secrets"))
+  :post! (fn [ctx]
+           (let [secret (fxc/create-secret ssss/config)
+                 id (:_id secret)]
+             (swap! secrets-store assoc id secret)
+             {::id id}))
+  :post-redirect? (fn [ctx] {:location (format "/secrets/%s" (::id ctx))}))
+
+(defresource secret [request secret-id]
+  :allowed-methods [:get]
+  :available-media-types ["text/plain"]
+  :exists? (fn [ctx]
+             (when-let [the-secret (get @secrets-store secret-id)]
+               {::data the-secret}))
+  :handle-ok (fn [ctx] (str (::data ctx))))

 (defresource serve [request content]
   :allowed-methods [:get]


add missing stefon entry

add missing stefon entry

--- src/frontend/stefon.clj
+++ src/frontend/stefon.clj
@@ -100,6 +100,7 @@
            "docs/skip-a-build.md"
            "docs/ssh-build.md"
            "docs/status-badges.md"
+           "docs/test-metadata.md"
            "docs/test-with-solr.md"
            "docs/time-day.md"
            "docs/time-seconds.md"


todo comment

todo comment

--- src/terraboot/infra.clj
+++ src/terraboot/infra.clj
@@ -5,6 +5,7 @@

 (def infra-path "infra/")

+;; other todo: public slave port and listeners being parameters (as this is determined by applications)
 (defn generate-json [target]
   (let [account-number "165664414043"
         azs [:a]]


[#2254] Allow remove columns with isolated txs applied

--- backend/test/akvo/lumen/lib/transformation_test.clj
+++ backend/test/akvo/lumen/lib/transformation_test.clj
@@ -306,20 +306,37 @@
                                       :data (import.s/sample-imported-dataset [:text :number :text :number :text :number :text :number] 2)
                                       :with-job? true})
           dataset-id (:dataset_id dataset)
+          apply-transformation (partial async-tx-apply {:tenant-conn *tenant-conn*} dataset-id)
           dataset (dataset-version-by-dataset-id *tenant-conn* {:dataset-id dataset-id
                                                                 :version 1})
           stored-data (->> (latest-dataset-version-by-dataset-id *tenant-conn*
                                                                  {:dataset-id dataset-id})
                            (get-data *tenant-conn*))]
       (testing "Testing columns are removed without tx"
-        (log/error :job job)
-       (let [updated-res (update-file *tenant-conn* *error-tracker* (:dataset-id job) (:data-source-id job)
-                                      {:kind "clj"
-                                       :with-job? true
-                                       :data (import.s/sample-imported-dataset [:text :number :text :number :text :number] 2)})]
-         (log/error :updated-res updated-res)
-         (is (some? updated-res))))
-      )))
+        (let [updated-res (update-file *tenant-conn* *error-tracker* (:dataset-id job) (:data-source-id job)
+                                       {:kind "clj"
+                                        :with-job? true
+                                        :data (import.s/sample-imported-dataset [:text :number :text :number :text :number] 2)})]
+          (is (some? updated-res))))
+
+      (testing "Removing column with change-datatype tx"
+        (let [_ (apply-transformation (change-datatype-tx "c6" "text"))
+              updated-res (update-file *tenant-conn* *error-tracker* (:dataset-id job) (:data-source-id job)
+                                       {:kind "clj"
+                                        :with-job? true
+                                        :data (import.s/sample-imported-dataset [:text :number :text :number :text] 2)})]
+          (is (some? updated-res))))
+      (testing "Removing column with delete-column tx"
+        (let [_ (apply-transformation {:type :transformation
+                                       :transformation
+                                       (gen-transformation "core/delete-column"
+                                                           {::db.dataset-version.column.s/columnName "c5"
+})})
+              updated-res (update-file *tenant-conn* *error-tracker* (:dataset-id job) (:data-source-id job)
+                                       {:kind "clj"
+                                        :with-job? true
+                                        :data (import.s/sample-imported-dataset [:text :number :text :number] 2)})]
+          (is (some? updated-res)))))))

 (deftest ^:functional derived-column-test
   (let [dataset-id (import-file *tenant-conn* *error-tracker* {:has-column-headers? true


Fix a mistake.

Fix a mistake.


Added a 'reset' method to allow admin to put state back to 'default config'

--- src/toggler/handler.clj
+++ src/toggler/handler.clj
@@ -5,7 +5,10 @@
             [liberator.core :refer [resource defresource]]
             [cheshire.core :refer :all]))

-(def cfg (atom (decode (slurp "resources/config.json") true)))
+(defn read-default-config []
+  (decode (slurp "resources/config.json") true))
+
+(def cfg (atom (read-default-config)))

 (defn getoggle
   ([] @cfg)
@@ -17,6 +20,9 @@

 (defn reload-config [config]
   (reset! cfg config))
+
+(defn reset-cfg []
+  (reload-config read-default-config))

 (defresource status
   :allowed-methods [:get]
@@ -68,6 +74,7 @@
   (GET "/" [] status)
   (PUT "/reconfigure" {body :body} (let [bodydecoded (decode (slurp body) true)]
                                      (reload-config bodydecoded)))
+  (GET "/reset" [] (reset-cfg))
   (GET "/toggle" [] get-toggle-all)
   (GET "/toggle/:component" [component] (get-toggle-all-for-component component))
   (GET "/toggle/:component/:setting" [component setting] (get-toggle-for-component-and-setting component setting))


[scamp] remove unused 'node-contact-address->node-neighbors fn

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -259,11 +259,6 @@
           :heartbeat-timeout-milli-time nil
           :clock nil}
          init-vals))
-
-(s/defn node-contact-address->node-neighbors :- NodeNeighborsSchema
-  "Take a 'node-contact-address, and return an initialized node-neighbor."
-  [node-contact-address :- NodeContactAddressSchema]
-  {node-contact-address default-node-neighbor})

 (s/defn node-neighbors->contact-addresses :- [NodeContactAddressSchema]
   [node-neighbors :- NodeNeighborsSchema]


[scamp] update some comments & docstrings

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -82,6 +82,8 @@
    })

 (def SelflessNodeSchemaOptional
+  "Just like SelflessNodeSchema, but every key is optional.
+  This is used for schema checking of init-value maps."
   (->> SelflessNodeSchema
        (map
         (fn [[k v]]
@@ -107,7 +109,7 @@
    ;; inform newly :downstream node that you are now in its :upstream
    :new-upstream-node

-   ;; I added this to make it possible to instruct a node to
+   ;; Not in SCAMP: added to make it possible to instruct a node to
    ;; unsubscribe.
    :node-unsubscription

@@ -183,8 +185,8 @@
           ;; :port 2005
           }

-   ;; :partial-view :downstream
-   ;; :local-view :downstream
+   ;; :partial-view from [1] = :downstream
+   ;; :local-view from [1] = :downstream
    :downstream #{"node-id1" ; node-contact-address for node-id1
                  "node-id2" ; node-contact-address for node-id2
                  }


fix typo

fix typo

--- src/wma_clj/gen/app.clj
+++ src/wma_clj/gen/app.clj
@@ -9,7 +9,7 @@
   (let [data {:name name
               :sanitized (name-to-path name)}
         render (renderer "wma-clj")]
-       (main/info "Generating fresh 'lein new' wma-clj 'command line' project.")
+       (main/info "Generating fresh 'lein new' wma-clj 'application' project.")
        (->files data
                 [".gitignore" (render "app/gitignore" data)]
                 ["project.clj" (render "app/project.clj" data)]


Provide feedback when BPM locked due to sync.

--- src/afterglow/controllers/ableton_push.clj
+++ src/afterglow/controllers/ableton_push.clj
@@ -405,11 +405,28 @@
         :dj-link (rhythm/metro-bar-start metronome (rhythm/metro-bar metronome))
         (warn "Don't know how to tap tempo for sync type" (show/sync-status))))))

+(defn- metronome-sync-label
+  "Determine the sync type label to display under the BPM section."
+  [controller]
+  (with-show (:show controller)
+    (case (:type (show/sync-status))
+      :manual "Manual"
+      :midi "MIDI"
+      :dj-link "DJ Link"
+      "Unknown")))
+
 (defn- bpm-adjusting-interface
-  "Add an arrow showing the BPM is being adjusted."
-  [controller]
-  ;; TODO: Unless it is being externally synced...
-  (aset (get (:next-display controller) 2) 16 (:up-arrow special-symbols)))
+  "Add an arrow showing the BPM is being adjusted, or point out that
+  it is being externally synced."
+  [controller]
+  (if (= (:type (show/sync-status)) :manual)
+    (aset (get (:next-display controller) 2) 16 (:up-arrow special-symbols))
+    (do
+      (aset (get (:next-display controller) 2) 9 (:down-arrow special-symbols))
+      (when-not (:showing (:metronome-mode controller))
+        ;; We need to display the sync mode in order to point at it
+        #_(write-display-cell controller 3 0
+                            (str "         " (metronome-sync-label controller)))))))

 (defn sign-velocity
   "Convert a midi velocity to its signed equivalent, to translate
@@ -420,11 +437,13 @@
      val))

 (defn- adjust-bpm-from-encoder
-  "Adjust the current BPM based on how the encoder was twisted."
+  "Adjust the current BPM based on how the encoder was twisted, unless
+  the metronome is synced."
   [controller message]
-  (let [delta (/ (sign-velocity (:velocity message)) 10)
-        bpm (rhythm/metro-bpm (:metronome (:show controller)))]
-    (rhythm/metro-bpm (:metronome (:show controller)) (+ bpm delta))))
+  (when (= (:type (show/sync-status)) :manual)
+    (let [delta (/ (sign-velocity (:velocity message)) 10)
+          bpm (rhythm/metro-bpm (:metronome (:show controller)))]
+      (rhythm/metro-bpm (:metronome (:show controller)) (+ bpm delta)))))

 (defn- encoder-above-bpm-touched
   "Add a user interface overlay to give feedback when turning the
@@ -491,16 +510,6 @@
                    (when (zero? (:note message))
                      ;; They released us, end the overlay.
                      :done)))))
-
-(defn- metronome-sync-label
-  "Determine the sync type label to display under the BPM section."
-  [controller]
-  (with-show (:show controller)
-    (case (:type (show/sync-status))
-      :manual "Manual"
-      :midi "MIDI"
-      :dj-link "DJ Link"
-      "Unknown")))

 (defn- enter-metronome-showing
   "Activate the persistent metronome display, with sync and reset pads


Added key-str function. Thanks to Yuri Niyazov for the suggestion and the patch.

--- src/appengine_magic/services/datastore.clj
+++ src/appengine_magic/services/datastore.clj
@@ -223,7 +223,7 @@

 ;;; ----------------------------------------------------------------------------
-;;; query helper objects and functions
+;;; query helper objects and functions; do not use these directly
 ;;; ----------------------------------------------------------------------------

 (defrecord QueryFilter [operator property value])
@@ -510,3 +510,76 @@
                      ~start-cursor ~end-cursor
                      ~prefetch-size ~chunk-size
                      ~entity-record-type))))
+
+
+(defn- get-key-str-helper [key]
+  (let [str-key (str key)]
+    (if (empty? str-key)
+        (throw (IllegalArgumentException.
+                (str "get-key-str must be called on an object with a datastore key, "
+                     "i.e., an object already persisted with save!")))
+        str-key)))
+
+
+(defn key-str
+  "Given an object, or a kind and an object, returns a string representation of
+   the object's key, e.g., \"User(10)\". It must be called after an object
+   already has acquired a key. The kind may be a string representing a datastore
+   kind, or an entity record defined with defentity. This function provides a
+   useful general-purpose mechanism for determining a unique identifier for a
+   datastore entity. Note that the resulting key string cannot, by itself, be
+   used for datastore queries. It is likely to be more helpful for saving
+   entities in, e.g., memcache.
+
+   The object argument can be the result of a KeyFactory/keyToString call, an
+   existing Key, or an existing entity record instance.
+
+   > (key-str \"ahNhcHBlbmdpbmUtbWFnaWMtYXBwcgoLEgRVc2VyGAgM\")
+   \"User(8)\"
+   > (key-str User 8)
+   \"User(8)\"
+   > (key-str User \"8\")
+   \"User(8)\"
+   > (key-str user-object)
+   \"User(8)\""
+  ([obj]
+     (let [key (cond
+                ;; an entity; use its existing key
+                (extends? EntityProtocol (class obj))
+                (str (get-key-object obj))
+                ;; already a Key; use it
+                (instance? Key obj)
+                obj
+                ;; a string; make a Key
+                (string? obj)
+                (KeyFactory/stringToKey obj))]
+       (get-key-str-helper key)))
+  ([kind obj]
+     (let [kind (cond
+                 ;; already a string
+                 (string? kind)
+                 kind
+                 ;; probably an entity class
+                 (class? kind)
+                 (unqualified-name kind)
+                 ;; no clue
+                 :else (throw (IllegalArgumentException. "unsupported kind argument type")))
+           key (cond
+                ;; an entity; use its existing key
+                (extends? EntityProtocol (class obj))
+                (str (get-key-object obj))
+                ;; already a Key; use it
+                (instance? Key obj)
+                obj
+                ;; an ID, probably assigned by the datastore
+                (number? obj)
+                (KeyFactory/createKey kind (coerce-key-value-type obj))
+                ;; string - either a stringified number e.g. "8"
+                ;; or the result of calling KeyFactory/keyToString
+                ;; or something unrecognizable - throws IllegalArgumentException
+                (string? obj)
+                (if-let [long-key (try (Long/parseLong obj)
+                                       (catch NumberFormatException _ nil))]
+                    (KeyFactory/createKey kind long-key)
+                    (KeyFactory/stringToKey obj)))]
+       (get-key-str-helper key))))


identifier search within the parse tree

identifier search within the parse tree

--- src/be/ac/ua/aspchecker/transformation.clj
+++ src/be/ac/ua/aspchecker/transformation.clj
@@ -90,20 +90,20 @@
 (defn ternary? [exp]
   (and
     (= (.getChildCount exp) 5)
-    (= ":" (.getText (.getChild exp 1)))
-    (= "?" (.getText (.getChild exp 3)))))
+    (= "?" (.getText (.getChild exp 1)))
+    (= ":" (.getText (.getChild exp 3)))))

 (defn method-call? [exp]
   (or
-  (and
-    (= (.getChildCount exp) 3)
-    (= "(" (.getText (.getChild exp 1)))
-    (= ")" (.getText (.getChild exp 2))))
-  (and
-    (= (.getChildCount exp) 4)
-    (= "(" (.getText (.getChild exp 1)))
-    (= ")" (.getText (.getChild exp 3))))))
+    (and
+      (= (.getChildCount exp) 3)
+      (= "(" (.getText (.getChild exp 1)))
+      (= ")" (.getText (.getChild exp 2))))
+    (and
+      (= (.getChildCount exp) 4)
+      (= "(" (.getText (.getChild exp 1)))
+      (= ")" (.getText (.getChild exp 3))))))

 (defn member-access? [exp]
@@ -117,7 +117,7 @@
   (and
     (= (.getChildCount exp) 4)
     (= "[" (.getText (.getChild exp 1)))
-    (= "]" (.getText (.getChild exp 3)))
+    (= "]" (.getText (.getChild exp 3)))))

 ;Contract parsing
@@ -191,11 +191,11 @@

 (defn visit-method-call [rule]
   (str
-  "__method_call__"
-  (visit-rule (.getChild rule 0))
-  (when
-    (= (.getChildCount rule) 4)
-    (hash (.getText (.getChild rule 2))))))
+    "__method_call__"
+    (visit-rule (.getChild rule 0))
+    (when
+      (= (.getChildCount rule) 4)
+      (hash (.getText (.getChild rule 2))))))

 (defn visit-member-access [rule]
@@ -210,10 +210,12 @@
     "__vector_access__"
     (visit-rule (.getChild rule 0))
     (hash (.getText (.getChild rule 2)))))
-
+

 (defn visit-children [rule]
-  (loop [result "" i 0 max (.getChildCount rule)]
+  (loop [result ""
+         i 0
+         max (.getChildCount rule)]
     (if
       (= i max)
       result
@@ -242,4 +244,44 @@

 (defn transform [contract]
-  (visit-rule (parse-contract contract)))+  (visit-rule (parse-contract contract)))
+
+
+;Sort retrieval
+
+(defn creates-identifier? [rule]
+  (or
+    (and
+      (terminal? rule)
+      (.contains (.toString (.getPayload rule)) "<100>"))
+    (method-call? rule)
+    (member-access? rule)
+    (vector-access? rule)))
+
+
+(defn infer-type [rule])
+
+
+;Get the type of the other element of the binary relationship
+(defn match-symmetric-type [rule]
+  (if
+    (= (.getChild (.getParent rule) 0) rule)
+    (infer-type (.getChild (.getParent rule) 2))
+    (infer-type (.getChild (.getParent rule) 0))))
+
+
+(defn retrieve-sorts [root]
+  (loop [result []
+         i 0
+         max (.getChildCount root)]
+    (if
+      (= i max)
+      result
+      (let [cur (.getChild root i)]
+        (cond
+          ;adds the identifier and keep iterating children
+          (creates-identifier? cur) (recur (conj result (visit-rule cur)) (+ i 1) max)
+          ;skips terminal
+          (terminal? cur) (recur result (+ i 1) max)
+          ;keeps going down on the tree
+          :else (recur (into [] (concat result (retrieve-sorts cur))) (+ i 1) max))))))


Add comment explaining lack of bounds checking

--- src/braid/core/client/ui/views/thread.cljs
+++ src/braid/core/client/ui/views/thread.cljs
@@ -102,6 +102,8 @@
                       (swap! selected-row (comp (partial max 0) dec))

                       "ArrowDown"
+                      ;; not guarding this because the above `run!`
+                      ;; will make sure that it stays in bounds
                       (swap! selected-row inc)

                       "Enter"


adding more file metadata

adding more file metadata

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -35,11 +35,15 @@
   (let [tmpfile  (boot/tmp-file f)
         filename (.getName tmpfile)
         tmp-path (boot/tmp-path f)]
-    {:filename  filename
-     :path      tmp-path
+    {; filename with extension
+      :filename    filename
+     ; filename without extension
+     :name        (perun/filename filename)
+     :path        tmp-path
+     ; parent folder path
      :parent-path (perun/parent-path tmp-path filename)
-     :full-path (.getPath tmpfile)
-     :extension (perun/extension filename)}))
+     :full-path   (.getPath tmpfile)
+     :extension   (perun/extension filename)}))

 (deftask base
   "Adds some basic information to the perun metadata and


Optimize default sketch so it opens faster.

--- src/clj/quil_site/controllers/sketches.clj
+++ src/clj/quil_site/controllers/sketches.clj
@@ -82,9 +82,10 @@
         id))))

 (defn get-source-for-id [id]
-  (if (.startsWith id "example_")
-    (get-example id)
-    (s/load-source id)))
+  (cond
+    (.startsWith id "example_") (get-example id)
+    (= id "basic") test-source
+    :default (s/load-source id)))

 (defn sketch-from-source [source id]
   (let [parsed (parse-cljs source)


Edited the returned actions and spec-refs so that they are proper maps instead of the id being the key to the data.

--- src/clj_formal_specifications_app/core.clj
+++ src/clj_formal_specifications_app/core.clj
@@ -44,23 +44,25 @@
   [map-entry]
   (:spec-ref (meta (var-get (val map-entry)))))

-(defn assoc-action-to-spec
-  [spec action-entry]
-  (assoc-in spec
-            [:actions (key action-entry)]
-            {:arglists (:arglists (meta (val action-entry)))}))
+(defn conj-actions
+  [actions action-entry]
+  (conj actions {:id (key action-entry)
+                 :arglist (first (:arglists (meta (val action-entry))))}))

-(defn assoc-spec-ref-to-spec
-  [spec spec-ref-entry]
-  (assoc-in spec
-            [:spec-refs (key spec-ref-entry)]
-            {:data @(var-get (val spec-ref-entry))}))
+(defn conj-spec-refs
+  [spec-refs spec-ref-entry]
+  (conj spec-refs {:id (key spec-ref-entry)
+                   :data @(var-get (val spec-ref-entry))}))

 (defn assoc-to-spec
  [spec map-entry]
   (cond
-   (action-entry? map-entry) (assoc-action-to-spec spec map-entry)
-   (spec-ref-entry? map-entry) (assoc-spec-ref-to-spec spec map-entry)
+   (action-entry? map-entry)
+   (assoc spec :actions (conj-actions (:actions spec) map-entry))
+
+   (spec-ref-entry? map-entry)
+   (assoc spec :spec-refs (conj-spec-refs (:spec-refs spec) map-entry))
+
    :else spec))

 (defn ns-spec


pass in char set rather than mutate

pass in char set rather than mutate

--- src/cljs/infinitelives/pixi/pixelfont.cljs
+++ src/cljs/infinitelives/pixi/pixelfont.cljs
@@ -44,45 +44,39 @@
                                          x y visible
                                          xhandle yhandle]
                                   :or {scale s/*default-scale*
-                                       visible true}}]
-  (let [font (get-font font-key)
-        batch (s/make-container
-               []
-               :particle (not tint)
-               :scale scale
-               :rotation rotation
-               :x x
-               :y y
-               :visible visible
-               )]
-    (loop [[c & l] (seq text)
-           xp 0 yp 0
-           last-c nil]
-      (let [char ((:font font) c)
-            {:keys [texture pos size]} char
-            [x y] pos
-            [w h] size
-            pair (str last-c c)
-            koff ((:kerning font) pair)
-            ]
-        (if (nil? char)
-          ;; if character is not present in font map, put a space
-          (when (seq l)
-            (recur l (+ xp (:space font)) yp c))
+                                       visible true
+                                       xhandle 0.5
+                                       yhandle 0.5}}]
+  (let [font (get-font font-key)]
+    (s/make-container
+     (loop [[c & l] (seq text)
+            xp 0 yp 0
+            last-c nil ;; remember last character for kerning
+            sprite-set []]
+       (let [char ((:font font) c)
+             {:keys [texture pos size]} char
+             [x y] pos
+             [w h] size
+             pair (str last-c c)
+             koff ((:kerning font) pair)
+             ]
+         (if (nil? char)
+           ;; if character is not present in font map, put a space
+           (when (seq l)
+             (recur l (+ xp (:space font)) yp c sprite-set))

-          (do
-                                        ;character is present, add the sprite to the container
-            (.addChild batch (s/make-sprite texture :x (+ xp koff) :y yp :xhandle 0 :yhandle 0 :tint tint :scale 1))
-            (if (seq l)
-              (recur l (+ xp w 1.0 koff) yp c)
-              (s/set-pivot! batch (/ (+ xp w koff) 2.0) 0))))))
-
-    ;; set setup details
-    ;; (when xhandle
-    ;;   (s/set-xhandle! batch xhandle))
-    ;; (when yhandle
-    ;;   (s/set-yhandle! batch yhandle))
-    batch))
+           (let [sprite (s/make-sprite texture :x (+ xp koff) :y yp :xhandle 0 :yhandle 0 :tint tint :scale 1)]
+             (if (seq l)
+               (recur l (+ xp w 1.0 koff) yp c (conj sprite-set sprite))
+               (conj sprite-set sprite))))))
+     :particle (not tint)
+     :scale scale
+     :rotation rotation
+     :x x
+     :y y
+     :visible visible
+     :xhandle xhandle
+     :yhandle yhandle)))

 (comment
   (infinitelives.pixi.pixelfont/load-pixel-font :test-font :test [["A" 146 89 140 97] ["B" 154 89 148 97]])


Add remaining test cases for anchor circle.

--- spec/freefrog/rest_spec.clj
+++ spec/freefrog/rest_spec.clj
@@ -151,6 +151,25 @@
           (it "should return method-not-allowed."
             (should= 405 (:status @delete-response))))

+        (context "with updating the anchor circle"
+          (context "with invalid parameters"
+            (with response (http-put-request
+                             "/"
+                             (json/generate-string
+                               {:command "anchorCircle",
+                                :params {:foo "Test Circle!"}})))
+            (xit "should return an error response"))
+
+          (context "with valid parameters"
+            (with response (http-put-request
+                             "/"
+                             (json/generate-string
+                               {:command "anchorCircle",
+                                :params {:name "Test Circle!"
+                                         :lead-link-name "Bill"
+                                         :lead-link-email "bfinn@example.com"}})))
+            (xit "should return the location of the updated resource")))
+
         (context "with creating a role"
           (context "with valid parameters"
             (with response (http-post-request
@@ -160,9 +179,10 @@
                                 :params {:name "Test Circle!"
                                          :lead-link-name "Bill"
                                          :lead-link-email "bfinn@example.com"}})))
-            (it "should return the location of the newly created resource"))))
-      ;(should= 201 (:status @response))
-      ;(should= (str "/circles/" (url-encode "Test Circle!")) (get-location @response))))))
+            (xit "should return the location of the newly created resource"
+                 (should= 201 (:status @response))
+                 (should= (str "/" (url-encode "Test Circle!"))
+                          (get-location @response))))))

       (should-return-4xx "with invalid paramaters"
                          (fn [] "circles")


+(deftest past-participle-orthography)

+(deftest past-participle-orthography)

--- test/babel/test/en.cljc
+++ test/babel/test/en.cljc
@@ -529,6 +529,12 @@
     (is (= "I am participating (right now)" (morph (generate spec1))))
     (is (= "I am hoping (right now)" (morph (generate spec2))))))

+(deftest past-participle-orthography
+  (is (= (babel.english.morphology/present-participle-of "hope") "hoping"))
+  (is (= (babel.english.morphology/present-participle-of "hop") "hopping"))
+  (is (= (babel.english.morphology/present-participle-of "knot") "knotting"))
+  (is (= (babel.english.morphology/present-participle-of "note") "noting")))
+
 (deftest present-progressive-vs-present-simple
   (let [base-spec {:modified false
                    :synsem {:cat :verb


+(defn mapping), (defn show-mapping)

+(defn mapping), (defn show-mapping)

--- test/babel/test/en.cljc
+++ test/babel/test/en.cljc
@@ -598,29 +598,11 @@
          {key val})
        vals))

-
 (def as [{:a 1}{:a 2}])
 (def bs [{:b 4}{:b 5}])
 (def cs [{:c 6}{:c 7}{:c 8}])

-(defn foo [elems]
-  (let [[a-s b-s c-s] elems]
-    (if c-s
-      (->> a-s
-           (mapcat (fn [a]
-                     (->> b-s
-                          (mapcat (fn [b]
-                                    (->> c-s
-                                         (map (fn [c]
-                                                (reduce merge [a b c]))))))))))
-      (if b-s
-        (->> a-s
-             (mapcat (fn [a]
-                       (->> b-s
-                            (map (fn [b]
-                                   (reduce merge [a b])))))))
-        a-s))))
-
+;; don't use: use combo/cartesian-product instead.
 ;; how to use:
 ;;(map flatten (cross-product [1 2 3][4 5 6 7][8 9 10]))
 ;;(count (map flatten (apply cross-product (take 5 (repeatedly #(range 0 10))))))
@@ -635,3 +617,33 @@
               [(first a) each-b])
             b)
        (cross-product (rest a) b)))))
+
+(def lbs (babel.generate/lightning-bolts model spec2 0 6))
+
+(def baz2 (map (fn [lb]
+                (babel.generate/create-mapping
+                 lb (babel.generate/find-comp-paths lb)
+                 model 0 6))
+              lbs))
+
+(defn baz3 [lb]
+  (babel.generate/create-mapping
+   lb (babel.generate/find-comp-paths lb)
+   model 0 6))
+
+
+(defn mapping [spec]
+  (map (fn [lb]
+         (babel.generate/create-mapping
+          lb (babel.generate/find-comp-paths lb)
+          model 0 6))
+       (babel.generate/lightning-bolts model spec 0 6)))
+
+;; usage: (show-mapping (mapping spec1))
+(defn show-mapping [mapping]
+  (map (fn [good-one]
+         (map (fn [path]
+                (map fo-ps (get good-one path)))
+              (keys good-one)))
+       mapping))
+


Conti-2 porting LFE version of find_equil_index.js to Clojure.

--- content/src/find_equil_index.clj
+++ content/src/find_equil_index.clj
@@ -85,22 +85,35 @@
     "The solution function."
     [A]

-    (let [num-of-A (count    A)]
-    (println num-of-A)
-
     ; Calculating the complete sum of elements of A.
     (let [sum-of-A (reduce + A)]
     (println sum-of-A)
+    (println        A)

     ; Searching for the equilibrium index of A.
-    (map (fn [A- ii-]
-        (let [i- ii-]
+    (try (do
+        (loop [AA A i 0 i- 0] (when (seq AA)
+            (let [A- (first AA)]

-        (println A-)
-        (println i-))
-    ) A))
+            ; Calculating the sum of elements of lower  indices of A.
+            (let [sum-of-A-1 i-]

-    num-of-A)
+            ; Calculating the sum of elements of higher indices of A.
+            (let [sum-of-A-2 (- (- sum-of-A sum-of-A-1) A-)]
+
+            (println (str "==> sum-of-A-1: " sum-of-A-1
+                         " ==> sum-of-A-2: " sum-of-A-2
+                         " ==> i: "          i
+                         " ==> A-: "         A-))
+
+            (if (not= sum-of-A-1 sum-of-A-2) i;(throw (Exception. i))
+                (recur (rest AA) (inc i) (+ i- A-)))
+        )))))
+
+        -1 ; Returning -1 if there's no such an equilibrium index exists.
+    ) (catch
+        Exception i ; Okay, the equilibrium index found.
+    )))
 )

 (defn main


:bug: Fix custom stroke on rotated shapes


made changed to method declarations

made changed to method declarations

--- storm-core/src/clj/backtype/storm/cluster.clj
+++ storm-core/src/clj/backtype/storm/cluster.clj
@@ -162,9 +162,9 @@
   (remove-storm-base! [this storm-id])
   (set-assignment! [this storm-id info])
   (remove-storm! [this storm-id])
-  (report-error [this storm-id task-id node port error])
-  (errors [this storm-id task-id])
-  (last-error [this storm-id task-id])
+  (report-error [this storm-id component-id node port error])
+  (errors [this storm-id component-id])
+  (last-error [this storm-id component-id])
   (set-credentials! [this storm-id creds topo-conf])
   (credentials [this storm-id callback])
   (disconnect [this]))


Moved get-teas into render fn.  We now have some "jank"

--- src-cljs/tea_time/core.cljs
+++ src-cljs/tea_time/core.cljs
@@ -118,8 +118,8 @@
 (defn tealister
   "The page component for listing tea"
   []
-  (get-teas)
   (fn []
+    (get-teas)
     [:div.row
      [:ul
       [:table.table.table-striped


replace flatten + take-nth with keys

replace flatten + take-nth with keys

doubles execution speed!

--- clojure/adventofcode/src/adventofcode/days/day4.clj
+++ clojure/adventofcode/src/adventofcode/days/day4.clj
@@ -11,8 +11,7 @@
   (->> (s/replace room-name "-" "")
        (frequencies)
        (sort compare-freq)
-       (flatten)
-       (take-nth 2)
+       (keys)
        (take 5)
        (s/join)))


Cleanup curate ns, add more comments

Cleanup curate ns, add more comments

--- dev/curate.clj
+++ dev/curate.clj
@@ -1,7 +1,6 @@
 (ns curate
   "Provides data curator with tools to load data and check progress."
-  (:require [clojure.java.io :as io]
-            [clojure.edn :as edn]
+  (:require [lcmap.aardvark.config :as config]
             [lcmap.aardvark.event :as event]
             [lcmap.aardvark.server :as server]
             [lcmap.aardvark.source :as source]
@@ -10,11 +9,6 @@
             [lcmap.aardvark.util :as util]
             [lcmap.aardvark.worker :as worker]
             [mount.core :as mount]))
-
-(defn read-edn
-  "Read EDN at path. Useful for loading tile-specs and sources."
-  [path]
-  (-> path io/file slurp edn/read-string))

 (defn save-tile-specs
   "Save all tile-specs in EDN at path."
@@ -36,31 +30,45 @@
        (frequencies)))

 (defn start
-  "Start enough of the system to work with Cassandra, Elasticsearch,
-  and RabbitMQ without consuming messages or handling HTTP requests."
+  "Start enough of the system to invoke ingest.
+
+  Does not start the HTTP server or AMQP worker; see `dev/user.clj`
+  if you want to start the full system with a REPL."
   []
   (->> (mount/with-args {:config (util/read-edn "lcmap.aardvark.edn")})
-       (mount/start-without #'lcmap.aardvark.worker/worker-consumer
-                            #_#'lcmap.aardvark.server/server
+       (mount/start-without #'lcmap.aardvark.server/server
+                            #'lcmap.aardvark.worker/worker
+                            #'lcmap.aardvark.worker/worker-consumer
                             #'lcmap.aardvark.db/db-schema)))

 (comment
+  "Step 0: Configuration!
+   Update `dev/resources/lcmap.aardvark.edn` to use desired Cassandra,
+   Elasticsearch, and RabbitMQ instance. This is almost definitely *not*
+   localhost if you are curating an operational system.
+  "
+  (-> config/config :database :cluster :contact-points)
+  (-> config/config :event :host)
+  (-> config/config :search :index-url)
+
+  "Step 1: Start system."
   (start)
-  (mount/stop))

-(comment
+  "Step 2: Create tile-specs, otherwise no tiles will be saved."
   (save-tile-specs "tile-specs/L4.edn")
   (save-tile-specs "tile-specs/L5.edn")
   (save-tile-specs "tile-specs/L7.edn")
-  (save-tile-specs "tile-specs/L8.edn"))
+  (save-tile-specs "tile-specs/L8.edn")

-(comment
+  "Step 3: Enqueue one path-row from each mission. If the scene
+  has already been processed, it will be processed again."
   (save-sources "sources/washington/LT04046026.edn" 1)
   (save-sources "sources/washington/LT05046026.edn" 1)
   (save-sources "sources/washington/LE07046026.edn" 1)
-  (save-sources "sources/washington/LC8046026.edn"  1))
+  (save-sources "sources/washington/LC8046026.edn"  1)

-(comment
+  "Step 5: See how things are going. This will get the most recent
+   progress name for each source and group them together by count."
   (progress-report "sources/washington/LT04046026.edn")
   (progress-report "sources/washington/LT05046026.edn")
   (progress-report "sources/washington/LE07046026.edn")