From 4893b8243c95877bb743e82965ac0675b7c6e234 Mon Sep 17 00:00:00 2001 From: niten Date: Wed, 15 Mar 2023 11:10:56 -0700 Subject: [PATCH] Working CLI utility --- .gitignore | 9 +++++++++ deps-lock.json | 10 ++++++++++ deps.edn | 1 + flake.nix | 4 ++-- src/objectifier_client/cli.clj | 17 +++++++++-------- src/objectifier_client/core.clj | 27 +++++++++++++++++---------- 6 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1b9f7c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +.idea +*.log +tmp/ + +.cpcache/ +.nrepl-port +target/ +result diff --git a/deps-lock.json b/deps-lock.json index 8cee345..04b6253 100644 --- a/deps-lock.json +++ b/deps-lock.json @@ -267,6 +267,16 @@ "mvn-repo": "https://repo1.maven.org/maven2/", "hash": "sha256-bY3hTDrIdXYMX/kJVi/5hzB3AxxquTnxyxOeFp/pB1g=" }, + { + "mvn-path": "org/clojure/tools.cli/1.0.214/tools.cli-1.0.214.jar", + "mvn-repo": "https://repo1.maven.org/maven2/", + "hash": "sha256-7h4iTowAv6wht2tSC3D5WF0nj4al16wMelXpGt8PTqM=" + }, + { + "mvn-path": "org/clojure/tools.cli/1.0.214/tools.cli-1.0.214.pom", + "mvn-repo": "https://repo1.maven.org/maven2/", + "hash": "sha256-ulk+rq6K6NhkVBgYjY1707XNndYKY5w04fBuGyqDpIQ=" + }, { "mvn-path": "potemkin/potemkin/0.4.5/potemkin-0.4.5.jar", "mvn-repo": "https://repo.clojars.org/", diff --git a/deps.edn b/deps.edn index fbfdb6a..25b9c73 100644 --- a/deps.edn +++ b/deps.edn @@ -3,6 +3,7 @@ :deps { org.clojure/clojure { :mvn/version "1.11.1" } org.clojure/data.json { :mvn/version "2.4.0" } + org.clojure/tools.cli { :mvn/version "1.0.214" } clj-http/clj-http { :mvn/version "3.12.3" } } } diff --git a/flake.nix b/flake.nix index a68afc8..2256343 100644 --- a/flake.nix +++ b/flake.nix @@ -16,14 +16,14 @@ default = objectifier-client; objectifier-client = helpers.packages."${system}".mkClojureBin { name = "org.fudo/objectifier-client"; - primary-namespace = "objectifier-client.cli"; + primaryNamespace = "objectifier-client.cli"; src = ./.; }; }; devShells = let pkgs = import nixpkgs { inherit system; }; in rec { - default = update-deps; + default = objectifier-client; objectifier-client = pkgs.mkShell { buildInputs = [ self.packages."${system}".objectifier-client ]; }; diff --git a/src/objectifier_client/cli.clj b/src/objectifier_client/cli.clj index add0f60..2765ab4 100644 --- a/src/objectifier_client/cli.clj +++ b/src/objectifier_client/cli.clj @@ -2,7 +2,8 @@ (:require [objectifier-client.core :as obj] [clojure.java.io :as io] [clojure.tools.cli :as cli] - [clojure.string :as str])) + [clojure.string :as str]) + (:gen-class)) (defn- read-file-bytes [filename] (with-open [in (java.io.FileInputStream. filename) @@ -41,20 +42,20 @@ prob))))) (defn- display-labels [client filenames] - (distinct - (mapcat (fn [filename] - (obj/get-labels! client (read-file-bytes filename))) - filenames))) + (let [labels (distinct + (mapcat (fn [filename] (obj/get-labels! client (read-file-bytes filename))) + filenames))] + (doseq [label labels] (println label)))) (defn -main [& args] - (let [{:keys [options arguments summary errors]}] + (let [{:keys [options arguments summary errors]} (cli/parse-opts args cli-opts)] (when (seq errors) (msg-quit 1 (usage summary errors))) (when (:help options) (msg-quit 0 (usage summary))) - (when (empty? (arguments)) + (when (empty? arguments) (msg-quit 0 (usage summary ["No files provided to scan."]))) - (let [client (obj/define-connection "http" (:server options) (:port options))] + (let [client (obj/define-connection :host (:server options) :port (:port options))] (if (:labels options) (display-labels client arguments) (doseq [file arguments] diff --git a/src/objectifier_client/core.clj b/src/objectifier_client/core.clj index f101a8c..3bee2ab 100644 --- a/src/objectifier_client/core.clj +++ b/src/objectifier_client/core.clj @@ -1,16 +1,17 @@ (ns objectifier-client.core (:require [clj-http.client :as client] [clojure.data.json :as json] + [clojure.string :as str] [slingshot.slingshot :refer [throw+]]) (:import java.net.URL java.io.ByteArrayInputStream)) (defprotocol IObjectifierClient - (get! [_ image-data]) - (get-labels! [_ image-data]) - (get-detections! [_ image-data]) - (get-highlights! [_ image-data]) - (get-probabilites! [_ image-data])) + (get! [_ image-data]) + (get-labels! [_ image-data]) + (get-detections! [_ image-data]) + (get-highlights! [_ image-data]) + (get-probabilities! [_ image-data])) (defn- url->string [url] (.toExternalForm url)) @@ -23,9 +24,15 @@ {:multipart [{:name "image" :content input-stream}]}))) +(defn- to-keyword [str] + (-> str + (str/lower-case) + (str/replace #" " "-") + (keyword))) + (defn- process-response [resp] (if (<= 200 (:status resp) 299) - (-> resp :body (json/read-str :key-fn keyword)) + (-> resp :body (json/read-str :key-fn to-keyword)) (throw+ {:type ::http-error :status (:status resp) :reason (:reason-phrase resp) @@ -48,13 +55,13 @@ (-> (get! self image-data) :output)) - (get-probabilites! [self image-data] + (get-probabilities! [self image-data] (into {} (map (juxt (comp keyword :label) :confidence)) (get-detections! self image-data)))) (defn define-connection - [{:keys [scheme host port] - :or {scheme "http" - port 80}}] + [& {:keys [scheme host port] + :or {scheme "http" + port 80}}] (->ObjectifierClient scheme host port))