Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,29 @@ jobs:

- run: bin/install-chrome
- run: bin/install-clojure
- run: sudo bin/install-node && npm install
# FIXME: the sha is not matching??
# - run: sudo bin/install-node && npm install
- run: lein check
- run:
name: 'Check artifact isolation + lack of reflection/boxing warnings'
# skip the first warning, which I believe is in leiningen itself
command: lein with-profile -dev,+check check 2>&1 | grep -v "form-init.*clj" | bin/check-for-warnings.sh
# TODO: re-enable when spec2 fixes reflection warnings
# - run:
# name: 'Check artifact isolation + lack of reflection/boxing warnings'
# # skip the first warning, which I believe is in leiningen itself
# command: lein with-profile -dev,+check check 2>&1 | grep -v "form-init.*clj" | bin/check-for-warnings.sh
- run: TEST_CHECK_FACTOR=20 lein with-profile test-common test
- run: lein clean
- run: lein with-profile test-web cljsbuild once test 2> >(tee -a stderr.log >&2)
- run: cat stderr.log | grep -v "Options passed to ClojureScript compiler" | bin/check-for-warnings.sh
- run: bin/tests
# TODO: reenable when CLJS has spec2 implementation
# - run: lein with-profile test-web cljsbuild once test 2> >(tee -a stderr.log >&2)
# - run: cat stderr.log | grep -v "Options passed to ClojureScript compiler" | bin/check-for-warnings.sh
# - run: bin/tests
- run: bin/golden_master_test.sh
- run: bin/deps_test.sh
- run: bin/build_comparison_doc.sh
- run: git diff --exit-code -- doc/comparison.md # make sure above step does not modify examples
- run: lein jar && diff -u <(jar tf target/*.jar | sort) <(cat expected-jar-contents.txt | sort)
# Check that we can load expound1 with spec1
- run: clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.1"} org.clojure/test.check {:mvn/version "0.9.0"}}}' -e "(require '[expound.alpha :as expound])"
# Check that we can load expound2 with spec2
- run: clojure -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.10.1"} org.clojure/test.check {:mvn/version "0.9.0"} org.clojure/alpha.spec {:git/url "https://github.com/clojure/spec-alpha2.git" :sha "b644e4d8c5553e10544d920306690fffe9b53e15"}}}}' -e "(require '[expound.alpha2 :as expound])"

test_cljs_old:
docker:
Expand Down Expand Up @@ -110,14 +117,14 @@ jobs:
- v1-dependencies-{{ checksum "project.clj" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: bin/install-chrome
#- run: bin/install-chrome
- run: bin/install-clojure
- run: sudo bin/install-node && npm install
#- run: sudo bin/install-node && npm install
# The version number (1.10.439) is important - it's the last version in which CLJS itself
# did NOT include 'goog.string.format' so it's the last version that will reproduce https://github.com/bhb/expound/issues/183
- run: clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.439"}}}' -m cljs.main -re node -i test/cljs_test.cljs
- run: lein clean && lein with-profile test-web,clj-1.9.0,cljs-1.10.238 cljsbuild once test && bin/tests
- run: lein clean && lein with-profile test-web,clj-1.9.0,cljs-1.10.339 cljsbuild once test && bin/tests
#- run: clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.439"}}}' -m cljs.main -re node -i test/cljs_test.cljs
#- run: lein clean && lein with-profile test-web,clj-1.9.0,cljs-1.10.238 cljsbuild once test && bin/tests
#- run: lein clean && lein with-profile test-web,clj-1.9.0,cljs-1.10.339 cljsbuild once test && bin/tests
- run: lein clean && lein with-profile test-web,clj-1.10.0,cljs-1.10.439 cljsbuild once test && bin/tests
- run: lein clean && lein with-profile test-web,clj-1.10.0,cljs-1.10.516 cljsbuild once test && bin/tests

Expand Down Expand Up @@ -147,7 +154,8 @@ jobs:
- v1-dependencies-{{ checksum "project.clj" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: lein with-profile test-common,clj-1.9.0,spec-0.2.168 test
# spec2 is not compatible with 1.9.0
# - run: lein with-profile test-common,clj-1.9.0,spec-0.2.168 test
- run: lein with-profile test-common,clj-1.10.0,spec-0.2.176 test

workflows:
Expand All @@ -158,9 +166,10 @@ workflows:
- test_current:
requires:
- build
- test_cljs_old:
requires:
- build
# TODO: reenable when CLJS has spec2 implementation
# - test_cljs_old:
# requires:
# - build
- test_clj_old:
requires:
- build
13 changes: 13 additions & 0 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
:linters
{:unused-namespace {:exclude [com.gfredericks.test.chuck.clojure-test expound.spec-gen]}
:unresolved-symbol {:exclude [(com.gfredericks.test.chuck.clojure-test/checking)
(clojure.alpha.spec/fdef)]}
:deprecated-var {:exclude
{expound.alpha/def
{:defs [expound.alpha/def]
:namespaces [expound.spec-gen
expound.alpha-test]}}}
}
}

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ repl-deps
test-deps
.cpcache
nashorn_code_cache
.rebel_readline_history
.rebel_readline_history
.clj-kondo
2 changes: 1 addition & 1 deletion bin/sample.clj
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
(throw (Exception. (main/err->msg e#))))))

(defn go [check-results?]
(set! s/*explain-out* (expound/custom-printer {:theme :figwheel-theme}))
(set! s/*explain-out* (expound/custom-printer {:theme :figwheel-theme :print-specs? true}))
(st/instrument)
(s/check-asserts true)

Expand Down
3 changes: 3 additions & 0 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.10.1"}
org.clojure/alpha.spec {:git/url "https://github.com/clojure/spec-alpha2.git"
:sha "b644e4d8c5553e10544d920306690fffe9b53e15"} }
:aliases {;; clj -Atest
:test {:extra-paths ["test"]
:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
Expand Down
14 changes: 12 additions & 2 deletions dev/user.clj
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
(ns user
(:require [clojure.spec.alpha :as s]
[orchestra.spec.test :as st]
[expound.alpha :as expound]))
[expound.alpha :as expound]
;;[speculative.instrument :as i]
))

(defn setup []
(set! s/*explain-out* expound/printer)
(st/instrument))
(st/instrument)
;;(i/instrument)
)

(defn unsetup []
(set! s/*explain-out* s/explain-printer)
(st/unstrument)
;;(i/unstrument)
)

(comment
(setup))
15 changes: 15 additions & 0 deletions doc/alpha2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# expound.alpha2

## Differences from `expound.alpha`

### Support for spec2

`expound.alpha` only supports spec1

`expound.alpha2` only supports spec2

### Relevant specs

The "Relevant specs" section [is hidden by default](https://twitter.com/bbrinck/status/1204595098207444993).

You can enable it with `show-specs?`
61 changes: 61 additions & 0 deletions doc/cljtogether/project_update6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Project Update 5: 2020-02-16 - 2020-02-29

I've been working on `expound.alpha2` and I'm happy to report I have an early version that works with `clojure.alpha.spec` AKA `spec2`.

If you are experimenting with `spec2` and want to use Expound, you can use commits from the [`spec2` branch](https://github.com/bhb/expound/pull/186). I won't be releasing JARs for some time, but you can use `tools.deps` or [`lein-git-down`](https://github.com/reifyhealth/lein-git-down) to depend on specific commits.

Here's an example using the "movie-times-user" example from the ["Schema and select" wiki page](https://github.com/clojure/spec-alpha2/wiki/Schema-and-select)

```clojure
(ns example)
(require '[clojure.alpha.spec :as s])
(require '[expound.alpha2 :as expound])

(s/def ::street string?)
(s/def ::city string?)
(s/def ::state string?) ;; simplified
(s/def ::zip int?) ;; simplified
(s/def ::addr (s/schema [::street ::city ::state ::zip]))
(s/def ::id int?)
(s/def ::first string?)
(s/def ::last string?)
(s/def ::user (s/schema [::id ::first ::last ::addr]))
(s/def ::movie-times-user (s/select ::user [::id ::addr {::addr [::zip]}]))

(s/explain ::movie-times-user {})
;; {} - failed: (fn [m] (contains? m :example/id)) spec: :example/movie-times-user
;; {} - failed: (fn [m] (contains? m :example/addr)) spec: :example/movie-times-user

(expound/expound ::movie-times-user {})

;;-- Spec failed --------------------
;;
;; {}
;;
;;should satisfy
;;
;; (fn [m] (contains? m :example/id))
;;
;;or
;;
;; (fn [m] (contains? m :example/addr))
;;
;;-- Relevant specs -------
;;
;;:example/movie-times-user:
;; (clojure.alpha.spec/select
;; :example/user
;; [:example/id :example/addr #:example{:addr [:example/zip]}])
;;
;;————————————
;;Detected 1 error
```

As you can see, there are many rough edges, but it should work for common cases. Please feel free to [report issues](https://github.com/bhb/expound/issues)!

### Caveats

* The API for `expound.alpha2` is in flux: breaking changes are expected!
* No ClojureScript support
* `fspec` is currently broken
* Many new features in spec2 may not work, but most of the features ported from spec1 should work fine (except `fspec`, see above)
59 changes: 59 additions & 0 deletions doc/spec2_bugs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Spec2 bugs

A list of bugs in spec2. I will report them as spec2 gets more stable.

### Using binding in spec fn

```clojure
;; make sure `n` is not defined
(let [n 1]
(s/def ::foobar #(< n %))
)
;; Expected: no error
;; Actual: 'Unable to resolve symbol: n in this context'
```

Note: this might be doable with a different strategy e.g.

```clojure
(let [max-v 10]
(s2/register ::foo
(s2/resolve-spec `(s2/int-in 1 (inc ~max-v))))
(s2/valid? ::foo 20))
```

### Bug with s/nest

```clojure
(s/def :alt-spec/one-many-int (s/cat :bs (s/alt :one int?
:many (s/nest (s/+ int?)))))

(s/explain :alt-spec/one-many-int [["2"]])
;; Attempting to call unbound fn: #'clojure.core/unquote
```

### Bug with using symbols in specs e.g.

```
> (s/def ::is-foo #{foo})
:expound.alpha2.core-test/is-foo
> (s/form ::is-foo)
#{foo}
> (s/explain ::is-foo 'foo)
Success!
nil
> (s/def ::is-or #{or})
:expound.alpha2.core-test/is-or
> (s/form ::is-or)
#{clojure.core/or}
> (s/explain ::is-or 'or)
or - failed: #{clojure.core/or} spec: :expound.alpha2.core-test/is-or
nil
```

From Alex Miller: "there is actually a known issue around sets of symbols (kind of a collision with symbol as function reference, which need qualification)"

### Bug with Clojure 1.9.0

`lein with-profile test-common,clj-1.9.0 test` fails (but moving to 1.10.0 works)

9 changes: 9 additions & 0 deletions expected-jar-contents.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,12 @@ expound/problems.cljc
expound/printer.cljc
expound/specs.cljc
expound/ansi.cljc
expound/alpha2/
expound/alpha2/core.cljc
expound/alpha2/ansi.cljc
expound/alpha2/printer.cljc
expound/alpha2/problems.cljc
expound/alpha2/util.cljc
expound/alpha2/paths.cljc
expound/alpha2/specs.cljc
expound/alpha2.cljc
19 changes: 15 additions & 4 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
(defproject expound "0.8.4"
(defproject expound "0.8.5-SNAPSHOT"
:description "Human-optimized error messages for clojure.spec"
:url "https://github.com/bhb/expound"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:scm {:name "git" :url "https://github.com/bhb/expound"}
:dependencies [[org.clojure/clojure "1.10.1" :scope "provided"]
[org.clojure/clojurescript "1.10.520" :scope "provided"]
[org.clojure/spec.alpha "0.2.176" :scope "provided"]]
[org.clojure/spec.alpha "0.2.176" :scope "provided"]
[org.clojure/alpha.spec "b644e4d8c5553e10544d920306690fffe9b53e15" :scope "provided"]
]
:deploy-repositories [["releases" :clojars]]
:jar-exclusions [#"^public/.*"]
:plugins [
[reifyhealth/lein-git-down "0.3.5"] ; Can remove this once spec has maven release
[com.jakemccrary/lein-test-refresh "0.23.0"]
[lein-cljfmt "0.6.4"]
[lein-cljsbuild "1.1.7" :exclusions [[org.clojure/clojure]]]
[lein-figwheel "0.5.18"]
[lein-hiera "1.1.0"]
]
:git-down {org.clojure/alpha.spec {:coordinates clojure/spec-alpha2}} ; Can remove this once spec has maven release
:repositories [["public-github" {:url "git://github.com"}]] ; Can remove this once spec has maven release
:middleware [lein-git-down.plugin/inject-properties] ; Can remove this once spec has maven release
:cljsbuild {:builds
[{:id "test"
:source-paths ["src" "test"]
Expand Down Expand Up @@ -86,7 +92,12 @@
[ring/ring-spec "0.0.4"] ; to test specs
[org.onyxplatform/onyx-spec "0.13.0.0"] ; to test specs
[com.gfredericks/test.chuck "0.2.10"]
[cider/cider-nrepl "0.22.4"]
[cider/cider-nrepl "0.24.0"]
;; Disabling speculative because
;; instaparse runs into problem with re-matcher (appears to be used by test.chuck)
;; Also, running with all specs enabled slows doesn testing, so I need a better way
;; to only instrument in some cases, or the functions only within expound
;; [speculative "0.0.3"]
]
:injections [(require 'sc.api)]
:plugins [
Expand Down Expand Up @@ -128,7 +139,7 @@
:check {:global-vars {*unchecked-math* :warn-on-boxed
*warn-on-reflection* true}}
:kaocha [:test-common
{:dependencies [[lambdaisland/kaocha "0.0-565"]
{:dependencies [[lambdaisland/kaocha "0.0-590"]
[lambdaisland/kaocha-cloverage "0.0-41"]]}]
:test-common {:dependencies [[org.clojure/test.check "0.10.0-alpha3"]
[pjstadig/humane-test-output "0.9.0"]
Expand Down
5 changes: 5 additions & 0 deletions src/expound/alpha2.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(ns expound.alpha2
"Generates human-readable errors for `clojure.spec`"
(:require [expound.alpha2.core :as expound]))

(def expound expound/expound)
Loading