Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cljx => cljc, no cljsee #426

Merged
merged 34 commits into from Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/test.yml
@@ -0,0 +1,44 @@
name: Test

on:
push:
branches:
- master
pull_request:
schedule:
# monthly
- cron: "0 0 1 * *"

env:
#bump to clear caches
ACTION_CACHE_VERSION: 'v1'

jobs:
test:
strategy:
matrix:
java: ['8', '11', '17']
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ env.ACTION_CACHE_VERSION }}-${{ runner.os }}-maven-${{ hashFiles('**/project.clj') }}-${{ matrix.java }}
restore-keys: |
${{ env.ACTION_CACHE_VERSION }}-${{ runner.os }}-maven-${{ hashFiles('**/project.clj') }}-
- name: Prepare java
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
- uses: actions/setup-node@v2
with:
node-version: '10.13.0'
- name: Install clojure tools
uses: DeLaGuardo/setup-clojure@3.5
with:
lein: 2.9.7
- name: Run tests
run: lein all test
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,6 @@
## NEXT
* **BREAKING** use `cljc` instead of `cljx`, which requires Clojure 1.7 or later. (#425)

## 1.1.12 (`2019-08-10`)
* Fixes a "wrong number of arguments" warning in clojurescript (#418)
* Fixes an issue with function name inference introduced in the previous
Expand Down
4 changes: 1 addition & 3 deletions CONTRIBUTING.md
Expand Up @@ -8,14 +8,12 @@ For questions, feature requests, or discussion, please post on the Plumbing [mai

Contributions are preferred as GitHub pull requests on topic branches. If you want to discuss a potential change before coding it up, please post on the mailing list.

Schema uses the excellent [cljx](https://github.com/lynaghk/cljx) project to share source between Clojure and ClojureScript. For any in-depth changes to Schema, you will probably want to be familiar with its feature expressions (`#clj` and `#cljx`), and the inherent differences between Clojure and ClojureScript. In particular, if you're wondering why the code is divided the way it is, this is probably the answer. If you develop with Emacs, the included `:nrepl-middleware` should allow you to work at the REPL as you're used to.

Schema is relatively well-tested, on both Clojure and ClojureScript. Before submitting a pull request, we ask that you:

* please try to follow the conventions in the existing code, including standard Emacs indentation, no trailing whitespace, and a max width of 95 columns
* rebase your feature branch on the latest master branch
* ensure any new code is well-tested, and if possible, any issue fixed is covered by one or more new tests
* check that all of the tests pass **in both Clojure and ClojureScript**

To run the Clojure and ClojureScript tests, first run `lein cljx`, then run `lein test`. You must have phantomjs installed for the ClojureScript tests to run.
To run the Clojure and ClojureScript tests, run `lein test`. You must have phantomjs installed for the ClojureScript tests to run.

6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -211,7 +211,7 @@ Finally, we use validation with coercion for API inputs and outputs. See the co

## More examples

The source code in [schema/core.cljx](https://github.com/plumatic/schema/blob/master/src/cljx/schema/core.cljx) provides a wealth of extra tools for defining schemas, which are described in docstrings. The file [schema/core_test.cljx](https://github.com/plumatic/schema/blob/master/test/cljx/schema/core_test.cljx) demonstrates a variety of sample schemas and many examples of passing & failing clojure data. We'll just touch on a few more examples here, and refer the reader to the code for more details and examples (for now).
The source code in [schema/core.cljc](https://github.com/plumatic/schema/blob/master/src/cljc/schema/core.cljc) provides a wealth of extra tools for defining schemas, which are described in docstrings. The file [schema/core_test.cljc](https://github.com/plumatic/schema/blob/master/test/cljc/schema/core_test.cljc) demonstrates a variety of sample schemas and many examples of passing & failing clojure data. We'll just touch on a few more examples here, and refer the reader to the code for more details and examples (for now).

### Map schema details

Expand Down Expand Up @@ -270,7 +270,7 @@ Similarly, you can also write sequence schemas that expect particular values in

### Other schema types

[`schema.core`](https://github.com/plumatic/schema/blob/master/src/cljx/schema/core.cljx) provides many more utilities for building schemas, including `maybe`, `eq`, `enum`, `pred`, `conditional`, `cond-pre`, `constrained`, and more. Here are a few of our favorites:
[`schema.core`](https://github.com/plumatic/schema/blob/master/src/cljc/schema/core.cljc) provides many more utilities for building schemas, including `maybe`, `eq`, `enum`, `pred`, `conditional`, `cond-pre`, `constrained`, and more. Here are a few of our favorites:

```clojure
;; anything
Expand Down Expand Up @@ -404,7 +404,7 @@ If you make something new, please feel free to PR to add it here!

## Supported Clojure versions

Schema is currently supported on 1.6 through 1.8 and the latest version of ClojureScript.
Schema is currently supported on 1.7 through 1.10 and the latest version of ClojureScript.

## License

Expand Down
1 change: 1 addition & 0 deletions deps.edn
@@ -0,0 +1 @@
{:paths ["src/clj" "src/cljc"]}
44 changes: 13 additions & 31 deletions project.clj
Expand Up @@ -9,69 +9,51 @@
[org.clojure/tools.nrepl "0.2.5"]
[org.clojure/test.check "0.9.0"]
[potemkin "0.4.1"]]
:plugins [[com.keminglabs/cljx "0.6.0" :exclusions [org.clojure/clojure]]
[codox "0.8.8"]
:plugins [[codox "0.8.8"]
[lein-cljsbuild "1.1.7"]
[lein-release/lein-release "1.0.4"]
[lein-doo "0.1.10"]]
:cljx {:builds [{:source-paths ["src/cljx"]
:output-path "target/generated/src/clj"
:rules :clj}
{:source-paths ["src/cljx"]
:output-path "target/generated/src/cljs"
:rules :cljs}
{:source-paths ["test/cljx"]
:output-path "target/generated/test/clj"
:rules :clj}
{:source-paths ["test/cljx"]
:output-path "target/generated/test/cljs"
:rules :cljs}]}}
[lein-doo "0.1.10"]]}
:1.9 {:dependencies [[org.clojure/clojure "1.9.0"] [org.clojure/clojurescript "1.10.520"]]}
:1.10 {:dependencies [[org.clojure/clojure "1.10.0"] [org.clojure/clojurescript "1.10.520"]]}}

:aliases {"all" ["with-profile" "dev:dev,1.9:dev,1.10"]
"deploy" ["do" "clean," "cljx" "once," "deploy" "clojars"]
"test" ["do" "clean," "cljx" "once," "test," "with-profile" "dev" "doo" "node" "test" "once"]}
"deploy" ["do" "clean," "deploy" "clojars"]
"test" ["do" "clean," "test," "with-profile" "dev" "doo" "node" "test" "once"]}

:jar-exclusions [#"\.cljx|\.swp|\.swo|\.DS_Store"]
:jar-exclusions [#"\.swp|\.swo|\.DS_Store"]

:lein-release {:deploy-via :shell
:shell ["lein" "deploy"]}

:auto-clean false

:source-paths ["target/generated/src/clj" "src/clj"]
:source-paths ["src/clj" "src/cljc"]

:resource-paths ["target/generated/src/cljs"]

:test-paths ["target/generated/test/clj" "test/clj" "test/cljs"]
:test-paths ["test/clj" "test/cljc" "test/cljs"]

:cljsbuild {:builds
[{:id "dev"
:source-paths ["src/clj" "target/generated/src/cljs"]
:source-paths ["src/clj" "src/cljc"]
:compiler {:output-to "target/main.js"
:optimizations :whitespace
:pretty-print true}}
{:id "test"
:source-paths ["src/clj" "test/clj" "test/cljs"
"target/generated/src/cljs"
"target/generated/test/cljs"]
:source-paths ["src/clj" "src/cljc"
"test/clj" "test/cljc" "test/cljs"]
:compiler {:output-to "target/unit-test.js"
:main schema.test-runner
:target :nodejs
:pretty-print true}}
{:id "test-no-assert"
:source-paths ["src/clj" "test/clj" "test/cljs"
"target/generated/src/cljs"
"target/generated/test/cljs"]
:source-paths ["src/clj" "src/cljc"
"test/clj" "test/cljc" "test/cljs"]
:assert false
:compiler {:output-to "target/unit-test.js"
:main schema.test-runner
:target :nodejs
:pretty-print true}}]}

:codox {:src-uri-mapping {#"target/generated/src/clj" #(str "src/cljx/" % "x")}
:src-dir-uri "http://github.com/plumatic/schema/blob/master/"
:codox {:src-dir-uri "http://github.com/plumatic/schema/blob/master/"
:src-linenum-anchor-prefix "L"}

:signing {:gpg-key "66E0BF75"})
4 changes: 2 additions & 2 deletions src/clj/schema/macros.clj
Expand Up @@ -53,8 +53,8 @@
(throw (clojure.lang.ExceptionInfo. ~(with-meta s `{:tag java.lang.String}) ~m))))))

(defmacro safe-get
"Like get but throw an exception if not found. A macro just to work around cljx function
placement restrictions. "
"Like get but throw an exception if not found. A macro for historical reasons (to
work around cljx function placement restrictions)."
[m k]
`(let [m# ~m k# ~k]
(if-let [pair# (find m# k#)]
Expand Down
61 changes: 31 additions & 30 deletions src/cljx/schema/coerce.cljx → src/cljc/schema/coerce.cljc
@@ -1,14 +1,15 @@
(ns schema.coerce
"Extension of schema for input coercion (coercing an input to match a schema)"
(:require
#+cljs [cljs.reader :as reader]
#+clj [clojure.edn :as edn]
#+clj [schema.macros :as macros]
[schema.core :as s :include-macros true]
#?(:cljs [cljs.reader :as reader])
#?(:clj [clojure.edn :as edn])
#?(:clj [schema.macros :as macros])
#?(:clj [schema.core :as s]
:cljs [schema.core :as s :include-macros true])
[schema.spec.core :as spec]
[schema.utils :as utils]
[clojure.string :as str])
#+cljs (:require-macros [schema.macros :as macros]))
#?(:cljs (:require-macros [schema.macros :as macros])))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Generic input coercion
Expand Down Expand Up @@ -71,14 +72,14 @@
(if (string? s) (= "true" (str/lower-case s)) s))

(defn keyword-enum-matcher [schema]
(when (or (and (instance? #+clj schema.core.EnumSchema #+cljs s/EnumSchema schema)
(when (or (and (instance? #?(:clj schema.core.EnumSchema :cljs s/EnumSchema) schema)
(every? keyword? (.-vs ^schema.core.EnumSchema schema)))
(and (instance? #+clj schema.core.EqSchema #+cljs s/EqSchema schema)
(and (instance? #?(:clj schema.core.EqSchema :cljs s/EqSchema) schema)
(keyword? (.-v ^schema.core.EqSchema schema))))
string->keyword))

(defn set-matcher [schema]
(if (instance? #+clj clojure.lang.APersistentSet #+cljs cljs.core.PersistentHashSet schema)
(if (instance? #?(:clj clojure.lang.APersistentSet :cljs cljs.core.PersistentHashSet) schema)
(fn [x] (if (sequential? x) (set x) x))))

(defn safe
Expand All @@ -89,36 +90,36 @@
[f]
(fn [x] (macros/try-catchall (f x) (catch e x))))

#+clj (def safe-long-cast
"Coerce x to a long if this can be done without losing precision, otherwise return x."
(safe
(fn [x]
(let [l (long x)]
(if (== l x)
l
x)))))
#?(:clj (def safe-long-cast
"Coerce x to a long if this can be done without losing precision, otherwise return x."
(safe
(fn [x]
(let [l (long x)]
(if (== l x)
l
x))))))

(def string->uuid
"Returns instance of UUID if input is a string.
Note: in CLJS, this does not guarantee a specific UUID string representation,
similar to #uuid reader"
#+clj
(safe #(java.util.UUID/fromString ^String %))
#+cljs
#(if (string? %) (uuid %) %))
#?(:clj
(safe #(java.util.UUID/fromString ^String %))
:cljs
#(if (string? %) (uuid %) %)))


(def ^:no-doc +json-coercions+
(merge
{s/Keyword string->keyword
s/Bool string->boolean
s/Uuid string->uuid}
#+clj {clojure.lang.Keyword string->keyword
s/Int safe-long-cast
Long safe-long-cast
Double (safe double)
Float (safe float)
Boolean string->boolean}))
#?(:clj {clojure.lang.Keyword string->keyword
s/Int safe-long-cast
Long safe-long-cast
Double (safe double)
Float (safe float)
Boolean string->boolean})))

(defn json-coercion-matcher
"A matcher that coerces keywords and keyword eq/enums from strings, and longs and doubles
Expand All @@ -130,16 +131,16 @@

(def edn-read-string
"Reads one object from a string. Returns nil when string is nil or empty"
#+clj edn/read-string #+cljs reader/read-string)
#?(:clj edn/read-string :cljs reader/read-string))

(def ^:no-doc +string-coercions+
(merge
+json-coercions+
{s/Num (safe edn-read-string)
s/Int (safe edn-read-string)}
#+clj {s/Int (safe #(safe-long-cast (edn-read-string %)))
Long (safe #(safe-long-cast (edn-read-string %)))
Double (safe #(Double/parseDouble %))}))
#?(:clj {s/Int (safe #(safe-long-cast (edn-read-string %)))
Long (safe #(safe-long-cast (edn-read-string %)))
Double (safe #(Double/parseDouble %))})))

(defn string-coercion-matcher
"A matcher that coerces keywords, keyword eq/enums, s/Num and s/Int,
Expand Down