task scheduling which triggers execution of the pulses.

--- src/metabase/task/send_pulses.clj
+++ src/metabase/task/send_pulses.clj
@@ -1,120 +1,112 @@
 (ns metabase.task.send-pulses
   "Tasks related to running `Pulses`."
   (:require [clojure.tools.logging :as log]
+            (clojurewerkz.quartzite [jobs :as jobs]
+                                    [triggers :as triggers])
+            [clojurewerkz.quartzite.schedule.cron :as cron]
             [clj-time.core :as time]
-            [korma.core :refer :all]
-            [metabase.db :refer :all]
+            [metabase.db :as db]
             [metabase.driver :as driver]
-            ;[metabase.email.messages :refer [send-email-report]]
-            ;(metabase.models [pulse :refer [EmailReport
-            ;                                      days-of-week
-            ;                                      execution-details-fields
-            ;                                      mode->id
-            ;                                      time-of-day->realhour]]
-            ;                 [emailreport-executions :refer [EmailReportExecutions]]
-            ;                 [pulse-channel-recipient :refer [EmailReportRecipients]]
-            ;                 [hydrate :refer :all])
+            [metabase.email :as email]
+            (metabase.models [card :refer [Card]]
+                             [hydrate :refer :all]
+                             [pulse :refer [Pulse] :as pulse]
+                             [pulse-channel :as pulse-channel]
+                             [setting :as setting])
             [metabase.task :as task]
             [metabase.util :as u]))

-;(declare execute-scheduled-reports
-;         execute-if-scheduled
-;         execute-and-send
-;         execute
-;         report-fail
-;         report-complete)
-;
-;(defn execute-reports-hourly-job
-;  "Simple wrapper for `execute-scheduled-reports` function which we can place on a `task/hourly-tasks-hook`"
-;  [_]
-;  (log/debug "Executing EmailReports hourly job")
-;  (execute-scheduled-reports))
-;
-;;; this adds our email report executions to our hourly task runner
-;(task/add-hook! #'task/hourly-tasks-hook execute-reports-hourly-job)
-;
-;(defn execute-scheduled-reports
-;  "Execute and Send all `EmailReports` in the system.
-;   This function checks the schedule on all :active email reports and runs them if appropriate."
-;  []
-;  (log/debug "Executing ALL scheduled EmailReports")
-;  (->> (sel :many :fields [EmailReport :id :schedule] :mode (mode->id :active))
-;       (map execute-if-scheduled)
-;       dorun))
-;
-;(defn- execute-if-scheduled
-;  "Test if a given report is scheduled to run at the current time and if so execute it."
-;  [{{:keys [days_of_week time_of_day timezone]} :schedule id :id}]
-;  (log/debug "Processing: " id days_of_week time_of_day timezone)
-;  (let [now (time/to-time-zone (time/now) (time/time-zone-for-id (or timezone "UTC"))) ; NOTE this is in LOCAL timezone
-;        curr-hour (time/hour now)
-;        curr-weekday (:id (get days-of-week (time/day-of-week now)))]
-;    ;; report schedule should look like:
-;    ;;   `{:days_of_week {:mon true :tue true :wed false ...} :time_of_day "morning" :timezone "US/Pacific"}`
-;    (when (and (get days_of_week (keyword curr-weekday))   ; scheduled weekdays include curr-weekday
-;               (= curr-hour (time-of-day->realhour time_of_day)))  ; scheduled hour matches curr-hour
-;      (try
-;        (execute-and-send id)
-;        (catch Throwable t
-;          (log/error (format "Error executing email report: %d" id) t))))))
-;
-;(defn execute-and-send
-;  "Execute and Send an `EmailReport`.  This includes running the data query behind the report, formatting the email,
-;   and sending the email to any specified recipients."
-;  [report-id]
-;  {:pre [(integer? report-id)]}
-;  (let [email-report (-> (sel :one :fields execution-details-fields :id report-id)
-;                         ;; TODO - this feels heavy handed.  need to check `sel` macro about clob handling
-;                         (u/assoc* :description (u/jdbc-clob->str (:description <>))
-;                                   :email_addresses (u/jdbc-clob->str (:email_addresses <>))
-;                                   :recipients (sel :many :fields ['metabase.models.user/User :id :email]
-;                                                 (where {:id [in (subselect EmailReportRecipients
-;                                                                   (fields :user_id)
-;                                                                   (where {:emailreport_id report-id}))]}))))
-;        report-execution (ins EmailReportExecutions
-;                           :report_id report-id
-;                           :organization_id (:organization_id email-report)
-;                           :details email-report
-;                           :status "running"
-;                           :created_at (u/new-sql-timestamp)
-;                           :started_at (u/new-sql-timestamp)
-;                           :error ""
-;                           :sent_email "")]
-;    (log/debug (format "Starting EmailReport Execution: %d" (:id report-execution)))
-;    (execute report-execution)
-;    (log/debug (format "Finished EmailReport Execution: %d" (:id report-execution)))
-;    ;; return the id of the report-execution
-;    (:id report-execution)))
-;
-;
-;(defn- execute
-;  "Internal handling of EmailReport sending."
-;  [{execution-id :id {:keys [name creator_id dataset_query recipients email_addresses]} :details}]
-;  (let [email-subject (str (or name "Your Email Report") " - " (u/now-with-format "MMMM dd, YYYY"))
-;        email-recipients (->> (filter identity (map (fn [recip] (:email recip)) recipients))
-;                              (into (clojure.string/split email_addresses #","))
-;                              (filter u/is-email?)
-;                              (into []))
-;        email-data (driver/dataset-query dataset_query {:executed_by creator_id
-;                                                        :synchronously true})]
-;    (if (= :completed (:status email-data))
-;      (->> (send-email-report email-subject email-recipients email-data)
-;           (report-complete execution-id))
-;      (report-fail execution-id (format "dataset_query() failed for email report (%d): %s" execution-id (:error email-data))))))
-;
-;(defn- report-fail
-;  "Record report failure"
-;  [execution-id msg]
-;  (upd EmailReportExecutions execution-id
-;    :status "failed"
-;    :error msg
-;    :finished_at (u/new-sql-timestamp)))
-;
-;(defn- report-complete
-;  "Record report completion"
-;  [execution-id sent-email]
-;  (upd EmailReportExecutions execution-id
-;    :status "completed"
-;    :finished_at (u/new-sql-timestamp)
-;    :sent_email (or sent-email "")))
+(declare send-pulses)
+
+(def send-pulses-job-key "metabase.task.send-pulses.job")
+(def send-pulses-trigger-key "metabase.task.send-pulses.trigger")
+
+(defonce ^:private send-pulses-job (atom nil))
+(defonce ^:private send-pulses-trigger (atom nil))
+
+;; simple job which looks up all databases and runs a sync on them
+(jobs/defjob SendPulses
+             [ctx]
+             ;; determine what time it is right now (hour-of-day & day-of-week) in local timezone
+             (send-pulses))
+
+(defn task-init []
+  (log/info "Submitting sync-database task to scheduler")
+  ;; build our job
+  (reset! send-pulses-job (jobs/build
+                               (jobs/of-type SendPulses)
+                               (jobs/with-identity (jobs/key send-pulses-job-key))))
+  ;; build our trigger
+  (reset! send-pulses-trigger (triggers/build
+                                   (triggers/with-identity (triggers/key send-pulses-trigger-key))
+                                   (triggers/start-now)
+                                   (triggers/with-schedule
+                                     ;; run at the top of every hour
+                                     (cron/schedule (cron/cron-schedule "0 0 * * * ? *")))))
+  ;; submit ourselves to the scheduler
+  (task/schedule-task! @send-pulses-job @send-pulses-trigger))
+
+
+;;; ## ---------------------------------------- PULSE SENDING ----------------------------------------
+
+
+(defn- ^:private execute-card
+  "Execute the query for a single card."
+  [card-id]
+  {:pre [(integer? card-id)]}
+  (let [{:keys [creator_id dataset_query]} (db/sel :one Card :id card-id)]
+    (try
+      (driver/dataset-query dataset_query {:executed_by creator_id})
+      (catch Throwable t
+        (log/warn (format "Error running card query (%n)" card-id) t)))))
+
+(defn send-pulse-email
+  ""
+  [{:keys [id name]} results recipients]
+  (log/debug (format "Sending Pulse (%d) via Channel :email" id))
+  (let [email-subject (str "Pulse Email: " name)
+        email-recipients (filterv u/is-email? (map :email recipients))]
+    (email/send-message
+      :subject      email-subject
+      :recipients   email-recipients
+      :message-type :text
+      :message      (with-out-str (clojure.pprint/pprint results)))))
+
+(defn send-pulse-slack
+  ""
+  [{:keys [id] :as pulse} results details]
+  (log/debug (format "Sending Pulse (%d) via Channel :slack" id)))
+
+(defn send-pulse
+  "Execute and Send a `Pulse`, optionally specifying the specific `PulseChannels`.  This includes running each
+   `PulseCard`, formatting the results, and sending the results to any specified destination.
+
+   Example:
+       (send-pulse pulse)                       Send to all Channels
+       (send-pulse pulse :channel-ids [312])    Send only to Channel with :id = 312"
+  [{:keys [cards] :as pulse} & {:keys [channel-ids]}]
+  {:pre [(map? pulse)]}
+  (let [results  (map execute-card (mapv :id cards))
+        channels (or channel-ids (mapv :id (:channels pulse)))]
+    (doseq [channel-id channels]
+      (let [{:keys [channel_type details recipients]} (first (filter #(= channel-id (:id %)) (:channels pulse)))]
+        (cond
+          (= :email channel_type) (send-pulse-email pulse results recipients)
+          (= :slack channel_type) (send-pulse-slack pulse results details))))))
+
+(defn send-pulses
+  ""
+  []
+  (let [now               (time/to-time-zone (time/now) (time/time-zone-for-id (or (setting/get :report_timezone) "UTC")))
+        curr-hour         (time/hour now)
+        curr-weekday      (:id (get pulse-channel/days-of-week (time/day-of-week now)))
+        channels-by-pulse (group-by :pulse_id (pulse-channel/retrieve-scheduled-channels curr-hour curr-weekday))]
+    (doseq [pulse-id (keys channels-by-pulse)]
+      (try
+        (log/debug (format "Starting Pulse Execution: %d" pulse-id))
+        (when-let [pulse (pulse/retrieve-pulse pulse-id)]
+          (send-pulse pulse (mapv :id (get channels-by-pulse pulse-id))))
+        (log/debug (format "Finished Pulse Execution: %d" pulse-id))
+        (catch Exception e
+          (log/error "Error sending pulse: " pulse-id e))))))


Accidentally reinserted dropping buffers.

--- src/onyx/messaging/core_async.clj
+++ src/onyx/messaging/core_async.clj
@@ -30,8 +30,8 @@

   (start [component]
     (taoensso.timbre/info "Starting core.async Messaging Channel")
-    (let [release-ch (chan (dropping-buffer (:onyx.messaging/release-ch-buffer-size defaults)))
-          retry-ch (chan (dropping-buffer (:onyx.messaging/retry-ch-buffer-size defaults)))]
+    (let [release-ch (chan (sliding-buffer (:onyx.messaging/release-ch-buffer-size defaults)))
+          retry-ch (chan (sliding-buffer (:onyx.messaging/retry-ch-buffer-size defaults)))]
       (assoc component :release-ch release-ch :retry-ch retry-ch)))

   (stop [component]


Log raw HTTP requests

Log raw HTTP requests

--- src/org/spootnik/cyanite/http.clj
+++ src/org/spootnik/cyanite/http.clj
@@ -25,9 +25,10 @@
     (handler (assoc request :local-params params))))

 (defn paths-handler [response-channel {{:keys [query tenant]}  :params
-                                       {:keys [index]} :local-params}]
+                                       {:keys [index]} :local-params
+                                       :as request}]
   (debug "query now: " query)
-  (info (format "Paths request: tenant: %s, query: %s" tenant query))
+  (info "Paths request:" (str (:uri request) "?" (:query-string request)))
   (enqueue
     response-channel
     (try
@@ -63,8 +64,7 @@
                        {{:keys [index store rollup-finder]} :local-params
                         {:keys [from to path agg tenant]} :params :as request}]
   (debug "fetching paths: " path)
-  (info (format "Metrics request: tenant: %s, path: %s, from: %s, to: %s, agg: %s"
-                tenant path from to agg))
+  (info "Metrics request:" (str (:uri request) "?" (:query-string request)))
   (enqueue
    response-channel
     (try


CMR-2201: Changed comment to docstring.

CMR-2201: Changed comment to docstring.

--- common-app-lib/src/cmr/common_app/test/side_api.clj
+++ common-app-lib/src/cmr/common_app/test/side_api.clj
@@ -25,12 +25,12 @@
   (format "http://localhost:%s/eval" (side-api-port)))

 (def eval-routes
-  ;; Reads and evaluates code then encodes the response as clojure EDN for the
-  ;; caller to read. This avoids having to add a million different endpoints to dev system control
-  ;; to do different things inside the system.
-  ;;
-  ;; Example usage:
-  ;; curl -XPOST -H "Content-Type: text" http://localhost:2999/eval -d "(+ 1 1)"
+  "Reads and evaluates code then encodes the response as clojure EDN for the
+   caller to read. This avoids having to add a million different endpoints to dev system control
+   to do different things inside the system.
+
+   Example usage:
+   curl -XPOST -H \"Content-Type: text\" http://localhost:2999/eval -d \"(+ 1 1)\""
   (POST "/eval" {:keys [body]}
     (let [body-str (slurp body)]
       (debug (str "Evaling [" body-str "]"))


validate that a superuser can access other user details via GET /api/user/:id

--- test/metabase/api/user_test.clj
+++ test/metabase/api/user_test.clj
@@ -105,6 +105,18 @@
 (expect "You don't have permissions to do that."
   ((user->client :rasta) :get 403 (str "user/" (user->id :trashbird))))

+;; A superuser should be allowed to fetch another users data
+(expect (match-$ (fetch-user :rasta)
+          {:email "rasta@metabase.com"
+           :first_name "Rasta"
+           :last_login $
+           :is_superuser false
+           :id $
+           :last_name "Toucan"
+           :date_joined $
+           :common_name "Rasta Toucan"})
+  ((user->client :crowberto) :get 200 (str "user/" (user->id :rasta))))
+

 ;; ## PUT /api/user/:id
 ;; Test that we can edit a User


delaney.clj: added a function for reading D-symbol lists from files

--- clojure/org/gavrog/clojure/delaney.clj
+++ clojure/org/gavrog/clojure/delaney.clj
@@ -632,6 +632,12 @@
                                       [(emap D) (v ds i j D)]))]))]
       (DSymbol. (dim ds) n ops vs))))

+
+;; === Reading a sequence of symbols from a file (very naive method for now)
+
+(defn read-symbols [filename]
+     (=> (-> filename slurp (split "<")) (drop 1) (map dsymbol)))
+
 ;; === Tests

 (deftest delaney-test


Hashing Optimization (hash by node instead of by seq)

--- src/main/cljs/lean_map/core.cljs
+++ src/main/cljs/lean_map/core.cljs
@@ -229,6 +229,18 @@
         :else
         inode)))

+  (hash-node [_ hash-code]
+    (let [data-len (* (bit-count datamap) 2)
+          len (alength arr)
+          node-start (if (zero? datamap) 0 data-len)]
+      (loop [d 0 hash-code hash-code]
+        (if (< d data-len)
+          (recur (+ d 2) (bit-or (+ hash-code (hash [(aget arr d) (aget arr (inc d))])) 0))
+          (loop [n node-start hash-code hash-code]
+            (if (< n len)
+              (recur (inc n) (.hash-node (aget arr n) hash-code))
+              hash-code))))))
+
   IEquiv
   (-equiv [inode other]
     (if (identical? inode other)
@@ -331,6 +343,13 @@
   (single-kv? [_]
     false)

+  (hash-node [_ hash-code]
+    (let [len (alength arr)]
+      (loop [n 0 hash-code hash-code]
+        (if (< n len)
+          (recur (+ n 2) (bit-or (+ hash-code (hash [(aget arr n) (aget arr (inc n))])) 0))
+          hash-code))))
+
   IEquiv
   (-equiv [inode other]
     (if (identical? inode other)
@@ -347,6 +366,9 @@
                          (and (> idx -1) (= (aget arr (inc i)) (aget other-arr (inc idx))))))
                 eq))))))))

+(defn- persistent-map-hash [m]
+  (mix-collection-hash (if (zero? (.-cnt m)) 0 (.hash-node (.-root m) 0)) (.-cnt m)))
+
 (deftype PersistentHashMap [meta cnt root ^:mutable __hash]
   Object
   (toString [coll]
@@ -404,7 +426,8 @@
        (equiv-map coll other))))

   IHash
-  (-hash [coll] (caching-hash coll hash-unordered-coll __hash))
+  (-hash [coll]
+    (caching-hash coll persistent-map-hash __hash))

   ILookup
   (-lookup [coll k]


Additional fixes for intermittent test failures :unamused:

--- src/metabase/driver/bigquery.clj
+++ src/metabase/driver/bigquery.clj
@@ -172,22 +172,29 @@
    "STRING"    identity
    "TIMESTAMP" parse-timestamp-str})

-(defn- post-process-native [^QueryResponse response]
-  (when-not (.getJobComplete response)
-    (throw (Exception. (str (.getErrors response)))))
-  (let [^TableSchema schema (.getSchema response)
-        parsers             (for [^TableFieldSchema field (.getFields schema)]
-                              (type->parser (.getType field)))
-        cols                (table-schema->metabase-field-info schema)]
-    {:columns (map :name cols)
-     :cols    cols
-     :rows    (for [^TableRow row (.getRows response)]
-                (for [[^TableCell cell, parser] (partition 2 (interleave (.getF row) parsers))]
-                  (when-let [v (.getV cell)]
-                    ;; There is a weird error where everything that *should* be NULL comes back as an Object. See https://jira.talendforge.org/browse/TBD-1592
-                    ;; Everything else comes back as a String luckily so we can proceed normally.
-                    (when-not (= (class v) Object)
-                      (parser v)))))}))
+(defn- post-process-native
+  ;; 99% of the time by the time this is called `.getJobComplete` will return `true`. On the off chance it doesn't, wait a few seconds for the job to finish.
+  ([^QueryResponse response]
+   (post-process-native response 5))                     ; wait up to 5 seconds for `.getJobComplete` to return `true`
+  ([^QueryResponse response, ^Integer timeout-seconds]
+   (when-not (.getJobComplete response)
+     (when (zero? timeout-seconds)                       ; if we've ran out of wait time throw an exception
+       (throw (Exception. (str (.getErrors response)))))
+     (Thread/sleep 1000)                                 ; otherwise sleep a second, try again, and decrement the remaining `timeout-seconds`
+     (post-process-native response (dec timeout-seconds)))
+   (let [^TableSchema schema (.getSchema response)
+         parsers             (for [^TableFieldSchema field (.getFields schema)]
+                               (type->parser (.getType field)))
+         cols                (table-schema->metabase-field-info schema)]
+     {:columns (map :name cols)
+      :cols    cols
+      :rows    (for [^TableRow row (.getRows response)]
+                 (for [[^TableCell cell, parser] (partition 2 (interleave (.getF row) parsers))]
+                   (when-let [v (.getV cell)]
+                     ;; There is a weird error where everything that *should* be NULL comes back as an Object. See https://jira.talendforge.org/browse/TBD-1592
+                     ;; Everything else comes back as a String luckily so we can proceed normally.
+                     (when-not (= (class v) Object)
+                       (parser v)))))})))

 (defn- process-native* [database query-string]
   (post-process-native (execute-query database query-string)))


Store duration and distance as integers.

--- s3/src/s3/blog.clj
+++ s3/src/s3/blog.clj
@@ -23,18 +23,19 @@
 (defn own? [user dbo]
   (= user (:user dbo)))

-(defn transform-using [params transform-rules]
-  (let [dropped (apply dissoc params (:drop transform-rules))
+(defn transform-using [blog transform-rules]
+  (let [dropped (apply dissoc blog (:drop transform-rules))
         tf-fns (:transform transform-rules)
         transformed (merge dropped (reduce (fn [m [key transform]]
                                              (assoc m key (transform (key dropped))))
                                              {}
                                              (select-keys
-                                              tf-fns
-                                              (vec (clojure.set/intersection (set (keys dropped)) (set (keys tf-fns)))))))]
+                                                tf-fns
+                                                (vec (clojure.set/intersection (set (keys dropped))
+                                                                               (set (keys tf-fns)))))))]
     (if (every? identity ((apply juxt (:validation transform-rules)) transformed))
       transformed
-      (error "cannot validate blog object" params))))
+      (error "cannot validate blog object" blog))))

 (def from-db-transform
   {:drop []
@@ -53,8 +54,8 @@

 (def to-db-transform
   {:drop [:id]
-   :transform {:distance parse-distance
-               :time parse-duration}
+   :transform {:distance #(-> % parse-distance int)
+               :time #(-> % parse-duration int)}
    :validation [:user #(-> % :draft nil? not)]})

 (defn find-dbo [id]
@@ -68,7 +69,7 @@
       (-> blog
           (transform-using to-db-transform)
           (insert-and-return dbo))
-      (error "Refusing to create" user blog dbo))))
+      (error "Db object deleted or not own. Refusing to create" user blog dbo))))

 (defn get [id]
   (from-db-to-user (find-dbo id)))


Azure Blob names are now the same as S3 keys

--- src/uswitch/bifrost/azureblob.clj
+++ src/uswitch/bifrost/azureblob.clj
@@ -10,14 +10,12 @@
            [com.microsoft.windowsazure.services.blob.client CloudBlobClient CloudBlobContainer CloudBlockBlob BlobRequestOptions]
            [java.io FileInputStream]))

-(defn generate-blob-name [consumer-group-id topic partition first-offset last-offset]
-  (format "%s/%s/partition=%s/T%s-%s-%s.baldr.gz"
+(defn generate-blob-name [consumer-group-id topic partition first-offset]
+  (format "%s/%s/partition=%s/%s.baldr.gz"
           consumer-group-id
           topic
           partition
-          (format "%013d" (System/currentTimeMillis))
-          (format "%010d" first-offset)
-          (format "%010d" last-offset)))
+          (format "%010d" first-offset)))

 (defn- ensure-container-exists
   [{:keys [account-name account-key storage-container endpoint-protocol] :as azurestorage-credentials
@@ -64,7 +62,7 @@
                                                              :first-offset first-offset
                                                              :last-offset last-offset})
                     (let [consumer-group-id (consumer-properties "group.id")
-                          blob-name (generate-blob-name consumer-group-id topic partition first-offset last-offset)]
+                          blob-name (generate-blob-name consumer-group-id topic partition first-offset)]
                       (upload-to-azure blob-container topic blob-name file-path))
                     {:goto :commit}
                     (catch Exception e


No newline needed

No newline needed

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -137,8 +137,7 @@
         start-ack-val (or (:ack-val root) 0)]
     (reduce (fn process-leaf [accum {:keys [message] :as leaf}]
               (let [routes (route-data event result message flow-conditions egress-ids)
-                    message* (flow-conditions-transform message routes egress-ids
-                                                        flow-conditions event)
+                    message* (flow-conditions-transform message routes egress-ids flow-conditions event)
                     hash-group (hash-groups message* egress-ids task->group-by-fn)
                     leaf* (if (= message message*)
                             leaf


Compile predicates ahead of time.

Compile predicates ahead of time.

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -6,7 +6,7 @@
               [onyx.log.commands.common :as common]
               [onyx.log.entry :as entry]
               [onyx.queue.hornetq :refer [hornetq]]
-              [onyx.planning :refer [find-task]]
+              [onyx.planning :refer [find-task build-pred-fn]]
               [onyx.peer.task-lifecycle-extensions :as l-ext]
               [onyx.peer.pipeline-extensions :as p-ext]
               [onyx.peer.function :as function]
@@ -216,6 +216,16 @@
     (let [entry (entry/create-log-entry :kill-job {:job job-id})]
       (>!! outbox-ch entry))))

+(defn only-relevant-branches [flow task]
+  (filter #(= (:flow/from (:name task)) %) flow task))
+
+(defn compile-flow-conditions [flow-conditions task-name]
+  (let [conditions (only-relevant-branches flow-conditions task-name)]
+    (map
+     (fn [condition]
+       (update-in condition [:flow/predicate] build-pred-fn))
+     conditions)))
+
 (defrecord TaskLifeCycle [id log queue job-id task-id restart-ch outbox-ch seal-resp-ch opts]
   component/Lifecycle

@@ -300,6 +310,7 @@

             catalog (extensions/read-chunk log :catalog job-id)
             task (extensions/read-chunk log :task task-id)
+            flow-conditions (extensions/read-chunk log :flow-conditions job-id)
             catalog-entry (find-task catalog (:name task))

             _ (taoensso.timbre/info (format "[%s] Starting Task LifeCycle for %s" id (:name task)))
@@ -310,6 +321,8 @@
                            :onyx.core/task (:name task)
                            :onyx.core/catalog catalog
                            :onyx.core/workflow (extensions/read-chunk log :workflow job-id)
+                           :onyx.core/flow-conditions flow-conditions
+                           :onyx.core/compiled-flow-conditions (compile-flow-conditions flow-conditions (:name task))
                            :onyx.core/task-map catalog-entry
                            :onyx.core/serialized-task task
                            :onyx.core/ingress-queues (:ingress-queues task)


Minor output formatting improvement.

Minor output formatting improvement.

--- src/open_company/util/import.clj
+++ src/open_company/util/import.clj
@@ -54,7 +54,7 @@

 (defn usage [options-summary]
   (s/join \newline
-     ["This program imports OpenCompany data from EDN file(s)."
+     ["\nThis program imports OpenCompany data from EDN file(s)."
       ""
       "Usage:"
       "  lein run -m open-company.util.import -- [options] company-data.edn"


fixed the unit test

fixed the unit test

--- test/bluebell/utils/core_test.clj
+++ test/bluebell/utils/core_test.clj
@@ -51,7 +51,7 @@
          [{1 {:mapped 2, :parents {[1 1 1 3] 3}},
            3 {:mapped 4, :parents {[1 1 1 3] 1}},
            [1 1 1 3]
-           {:mapped [2 2 2 4], :parents #:bluebell.utils.core{:parent 1}}}
+           {:mapped [2 2 2 4], :parents #:bluebell.utils.traverse{:parent 1}}}
           [2 2 2 4]]
          )))


(PDB-5483) Fix set transaction read write error on hot standby

Fix upgrade error introducted in (PDB-5483) #3643.  Conditionally set
jit setting if server_version > 11.

Ref: https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-USERS

  Transaction management commands that explicitly set non-read-only
  state: (SET TRANSACTION READ WRITE) are explicitly denied while
  configured as hot standby, but you can change a run time parameter
  settings using SET

[rlb@puppet.com: squash related patches]
[rlb@puppet.com: adjust commit message to include ticket, etc.]

--- src/puppetlabs/puppetdb/jdbc.clj
+++ src/puppetlabs/puppetdb/jdbc.clj
@@ -648,10 +648,11 @@
        ;; level to fail (because the pending transaction already
        ;; includes that select).
        (.setIsolateInternalQueries true))
-     (->> [(when read-only? "set transaction read write;")
-           "update pg_settings set setting = false"
-           "  where name = 'jit';"
-           (when read-only? "set transaction read only;")
+     (->> ["DO $$ BEGIN"
+           "IF CAST((SELECT setting FROM pg_settings WHERE name = 'server_version_num') AS INTEGER) >= 110000 THEN"
+           "SET SESSION jit = off;"
+           "END IF;"
+           "END $$;"
            (when expected-schema
              (block-on-schema-mismatch expected-schema))]
           (str/join " ")


test columns toggler

test columns toggler

--- test/desdemona/ui/table_test.cljs
+++ test/desdemona/ui/table_test.cljs
@@ -5,6 +5,12 @@
    [reagent.core :as r]
    [reagent.session :as session]
    [cljs.core.match :refer-macros [match]]))
+
+(def test-state {:results [{:a 1 :b 2}
+                           {:a 4 :b 2}]
+                 :table-toggled-ks (sorted-set :a :b)
+                 :all-table-ks (sorted-set :a :b)
+                 :columns-toggler-open? false})

 (def isClient (not (nil? (try (.-document js/window)
                               (catch js/Object e nil)))))
@@ -26,15 +32,27 @@
         (r/flush)
         (.removeChild (.-body js/document) div)))))

+(deftest columns-toggler-component-test
+  (session/reset! test-state)
+  (with-mounted-component [table/columns-toggler-component
+                           (:all-table-ks @session/state)
+                           :table-toggled-ks]
+    (fn [c div]
+      (let [first-li (.querySelector div "li:first-of-type")
+            first-link (.querySelector div "li:first-of-type a")
+            active? #(.contains (.-classList %) "active")]
+        (testing "generated markup"
+          (is (= (.-innerHTML first-link) "A"))
+          (is (active? first-li)))
+        (testing "clicks"
+          (is (some #{:a} (:table-toggled-ks @session/state)))
+          (.click first-link)
+          (is (nil? (some #{:a} (:table-toggled-ks @session/state)))))))))
+
 (deftest table-component-test
-  (let [state {:results [{:a 1 :b 2}
-                         {:a 4 :b 2}]
-               :table-toggled-ks [:a :b]
-               :all-table-ks [:a :b]
-               :columns-toggler-open? false}
-        results-count (count (:results state))
+  (let [results-count (count (:results test-state))
         component [table/table-component]]
-    (session/swap! merge state)
+    (session/reset! test-state)
     (with-mounted-component component
       (fn [c div]
         (let [first-th (.querySelector div "th:first-of-type")


Output when errors

Output when errors

--- test/runbld/test/publish_test.clj
+++ test/runbld/test/publish_test.clj
@@ -65,6 +65,8 @@
                                    "--job-name" "elastic,proj1,master"
                                    "test/success.bash"])
             res (main/run opts)]
+        (when (pos? (count @(:errors res)))
+          (clojure.pprint/pprint @(:errors res)))
         (is (= 0 (count @(:errors res))))
         (is (= [["foo@example.com"
                  "greetings elastic-proj1-master!\n"]] @sent)))
@@ -75,6 +77,8 @@
                                    "--job-name" "elastic,proj2,master"
                                    "test/success.bash"])
             res (main/run opts)]
+        (when (pos? (count @(:errors res)))
+          (clojure.pprint/pprint @(:errors res)))
         (is (= 0 (count @(:errors res))))
         (is (= [[["foo@example.com" "bar@example.com"]
                  "in template for elastic-proj2-master\n"]] @sent))))))


bug #5899 - restored missing transaction error messages

Signed-off-by: Goran Jovic <fc686822162e6f379ea05b6f92d78d206147085c@gmail.com>

--- src/status_im/models/wallet.cljs
+++ src/status_im/models/wallet.cljs
@@ -167,16 +167,13 @@
       {:db (-> db
                (assoc-in [:wallet :send-transaction :wrong-password?] true))}

-      (merge (let [cofx {:db
-                         (-> db
-                             (assoc-in [:wallet :transactions-queue] nil)
-                             (assoc-in [:wallet :send-transaction] {}))
-                         :wallet/show-transaction-error
-                         message}]
-               (navigation/navigate-back cofx))
-
-             (when on-error
-               {:dispatch (conj on-error message)})))))
+      (fx/merge {:db (-> db
+                         (assoc-in [:wallet :transactions-queue] nil)
+                         (assoc-in [:wallet :send-transaction] {}))}
+                {:wallet/show-transaction-error message}
+                (navigation/navigate-back)
+                (when on-error
+                  {:dispatch (conj on-error message)})))))

 (defn transform-data-for-message [{:keys [method] :as transaction}]
   (cond-> transaction


user search is better

user search is better

--- src/thehex/youtube_api3/core.clj
+++ src/thehex/youtube_api3/core.clj
@@ -144,18 +144,21 @@
   another channel id = UC4u8goEsLgpPvDX2mKD70nQ
   "
   [query]
-  (let [url (str config/api-base "search?part=snippet&q=" query "&key=" @api-key)
+  (let [url (str config/api-base "search?part=snippet&q=" query
+                 "&type=channel" "&maxResults=50" "&key=" @api-key)
         body (-> (http/get url {:as :json}) :body)]
     ;; (log/debug (str "Got videos from search: " body))
     (let [as-json (json/read-str body)
           page-info (get as-json "pageInfo")]
       (log/debugf "Total Results: %s, resultsPerPage: %s" (get page-info "totalResults") (get page-info "resultsPerPage"))
       (let [items (get as-json "items")]
-        (log/info (seq (map #(get (get % "id") "channelId")
-                              (filter (fn [item]
-                                        (let [id (get item "id")]
-                                          (= (get id "kind") "youtube#channel")))
-                                      items))))))))
+        (log/info (apply str
+                         (map
+                          (fn [item] (str (get (get item "snippet") "title") ": " (get (get item "id") "channelId") "\n"))
+                          (filter (fn [item]
+                                    (let [id (get item "id")]
+                                      (= (get id "kind") "youtube#channel")))
+                                  items))))))))

 (defn report-comment-as-spam
   "Reports a comment as spam, provided a comment id.


add area for southern and arctic oceans

add area for southern and arctic oceans


Remove useless parameter.

Remove useless parameter.

--- src/uxbox/main/ui/workspace.cljs
+++ src/uxbox/main/ui/workspace.cljs
@@ -101,7 +101,7 @@
       (set! (.-scrollTop dom) (* c/canvas-start-scroll-y @wb/zoom-l)))))

 (defn- workspace-render
-  [own projectid]
+  [own]
   (let [{:keys [flags zoom page] :as workspace} (rum/react wb/workspace-l)
         left-sidebar? (not (empty? (keep flags [:layers :sitemap
                                                 :document-history])))


Increase the initial scroll to 1200px.

Increase the initial scroll to 1200px.

Signed-off-by: Andrey Antukh <8e6a32ae7580b30ec348e03f34a0953d9b475a56@niwi.nz>

--- src/uxbox/ui/workspace/base.cljs
+++ src/uxbox/ui/workspace/base.cljs
@@ -123,8 +123,8 @@
 (def ^:const viewport-width 4000)
 (def ^:const viewport-height 4000)

-(def ^:const canvas-start-x 600)
-(def ^:const canvas-start-y 600)
+(def ^:const canvas-start-x 1200)
+(def ^:const canvas-start-y 1200)
 (def ^:const canvas-scroll-padding 50)
 (def ^:const canvas-start-scroll-x (- canvas-start-x canvas-scroll-padding))
 (def ^:const canvas-start-scroll-y (- canvas-start-y canvas-scroll-padding))


lein-release plugin: preparing 0.3.6 release

--- backend/project.clj
+++ backend/project.clj
@@ -1,4 +1,4 @@
-(defproject lambdaui "0.3.6-SNAPSHOT"
+(defproject lambdaui "0.3.6"
   :description "LambdaCD-Plugin that provides a modern UI for your pipeline."
   :url "https://github.com/sroidl/lambda-ui"
   :license {:name "Apache License 2.0"


Update com.fasterxml.jackson.core/jackson-core to "2.9.9"

--- backend/project.clj
+++ backend/project.clj
@@ -29,7 +29,7 @@
                  [org.apache.tika/tika-core "1.21"]
                  [org.apache.tika/tika-parsers "1.21" :exclusions [org.slf4j/slf4j-api com.fasterxml.jackson.core/jackson-core org.apache.httpcomponents/httpcore org.apache.httpcomponents/httpclient org.apache.httpcomponents/httpmime]]
                  ;; explicit versions of commons deps used by tika-parsers and clj-http
-                 [com.fasterxml.jackson.core/jackson-core "2.9.6"]
+                 [com.fasterxml.jackson.core/jackson-core "2.9.9"]
                  [org.apache.httpcomponents/httpcore "4.4.10"]
                  [org.apache.httpcomponents/httpclient "4.5.5"]
                  [org.apache.httpcomponents/httpmime "4.5.5"]


azulenoids.clj: new functions iterate-cycle and boundary-chambers

--- clojure/org/gavrog/clojure/azulenoids.clj
+++ clojure/org/gavrog/clojure/azulenoids.clj
@@ -2,6 +2,9 @@
   (:import (org.gavrog.jane.numbers Whole)
            (org.gavrog.joss.dsyms.basic DSymbol DynamicDSymbol)
            (org.gavrog.joss.dsyms.generators CombineTiles DefineBranching2d)))
+
+(defn iterate-cycle [coll x]
+  (reductions (fn [x f] (f x)) x (cycle coll)))

 (defn walk [ds D & idxs]
   (reduce (fn [D i] (.op ds i D)) D idxs))
@@ -15,6 +18,11 @@
                    (= D E*) nil
                    :else (recur (walk ds E j i)))))]
     (step (walk ds D i))))
+
+(defn boundary-chambers [ds D i j k]
+  (let [a (fn [D] (walk ds D i))
+        b (fn [D] (chain-end ds D j k))]
+    (iterate-cycle [a b] D)))

 (defn max-curvature [ds]
   (let [dsx (.clone ds)]
@@ -30,7 +38,6 @@

 (defn subdivs-for [ds]
   (map (partial subdiv ds) (range 1 16 2)))
-

 (def template
   (new DSymbol (str "1.1:60:"


change to router

change to router

--- src/matcherwebservice/router.clj
+++ src/matcherwebservice/router.clj
@@ -39,6 +39,9 @@
    [{:get "/admin/:userhash/groups"}
     (fn [params]
       {:type :json :data (data/get-groups (params :userhash))})]
+   [{:get "/home"}
+    (fn [params]
+      {:type :html :data "https://gist.github.com/ewilson/f27ba22368c35d101d86
"})]
    ])
 (defn extract-from-rest-uri-fn-lst [i]
   (vec
@@ -48,8 +51,9 @@
 (def rest-uris (extract-from-rest-uri-fn-lst 0))
 (def rest-fns (extract-from-rest-uri-fn-lst 1))
 (def default-response
-  {"ok" true
-   "name" "people match service"})
+  {:type :json
+   :data {"ok" true
+          "name" "people match service"}})
 (def rest-uri-lst
   (-> rest-uris routerutil/map-to-vec routerutil/flatten-vecs))
 (defn route [request]


Add comment and review feedback (#1050)

Add comment and review feedback (#1050)

--- scheduler/src/cook/mesos/constraints.clj
+++ scheduler/src/cook/mesos/constraints.clj
@@ -236,19 +236,19 @@
           (->estimated-completion-constraint expected-end-time host-lifetime-mins))))))

 (defn build-launch-max-tasks-constraint
-  "This returns a Fenzo hard constraint that ensures that we don't match more than a given number of tasks per cycle."
+  "This returns a Fenzo hard constraint that ensures that we don't match more than a given number of tasks per cycle. Returns nil
+  if the constraint is disabled."
   []
   (let [enforcing? (ratelimit/enforce? ratelimit/global-job-launch-rate-limiter)
         max-tasks (ratelimit/get-token-count! ratelimit/global-job-launch-rate-limiter ratelimit/global-job-launch-rate-limiter-key)]
-    (if enforcing?
+    (when enforcing?
       (reify com.netflix.fenzo.ConstraintEvaluator
         (getName [_] "launch_max_tasks")
         (evaluate [_ _ _ task-tracker-state]
           (let [num-assigned (-> task-tracker-state .getAllCurrentlyAssignedTasks .size)]
             (com.netflix.fenzo.ConstraintEvaluator$Result.
               (< num-assigned max-tasks)
-              (str "Hit the global rate limit")))))
-      nil)))
+              (str "Hit the global rate limit"))))))))

 (def job-constraint-constructors [build-novel-host-constraint build-gpu-host-constraint build-user-defined-constraint build-estimated-completion-constraint build-data-locality-constraint])


Remove debug println

Remove debug println

--- src/onyx/log/commands/common.clj
+++ src/onyx/log/commands/common.clj
@@ -139,7 +139,6 @@
     (warn (format "IMPORTANT: timed out stopping task %s on peer %s" (:task-id (:task-state state)) (:id state)))))

 (s/defn start-new-lifecycle [old :- os/Replica new :- os/Replica diff state scheduler-event :- os/PeerSchedulerEvent]
-  (println "state is " state)
   (let [old-allocation (peer->allocated-job (:allocations old) (:id state))
         new-allocation (peer->allocated-job (:allocations new) (:id state))]
     (if (not= old-allocation new-allocation)


c.async plugin is not be required task-lifecycle

--- src/onyx/peer/task_lifecycle.clj
+++ src/onyx/peer/task_lifecycle.clj
@@ -9,7 +9,6 @@
               [onyx.messaging.acking-daemon :as acker]
               [onyx.peer.pipeline-extensions :as p-ext]
               [onyx.peer.function :as function]
-              [onyx.plugin.core-async]
               [onyx.peer.operation :as operation]
               [onyx.extensions :as extensions]
               [onyx.compression.nippy]


Note which variation of the algorithm we're using.

[ci skip]

--- src/onyx/windowing/window_id.clj
+++ src/onyx/windowing/window_id.clj
@@ -44,7 +44,9 @@
 ;;13                                       |---------------|      [50 - 69]
 ;;14                                           |---------------|  [55 - 74]

-;; Now we implement the `extents` function from the paper in section 3.3.
+;; Let's do some implementation. We're first going to implement `extents`
+;; for queries whose range and slide values are the same. This is the
+;; first algorithm detailed in section 3.3.

 (defn extent-lower [min-windowing-attr w-range w-slide w]
   (max min-windowing-attr (- (+ min-windowing-attr (* w-slide (inc w))) w-range)))
@@ -90,7 +92,9 @@

 ;; Now we need to implement the inverse, `wids`. `wids` lets us take
 ;; segment and directly find the window IDs that it corresponds to.
-;; `wids` is defined in section 3.4 of the paper.
+;; `wids` is defined in section 3.4 of the paper. This is the variant
+;; of the algorithm that also covers the case where range and slide
+;; are defined on the same value.
 (defn wids-lower [min-windowing-attr t]
   (dec (int (Math/floor (/ (- (:window-attr t)
                               min-windowing-attr) w-slide)))))


Fix: wrong handling of mode parameter to applet size

--- src/rosado/processing/applet.clj
+++ src/rosado/processing/applet.clj
@@ -35,6 +35,10 @@
             (update-proxy prx# ~methods)
             prx#))))

+(def #^{:private true}
+     modes {:JAVA2D JAVA2D :OPENGL OPENGL
+            :P3D P3D :P2D P2D :PDF PDF})
+
 (defn run
   "Launches the applet. If given the flag :interactive, it won't exit
   on clicking the close button - it will only dispose the window."
@@ -43,7 +47,7 @@
   (let [m (.meta applet)
         [width height & mode] (or (:size m) [200 200])
         mode (if-let [kw (first mode)]
-               (tosymb kw)
+               (modes (-> kw name toupper keyword))
                JAVA2D)
         close-op (if (first interactive?)
                    JFrame/DISPOSE_ON_CLOSE


change to test interface.

change to test interface.

--- test/forma/source/modis_test.clj
+++ test/forma/source/modis_test.clj
@@ -1,6 +1,7 @@
 (ns forma.source.modis-test
-  (:use forma.source.modis
-        midje.sweet))
+  (:use [forma.source.modis] :reload)
+  (:use midje.sweet
+        clojure.test))

 (facts
  "Lat lon conversions."


Force failure.

Force failure.

--- test/lambdajam/jobs/test_1_4.clj
+++ test/lambdajam/jobs/test_1_4.clj
@@ -34,8 +34,8 @@
                  :catalog catalog
                  :lifecycles lifecycles
                  :task-scheduler :onyx.task-scheduler/balanced}]
-        (onyx.api/submit-job peer-config job)
-        (throw (ex-info "The test failed, submit-job completed without an error!" {}))))
+        (onyx.api/submit-job peer-config job)))
+    (is (= true false) "Job passed! It should fail!")
     (catch InterruptedException e
       (Thread/interrupted))
     (catch Exception e


Fixed bug with expected value in doctest being quoted twice

--- lib/compojure/doctest/doctest.clj
+++ lib/compojure/doctest/doctest.clj
@@ -84,7 +84,7 @@
   (doseq result (filter (complement :success?) results)
     (.println *test-out*
       (str (pr-str (last (result :expr)))
-           "\n  expected: " (pr-str (result :expected))
+           "\n  expected: " (result :expected)
            "\n  actual:   " (pr-str (result :actual)) "\n")))
   (.println *test-out*
     (str "Success: " (count (filter :success? results)) "/"


head-user doesn't add "actions" itself

head-user doesn't add "actions" itself

Instead, the component that builds it adds extra actions as necessary.

--- src-cljs/frontend/components/header.cljs
+++ src-cljs/frontend/components/header.cljs
@@ -28,40 +28,52 @@
          (= (vcs-url/repo-name (:vcs_url project))
             (get-in app [:navigation-data :repo])))))

+(defn follow-project-button [project owner]
+  (reify
+    om/IRender
+    (render [_]
+      (let [project-id (project-model/id project)
+            vcs-url (:vcs_url project)]
+        (forms/managed-button
+         [:button#follow-project-button.btn.btn-primary
+          {:on-click #(do
+                        (raise! owner [:followed-project {:vcs-url vcs-url :project-id project-id}])
+                        ((om/get-shared owner :track-event) {:event-type :header-follow-project-clicked
+                                                             :properties {:vcs-url vcs-url}}))
+           :data-spinner true}
+          "follow the " (vcs-url/repo-name vcs-url) " project"])))))
+
 (defn show-settings-link? [app]
   (and
     (:read-settings (get-in app state/page-scopes-path))
     (not= false (-> app :navigation-data :show-settings-link?))))

 (defn settings-link [app owner]
-  (when (show-settings-link? app)
-    (let [{:keys [repo org] :as navigation-data} (:navigation-data app)]
-      (cond repo (when (:write-settings (get-in app state/project-scopes-path))
-                   [:a.settings.project-settings
-                    {:href (routes/v1-project-settings-path navigation-data)}
-                    [:img.dashboard-icon {:src (common/icon-path "QuickLink-Settings")}]
-                    "Project Settings"])
-            org [:a.settings.org-settings
-                 {:href (routes/v1-org-settings-path navigation-data)
-                  :on-click #((om/get-shared owner :track-event) {:event-type :header-org-settings-link-clicked
-                                                                  :properties {:org org}})}
-                 [:img.dashboard-icon {:src (common/icon-path "QuickLink-Settings")}]
-                 "Organization Settings"]
-            :else nil))))
+  (let [{:keys [repo org] :as navigation-data} (:navigation-data app)]
+    (cond repo (when (:write-settings (get-in app state/project-scopes-path))
+                 [:a.settings.project-settings
+                  {:href (routes/v1-project-settings-path navigation-data)}
+                  [:img.dashboard-icon {:src (common/icon-path "QuickLink-Settings")}]
+                  "Project Settings"])
+          org [:a.settings.org-settings
+               {:href (routes/v1-org-settings-path navigation-data)
+                :on-click #((om/get-shared owner :track-event) {:event-type :header-org-settings-link-clicked
+                                                                :properties {:org org}})}
+               [:img.dashboard-icon {:src (common/icon-path "QuickLink-Settings")}]
+               "Organization Settings"]
+          :else nil)))

 (defn head-user
   "Builds the header section which contains, among other things, the breadcrumb.
-  actions is an optional component which will be placed on the right of the
-  header; this is where page-wide actions are placed."
+  actions is an optional component (or collection of components which will be
+  placed on the right of the header; this is where page-wide actions are
+  placed."
   [{:keys [app actions]} owner]
   (reify
     om/IDisplayName (display-name [_] "User Header")
     om/IRender
     (render [_]
-      (let [crumbs-data (get-in app state/crumbs-path)
-            project (get-in app state/project-path)
-            project-id (project-model/id project)
-            vcs-url (:vcs_url project)]
+      (let [crumbs-data (get-in app state/crumbs-path)]
         (html
          [:div.head-user
           ;; Avoids a React warning for not giving each `li` a key. Correctly,
@@ -69,18 +81,7 @@
           ;; each one a `:key` here. This gets rid of the warning for now and
           ;; avoids re-architecting the crumbs rendering.
           (apply vector :ol.breadcrumb (crumbs/crumbs crumbs-data))
-          [:div.actions
-           (settings-link app owner)
-           actions
-           (when (show-follow-project-button? app)
-             (forms/managed-button
-              [:button#follow-project-button.btn.btn-primary
-               {:on-click #(do
-                             (raise! owner [:followed-project {:vcs-url vcs-url :project-id project-id}])
-                             ((om/get-shared owner :track-event) {:event-type :header-follow-project-clicked
-                                                                  :properties {:vcs-url vcs-url}}))
-                :data-spinner true}
-               "follow the " (vcs-url/repo-name vcs-url) " project"]))]])))))
+          [:div.actions actions]])))))

 (defn maybe-active [current goal]
   {:class (when (= current goal)
@@ -302,7 +303,7 @@
            [:a.dismiss {:on-click #(raise! owner [:dismiss-trial-offer-banner event-data])}
             [:i.material-icons "clear"]]])))))

-(defn inner-header [{:keys [app actions] :as params} owner]
+(defn inner-header [{:keys [app actions]} owner]
   (reify
     om/IDisplayName (display-name [_] "Inner Header")
     om/IRender
@@ -371,9 +372,18 @@
                                        "Account Notifications"]]
                             :dismiss-fn #(raise! owner [:dismiss-web-notifications-confirmation-banner])}))))
            (when (seq (get-in app state/crumbs-path))
-             (om/build head-user params))])))))
-
-(defn header [{:keys [app actions] :as params} owner]
+             (om/build head-user {:app app
+                                  :actions (cond-> []
+                                             (show-settings-link? app)
+                                             (conj (settings-link app owner))
+
+                                             true
+                                             (conj actions)
+
+                                             (show-follow-project-button? app)
+                                             (conj (om/build follow-project-button project)))}))])))))
+
+(defn header [{:keys [app actions] :as props} owner]
   (reify
     om/IDisplayName (display-name [_] "Header")
     om/IRender
@@ -383,5 +393,5 @@
             _ (utils/mlog "header render inner? " inner? " logged-in? " logged-in?)]
         (html
           (if inner?
-            (om/build inner-header params)
+            (om/build inner-header props)
             (om/build outer-header app)))))))


Update funcs added

Update funcs added

--- src/wishlistd/models/queries.clj
+++ src/wishlistd/models/queries.clj
@@ -34,6 +34,11 @@
   (sql/with-connection db
     (sql/delete-rows :wishlist ["code=?" code])))

+(defn update-wishlist [wishlist]
+  (let [{:keys [id]} wishlist]
+    (sql/with-connection db
+	  (sql/update-values :wishlist ["id=?" id] wishlist))))
+
 (defn get-wishes-for-wishlist [{:keys [id]}]
   (sql/with-connection db
     (sql/with-query-results results
@@ -46,4 +51,9 @@

 (defn delete-wish [{:keys [id]}]
   (sql/with-connection db
-    (sql/delete-rows :wish ["id=?" id])))+    (sql/delete-rows :wish ["id=?" id])))
+
+(defn update-wishlist [wish]
+  (let [{:keys [id]} wish]
+    (sql/with-connection db
+	  (sql/update-values :wish ["id=?" id] wish))))


add benchmark for custom keyword function

--- test/cheshire/test/benchmark.clj
+++ test/cheshire/test/benchmark.clj
@@ -57,3 +57,17 @@
     (bench/with-progress-reporting
       (bench/quick-bench (custom/decode (custom/encode* custom-obj)) :verbose)))
   (println "-------------------------------------"))
+
+(deftest ^{:benchmark true} t-bench-custom-kw-coercion
+  (println "---- Custom keyword-fn Benchmarks ---")
+  (let [t (core/encode test-obj)]
+    (println "[+] (fn [k] (keyword k))")
+    (bench/with-progress-reporting
+      (bench/quick-bench (core/decode t (fn [k] (keyword k)))))
+    (println "[+] basic 'true' keyword-fn")
+    (bench/with-progress-reporting
+      (bench/quick-bench (core/decode t true)))
+    (println "[+] no keyword-fn")
+    (bench/with-progress-reporting
+      (bench/quick-bench (core/decode t))))
+  (println "-------------------------------------"))


Remove comment and confirm that fix #117 works

--- test/cljs/replumb/repl_test.cljs
+++ test/cljs/replumb/repl_test.cljs
@@ -329,7 +329,6 @@
       (reset-env! '[foo.bar foo.bar.baz]))

     ;; https://github.com/Lambda-X/replumb/issues/117
-    ;; To uncomment when the source path will include cljs.tools.reader.reader-types
     (let [res (do (read-eval-call "(require '[cljs.tools.reader :as r])")
                   (read-eval-call "(binding [r/resolve-symbol (constantly 'cljs.user/x)] (r/read-string \"`x\"))"))
           out (unwrap-result res)]


Working on the cannons thing a little more

--- cannons/cannons.clj
+++ cannons/cannons.clj
@@ -1,13 +1,12 @@
-(ns app.core
-  (:require clojure.set))
+(ns cannons.core)

 (defn word-collision
-  "I don't do a whole lot."
   [w1 w2]
-  (clojure.set/union
-    (set (map (fn [x] (when (not (.contains w2 (.toString x))) x)) w1))
-    (set (map (fn [x] (when (not (.contains w1 (.toString x))) x)) w2))))
+    [(reduce (fn [x] (.replaceFirst w2 (.toString x) "")) w1)
+     (reduce (fn [x] (.replaceFirst w1 (.toString x) "")) w2)])

-(defn main
-  []
-  (println (word-collision "hill" "bill")))
+(doseq [line (take-while (partial not= ":q") (repeatedly read-line))]
+  (let [[left-word right-word] (.split line " ")
+        [left-score right-score] (word-collision left-word right-word)]
+    (println (into left-score right-score))
+    (println (count left-score) (count right-score))))


Update morph model to Mario World

Update morph model to Mario World

--- src-clj/cljs_workspace/server.clj
+++ src-clj/cljs_workspace/server.clj
@@ -26,12 +26,39 @@
   (atom {:url "/data"
           :server/id 42
           :coll {:id 4
-                                       :morph {:MorphClass "Text"
-                                               :Position {:x 200 :y 200}
-                                               :TextString "Hallo Welt! Write something!"
-                                               :isDraggable true}
-                                       :shape {:ShapeClass "Text"
-                                               :Extent {:x 200 :y 400}}}}))
+                 :morph {:MorphClass "Text"
+                         :Position {:x 200 :y 200}
+                         :TextString "Hallo Welt! Write something!"
+                         :isDraggable true}
+                 :shape {:ShapeClass "Text"
+                         :Extent {:x 200 :y 400}}}}))
+
+(def mario {:id "Mario", :shape {:ShapeClass "Image", :url "http://www.veryicon.com/icon/png/Game/Super%20Mario/Super%20Paper%20Mario.png", :Extent {:x 100, :y 100}}, :submorphs [], :morph {:isDraggable true, :Position {:x 50, :y 50}}})
+
+(def luigi {:id "Luigi", :shape {:ShapeClass "Image", :url "http://img4.wikia.nocookie.net/__cb20111019211716/villains/images/2/23/Super_paper_mario_-_luigi_2.png", :Extent {:x 100, :y 100}}, :submorphs [], :morph {:isDraggable true, :Position {:x 200, :y 200}}})
+
+(def subtitle {:id 5
+               :morph {:Position {:x 0 :y 420} :isDraggable true}
+               :shape {:Extent {:x 510 :y 200}
+                       :BorderColor "darkgrey"
+                       :BorderWidth 2
+                       :Fill "lightgrey"}
+                :submorphs [{:id 4
+                             :morph {:Preserve true
+                                     :MorphClass "Text"
+                                     :Position {:x 10 :y 10}
+                                     :TextString "Welcome to Super Mario World!"
+                                     :isDraggable true}
+                             :shape {:ShapeClass "Text"
+                                     :Extent {:x 510 :y 200}}}]})
+
+(def mario-world
+  {:id "World"
+   :morph {:Position {:x 10 :y 10} :isDraggable true}
+   :shape {:Extent {:x 500 :y 400}
+           :ShapeClass "Image"
+           :url "http://images4.alphacoders.com/245/2456.jpg"}
+   :submorphs []})

 (def app-state
   (atom {:url "/data"


And now it works!

And now it works!

--- src-cljs/githubcomments/core.cljs
+++ src-cljs/githubcomments/core.cljs
@@ -7,10 +7,12 @@
                                            render-user-content-markdown]]))

 (defn display-comments [comments element]
-  (do (go (set! (.-innerHTML element) (loop [concated-comments ""]
-                                        (let [comment (async/<! comments)]
-                                          (recur (str concated-comments comment)))))
-          )))
+  (do (go (set! (.-innerHTML element)
+                (loop [concated-comments ""]
+                  (let [comment (async/<! comments)]
+                    (if (nil? comment)
+                      concated-comments
+                      (recur (str concated-comments comment)))))))))

 (defn rendered-comment [repo comment]
   "Render the given comment in the context of the given repository."


Fixed NPE if no headers are received by headers-collect, thanks AWizzArd.

--- src/async/http/client/request.clj
+++ src/async/http/client/request.clj
@@ -58,7 +58,9 @@
   "Stores headers under :headers in state."
   (if headers
     (dosync (alter state assoc :headers headers))
-    ((println "Received empty headers, aborting.") :abort)))
+    (do
+      (println "Received empty headers, aborting.")
+      :abort)))

 (defn print-headers [state headers]
   (doall (map #(println (str (:id @state) "< " % ": " (get headers %))) (keys headers))))


reshuffling editor code, syntax update, clean up refs to history/undo/redo

--- src/app/cljs/one/sample/view/editor.cljs
+++ src/app/cljs/one/sample/view/editor.cljs
@@ -3,6 +3,7 @@
         [domina           :only [append! destroy-children! detach! nodes
                                  single-node]]
         [one.sample.model :only [docs]])
+  (:use-macros [crate.macros :only [defpartial]])
   (:require [goog.events               :as event]
             [goog.editor.Field         :as editor-iframe]
             [goog.editor.SeamlessField :as editor-div]
@@ -12,57 +13,14 @@
 (def CHANGE goog.editor.Field.EventType.DELAYEDCHANGE)
 (def CLICK  goog.events.EventType.CLICK)

-(defn spawn-editor
-  ([element] (spawn-editor element false))
-  ([element iframe?]
-     (if iframe?
-       (goog.editor/Field. element)
-       (goog.editor/SeamlessField. element))))
-
-(declare list-documents)
-
-(defn launch [element doc-session]
-  (let [field     (spawn-editor element)
-        content   (doc-session :get :content)
-        new       ($ "button#new")
-        set-html! (fn [content] (. field (setHtml false (or content "") true)))]
-    (do
-      (set-html! content)
-      (. field (makeEditable))
-      (. element (focus)))
-    (event/listen field
-                  CHANGE
-                  (fn [e] (let [content (. field (getCleanContents))
-                                previous (first (doc-session :get-history))]
-                            (doc-session :set! :content content)
-                            (if (not= content previous)
-                              (do
-                                (doc-session :conj-history! content)
-                                (doc-session :reset-cursor!))))))
-    (event/listen new
-                  CLICK
-                  (fn [e]
-                    (append! ($ "#content") (detach! ($ "#workspace")))
-                    (dispatch/fire :document-requested)))))
-
-(defn add-documents-list-listeners []
-  (let [items (nodes ($ "#sidebar-documents > ol > li"))]
-    (doseq [item items]
-      (event/listen ($ "a.bookmark" item)
-                    CLICK
-                    (fn [e] (. e (preventDefault))))
-      (event/listen item
-                    CLICK
-                    (fn [e] (dispatch/fire :document-requested (.-id item)))))))
-
-(defn strip-html [s]
+(defn- strip-html [s]
   (-> s
       (.replace "
" "
 ")
       (.replace "
" "\n")
       (.replace " " " ")
       (.replace (js/RegExp. "(<([^>]+)>)" "ig") "")))

-(defn excerpt [s chars]
+(defn- excerpt [s chars]
   (let [stripped (strip-html s)
         trimmed  (.trim stripped)
         length   (.-length trimmed)
@@ -79,19 +37,69 @@
             (str substr "..."))
           trimmed)))))

+(defn- spawn-editor
+  ([element] (spawn-editor element false))
+  ([element iframe?]
+     (if iframe?
+       (goog.editor/Field. element)
+       (goog.editor/SeamlessField. element))))
+
+(declare list-documents)
+
+(defn launch [element doc-session]
+  (let [field     (spawn-editor element)
+        content   (doc-session :get :content)
+        new       ($ "button#new")
+        title     ($ "#star-title span#title")
+        set-title! (fn [t]
+                     (doc-session :set! :title))
+        set-html! (fn [content] (.setHtml field false (or content "") true))]
+    (do
+      (set-html! content)
+      (.makeEditable field)
+      (.focus element))
+    (event/listen field
+                  CHANGE
+                  (fn [e] (doc-session :set! :content (.getCleanContents field))))
+    (event/listen new
+                  CLICK
+                  (fn [e]
+                    (append! ($ "#content") (detach! ($ "#workspace")))
+                    (dispatch/fire :document-requested)))
+    (event/listen title
+                  CLICK
+                  (fn [e]
+                    (.setAttribute title "contenteditable" true)))))
+
+(defn- add-documents-list-listeners []
+  (let [items (nodes ($ "#sidebar-documents > ol > li"))]
+    (doseq [item items]
+      (event/listen ($ "a.bookmark" item)
+                    CLICK
+                    (fn [e] (.preventDefault e)))
+      (event/listen item
+                    CLICK
+                    (fn [e]
+                      (dispatch/fire :document-requested
+                                     (.getAttribute item "docid")))))))
+
+(defpartial document-list-item [{:keys [id content ts]}]
+  [:li {:docid (name id)}
+   [:div.excerpt
+    [:span (excerpt content 20)]]
+   [:div.document-id
+    [:span [:a.bookmark {:href (str \# (name id))}
+            (.toString (js/Date. ts))]]]])
+
+(defn- append-list-items! [target items]
+  (doseq [item items]
+    (append! target (document-list-item item))))
+
 (defn list-documents [documents]
-  (let [element ($ "#sidebar-documents > ol")
-        sorted  (reverse (sort-by :ts (vals documents)))]
-    (destroy-children! element)
-    (doseq [{id :id :as doc} sorted]
-      (append! element
-               (crate/html [:li {:id (name id)}
-                            [:div.excerpt
-                             [:span (excerpt (:content doc) 20)]]
-                            [:div.document-id
-                             [:span
-                              [:a.bookmark {:href (str \# (name id))}
-                               (name id)]]]])))
+  (let [ol    ($ "#sidebar-documents > ol")
+        items (rest (reverse (sort-by :ts (vals documents))))]
+    (destroy-children! ol)
+    (append-list-items! ol items)
     (add-documents-list-listeners)))

 (dispatch/react-to #{:documents-changed}


feat: return tab search via gql

feat: return tab search via gql

--- src/clj/meins/jvm/graphql/tab_search.clj
+++ src/clj/meins/jvm/graphql/tab_search.clj
@@ -68,4 +68,4 @@
             (put-fn (with-meta [:gql/res2 diff-res] msg-meta))))
         (let [res {:res res :del #{} :tab tab :query m :n n :incremental false}]
           (put-fn (with-meta [:gql/res2 res] msg-meta))))
-      [])))
+      res)))


Make the :open? state of the debug component configurable

--- src/cljs/dato/debug/components/core.cljs
+++ src/cljs/dato/debug/components/core.cljs
@@ -154,7 +154,7 @@
       (om/set-state! owner [:current-save-slot] 0)
       (om/set-state! owner [:tool] :components)
       (om/set-state! owner [:current-query] "default")
-      (om/set-state! owner [:open?] true)
+      (om/set-state! owner [:open?] (or (:open? data) false))
       (om/set-state! owner [:query] (or (:expressions opts) [])))
     om/IDidUpdate
     (did-update [_ _ prev]


Move an inlined function to top level

Move an inlined function to top level

Hopefully it promotes readability.

--- src/clojure/frereth_cp/client/cookie.clj
+++ src/clojure/frereth_cp/client/cookie.clj
@@ -316,6 +316,29 @@
                                          ::hello-response-failed!))
   (dfrd/error! terminated failure))

+(s/fdef wrap-received
+        :args (s/cat :this ::state/state
+                     :incoming ::specs/network-packet)
+        :ret ::state/state)
+(defn wrap-received
+  [{log-state ::log/state
+    :keys [::log/logger]
+    :as this}
+   incoming]
+  ;; It seems a bit silly to have a lambda here.
+  ;; The println debugging adds insult to injury.
+  ;; TODO: Refactor this into its own top-level named
+  ;; function
+  (println "The wait for the cookie has ended")
+  (pprint incoming)
+  (let [this
+        (assoc this
+               ::log/state (log/flush-logs! logger (log/trace log-state
+                                                              ::wait-for-cookie!
+                                                              "Pulled from server"
+                                                              {::specs/network-packet incoming})))]
+    (received-response! this incoming)))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;; Public

@@ -396,17 +419,7 @@
                                   timeout
                                   ::state/response-timed-out)
           (dfrd/chain
-           #_(received-response! this %)
-           (fn [incoming]
-             (println "The wait for the cookie has ended")
-             (pprint incoming)
-             (let [this
-                   (assoc this
-                          ::log/state (log/flush-logs! logger (log/trace log-state
-                                                                         ::wait-for-cookie!
-                                                                         "Pulled from server"
-                                                                         {::specs/network-packet incoming})))]
-               (received-response! this incoming))))
+           (partial wrap-received this))
           (dfrd/catch (fn [ex]
                         (println "cookie/received-response! failed:" ex)
                         (throw (ex-info "received-response! failed"


improving httpd server response for debugging

--- src/clojure/my/company/superapp/main.clj
+++ src/clojure/my/company/superapp/main.clj
@@ -33,15 +33,23 @@
   [bind-address port]
   (let [httpd (proxy [NanoHTTPD] [bind-address port]
                 (serve [session]
-                  (let [msg "
Hello server
\n"]
-                    (log/i "trying to response the server..." :tag "my.company.superapp.main")
+                  (let [msg "
Hello from server!
\n
Session info:
"
+                        uri (.getUri session)
+                        method (.getMethod session)
+                        headers (.getHeaders session)]
+                    (log/i "Session info:")
+                    (log/i (str "URI: " uri))
+                    (log/i (str "Method: " method))
+                    (log/i (str "Headers: " headers))
                     ;; Testing what happends when I raise an exception:
                     ;; Same HTTP error as I get when calling: newFixedLegthReponse
                     ;; (throw (Exception. "my exception message"))
-                    ;; calling static method way 1: (This hang the connection so nothing is being return "empty reponse)
                     ;; (.newFixedLengthResponse NanoHTTPD (str msg "\n"))
                     ;; calling static method way 2: (This cause the application to crash
-                    (NanoHTTPD/newFixedLengthResponse (str msg "\n"))
+                    (NanoHTTPD/newFixedLengthResponse (str msg "
URI: " uri "
\n"
+                                                           "
METHOD: " method "
\n"
+                                                           "
HEADERS: " headers "
\n"
+                                                           "\n"))
                     )
                   )
                 )]
@@ -50,7 +58,7 @@
   )

 ;;Define httpd instance as a global variable
-(def httpd (init-httpd "0.0.0.0" 5555))
+(def httpd (init-httpd "0.0.0.0" 5557))

 ;; This is how an Activity is defined. We create one and specify its onCreate
 ;; method. Inside we create a user interface that consists of an edit and a
@@ -61,7 +69,7 @@
   (onCreate [this bundle]
     (.superOnCreate this bundle)
     (toast "starting HTTPD server..." :long)
-    (log/i "staring httpd server logging")
+    (log/i "staring httpd server")
     (.start httpd)
     (neko.debug/keep-screen-on this)
     (on-ui


core: comment

core: comment

--- core/data/core.clj
+++ core/data/core.clj
@@ -2374,7 +2374,10 @@
     `(let [iter# ~(emit-bind (to-groups seq-exprs))]
        (iter# ~(second seq-exprs)))))

-
+(defmacro comment
+  "Ignores body, yields nil"
+  {:added "1.0"}
+  [& body])

 (defmacro assert


core: reduce-kv

core: reduce-kv

--- core/data/core.clj
+++ core/data/core.clj
@@ -2485,6 +2485,17 @@
           g
           (last steps)))))

+(defn reduce-kv
+  "Reduces an associative collection. f should be a function of 3
+  arguments. Returns the result of applying f to init, the first key
+  and the first value in coll, then applying f to that result and the
+  2nd key and value, etc. If coll contains no entries, returns init
+  and f is not called. Note that reduce-kv is supported on vectors,
+  where the keys will be the ordinals."
+  {:added "1.0"}
+  ([f init coll]
+   (reduce1 (fn [ret [k v]] (f ret k v)) init coll)))
+
 (defn keep
   "Returns a lazy sequence of the non-nil results of (f item). Note,
   this means false return values will be included.  f must be free of


Whitespace.

Whitespace.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -42,12 +42,11 @@

 (defn vis-add-ch [vis ch first-taker-actx]
   (-> vis
-      (update-in [:chs ch]
-                 #(if (nil? %)
-                    {:id ((:gen-id vis))
-                     :msgs {}
-                     :first-taker-actx first-taker-actx}
-                    %))
+      (update-in [:chs ch] #(if (nil? %)
+                              {:id ((:gen-id vis))
+                               :msgs {}
+                               :first-taker-actx first-taker-actx}
+                              %))
       (update-in [:chs ch :first-taker-actx]
                  #(if % % first-taker-actx))))


fix vars idx

fix vars idx

--- src/cljss/core.clj
+++ src/cljss/core.clj
@@ -16,13 +16,19 @@
 (defn- collect-styles [cls id idx styles]
   (let [dynamic (filterv dynamic? styles)
         static (filterv (comp not dynamic?) styles)
-        vars (map-indexed #(varid id (+ idx %1) %2) dynamic)
+        [vars idx]
+        (reduce
+          (fn [[vars idx] ds]
+            [(conj vars (varid id idx ds))
+             (inc idx)])
+          [[] idx]
+          dynamic)
         vals (mapv (fn [[_ var] [_ exp]] [var exp]) vars dynamic)
         static (->> vars
                     (map (fn [[rule var]] [rule (str "var(" var ")")]))
                     (concat static)
                     (build-css cls))]
-    [static vals (count vars)]))
+    [static vals idx]))

 (defn build-styles [styles]
   (let [pseudo (filterv pseudo? styles)
@@ -134,10 +140,3 @@
   (let [[id# keyframes# vals#] (build-keyframes keyframes)]
     `(defn ~var ~args
        (cljss.core/css-keyframes ~id# ~keyframes# ~vals#))))
-
-(macroexpand
-  '(defkeyframes bounce [bounce-height]
-                 {[:from 20 53 80 :to] {:transform "translate3d(0,0,0)"}
-                  [40 43]              {:transform (str "translate3d(0,-" bounce-height "px,0)")}
-                  70                   {:transform (str "translate3d(0,-" (/ bounce-height 2) "px,0)")}
-                  90                   {:transform (str "translate3d(0,-" (/ bounce-height 4) "px,0)")}}))


remove obsolete dependency

remove obsolete dependency

--- transports/embedded/project.clj
+++ transports/embedded/project.clj
@@ -4,9 +4,7 @@
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.8.0"]
-                 [org.clojure/core.async "0.3.442"]
-
-                 [clj-factum/serverlib "0.1.1-SNAPSHOT"]]
+                 [org.clojure/core.async "0.3.442"]]

   :min-lein-version "2.6.1"


Add more trace output.

Add more trace output.

--- src/dsbdp/main.clj
+++ src/dsbdp/main.clj
@@ -365,7 +365,9 @@
               (.inc ^Counter in-cntr)
               (recur)))
           (sleep 130000))
-        (.start in-loop))
+        (do
+          (println "Starting in-loop.")
+          (.start in-loop)))
       (if
         (not (nil? async-out-count-loop))
         (.start async-out-count-loop)))))


Add no-op option.

Add no-op option.

--- src/dsbdp/main.clj
+++ src/dsbdp/main.clj
@@ -25,6 +25,7 @@
   (println "Starting dsbdp main...")
   (let [in-cntr (Counter.)
         out-cntr (Counter.)
+        no-op true
         delta-cntr (delta-counter)
         stats-fn (fn []
                    (println
@@ -33,16 +34,23 @@
         out-fn (fn [_ _]
                  (.inc out-cntr))
 ;        in-data 24N
-        in-data 1
-        pipeline (create-local-processing-pipeline
-                   (create-no-op-proc-fns 2)
-;                   (create-factorial-proc-fns 2)
-                   out-fn)
-        in-fn (get-in-fn pipeline)
-        in-loop (ProcessingLoop.
-                  (fn []
-                    (in-fn in-data)
-                    (.inc in-cntr)))]
+        in-data (if (not no-op)
+                  1)
+        pipeline (if (not no-op)
+                   (create-local-processing-pipeline
+                     (create-no-op-proc-fns 2)
+;                     (create-factorial-proc-fns 2)
+                     out-fn))
+        in-fn (if (not (nil? pipeline))
+                (get-in-fn pipeline))
+        in-loop (if (not (nil? in-fn))
+                  (ProcessingLoop.
+                    (fn []
+                      (in-fn in-data)
+                      (.inc in-cntr)))
+                  (ProcessingLoop.
+                    (fn []
+                      (.inc in-cntr))))]
     (.start in-loop)
     (run-repeat (executor) stats-fn 1000)))


Fix #198. Allow passing map to `chrome-headless` and `firefox-headless`. (#216)

--- src/etaoin/api.clj
+++ src/etaoin/api.clj
@@ -2819,11 +2819,13 @@

   - `opt` a map of all possible parameters that `create-driver`,
   `run-driver` and `connect-driver` may accept."
-  [type & [opt]]
-  (-> type
-      (create-driver opt)
-      (run-driver opt)
-      (connect-driver opt)))
+  ([type]
+   (boot-driver type {}))
+  ([type opt]
+   (-> type
+       (create-driver opt)
+       (run-driver opt)
+       (connect-driver opt))))

 (defn quit
   "Closes the current session and stops the driver."
@@ -2854,13 +2856,24 @@

 (defn chrome-headless
   "Launches headless Chrome driver. A shortcut for `boot-driver`."
-  [& opt]
-  (boot-driver :chrome (assoc opt :headless true)))
+  ([]
+   (chrome-headless {}))
+  ([opt]
+   (boot-driver :chrome (assoc opt :headless true))))

 (defn firefox-headless
   "Launches headless Firefox driver. A shortcut for `boot-driver`."
-  [& opt]
-  (boot-driver :firefox (assoc opt :headless true)))
+  ([]
+   (firefox-headless {}))
+  ([opt]
+   (boot-driver :firefox (assoc opt :headless true))))
+
+(defn firefox-headless
+  "Launches headless Firefox driver. A shortcut for `boot-driver`."
+  ([]
+   (firefox-headless {}))
+  ([opt]
+   (boot-driver :firefox (assoc opt :headless true))))

 (defmacro with-driver
   "Performs the body within a driver session.


Working on getting neocons / Neo4J working with replacement parameters in IN clauses.

--- src/alfresco_technical_validation/validation.clj
+++ src/alfresco_technical_validation/validation.clj
@@ -27,7 +27,9 @@
 (defn- validate-alfresco-api-usage
   []
   (let [alfresco-public-java-api (alf-api/public-java-api)
-        res                      (cy/tquery "START n=node(*)
+        _                        (println "alfresco-public-java-api=" alfresco-public-java-api)
+        res                      (cy/tquery "
+START n=node(*)
 MATCH (n)-->(m)
 WHERE has(n.name)
   AND has(m.name)
@@ -39,8 +41,8 @@
                     ])
 RETURN m.name as Blacklisted_Alfresco_API, collect(distinct n.name) as Used_By
  ORDER BY m.name;
-  " {:public-apis alfresco-public-java-api})]
-    println res))  ;####TEST
+                                            " {:public-apis alfresco-public-java-api})]
+    (println "res=" res)))  ;####TEST

 (defn- validate-criteria
   [neo4j-url


redundant function

redundant function

--- src/etaoin/api.clj
+++ src/etaoin/api.clj
@@ -2796,7 +2796,7 @@
          (if (not (= 404 (:status (ex-data e))))
            ;; the exception was caused by something other than "session not found"
            (throw e))))
-
+
   (swap! driver dissoc
          :session :capabilities)
   driver)
@@ -2860,13 +2860,6 @@
    (chrome-headless {}))
   ([opt]
    (boot-driver :chrome (assoc opt :headless true))))
-
-(defn firefox-headless
-  "Launches headless Firefox driver. A shortcut for `boot-driver`."
-  ([]
-   (firefox-headless {}))
-  ([opt]
-   (boot-driver :firefox (assoc opt :headless true))))

 (defn firefox-headless
   "Launches headless Firefox driver. A shortcut for `boot-driver`."


Remove "non-empty" from #'cats.core/sequence docstring

--- src/cats/core.cljc
+++ src/cats/core.cljc
@@ -538,7 +538,7 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defn sequence
-  "Given a non-empty collection of monadic values, collect
+  "Given a collection of monadic values, collect
   their values in a seq returned in the monadic context.

       (require '[cats.context :as ctx]


Work on sequencer...

Work on sequencer...

Summary...
 * alt-click-drag to modify the currenlty selected param for each
   row relative to the row's height. Works like a pencil tool.
 * click-drag turn cells on or add entries to empty cells.
 * click-shift-drag turns cells off (like mute).
 * ctl-click and ctl-click-drag now delete items.

Details...
 * define #'play-step and use it in #'step-player and #'on-grid-click
 * modify #'on-grid-click to only trigger inst when the cell is enabled.
 * add #'inst-param for selecting the parameter to edit.
 * add #'inst-panel and use to contain #'inst-button, #'inst-param, etc.

 * use seesaw.mig/mig-panel
 * use a regular button for inst-button
 * use a mig-panel for inst-panel

 * add :param key to each row in state-atom
 * add #'inst->index and #'on-param-selection.
 * add mute and solo buttons to inst-panel.
 * add :class to buttons

 * added update-entry, delete-entry, muted-entry-stle,
   scale-val, get-param-name, get-param-range, scale-param-val,
   inst->index, on-param-selection, inst-mute, inst-solo,
 * rename inst-param-menu to inst-param
 * pass state-atom to inst-panel as first arg.

 * add #'parse-grid-click and use in #'on-grid... events.

 * use update-style from seesaw.graphics
 * add mute-entry, get-row-param, scaled-entry-style, and
   get-param-factor.
 * use scaled-entry-style in paint-grid
 * fix up on-grid-drag behavior
 * remove unused seesaw.swingx lib.

--- src/overtone/gui/sequencer.clj
+++ src/overtone/gui/sequencer.clj
@@ -4,8 +4,8 @@
         [overtone.gui.control :only [synth-controller]]
         [seesaw core]
         [seesaw.color :only [color]]
-        [seesaw.graphics :only [style draw rounded-rect line]]
-        [seesaw.swingx :only [hyperlink]])
+        [seesaw.graphics :only [style update-style draw rounded-rect line]]
+        [seesaw.mig :only [mig-panel]])
   (:require [seesaw.bind :as bind]))

 (defn- make-initial-state [metro steps instruments init-vals]
@@ -17,26 +17,69 @@
                 (for [i instruments]
                   (let [i-vals (or (get init-vals (:name i))
                                    (vec (repeat steps false)))]
-                    {:inst i
+                    {:inst  i
+                     :param (-> i :params first :name)
                      :value i-vals})))
    })

+(def ^{:private true} NEW_ENTRY {:on true})
+
 (defn- toggle-playing [state]
   (update-in state [:playing?] not))

-(defn- toggle-entry [state row col]
-  (update-in state [:rows row :value col] not))
+(defn- get-entry [state row col]
+  (get-in state [:rows row :value col]))

 (defn- set-entry [state row col v]
   (if (< row (count (:rows state)))
     (assoc-in state [:rows row :value col] v)
     state))

-(defn- get-entry [state row col]
-  (get-in state [:rows row :value col]))
+(defn- update-entry [state row col v]
+  (if (< row (count (:rows state)))
+    (update-in state [:rows row :value col] merge NEW_ENTRY v)
+    state))
+
+(defn- mute-entry [state row col]
+  (update-in state [:rows row :value col]
+             (fn [v]
+               (if (associative? v)
+                 (assoc-in v [:on] false)
+                 v))))
+
+(defn- toggle-entry [state row col]
+  (update-in state [:rows row :value col]
+             (fn [v]
+               (if (associative? v)
+                 (update-in v [:on] not)
+                 NEW_ENTRY))))
+
+(defn- delete-entry [state row col]
+  (set-entry state row col false))
+
+(defn- get-row-param
+  [state row]
+  (get-in state [:rows row :param]))
+
+(defn- get-param-info
+  [state row]
+  (let [p-name (get-row-param state row)]
+    (first (filter #(= (:name %) p-name)
+                 (get-in state [:rows row :inst :params])))))

 (defn- clear-row [state row]
   (assoc-in state [:rows row :value] (vec (repeat (:steps state) false))))
+
+(defn- play-step
+  [row index]
+  (let [{:keys [inst value]} row
+        step-val (nth value index)]
+
+    (when (:on step-val)
+      (apply inst (-> step-val
+                      (dissoc :on)
+                      seq
+                      flatten)))))

 (defn- step-player
   [state-atom beat]
@@ -45,11 +88,13 @@
       (let [metro (:metronome state)
             steps (:steps state)
             index (mod beat steps)
-            next-beat (inc beat) ]
+            next-beat (inc beat)]
+
         (swap! state-atom assoc-in [:step] index)
-        (doseq [{:keys [inst value]} (:rows state)]
-          (when (nth value index)
-            (at (metro beat) (inst))))
+
+        (doseq [row (:rows state)]
+          (at (metro beat) (play-step row index)))
+
         (apply-at (metro next-beat) #'step-player
                   [state-atom next-beat])))))

@@ -62,11 +107,30 @@
     :background (color 0 255 0 200)
     :foreground (color 0 150 0)))

+(def ^{:private true} muted-entry-style
+  (style
+    :stroke 1.0
+    :background (color 150 255 150 200)
+    :foreground (color 0 150 0)))
+
 (def ^{:private true} current-step-style
   (style
     :stroke 1.0
     :background (color 128 128 224 200)
     :foreground (color 0 150 0)))
+
+(defn- scaled-entry-style
+  [n]
+  (let [g (int (+ (* n 200) 55))
+        bg (color 0 g 0 200)]
+    (update-style enabled-entry-style :background bg)))
+
+(defn- get-param-factor
+  [p-info val]
+  (let [{:keys [max min name default]} p-info
+        p-val (or ((keyword name) val)
+                  default)]
+    (double (/ (- p-val min) (- max min)))))

 (defn- paint-grid [state ^javax.swing.JComponent c g]
   (let [w    (width c)
@@ -80,40 +144,80 @@
       (let [x (* step dx)]
         (draw g (rounded-rect x 0 dx h) current-step-style)))
     (dotimes [r rows]
-      (let [y (* r dy)]
+      (let [y (* r dy)
+            p (get-param-info state r)]
         (draw g (line 0 y w y) grid-line-style)
         (dotimes [c cols]
           (let [x (* c dx)]
             (draw g (line x 0 x h) grid-line-style)
-            (when (get-entry state r c)
-              (draw g
-                    (rounded-rect (+ x 2) (+ y 2) (- dx 3) (- dy 3) 3 3)
-                    enabled-entry-style))))))))
+            (when-let [val (get-entry state r c)]
+              (let [paint-cell
+                    #(draw g
+                           (rounded-rect (+ x 2) (+ y 2) (- dx 3) (- dy 3) 3 3)
+                           %)]
+                (if (:on val)
+                  (let [p-fact (get-param-factor p val)]
+                    (paint-cell (scaled-entry-style p-fact)))
+                  (paint-cell muted-entry-style))))))))))
+
+(defn- scaled-param-map
+  [state row val]
+  (let [{:keys [max min name]} (get-param-info state row)
+        p-name (keyword name)
+        p-val (-> val
+                (* (- max min))
+                (+ min))]
+    {p-name p-val}))
+
+(defn- parse-grid-click
+  [state e]
+  (let [grid   (to-widget e)
+        x      (.getX e)
+        y      (.getY e)
+        n-rows (count (:rows state))
+        n-cols (:steps state)
+        r-size (/ (height grid) n-rows)
+        c-size (/ (width  grid) n-cols)
+        r      (int (/ y r-size))
+        c      (int (/ x c-size))
+        r-top  (* r-size r)
+        r-btm  (+ r-top r-size)
+        y-val  (-> y (max r-top) (min r-btm) (- r-top))
+        y-val  (- 1 (double (/ y-val r-size)))
+        param  (scaled-param-map state r y-val)]
+    {:row r :col c :r-size r-size :c-size c-size :y-val y-val :param param}))

 (defn- on-grid-clicked [state e]
-  (let [grid (to-widget e)
-        x    (.getX e)
-        y    (.getY e)
-        rows (count (:rows state))
-        cols (:steps state)
-        c    (int (/ x (/ (width grid) cols)))
-        r    (int (/ y (/ (height grid) rows)))
-        new-state (toggle-entry state r c)]
-    ; when they enable a cell, play the sample.
-    (if (and (get-in new-state [:rows r :value c])
-             (not (:playing? new-state)))
-      ((get-in new-state [:rows r :inst])))
-    (toggle-entry state r c)))
+  (let [{:keys [row col param]} (parse-grid-click state e)
+        new-state (cond (.isControlDown e) (delete-entry state row col)
+                        (.isAltDown e)     (update-entry state row col param)
+                        :else (toggle-entry state row col))]
+
+    ;;when they enable a cell, play the sample.
+    (when (not (:playing? new-state))
+      (let [row (get-in new-state [:rows row])]
+        (play-step row col)))
+
+    new-state))

 (defn- on-grid-drag [state e]
-  (let [grid (to-widget e)
-        x    (.getX e)
-        y    (.getY e)
-        rows (count (:rows state))
-        cols (:steps state)
-        c    (int (/ x (/ (width grid) cols)))
-        r    (int (/ y (/ (height grid) rows)))]
-    (set-entry state r c (not (.isShiftDown e)))))
+  (let [{:keys [row col r-size c-size y-val param]} (parse-grid-click state e)]
+    (cond (.isControlDown e) (delete-entry state row col)
+          (.isShiftDown e)   (mute-entry state row col)
+          (.isAltDown e)     (update-entry state row col param)
+          :else              (update-entry state row col {}))))
+
+(defn- inst->index
+  [rows inst]
+  (first (keep-indexed
+          (fn [index item]
+            (when (= inst (:inst item))
+              index))
+          rows)))
+
+(defn- on-param-selection [state inst e]
+  (let [r (inst->index (:rows state) inst)]
+    (assoc-in state [:rows r :param] (selection e))))

 (defn- step-grid [state-atom]
   (let [state @state-atom
@@ -123,14 +227,40 @@
                   :preferred-size [(* 25 (:steps state))
                                    :by
                                    (* 25 (count (:rows state)))])]
+
     (listen c :mouse-clicked #(swap! state-atom on-grid-clicked %)
               :mouse-dragged #(swap! state-atom on-grid-drag %))
     c))

 (defn- inst-button
   [inst]
-  (hyperlink :text (:name inst)
-             :listen [:action (fn [e] (synth-controller inst))]))
+  (button :text (:name inst)
+          :listen [:action (fn [e] (synth-controller inst))]))
+
+(defn- inst-param
+  [inst]
+  (combobox :model (map :name (:params inst))
+            :class :param))
+
+(defn- inst-mute
+  [inst]
+  (toggle :text "Mute" :class :mute))
+
+(defn- inst-solo
+  [inst]
+  (toggle :text "Solo" :class :solo))
+
+(defn- inst-panel
+  [state-atom inst]
+  (let [panel (mig-panel :constraints ["wrap 2"
+                                       "grow"]
+                         :items [[(inst-button inst) "span, growx"]
+                                 [(inst-param  inst) "span, growx"]
+                                 [(inst-mute   inst) "growx"]
+                                 [(inst-solo   inst) "growx"]])]
+    (listen (select panel [:.param])
+             :selection #(swap! state-atom on-param-selection inst %))
+    panel))

 (defn step-sequencer
   [metro steps instruments & [init-vals]]
@@ -149,15 +279,17 @@
                                         :separator
                                         controls-btn])
           grid         (step-grid state-atom)
-          inst-btns    (map inst-button instruments)
+          inst-panels  (map (partial inst-panel state-atom)
+                            instruments)
           f (frame :title    "Sequencer"
                    :content  (border-panel
                                :border 5 :hgap 5 :vgap 5
                                :north control-pane
                                :west (grid-panel :columns 1
-                                                 :items inst-btns)
+                                                 :items inst-panels)
                                :center grid)
                    :on-close :dispose)]
+
       (bind/bind bpm-spinner (bind/b-do [v] (metro :bpm v)))
       (bind/bind state-atom (bind/b-do [v] (repaint! grid)))

@@ -184,10 +316,10 @@
     (into {} rows)))

 (comment
-  (use 'overtone.live)
-  (use 'overtone.gui.sequencer)
-  (use 'overtone.gui.control)
-  (use 'overtone.inst.drum)
-  (def m (metronome 128))
-  (step-sequencer m 8 [kick closed-hat snare])
-)
+  (do (use 'overtone.live)
+      (use 'overtone.gui.sequencer)
+      (use 'overtone.gui.control)
+      (use 'overtone.inst.drum)
+      (def m (metronome 128))
+      (step-sequencer m 8 [kick closed-hat snare]))
+  )


Fix AST variable name

Fix AST variable name

--- src/oxcart/passes/warnings.clj
+++ src/oxcart/passes/warnings.clj
@@ -188,5 +188,5 @@

     (assert (not @error?)
             "Errors were generated in checking."))
-  (-> ast
+  (-> whole-ast
       (record-pass check-ops)))


auto-documentation for terms

auto-documentation for terms

--- src/latte/core.clj
+++ src/latte/core.clj
@@ -99,8 +99,9 @@
           (register-term-definition! def-name definition)
           (let [name# (name def-name)]
             `(do
-             (def ~def-name ~quoted-def)
-             [:registered ~name#])))))))
+               (def ~def-name ~quoted-def)
+               (alter-meta! (var ~def-name)  (fn [m#] (assoc m# :doc ~doc)))
+               [:registered ~name#])))))))

 (defn parse-context-args [def-env args]
   (loop [args args, ctx []]
@@ -142,3 +143,5 @@
     (n/beta-delta-eq? def-env t1 t2)))

+(def term= ===)
+


update example

update example

--- example/src/example/core.cljs
+++ example/src/example/core.cljs
@@ -1,4 +1,5 @@
 (ns example.core
+  (:require-macros [cljss.core])
   (:require [rum.core :as rum]
             [cljss.core :as css :refer-macros [defstyles defkeyframes]]
             [cljss.rum :refer-macros [defstyled]]


Upgraded datatype library as it now does much better marshalling between types.

--- compute/project.clj
+++ compute/project.clj
@@ -5,7 +5,7 @@
             :url "http://www.eclipse.org/legal/epl-v10.html"}
   :dependencies [[org.clojure/clojure "1.8.0"]
                  [org.clojure/core.async "0.2.391"]
-                 [thinktopic/datatype "0.1.0"]
+                 [thinktopic/think.datatype "0.3.1"]
                  [thinktopic/cortex "0.3.1-SNAPSHOT"]
                  [thinktopic/cortex-datasets "0.3.1-SNAPSHOT"]
                  [com.github.fommil.netlib/all "1.1.2" :extension "pom"]]


(SERVER-1772) Use clojars in extra dep resolution

--- src/puppetlabs/ezbake/core.clj
+++ src/puppetlabs/ezbake/core.clj
@@ -542,7 +542,8 @@
   "Resolves a single dependency and returns a File pointing to it's jar"
   [[project-symbol version :as dependency-coordinates]]
   (lein-main/info "Resolving dependency for " dependency-coordinates)
-  (let [project {:dependencies [dependency-coordinates]}
+  (let [project {:dependencies [dependency-coordinates]
+                 :repositories [["releases" {:url "https://clojars.org/repo"}]]}
         ; resolved-dependencies will be a list of jars, one for each dependency
         ; in the project, including the jar for this project
         resolved-dependencies (lein-classpath/resolve-managed-dependencies :dependencies nil project)


Persist new items to the backend before updating local state

When adding a new item we now POST it to the backend API first, getting
a response back with the complete new item including ID, before adding
this to the local state cache.

The client side application is now completely in sync with the backend
data store!

Further improvements should be made though, like using core.async to
avoid callbacks on async requests, and implement optimistic update of
local cache to avoid waiting for API response.

--- src/scavenger/client/main.cljs
+++ src/scavenger/client/main.cljs
@@ -12,11 +12,14 @@

 (enable-console-print!)

+(def api-url "http://localhost:3000")
+
 ; Utility function to send XHR requests with correct content type and parse
 ; the EDN response appropriately.
 ; TODO: Use core.async to avoid on-complete callback
-(defn edn-xhr [{:keys [method url data on-complete]}]
-  (let [xhr (XhrIo.)]
+(defn edn-xhr [{:keys [method path data on-complete]}]
+  (let [xhr (XhrIo.)
+        url (str api-url path)]
     (events/listen xhr goog.net.EventType.COMPLETE
       (fn [e]
         (on-complete (reader/read-string (.getResponseText xhr)))))
@@ -40,10 +43,20 @@
 (defmulti mutate om/dispatch)

 ; Add a single item
+; Persists to the backend API first, before adding the complete
+; item from the API response to the locale state cache.
+; TODO: Add to local state cache immediately, updating with response
+; data and reverting local transaction if persisting fails
 (defmethod mutate 'items/add
   [{:keys [state]} _ entity]
   {:value {:keys [:items]}
-   :action (fn [] (d/transact! state [entity]))})
+   :action (fn []
+             (edn-xhr {:method "POST"
+                       :path "/items"
+                       :data entity
+                       :on-complete
+                       (fn [data]
+                         (d/transact! state [data]))}))})

 ; Scavenger items list
 (defui ItemsList
@@ -110,7 +123,7 @@

 ; Load all items from API
 (edn-xhr {:method "GET"
-          :url "http://localhost:3000/items"
+          :path "/items"
           :on-complete (fn [data]
                          (d/transact! conn data))})


Use redirect-after-post where appropriate

--- src/mdr2/views.clj
+++ src/mdr2/views.clj
@@ -117,7 +117,7 @@
         ;; add the file
         (prod/add-structure production tempfile)
         ;; and redirect to the index
-        (response/redirect "/")))))
+        (response/redirect-after-post "/")))))

 (defn catalog [request & error]
   (let [identity (friend/identity request)
@@ -156,12 +156,12 @@
   (if (prod/library-signature? library_signature)
     (let [p (assoc (prod/find id) :library_signature library_signature)]
       (prod/set-state-cataloged! p)
-      (response/redirect "/catalog"))
+      (response/redirect-after-post "/catalog"))
     (catalog request "Library signature not valid")))

 (defn production-delete [id]
   (prod/delete! id)
-  (response/redirect "/"))
+  (response/redirect-after-post "/"))

 (defn production-bulk-import-form [request & [errors]]
   (let [user (friend/current-authentication request)]
@@ -224,7 +224,7 @@
      prod/set-state-structured!
      ;; write the dtbook template file
      dtbook/dtbook-file))
-  (response/redirect "/"))
+  (response/redirect-after-post "/"))

 (defn production-repair-form
   [request & [errors]]


[#7930] fix - No label is shown for empty chat screen if you open public chat via deep link after opening another public chat via deep link

Signed-off-by: Igor Mandrigin <042dc4512fa3d391c5170cf3aa61e6a638f84342@mandrigin.ru>

--- src/status_im/ui/screens/chat/views.cljs
+++ src/status_im/ui/screens/chat/views.cljs
@@ -271,6 +271,7 @@
                           :style                        style/scroll-root
                           :content-container-style      style/scroll-root
                           :keyboard-should-persist-taps :handled}
+       ^{:key current-chat-id}
        [react/view {:style     style/chat-view
                     :on-layout (fn [e]
                                  (re-frame/dispatch [:set :layout-height (-> e .-nativeEvent .-layout .-height)]))}


Handle arg-reference in resolve-plant-class

Signed-off-by: Tom Marble <b248307e886b80bf9cb4014595572a835b049bf4@info9.net>

--- src/pamela/htn.clj
+++ src/pamela/htn.clj
@@ -281,7 +281,12 @@
         {:keys [type name field method args]} plant-fn_
         pclass-ctor_ (cond
                        (= type :plant-fn-field)
-                       (get-in ir [hem-pclass :fields field :initial])
+                       (let [initial_ (get-in ir [hem-pclass :fields field :initial])
+                             {:keys [type name]} initial_]
+                         (case type
+                           :pclass-ctor initial_
+                           :arg-reference (first (filter #(= (:param %) name) pargs))
+                           {:error :unresolved-field}))

                        (= type :plant-fn-symbol)
                        (let [method-arg (get argument-mappings name)


remove errant 'v'

remove errant 'v'

--- src/riffle/cli.clj
+++ src/riffle/cli.clj
@@ -52,7 +52,7 @@

 (defn -main [& args]
   (let [{:keys [options arguments summary errors]}
-        (cli/parse-opts args options)v
+        (cli/parse-opts args options)

         {encode? :encode key :get keys? :keys base64? :base64 block-size :block-size compressor :compressor delimiter :delimiter}
         options