From b5d08eb60f1df1ed7330af3c38daa8fce3b856de Mon Sep 17 00:00:00 2001 From: Alan Thompson Date: Tue, 14 Mar 2023 17:14:26 -0700 Subject: [PATCH] Resolves issue "Invalid regex pattern in cljc file #21" --- build.clj | 2 +- src/clj/tupelo/uuid.clj | 83 ------------------------------- src/cljc/tupelo/core/impl.cljc | 49 ++++++++++-------- src/cljc/tupelo/uuid.cljc | 91 ++++++++++++++++++++++++++++++++++ test/clj/tst/tupelo/uuid.clj | 65 ------------------------ test/cljc/tst/tupelo/uuid.cljc | 72 +++++++++++++++++++++++++++ 6 files changed, 192 insertions(+), 170 deletions(-) delete mode 100644 src/clj/tupelo/uuid.clj create mode 100644 src/cljc/tupelo/uuid.cljc delete mode 100644 test/clj/tst/tupelo/uuid.clj create mode 100644 test/cljc/tst/tupelo/uuid.cljc diff --git a/build.clj b/build.clj index b7509820..fa89b938 100644 --- a/build.clj +++ b/build.clj @@ -4,7 +4,7 @@ [deps-deploy.deps-deploy :as dd] )) -(def version "23.03.04") ; snapshot versions MUST look like `23.03.03-SNAPSHOT` (i.e. no letters like `-03a`) +(def version "23.03.14") ; snapshot versions MUST look like `23.03.03-SNAPSHOT` (i.e. no letters like `-03a`) (def tag (str "v" version)) ; ***** ASSUMES YOU CREATE A GIT TAG LIKE `v23.01.31` ***** (def lib-name 'tupelo/tupelo) ; must be a namespaced-qualified symbol, interpreted as `group-id/artifact-id` (def scm-root "github.com/cloojure/tupelo") diff --git a/src/clj/tupelo/uuid.clj b/src/clj/tupelo/uuid.clj deleted file mode 100644 index 39d51dd0..00000000 --- a/src/clj/tupelo/uuid.clj +++ /dev/null @@ -1,83 +0,0 @@ -(ns tupelo.uuid - (:use tupelo.core) - (:refer-clojure :exclude [rand]) - (:require - [clj-uuid :as uuid] - [clojure.core :exclude [rand]] - [schema.core :as s] - [tupelo.schema :as tsk] - [tupelo.string :as str] - [tupelo.core.impl :as impl]) - (:import - [java.util UUID])) - -(def const-null-str - "A null UUID string '00000000-0000-0000-0000-000000000000' " - "00000000-0000-0000-0000-000000000000") -(def const-null-obj - "A null UUID object '00000000-0000-0000-0000-000000000000' " - (UUID/fromString const-null-str)) - -(def const-dummy-str - "A dummy UUID string '00000000-0000-0000-0000-000000000000' " - "cafebabe-1953-0510-0970-0123456789ff") -(def const-dummy-obj - "A dummy UUID object '00000000-0000-0000-0000-000000000000' " - (UUID/fromString const-dummy-str)) - -(def null-str - "Returns a null UUID string '00000000-0000-0000-0000-000000000000' " - (const->fn const-null-str)) -(def null - "Returns a null UUID object '00000000-0000-0000-0000-000000000000' " - (const->fn const-null-obj)) - -(def dummy-str - "Returns a dummy UUID string 'cafebabe-1953-0510-0970-0123456789ff' " - (const->fn const-dummy-str)) -(def dummy - "Returns a dummy UUID object 'cafebabe-1953-0510-0970-0123456789ff'" - (const->fn const-dummy-obj)) - -(def ^:no-doc uuid-regex-pattern impl/uuid-regex-pattern) -(def uuid-str? - "Returns true iff the string shows a valid UUID-like pattern of hex digits. Does not - distinguish between UUID subtypes." - impl/uuid-str?) - -;----------------------------------------------------------------------------- -(s/defn rand :- UUID - "Returns a random uuid as a UUID object" - [] (uuid/v4)) - -(s/defn rand-str :- s/Str - "Returns a random uuid as a String" - [] (str (tupelo.uuid/rand))) - -;----------------------------------------------------------------------------- -(def ^:no-doc uuid-counter (atom nil)) ; uninitialized -(defn counted-reset! [] (reset! uuid-counter 0)) -(counted-reset!) ; initialize upon load - -(defn counted-str [] - (let [cnt (swap-out! uuid-counter inc) - uuid-str (format "%08x-aaaa-bbbb-cccc-ddddeeeeffff" cnt)] - uuid-str)) - -(defn counted [] - (UUID/fromString (counted-str))) - -;----------------------------------------------------------------------------- -(defmacro with-null - "For testing, replace all calls to uuid/rand with uuid/null" - [& forms] - `(with-redefs [rand null] - ~@forms)) - -(defmacro with-counted - "For testing, replace all calls to uuid/rand with uuid/counted" - [& forms] - `(with-redefs [rand counted] - (counted-reset!) - ~@forms)) - diff --git a/src/cljc/tupelo/core/impl.cljc b/src/cljc/tupelo/core/impl.cljc index b63c8a73..b91c213c 100644 --- a/src/cljc/tupelo/core/impl.cljc +++ b/src/cljc/tupelo/core/impl.cljc @@ -11,18 +11,18 @@ [clojure.string :as str] [schema.core :as s])) -(defn cljs-env? ; from plumatic schema/macros.clj +(defn cljs-env? ; from plumatic schema/macros.clj "Take the &env from a macro, and tell whether we are expanding into cljs." [env] (boolean (:ns env))) -(defmacro if-cljs ; from plumatic schema/macros.clj +(defmacro if-cljs ; from plumatic schema/macros.clj "Return then if we are generating cljs code and else for Clojure code. https://groups.google.com/d/msg/clojurescript/iBY5HaQda4A/w1lAQi9_AwsJ" [then else] (if (cljs-env? &env) then else)) -(defmacro try-catchall ; from plumatic schema/macros.clj +(defmacro try-catchall ; from plumatic schema/macros.clj "A cross-platform variant of try-catch that catches all exceptions. Does not (yet) support finally, and does not need or want an exception class." [& body] @@ -58,23 +58,30 @@ (def ^:no-doc uuid-regex-pattern - #"(?x) # expanded mode - \p{XDigit}{8} # 8 hex digits - - # hyphen - \p{XDigit}{4} # 4 hex digits - - # hyphen - \p{XDigit}{4} # 4 hex digits - - # hyphen - \p{XDigit}{4} # 4 hex digits - - # hyphen - \p{XDigit}{12} # 12 hex digits - ") -(s/defn uuid-str? :- s/Bool - "Returns true iff the string shows a valid UUID-like pattern of hex digits. Does not - distinguish between UUID subtypes." - [arg] - (boolean - (when (string? arg) - (re-matches uuid-regex-pattern arg)))) + #?(:clj #"(?x) # expanded mode + \p{XDigit}{8} # 8 hex digits + - # hyphen + \p{XDigit}{4} # 4 hex digits + - # hyphen + \p{XDigit}{4} # 4 hex digits + - # hyphen + \p{XDigit}{4} # 4 hex digits + - # hyphen + \p{XDigit}{12} # 12 hex digits + " + :cljs #"[0-9a-fA-f]{8}-[0-9a-fA-f]{4}-[0-9a-fA-f]{4}-[0-9a-fA-f]{4}-[0-9a-fA-f]{12}" + )) + +; #todo fix for cljs +#?(:clj + + (s/defn uuid-str? :- s/Bool + "Returns true iff the string shows a valid UUID-like pattern of hex digits. Does not + distinguish between UUID subtypes." + [arg] + (boolean + (when (string? arg) + (re-matches uuid-regex-pattern arg)))) + ) diff --git a/src/cljc/tupelo/uuid.cljc b/src/cljc/tupelo/uuid.cljc new file mode 100644 index 00000000..45cb1273 --- /dev/null +++ b/src/cljc/tupelo/uuid.cljc @@ -0,0 +1,91 @@ +(ns tupelo.uuid + (:use tupelo.core) + (:refer-clojure :exclude [rand]) + (:require + [clj-uuid :as uuid] + [clojure.core :exclude [rand]] + [schema.core :as s] + [tupelo.schema :as tsk] + [tupelo.string :as str] + [tupelo.core.impl :as impl]) + (:import + [java.util UUID])) + +(def const-null-str + "A null UUID string '00000000-0000-0000-0000-000000000000' " + "00000000-0000-0000-0000-000000000000") + +(def const-dummy-str + "A dummy UUID string '00000000-0000-0000-0000-000000000000' " + "cafebabe-1953-0510-0970-0123456789ff") + +; #todo add code & tests for cljs +#?(:clj + (do + + (def uuid-str? ; #todo add tests for cljc + "Returns true iff the string shows a valid UUID-like pattern of hex digits. Does not + distinguish between UUID subtypes." + impl/uuid-str?) + + (def null-str + "Returns a null UUID string '00000000-0000-0000-0000-000000000000' " + (const->fn const-null-str)) + + (def dummy-str + "Returns a dummy UUID string 'cafebabe-1953-0510-0970-0123456789ff' " + (const->fn const-dummy-str)) + + (def const-null-obj + "A null UUID object '00000000-0000-0000-0000-000000000000' " + (UUID/fromString const-null-str)) + + (def const-dummy-obj + "A dummy UUID object '00000000-0000-0000-0000-000000000000' " + (UUID/fromString const-dummy-str)) + + (def null + "Returns a null UUID object '00000000-0000-0000-0000-000000000000' " + (const->fn const-null-obj)) + + (def dummy + "Returns a dummy UUID object 'cafebabe-1953-0510-0970-0123456789ff'" + (const->fn const-dummy-obj)) + + ;----------------------------------------------------------------------------- + (s/defn rand :- UUID + "Returns a random uuid as a UUID object" + [] (uuid/v4)) + + (s/defn rand-str :- s/Str + "Returns a random uuid as a String" + [] (str (tupelo.uuid/rand))) + + ;----------------------------------------------------------------------------- + (def ^:no-doc uuid-counter (atom nil)) ; uninitialized + (defn counted-reset! [] (reset! uuid-counter 0)) + (counted-reset!) ; initialize upon load + + (defn counted-str [] + (let [cnt (swap-out! uuid-counter inc) + uuid-str (format "%08x-aaaa-bbbb-cccc-ddddeeeeffff" cnt)] + uuid-str)) + + (defn counted [] + (UUID/fromString (counted-str))) + + ;----------------------------------------------------------------------------- + (defmacro with-null + "For testing, replace all calls to uuid/rand with uuid/null" + [& forms] + `(with-redefs [rand null] + ~@forms)) + + (defmacro with-counted + "For testing, replace all calls to uuid/rand with uuid/counted" + [& forms] + `(with-redefs [rand counted] + (counted-reset!) + ~@forms)) + + )) diff --git a/test/clj/tst/tupelo/uuid.clj b/test/clj/tst/tupelo/uuid.clj deleted file mode 100644 index bb69fcb2..00000000 --- a/test/clj/tst/tupelo/uuid.clj +++ /dev/null @@ -1,65 +0,0 @@ -(ns tst.tupelo.uuid - (:use tupelo.core tupelo.test) - (:refer-clojure :exclude [rand]) - (:require - [tupelo.uuid :as uuid])) - -(verify - (is= "00000000-0000-0000-0000-000000000000" - (uuid/null-str) - (str (uuid/null))) - (is= "cafebabe-1953-0510-0970-0123456789ff" - (uuid/dummy-str) - (str (uuid/dummy))) - - (is (uuid? (uuid/null))) - (is (uuid? (uuid/dummy))) - (is (uuid/uuid-str? (uuid/null-str))) - (is (uuid/uuid-str? (uuid/dummy-str))) - - (isnt (uuid/uuid-str? "cafebabe-1953-0510-0970-0123456789fff")) - (isnt (uuid/uuid-str? "cafebabe-1953-0510-09700-123456789ff")) - (isnt (uuid/uuid-str? "cafebabe-1953-0510-066x-0123456789ff")) - (isnt (uuid/uuid-str? "cafebabe-1953-0510-0123456789ff")) - (isnt (uuid/uuid-str? "cafebabe-1953-0510|0970-0123456789ff")) - (isnt (uuid/uuid-str? 5)) - (isnt (uuid/uuid-str? :nope)) - (isnt (uuid/uuid-str? nil)) - - ; we return uuids as an object or a string - (is= java.util.UUID (type (uuid/rand))) - (is (string? (uuid/rand-str))) - (is (with-exception-default false - (dotimes [i 99] ; 2 uuids are never equal - (assert (not= (uuid/rand) (uuid/rand))) - (assert (not= (uuid/rand-str) (uuid/rand-str)))) - true)) ; if no failures, we pass the test - - ; demonstrate uuid/with-null usage for testing - (uuid/with-null - (is= (uuid/rand-str) "00000000-0000-0000-0000-000000000000") - (is= (uuid/rand-str) "00000000-0000-0000-0000-000000000000") - (is= (uuid/rand-str) "00000000-0000-0000-0000-000000000000")) - - ; demonstrate uuid/with-counted for testing - (uuid/with-counted - (is= (uuid/rand-str) "00000000-aaaa-bbbb-cccc-ddddeeeeffff") - (is= (uuid/rand-str) "00000001-aaaa-bbbb-cccc-ddddeeeeffff") - (is= (uuid/rand-str) "00000002-aaaa-bbbb-cccc-ddddeeeeffff") - (let [r1 (uuid/rand) - r2 (uuid/rand-str)] - (is= (type r1) java.util.UUID) - (is= (type r2) java.lang.String) - (is= (str r1) "00000003-aaaa-bbbb-cccc-ddddeeeeffff") - (is= r2 "00000004-aaaa-bbbb-cccc-ddddeeeeffff") - (is (uuid/uuid-str? r2)))) - - ; demonstrate uuid/counted (manual) - (uuid/counted-reset!) - (is= (uuid/counted-str) "00000000-aaaa-bbbb-cccc-ddddeeeeffff") - (is= (uuid/counted-str) "00000001-aaaa-bbbb-cccc-ddddeeeeffff") - (is= (uuid/counted-str) "00000002-aaaa-bbbb-cccc-ddddeeeeffff") - (uuid/counted-reset!) - (is= (uuid/counted-str) "00000000-aaaa-bbbb-cccc-ddddeeeeffff") - (is= (uuid/counted-str) "00000001-aaaa-bbbb-cccc-ddddeeeeffff") -) diff --git a/test/cljc/tst/tupelo/uuid.cljc b/test/cljc/tst/tupelo/uuid.cljc new file mode 100644 index 00000000..3bbfea1a --- /dev/null +++ b/test/cljc/tst/tupelo/uuid.cljc @@ -0,0 +1,72 @@ +(ns tst.tupelo.uuid + (:use tupelo.core + tupelo.test) + (:refer-clojure :exclude [rand]) + (:require + [tupelo.uuid :as uuid])) + +; #todo add tests for cljs +#?(:clj + (do + + (verify + (is= "00000000-0000-0000-0000-000000000000" + (uuid/null-str) + (str (uuid/null))) + (is= "cafebabe-1953-0510-0970-0123456789ff" + (uuid/dummy-str) + (str (uuid/dummy))) + + (is (uuid? (uuid/null))) + (is (uuid? (uuid/dummy))) + (is (uuid/uuid-str? (uuid/null-str))) + (is (uuid/uuid-str? (uuid/dummy-str))) + + (isnt (uuid/uuid-str? "cafebabe-1953-0510-0970-0123456789fff")) + (isnt (uuid/uuid-str? "cafebabe-1953-0510-09700-123456789ff")) + (isnt (uuid/uuid-str? "cafebabe-1953-0510-066x-0123456789ff")) + (isnt (uuid/uuid-str? "cafebabe-1953-0510-0123456789ff")) + (isnt (uuid/uuid-str? "cafebabe-1953-0510|0970-0123456789ff")) + (isnt (uuid/uuid-str? 5)) + (isnt (uuid/uuid-str? :nope)) + (isnt (uuid/uuid-str? nil)) + + ; we return uuids as an object or a string + (is= java.util.UUID (type (uuid/rand))) + (is (string? (uuid/rand-str))) + (is (with-exception-default false + (dotimes [i 99] ; 2 uuids are never equal + (assert (not= (uuid/rand) (uuid/rand))) + (assert (not= (uuid/rand-str) (uuid/rand-str)))) + true)) ; if no failures, we pass the test + + ; demonstrate uuid/with-null usage for testing + (uuid/with-null + (is= (uuid/rand-str) "00000000-0000-0000-0000-000000000000") + (is= (uuid/rand-str) "00000000-0000-0000-0000-000000000000") + (is= (uuid/rand-str) "00000000-0000-0000-0000-000000000000")) + + ; demonstrate uuid/with-counted for testing + (uuid/with-counted + (is= (uuid/rand-str) "00000000-aaaa-bbbb-cccc-ddddeeeeffff") + (is= (uuid/rand-str) "00000001-aaaa-bbbb-cccc-ddddeeeeffff") + (is= (uuid/rand-str) "00000002-aaaa-bbbb-cccc-ddddeeeeffff") + (let [r1 (uuid/rand) + r2 (uuid/rand-str)] + (is= (type r1) java.util.UUID) + (is= (type r2) java.lang.String) + (is= (str r1) "00000003-aaaa-bbbb-cccc-ddddeeeeffff") + (is= r2 "00000004-aaaa-bbbb-cccc-ddddeeeeffff") + (is (uuid/uuid-str? r2)))) + + ; demonstrate uuid/counted (manual) + (uuid/counted-reset!) + (is= (uuid/counted-str) "00000000-aaaa-bbbb-cccc-ddddeeeeffff") + (is= (uuid/counted-str) "00000001-aaaa-bbbb-cccc-ddddeeeeffff") + (is= (uuid/counted-str) "00000002-aaaa-bbbb-cccc-ddddeeeeffff") + (uuid/counted-reset!) + (is= (uuid/counted-str) "00000000-aaaa-bbbb-cccc-ddddeeeeffff") + (is= (uuid/counted-str) "00000001-aaaa-bbbb-cccc-ddddeeeeffff") + ) + + ))