This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-04-01
Channels
- # announcements (3)
- # beginners (59)
- # calva (23)
- # cider (58)
- # clojure (125)
- # clojure-dev (18)
- # clojure-dusseldorf (1)
- # clojure-europe (21)
- # clojure-germany (1)
- # clojure-hamburg (1)
- # clojure-italy (13)
- # clojure-nl (29)
- # clojure-poland (3)
- # clojure-spec (61)
- # clojure-uk (74)
- # clojurescript (12)
- # core-async (6)
- # cursive (4)
- # data-science (7)
- # datomic (14)
- # defnpodcast (1)
- # events (4)
- # fulcro (72)
- # juxt (36)
- # kaocha (3)
- # nginx (3)
- # off-topic (14)
- # pathom (5)
- # ring-swagger (68)
- # shadow-cljs (25)
- # spacemacs (8)
- # sql (42)
- # tools-deps (8)
- # vim (6)
hi spec people!!
I’m trying to temporarily redefine the spec global registry in the same way as with-redefs
does …
My intention is to reduce possible valid values, eg: instead of only checking that value is a string, validate that is exactly foo
value
so far, this is the code that i’ve reached…
(s/def ::simple string?)
(s/def ::composed
(s/keys :req [::simple]))
(with-redefs [s/registry (constantly (assoc (s/registry) ::simple (#'s/res #{"foo"})))]
[(s/valid? ::composed {::simple "other"})
(s/valid? ::composed {::simple "foo"})]
) ;; [false true]
(s/valid? ::composed {::simple "other"}) ;; true
:thinking_face: what do you think about using with-redefs to redefine specs?the final idea is to apply authorisation
basically if certain path values of the speced data are “allowed”, the full data could be viewed by a user or not
i’s it more clear now?
Sounds like a nightmare for such a critical role
could you expand a bit why you think it could be a nightmare?
why would you base something as critical as auth on something as fragile as with-redefs?
sorry i didn’t realise about “These temporary changes will be visible in all threads” 😬 … I was trying for something thread isolated … but with-redefs was my quick first attempt
though so far the only things I've found with-redef
useful for is orthogonal instrumentation of functions (e.g. timing functions) or stubbing in testing
(def ^:dynamic my-fun string?)
(s/def ::simple #'my-fun)
(s/def ::composed (s/keys :req [::simple]))
(s/def ::extra-composed (s/keys :req [::composed]))
(assert (s/valid? ::extra-composed {::composed {::simple "one"}}))
(assert (= (binding [my-fun #{"foo"} ]
[(s/valid? ::extra-composed {::composed {::simple "other"}})
(s/valid? ::extra-composed {::composed {::simple "foo"}})])
[false true]))
(assert (s/valid? ::extra-composed {::composed {::simple "other"}}))
example using binding
^^ 🙂
ya - still hard to see how / when you might apply that but at least it's thread-safe now
@U064X3EF3 maybe less nightmare now with binding
?
Less but the idea of changing specs still seems like an idea likely to cause problems later
I'll take into account, thanks both for your help!
If it's a top level spec you can do:
(let [the-spec (if p? ::a ::b)]
(s/valid? the-spec data))
If it's a nested spec, you could try using :req-un
to have (s/keys :req-un [:very-specific/a])
and (s/keys :req-un [:general/a])
alternatively, you could try experimenting (s/or ...)
If you're using namespaced keys on your data, it's hard to understand why the spec for a namespaced entity would changemore than change, the spec should be more specific. so instead of having a predicate string?
would be #{"value1" "value2" "value3"}
being these values the returned of a sql execution
the thing (at this level) is getting spec validation messages
given that specs are typically named with just data can't you dispatch at real-time the spec you might want to validate against
I've got a question about spec design. The situation: I have an entity in mind, which I call a run
(for test run). It has two variants: it might be a test run from CI, or it might be a test run from my local machine.
Some data is present in runs of any variant, like results
and a revision
(the SHA of the codebase during the run). Only CI runs have a pipeline
. Both variants have logs
but only the local variant has api
logs under that key.
My design problem is, I'm trying to use mostly namespaced keywords, so that I can nest specs. For instance,
(s/def ::revision (fn [s] (boolean (re-find #"[a-f0-9]+" s))))
(s/def ::meta-v1
(s/keys :req [::date ::job ::pipeline ::revision]
:opt [::suites]))
But then I realized, ooooh when I start modeling runs of the local variant, project.ci.runs/revision
is overly specific
Do you have any thoughts on what I should keep in mind while spec'ing these variants out? Thanks!
I guess I should add, I'm trying to be careful about not over-spec'ing things --- this could be an example of, Don't spec this part
(The value-add that I see of spec'ing this data is, I've been doing these runs for months, and iterating on how they're shaped, so I'm interested in validating that I understand what 'type' of run I'm looking at)
a good guiding principle is to just try to spec the truth - what are all the values an attribute can actually take on?
if it's not constrained to the regex, then that's not the truth, it's just one variant
it's always possible to spec generally, then s/and an additional constraint for a particular context
How do you guys use clojure.test.check.generators/let
with Spec? It doesn't appear to be exposed in clojure.spec.gen.alpha
.
Also, you’re depending on it already if you’re actually using any of its functionality
We don't use the functionality in production but want to define the generators next to our specs.
True but it does it lazily -- it only requires test.check if you actually invoke a function in the gen namespace.
Yes but that begs the question of why it wasn't included to begin with. It may be because it is a macro.
yes, a macro has to run at compile time
so the normal trick that allows you to not have a runtime dependency on test.check doesn't work
You can do that, you could relax your requirement to not have test.check in prod, you could wrap in a simple proxying macro that expands to an exception throwing generator when tc isn't on the classpath
The problem with including test.check on the cp in prod is certain code paths check input structures via s/valid?
. If, by accident, a function is passed in a map of things, it would get generatively checked. That would have a significant impact on performance.
They skip that based on the namespaces being requirable or not?
If test.check isn't available on the cp and a fn is passed to the s/valid?
call, an exception will get thrown.
Ah, I see, I didn't notice the "by accident" part In any case, the other two approaches would work though
The latter seems like a good approach. Seems like a worthy addition to the Spec gen namespace as well.
I can see that