From a9cf9afab77ac34be48035678f5c7692ca783596 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Tue, 15 Nov 2022 13:28:58 -0500 Subject: [PATCH 1/3] Add a first version of an Intro to Bowtie post / announcement. --- pages/posts/bowtie-intro.md | 182 ++++++++++++++++++ public/img/posts/2022/bowtie-intro/cover.webp | Bin 0 -> 31650 bytes 2 files changed, 182 insertions(+) create mode 100644 pages/posts/bowtie-intro.md create mode 100644 public/img/posts/2022/bowtie-intro/cover.webp diff --git a/pages/posts/bowtie-intro.md b/pages/posts/bowtie-intro.md new file mode 100644 index 00000000..6a0eaed7 --- /dev/null +++ b/pages/posts/bowtie-intro.md @@ -0,0 +1,182 @@ +--- +title: "" +date: 2022-11-16 +tags: + - Update + - News + - validation +type: Engineering +cover: /img/posts/2022/bowtie-intro/cover.webp +authors: + - name: Julian Berman + photo: /img/avatars/julian.webp + link: https://twitter.com/JulianWasTaken + byline: JSON Schema Test Suite Maintainer & Technical Lead, API Specifications @Postman +excerpt: "Bowtie: a new tool for executing JSON Schema implementations & a call to help improve it" +--- + +*This is the first in what will hopefully be an intermittent series of posts about Bowtie. +I speak here without speaking on behalf of the JSON Schema organization or its members in any official capacity -- Bowtie isn't a tool we The JSON Schema Team are "blessing" in some way today, though I have personal hopes it does become a sort of official tool, and have developed it fully intending for it to be owned by "the community" in whatever sense that means. +For the moment, I speak only on behalf of myself as its author :)* + +## What It Is + +[Bowtie](https://github.com/bowtie-json-schema/bowtie/) is what I'm calling a "meta-validator", by which I mean a program which can execute *other* JSON Schema validation implementations and collect results from them. + +From the existing [list of JSON Schema implementations](https://json-schema.org/implementations.html#validators), Bowtie already [supports](https://github.com/orgs/bowtie-json-schema/packages) *12* implementations across *9* programming languages, allowing anyone to run any of these implementations and see what they have to say about schemas and instances. + +It ships with a [command line program](https://bowtie-json-schema.readthedocs.io/en/latest/cli/), but perhaps more excitingly, ongoing automated runs of this CLI have been set up, such that Bowtie emits a [report across all of its supported implementations](https://bowtie-json-schema.github.io/bowtie/draft2020). + +To produce this report, Bowtie runs the (existing) [official JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite), which is our existing set of tests meant to exercise compliance with the JSON Schema specifications. +Many implementations already [use the suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite#who-uses-the-test-suite), but this is the first time both users of JSON Schema as well as implementers can see results of running the suite in a single place, across many implementations. +The test suite already has great coverage of our specifications, meaning it well represents all corners of the *validation* portions of the specification. +The suite certainly isn't perfect, but Bowtie's results therefore cover the validation specification really well. + +## Why It Might Be Interesting + +The most noticeable thing Bowtie enables is an easy way to compare how close an implementation follows the specification. +This gives transparency to users of implementations, and also to the community about areas which might be hard to implement, or are commonly misimplemented. +Our hope is that this leads to improvement and energy to help fix issues, and overall to a stronger community! + +Even beyond the test suite, Bowtie is capable of providing a "uniform" interface to the implementations it supports, meaning you can quickly access results from each one. +If you have a schema and instance and want to run it across many implementations, or a single implementation which you're not already familiar with or don't have set up, Bowtie can help. + +## How Do I Run It? + +If you're just interested in its output (i.e. reports on runs of the test suite), you can currently find them at the following links, corresponding to each version of the specification: + +* [draft2020-12](https://bowtie-json-schema.github.io/bowtie/draft2020) +* [draft2019-09](https://bowtie-json-schema.github.io/bowtie/draft2019) +* [draft7](https://bowtie-json-schema.github.io/bowtie/draft7) +* [draft6](https://bowtie-json-schema.github.io/bowtie/draft6) +* [draft4](https://bowtie-json-schema.github.io/bowtie/draft4) +* [draft3](https://bowtie-json-schema.github.io/bowtie/draft3) + +The medium term goal is to combine these onto one nice, unified report, at which point the links may change (though hopefully we'll remember to put a redirect in place). + +If you want to go beyond the test suite reports, you can run Bowtie locally as well, on whatever input you'd like. +Bowtie is written in Python and published [on PyPI](https://pypi.org/project/bowtie-json-schema/). +If you have no existing preferred setup for installing Python applications, [install pipx using the platform-specific instructions for your OS](https://pypa.github.io/pipx/#install-pipx), then run: + +```sh +$ pipx install bowtie-json-schema +``` + +which should give you a working Bowtie, which you can check via: + +```sh +$ bowtie --help +``` + +The usage instructions are in [Bowtie's documentation](https://bowtie-json-schema.readthedocs.io/), but more documentation is definitely needed, so do ping myself (Julian) if there are things you can't figure out, it will motivate documenting them. + +## How Does It Work? + +I won't go into full details of Bowtie's implementation in this post, but at a high level, Bowtie is a command-line program written in Python which orchestrates spinning up and down OCI containers ("Docker containers" in a loose sense). +The containers it runs are "test harnesses" -- little bridge programs which take an implementation of JSON Schema, written in any programming language, and then allow incoming requests from Bowtie to call into the library under test. +Adding support for an implementation essentially means implementing a test harness in this fashion (which is generally simple to do), and once the harness is present, the implementation will light up in Bowtie's reports, and any user of Bowtie will be able to execute the implementation via Bowtie's uniform CLI. + +## How to Help + +There are two areas you (a user of JSON Schema, author of an implementation, or community member) can help with: + +### Improving Implementations + +The first and most obvious is by helping to take any issues uncovered by Bowtie back to implementations (after confirming them), and then helping implementations fix them. + +Find your favorite JSON Schema implementations and the tests it fails. +Are there existing open issues on the implementation's bug tracker about the failures? +If they aren't previously known, an issue ticket (with minimal reproducer) is likely going to be welcome by the implementer, so you may want to file one. +If they *are* known, you can file a pull request in Bowtie which contains information about the downstream issue, which Bowtie can make use of in reports (by showing that the test is explicitly skipped). +Here's an [example pull request](https://github.com/bowtie-json-schema/bowtie/pull/73) showing how to do so. + +Look out for [Bowtie-generated badges](https://github.com/bowtie-json-schema/bowtie/issues/55) in the near future which you can use to show off your spec-compliance (nothing could be cooler, eh?). + +### Improving Bowtie + +The second is by helping to improve Bowtie itself, which I already have a long list of ideas for, which can only grow as more people start to use it. + +To repeat part of the above, I myself have implemented support for [many implementations](https://github.com/bowtie-json-schema/bowtie/tree/main/implementations). +If you maintain or use one, look at the harness I wrote -- it's possible I misused your implementation (though so far thankfully hasn't happened). + +I'll also mention that I've been experimenting with doing work on Bowtie on [livestreams here](https://www.twitch.tv/julianberman) -- without too much self-promotion, feel free to stop by and say hello, or even to flip through previous streams where I fight with various Bowtie-adjacent things, it may give you some pointers on how to work on it. + +Below is some specific guidance around areas in need of help: + +*This is current as of the publication of this post, but my hopes are that it swiftly becomes out of date. If it seems to be, feel free to reach out!* + +#### Give Me Something Easy to Get My Feet Wet + +There's a list of [good first issues](https://github.com/bowtie-json-schema/bowtie/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) on Bowtie's issue tracker which I've attempted to curate. +They cover various portions of Bowtie's codebase (the Python bits, the frontend bits, and its surrounding infrastructure). +The label doesn't indicate that the issue is necessarily "small" to fix, though many are. +But it does indicate the relevant functionality or fix is "straightforward" or likely well-scoped. +If you don't see activity on one, feel free to leave a comment if you begin to work on it. + +#### I Want to Learn About a New Implementation or Programming Language + +This is possibly the most "fun" thing to work on, or at least I quite enjoyed doing it. +Pick an implementation Bowtie doesn't already support from the [list of implementations](https://json-schema.org/implementations.html#validators) and follow the [tutorial for writing a harness](https://bowtie-json-schema.readthedocs.io/en/latest/implementers/) which will guide you through what Bowtie expects from a harness. +If there are gaps in the tutorial, do raise them or ping me! +But this can be a nice way to play with a simple program in a language you haven't used before, as well as a way to learn a JSON Schema implementation which may have made different choices than one you're already familiar with. + +#### The Report is Ugly, I'm a Frontend Developer or UI Designer Who Can Help + +This is probably the most beneficial area you can help in. +I myself am not a frontend developer, in case that wasn't obvious. +What I put together (with Bootstrap) is essentially the bare minimum of what's needed to show off results Bowtie emits. +If you have more experience or headspace to think about how to effectively report test results, or compare implementations, please help! +All of Bowtie's "frontend code" today lives in one place, [a Jinja2 template which gets formatted into a static single page site](https://github.com/bowtie-json-schema/bowtie/blob/main/bowtie/templates/report.html.j2). +Beyond generally "make it prettier, more responsive, or more usable", here are a few specific issues to look at: + +* [Add client-side filtering and sorting](https://github.com/bowtie-json-schema/bowtie/issues/37) +* [Show combined errors+failures counts](https://github.com/bowtie-json-schema/bowtie/issues/53), or more generally improve the summary from a "table of counts" into a more graphically pleasing representation of what happened in a run +* [Display schemas & instances more prettily](https://github.com/bowtie-json-schema/bowtie/issues/28), or more generally, design a good widget or component for representing test cases, their schemas, instances, and (sub)tests +* [Show average compliance numbers](https://github.com/bowtie-json-schema/bowtie/issues/54), or more generally, what summary statistics *across* implementations should we show, and how should we show them? + +#### I Develop Other Tooling in the JSON Schema Ecosystem + +Great! +I have hopes Bowtie may hook in well with other upstream or downstream tooling. +As a concrete example, given that Bowtie provides uniform interfaces to downstream implementations, an "obvious" complimentary tool might be to fuzz-test across *all* implementations, looking for cases they disagree, or blow up, or more generally produce behavior non-compliant with the specification which isn't already covered by an explicit test in the suite. +Doing this likely simply means hooking such a tool up to Bowtie and letting it rip. +See [this issue](https://github.com/bowtie-json-schema/bowtie/issues/23) though it doesn't contain much beyond the above in the way of detail. + +Other tools may also have nice interactive properties when combined with Bowtie, so if you have other ideas, reach out, or try it! + +#### I Want to Contribute Tests + +This is definitely also helpful. +If they're tests of the specification itself, check whether they're already present in the official suite, and if not, do submit them there. +If they're *not* tests that the official suite covers today, e.g. because they cover pathological cases like causing implementations to "blow up" rather than produce a result, they are now "fair game" to add (somewhere, TBD where), because Bowtie can "gently" run implementations and catch these sorts of errors. +Bowtie also allows for a wider range of `$ref`-related testing, because its protocol specifically instruments harnesses with a sort of "registry" of schemas that the implementation is expected to be able to reference. +[This issue](https://github.com/bowtie-json-schema/bowtie/issues/61) is the relevant one, but ideas are welcome here on kinds of tests we can now add. + +#### I Found a Bug, or Have an Idea for Bowtie Itself +If it's with an implementation, you likely should take it to the implementation's issue tracker. +Please be polite, as there's still a small but non-zero chance that issues are caused by Bowtie itself. +And even if there isn't, please do be kind to maintainers, many (including myself!) are already aware of issues Bowtie is flagging and may really want to fix them but have things which make doing so difficult. +Help out implementations if you can! + +If it's with Bowtie itself, or is a new idea related to Bowtie, definitely [file an issue](https://github.com/bowtie-json-schema/bowtie/issues), [start a discussion](https://github.com/bowtie-json-schema/bowtie/discussions), or start a thread on the JSON Schema Slack. + +#### I Want to Do Something Random and Cool + +There are some funky ideas in this bin, even already. +I would love to figure out whether we can make use of Bowtie to *benchmark* implementations uniformly, rather than just test them. +Being able to [jump into a language-specific REPL](https://github.com/bowtie-json-schema/bowtie/issues/38) is also a kind of out-there idea but one which might be fun to play with. +There likely are many others! + +#### Setting Up Bowtie Was Hard But I Figured It Out / I Want to Help With CI, "Infrastructure" or Triaging + +These are all under-appreciated areas you can help with, so please do reach out if you're interested in anything here. +Even something like making Bowtie easier to install for those who don't use Python is a nice help! +(Right now, builds produce a `shiv`, but not a cross-platform one.) + +## Conclusion + +Thanks for taking the time to hear a bit about Bowtie. +I hope there's a lot more to come. +Please do share feedback, it's very welcome, and if you do want to get involved, that'd be very much appreciated! + +Cover photo generated via Stable Diffusion. diff --git a/public/img/posts/2022/bowtie-intro/cover.webp b/public/img/posts/2022/bowtie-intro/cover.webp new file mode 100644 index 0000000000000000000000000000000000000000..5040921fdf632abd808b1234635786a4f82e1875 GIT binary patch literal 31650 zcmV(lK=i*-Nk&GRdjJ4eMM6+kP&gotdjJ4%d;y&SDv$w?0X~sBmPe(dA|WofO<1rJ z328qsqG#Cgh?Gn!@E(8hA>CxId%1sOTi~!7a{lYZ@O|#x@+^;TPhfx6(Ld+B@%;n# zFZ6y3{(bhp^8dp7Vt%QIKZXAz%zwD=+5a!~XZRoe9{2xy@eBQ1Z*Qajr|1`gKhFQ) z|1tiv*#EHK_P@h?0RKP!&HrcC-}%4sKhA#t`bmA${U7{4^1qzFU|-C?t^d#e1O7Yr zTk4DcZ>yhpU&Z>0|6%`K=l|~e(U128Ct^Oc4EDf%_Kz!2&O4%OM1JX9OpdgpoW(C! z%3~8PQPSr)+98j~O}v(NhKm=gCpC;fn7E^fxH0QfiI!Mk+|2s)Bx&d(zhNbL?`?ti zoh=oo2-TXD6Q=i?ZJ?D~*Tf`C?&Z7SB4R}n!(v1&NA9UjlpB)t6u;wG+8GxB&kgzv zu8vX#ChLHnF>61FnRz5Iir8N%1{5?M`?p~(35)(tB5 zq@{slY7};)D`vI+FJV{ASY1jyji)TrPWz0saLB8_asJ`D=#)niUBP!JKq^@#Oy9D2 z#b>Fv#ZL|nJX4D(rX))=qDXo#GqYhlq0p;Jr0y%Ha&{1hWpO(O(HYzJQWqHbC`^_z7!NGW;jly|7b zUm0poeCGiD3M&n)BV+ zG8!PgbDOjAyc#1n`E?Rj!Ne@Ny3HFbvk<85iEW<{E`r5$#6{HbJG%FpfSzgc>Kb|e z7Yh1z{}()FCG(OB;|ak0HAO7c{Np^1`6U{=p;~E$bcU=5p5gf;&hXc1J%n zJkhLAU2#H-=+DUX8r z_lq(01N-}?Iz#1*|ufAHDWIvk*N%!&oykyoIcmhRYuFuDx62_ z%k#DC$^{Qp(=}E!FFh-t$i|S{X6E4zqV?W&C`q_ApL1x8<#2xFuRqJ&b6%m#c&iU2 z+E|Bo^&mx2*!cR}iUw1vKBlkP5*&gP4<$r+Eki$4EQc&6ttMMOP?a3&ILpG74AqMB zIxEL~utV0B$Zqa7cMHvV;z+;e%hKJ72TT$t6j8*S=ro$FFRys)8%K=b-`F8HiLSWe ziZ~Pbx6J#{tS7EW_Y!vN_R&v=Jcwx?@r`UjWjc9vu>}mp_0@q7eyOq=23c2Fko#k= zo;NOo^u=Mxh&Oq~-&f7FN}SCw=96Boo0@VBe-)MlhD)U>^n`&>9oG`8c-^h}@b4)L zK%RGA8VLv9U^)B7e^jbwpFB+>CQt62(|bJP;ejTZ>8QpeH5}Tk5itEgb#1zrh>Jw( zZ+)2l#va11K{3dtKci#0&thj_cjPNdEe7+4@`=H%3{qV9%Ret5OlwG^W;U;!XPj+x zLjmzJNp+b8i@T-VsY+4Y#k(RERnBLTG!E(CF+~`(N#o{+LwbfMRbvsLm391WHk28N zFgg4S$>{sSi23U9HRFm{&0aw%VItYj$pbxet^uxG~U|NumhOI4Gzo?0-cCvw8a#!Pkd<4J)SBDiCl?35p^l{lV>V@UlPTLc!dsG=S@h7>}V*bD~`pf)16!vC%s2}*$BY8Hkmah z9=CQ=Vc408ACYJA+XV9S^Qi%}6DR$5C+(!n9*p;JW-pH4@)=ka9t%pBxDkZMr6mmt z83JeDug5K=>X^#}Y)zFhW8bk@#J%@!w;tu$6w=K$w^_06;2$d*ubX|Unk@aW5pj|} ziF1k;3zjR6?uq8W+BP0(q{Qp|I#&S!)Q0MMPHq19?E8sPpQ-%jZZzAd+S=MkbKuq& z;;9eIWZ&MWZFs`P$cx1l?##Dy@^+3l2YzO$_(R*_>-Jp6Z87=$IUX<*7+pI9j$fiZSIG6hzWriKN;UCU8w?AOPd3%oPugb7gYP2_hXG&$mliI>CWOw_YLywah^ z8uxkE$45ccK@#{0+@{OkK(qI<^-$!7S1)}pMW`CobidyMq)}ZL7U^Pg8TY~jkfuTE zH(_hX9Va(L$8~=RC)U`nvlxh}nFR_CK@s0)d)o}P%jEb(Q#~4G*%+CaFknwBAZDju zZz>$j79~Jg0Pdw>i{tdTM1*#fV@ciXO)wJTwUJ$vWC^575bzjB-tbHNkLD8Guyi0= zvQLqQd|A-xJqTXexS=Wr%X2QWTIlBt&q*g^Kue2#TkQw*j zR$iDUGPx?uHlmc+Vo>1NvaiKBP1f^nnw zGxhF)t@65^46KF_lY<7(*B;0I&sO$HkOEdeQ z@o`EnK$l8rdDd;jU^Pb5cA=_~!`0vVh0rB`ag@j+9vataTvo~svxJNNKpO2Y`>wl> zyuaHcnN_EBWmiNYH($&6E5~^Z5?r+Rw6rH3nYJDR)vn=~*JIi+p!j#n~mKFDP^gr|R(vik}&y zXZOS-V5KU)D_)S?LOC@2DEAX^XkTN|PQVa|(e;j&D3CZL5^%D$@2uVLf*Tn1#QTyt zrYZzM676Wtdp;ZfYv32ikw?&3SJl36+S*BgEf>?F@X3l3wjbaExHU1k`)nv8h9Mv! zrK9o5pT={-o%r^rRw?8}z_%IsX_J6sOZ^mG0s)xZZaQ%fEL2^T(IE5BG zDdlV06Rnk6rl;%x`(DKVKt3cAGG9t+Gz5o(Ok$EsxPIuYW&3JhltERBs^>UdrT@Pk)HljGH_<7gw88E8gN-acR{B`^5KFQhWGnL6c)>NRVHZNy4g+x!E-vw z971+`U6QKl6Za1#k(Sd_o|v#d+wx?iD?xpq!m&>xcU<39 z!>>~sg+xv+0$Bw)ctHaxKH|8G9UHhTujd+!a8xIEKcF)E2q3sgm*q!L@(J{e(2~Tc zA@00Is>M@RTU4o;QeyQ`VP)l`JfjawW-TC1?@cpucqP&kPr3T6jmoc%(UiZdhtuwR zL9#%5`ej+wlxqI&+Ij@#4c78q+kKPmwNd`Q#ya-R9#tN zyDT|uI7Od{iw`>a%lF>AMKJp~sDDK82$I2C%O97$KcZ>>I15=#^x)wt-HPBp9mP5? za>24X7Zrn>?7T4gGG4)_MuHA2QcqLh=`?e(N~f=Xgs(i3X)aHUi5Qs=vTpX`aH5O3 zyQqFi0>OT=X8nG@_H&AQ6L7#2bc~Xr2gl|WSp@O~CYj%Q8UYnoOKo0*r?P zxFqxdf@Xr}CvW@(HoPZlU;;T444g$W*<_O1uINWdZ$ z3L^V2toUDg(|&pI?OzHN`5TQ1_D&~vSP>gGM>%sJwu3f^uy$%O5hS4Sxm5n)LIg}- zwsCO>RR&*U&CmqoZrDIk-F(M!9H{7s1swan7zLBh*$;X?OWP1UnLKrfQ{Tk%Uc~f3EY^^a>$+3jNZ$E^eudJCz!}m`ItJJl z)o!*kgmAT{Q9SulmM^zuA@VlAVYH@}sSX{6&*yCfJ$e$gAw~y_I_VcQ(oNf)brz*1 zp*|POamB*Dz3c+C60%mles6<|qkbolnj3=V9!pxQX8z$`6R~Ses=DWmO$SQ=2-`We zxZK{%m+J2yKl%d?JHvW%z|(h<=|c7IRZvoNWT@rX@-c>GMxepls5F;gY#pV}wHiYe z;1R<^`93s1DiT!WK+x)*s=nBlsQ(w7M>l-FHldErmOMn+giJ*a^OOAZ4a;n!EqrzEeo1)FGJZu3QY=S97<8t@ zzLd_ygI&H49?I$vzRqE_9f=yG*hQx5QyASFZCg=&vk2)E1&8fo&5>H_0_mC80whC* z+Psf^u>#xk~Z?)xB%4EtH21#U-Bbq$A6&n z`)a(UA;}_{*xT?r4zye98$(X<3`bJxFAZbP%}hv1<1j2gCdiWG%(5`!z2Kq&p4;P$ z)pxQQYPd>n48H=R0(%H@u;Yb_u1+&%=RNGT4XRj(_M4f`de>tpuDoA2BzESLoumFc{f3-h$yOGrU-odB2-DxmAlAIOVx$V|eo~33pci z$)7K(qYtj0RX?m0U}gESbrpWXsoL`%-`G~XC{ zx#u8fL$62=+EOtnEh&Xuf(X7c=g3Hc|_?4nQC0n<&2SZYOayZ8lll3xPc(PSK&Cu($`45;@L zI;}>>o@KzQWi;C3F60^s?k#45?xE+U_n{`LUj)^j>zX)6lZ@4@cqpFktPCDa7@_R3txV3GWpj2f+GN_G|oizRDOXrx}r z@8OcnG3soL3Xq8>zPnnMKG6Zgv;V#nDRk+rLm>O{}W5T9_3Hlqia~Uk~v7r!f?=7(hxu%gi zlS|8H#_Kc-XiW1v)F2ggUxJGzMp8l$XWTIFar>Nq4MS+b{G@PUtetPd-R@27LpaT$}w1PB(osvV&+FXk@F@c>| zPXk=a@5r`FK8n_X!nwEVW4cinri-d;wB;aXJ(E-=f+R}Ijw+WAue~R6=H--=9{;6C zB0}*Mo&Wb9E%ju8hlm|OFwm;7eY}&RVEE09t-2`g-}$y$I(99J!}9O-2Wx>~f;`7= zmCjVu^31$!9snhvHx!C_4g-KeXYHzcmPsbD>6POh;oT4_<8nD!&q6*D%&gibv{`3sh-xp22P@%PEv z>*Z>4QTFYg!~#@s={7?gVMt&&Lg5ZVHx;RU9a_G}e{F7Br>gEG-hz)(FLOUTP>~cD zdEes7u3tEV7BNGHTMc73&hHLhf2&Kw(#!e*`0-vu<)ETr@w{dH#wgXHv(COLf`IpV z?eUU}iER{NpxHj*7l}pXgH+D%-c&@x^~dcNZ285Kg<6Iv zOwYH_5sP0k<1;k8HN5dJ6ZiwMU5U)FvH!N`WwW!hX4>_Q{Qj}h-`(yO1(x#BE~2e5 z&cbaYp>=AbwFN>UO$sg;bZrRs-0pR4pgGyrxWI5HHv<`-ng9+hZquI`l8+^ZrB1M04a1#E zzU|8}!{zLt_*%(dD>wE4r05Agw_@F-!2M~b2pJ&T?%nq{kb3HJILB?~;&&)wykxlv zR!((9NONYY$eVPkHV+EJXN$W{&s;7=3MpsAN14N;6#C|W@_3okaO!V1WOZB(vCUx3 zbK=(PX{CM{X*Kz{&x~GSyVp|-07`zaL@gqyW_P-EU~@)ZsXn#|>luHB-z%mQS?qbb zba@S|aNQ>6EJ9LFjruFo9X;~s^QtL`><{s}hT zH)G&94y$5-y}o;C+~raVd8a&aQCpJXC2SXWMPZk8I$@YwO4FY+L!%clur1_$tXq)3 zeQAmQumH6@>+p@cnjG;^bC{U#27ZCZCATGR!$>RRbBbskoZDh7dsr<{kRC`n|$xZ7C@6s*6i(E7Dfhzz# zky1mic=;d;9u}Q?58^NG`h{1~h0J9*jTfOs{MK8sCiM_j3|uJVmMw~QAk9tE*;FB1 z{#mmfFY9Xsq_HpRLExh)Gv+Xiae*My(t1mUs0>t5Pd|I)YUhG$4^X0G>hUZ_-Dr&zOsHU!; zq$%K9MfO(K9!B3(s-j+cJHPp}PHBhI`@EJE*=FD5QS+$$bJVK zG~S&BP)ZnGDTad>OeMV=b>r0u6$vX zx=pC@<;BUO0G&o!R}yvkY|k`Yz$tWGbCM&6xSQTu&ZPtiE9swkd8ko(T}TF_&dwFm zWya63X&nW(uDP$b+h;+y#E?Tk!su-b7nf0uX1?>@9xVXK%Q}IrL~H4dN|RZ;>n7Bl zuBdr@Cy!>ccYrwlEk+D!OdhBg;PA;iM2$E{EoT=L%V8=@$@bh+pGA|2y;exBmL+56^0!8FF~?p1!9U};Hniy_8nasQk$ zzU!=N#ZGp9cTkkXv_IA1t7eV`5p$Nh)`?D1Yz%lG;qZ|1*%m*)b7MgKSDZ?mcOksA3FPLx;x`PfplhgkXkyTUL?-w2n5JI z1cFA6agD>r!O$!|m*;y~j>uo&ZQ)(3$MnmTU@J}C0egxu=6<@TO0t-E_ONX0efwKI zgc7l&G1U=v{MWf)zchNMC?eEB7g?-A$ch{rgU2bMgAli_y||2Aec&aq1&_YQECR)XGsT{7Cm2Ap;3bk2>F%0iv zv%nNur&{-d^X`%$s@$rS@a&-{hFv_;!(ut*r?K1XjR7%x-$nFYC!BfjyCh5%too;b zEjfRU$y${v;HC%T*h01tl#hO|%y%_|2_FWisFe$w87-8_?gJQDWgBzRiMv$Xn``gb zdw6JIV5Xg$Z+NDXsgMZCEN3En-JJ_S56Z&_k*i7D5eEHvhJ(RKamL3i_0k^_B+NJ` z=co>8N3Qh>z;#v?UH(#55BBC{*?I%=MB%&I1V#;SXoCckm8=|+c1vU=N(w)mh>%D+ zvj&NEXbAH+Ebn7R-7`?Miz3^z=BDUy+WwbzVpF6U1q5(BWwBRT=rTLyFnX>i1NMC?23ZXI7}~bmry!l?-islnGt> z@$BSF(}0`ULKkF-!3Pbl^k^S1WaPd{y7M98iTcAJP1{0Opza$Pw`05k;fJMED;;9_ zuPm4@9Khma{X`7(>{!>2EMQGi|EorL!PrXc_+1r_E(3@C_m4?9nNq%=Y++=ubfxL1 zG(r#r1my@-cABUtlM}fAemB*;JC{nZbbJ;ajR=HHAJ||WF|iQ+H;C2FM`C2TS$k;?IgeFl7TiF{6@z;;pHJGW z(~>xaFk!Xv3C%+Es}bYT#U){O)DBUb-*1Ve$sL%g4Bn>M&pKNw^hp3qVOlnPH>xru z5Ip=OC@*{|uVoNpcXad@2>DeI(JG%)sSs&aa1x+-3s{I@(~mBS)WRTu5D43(Kft2B zw73o4`V^8jJac;F&*~3>ysku_t1e2;?OEU}3c#nR-Ue#R3OO-t;zIv{Baksy4p20y zDt9%1j(*DIi>kxI<999`f2^cym7XasA=U{%qk;LEu(~PSvTIlRtilWig0*u)0pmci zajgiHJ0EolD;u-88 z@zJ41x2dL9+#ORZpwxgbG#q|m)Gch;^)}Vc_L<{SIN5QrW~R?nCi>X;u+%0wV&FWa zVi$nqt0*$@IwW_}SJZ;}nYry?-!<@PAchlM5@%l>9*eU1D@i`&J|k16J2( z4=281@j~1ZPrAPRh_k%^#!#L^H@(>(p*R&3Igrr~b7eSYd**oaoItDD%tJYnw&i|K90H}lTN z96RDDliewIJ7E4uNC{IbG-NDNK%sEto#Jb;YX$9Xc_{#uLe>k~4K zX+!jTEyCadC81QrB%06Kj4>sfu@mOE_(%0=GyeR#02?lRn!wfv$-0DJ_XhE8cOR(9 zFU|_B)gIo!oQUvr#|cL#zq(DYRwV=D8O6|k^Zn++uJ<~5RbUWx#9RFZ-Chaw z>l%ZBR-CRm7o8l##=7H4G-BhS-#%nj>D6D0h#FWyf=%1v2;skYY=rwSdyX5POXc`; z6O}5FKd-^BAnw4#Ny9M7gmg2l((1B7a=ziecDJw!g(Cnf(21IER^!xZa^l>R114bX_G zqjD6nAaqNGg$|ZSZU$~inAr$ZHa2oI%me!^h0IqP!n^jk3yry(?W&^>%-&+!vXA;r zdSQ}+^_gQT00S(K7YZ;CQU~BgWul|0w1Vd$;S3L#nDUQ@IR!ui1C*rE?&oiV-k=bM zw|fK-26zBlk@4zR!fcpyxPXu|FiG0bb<$c`#aa+gS}x`!@T?-c?=Y&2%7x@7FbBuK zn+`$v^W}I?&o*?PopL0^iu%?T1d4JtQ%zEtHFu7NZjC*9$ljh{_LiDX3jvbgMe2Oj z*2z+G0y;dz_SuF;#HvRD!?Aa4#w&V*m}TRp9BeHP`&}7sI2eD)XHo>YrS^i6jz<=f zPQ#0Rf|BA!m%^|T5CxTa%@Jo=_>P)70!AMdnmcxP6o+k_e_p>WAJ(htiV^@Ys za6#;S1lKs*R!I3p0UQ@m6&)x9+mbtHEMgnly*6vt6S35B8K%H3obGF|H%T2ABKgoP znr`6FAP5Z#e3E)^8;~AqX#|H0ONM+5HJ+)2f8EW~~n;e$I#pBqgPoZTk6LF8l7)D-(0zOpkOi0r(+3 z|9on8WS?tq6ygv##oVKg9DAeTxq5gh4L~+aZy;q*gyP`O zDM_l>Ql1yGK(myQ;cBA`cpsq(LeMFzQkeMOw)ML95nfZ;oADlj6U)_WRi(*4ksz~0 zoSkHsscQ$7&`tW@*cKA^X>Sh`+Scw>YtvwA*mIs)>0{6ko}`~eFSELi+fSSHbsmfyS6>erY}$3fTZJO0 zbY{5lu9z`rFV!iNF~222j8?RBH9ngc3J0CEY?17lnUnp>=)FOEVr?{a6ZBgfwwRrf zK5T^9`c0ek2U0#|S!NM+pD!vYA?8qdfDRO*3qBz=%%gdyW!m`6;R|k%1KDU>aft4Y zq)U`ZqmC2b<&73WPfykW7+c8pD)Zd`eK>c2h#)pzafDlm(GpKzKaYfQdAg@(!tbMC zkW%4Ryb2+r2LqV!9KK=^)GRaNly=7~w3s!Nd78^9PqnDd_MBsk$){j)6lqXIdcLIO@#0@1s$h_`$0rKUq%(Iiz zQHFhcQ)P0BGxrGHJ1-f`W6pcGNi3t~C6>1O)Lh~u{T`3^LO7(B!`juMtZ5IonY{vw zsUs(m<~eNc(U=m^s2@Uvnfw#1&H-pjE0aR2nfjIZ+sbOL<$x9u>+rE4^%OZc0)nH3_Ob$_PQUW}2yfB?_Jtd3 z&}BmOD|%5jKZDN_eEeB}`M0Ye23MM%ieGk0=gVhCS0IFjPm<#^L@)oYvC)j>iw*^g&Efb z866dy#tgpgG6;X{ygMk4i3jO*S-T}|cZzEH5rbogb^koTVSAC1%~Zz*b|3%A&N%eZ zDgdfWbntA7lG`=q{Z>z9sqy$_q*@c|S5EsH)&0F|-HAUDOTh+H^Y?WjuD~T5!Kvh; zPpr-HS3~Ixsc8BaK)Z z(t@d|>_#6Gb7r>qP}c`~Vv^5ixyU=`!R^%TOTn^HO~8v+w;Re2e$)^RA4!y#LlXL0 zksFp*@qG&E@4fS<$nf}+{^Y%reNq9!52`1uiP`gASUTug-Qo4>S+9E9esM0>NvnD( zg<`GdvxbCyk=>fhM9LcD_!MWlvycf&uy-bMg;2sMFmlrS@C`Ew%k(>V9#PrJ?lh2%jERV#F2CrjXg4Fl zMrEoXO>Q)@(t{m~p40+}wR2!s7(`pUN>g#5@*cvmg1nfUSU%$2Llv{zTw{gsjDcrw zU4G!65ZDbFHR|mz&{hMEq0NTyRO$HI%tF$^3NNf2HLDfG0K;V1{RIS}?*xU*a|jMpXD`$uQD{M8 zzij_I?Y4W)V1AhV-DM)J)qo*KE~*MfwU5JlO0q#Rx=vZoMP-7X9r309P|ZGO_AB)~ zVY#VFCDutP0rdVl-$NTcsV$X+sK7V)K|yB4ti}=CkeB?JM25 zjUu-sBBWMyPLp|jl*2teLX=|$%gi%N-vm6~39Z-4NsR^@D$dQeiG4Se;q`~&Dz-4h zO|V+qIstT7M3OR{yzdmKlxuym`;N{m3*L)*0GuJ&srUbk?%;y8ww4|1UhL?xhZk9<6(KTx z^`}|DLx8+)IByrXyf@-8nmflQeb_abJ?-de3=2w7E+$2$*3ipYJLwds&8|@-u8S|Z z!8(>ehJeI`cZ9@m^ntR>0Q_D{tk!sGv_d{S>6`4Cr4N_tCwA&IvHeBrWw z;G(QYVthAs_tzMRBBSV4uyHh>%ndsi_Liw2QYlQ5)|m~A2|np*@#7$QQc^{)Cchu& z9Q?w-kq@vUlc>Sco;-6RctF95B`?+dV?RU~!?=H;3T;FKKH$7*2I375Vn1)MjSHvJ+6nLq^P9u5{X;XU~ zoa#HOXTZWZm2KK^vCG=pN*dAeJUMQ4D(Y0)F~1aMmf9+{5>L%_xh4(+B|sH2o3#FZ zP?nof{~3EXzwndcil_mQRk7vMB-#8m{Bf+ykP~fi*A7pwW4wx`d8A z0lt#j`el&>!u8Fzx)~bAK~}Al`)Qznc=t06$uUbdqTv!+yk(NpC#h~&U$ICtT&{iV z2wN*0&b}1FxDGoAv9OYcmJz%sve-32>IntOtGDFtA9 zo_p(`c;&Q;XfO8cds@NEVzW{?AKut;_kTLaG?rS2dWp4w0d2mA7N5%_2ne|QV&-Z(b(ZuZYjzw z41n!$3v_+HR*~`agrJoP|Av~!2MA)H{+WD(K}2W|NI!9o7*c{XES&>6j}e`}g+**1 z>>D1<2n*IE{mRZUfg-iO=F;A#iIaPDH{VPwB=Bpu>1#? z$O!1CNSyt-yJBBT6?z!=L~TKeh%J{J1lT=EL9Omrp!?@Q&C>--+i)3aay?O(S2EX? z6rRTeD(o2`HoKY=E@;=AkA>l=iutDdPO+d5R=1>-AY(cc^WV$x=YMbA!U|JuUeyyn z;+N^?{df`^BFp?+Fn>A*ElZN^H3G;Cmi-6xP7fyld?8)|FY7Y`!``q~gvl`marrb_ zIB(AE;PXouW^F^djlrQ(tD<|eG79TE9zV%r$CscdAJf-9mf_lYn5QyBXMvL|N@pS_ zP6Y)g4iNZW%IT+0hEwqzbVKkQ4Luu~A>HVqu7{C+{cjx$90~b1pV%HBG}E8UoST+D zR|)>R!cCkIm4fAUEPlyv786QhN4@?nzn&2ClPPW+3OEgiF=W_eEGQ7f{Y(Q0?DaHU z7j<|CLTB0SvPMfybxyT5lpy0P&S}lM;-2}u(7vE4=aXv6YFbAqqsRuj3lWpyHd7k5 z3hcgc*uI9vRmf)w;(8q>Tq}^M2tO$ zU9|t~FfN)P)In;kPPGjgnCDdCh5swqZ(`4JqjC4WE1>%>+9#F zcilscsr2cqSd)V;Q>2MAf7GruU_GO%91-^P6>M;Sd-{sz?{eu0SNV$sel z%T`X$s}^0fZG9)3^91Y?5EtuE-4&szGs<}o7N_nQA6BXp&b+n!U}>81Svcq4d&d{l%WdZPP~|V%AZx5MF-X8j>{W_1M|9kF(jHtyTLca)bQyc5Wh_-^EPluP=$zhiee?&%x^m# zdAR3u6M51$MlPuXu2#xNId-`Sf!rkI#w?o0q&FEd$`DtH)}9ElbYTz*?hgm#@q;5_ zA}78HK*d7s3A;I7Y!hlGMGw{pkxHYH~%s|Ng7Pn7?WWjq8BJWZFqHwAgreL8V{ z5R7tm5Gz8n6<+1)+L^Vk%FO!f_6FbLJ|wmof)XSPakqoPC!&nR+to2_RaNlX{b*7) zt{v-N#d;QfjBmM-*Iu7NWlNn<{{;%VM^+eM}!cF96l zIN&hEGJ!p~LTF||5kQyp2FRg~Rmahl;NY?!>BlVf>%;F+ zQ$hyQbex8hMv(Z>#shgHj6%@4xCaoiW^j1CBf9=ijCu%<0xPTK#6>E1!6lJE*&uQr zqj+qZ(rAZ21|D8glf)b$bEpbuM=7dzd*x)1+COnc&e^a)p2udB^4_WGzspL_iF#wA z5C>pCTV*8n0bvF+P6}#(W!2_)=&c%$n9}YaFL%`Xj-A!Ie#Avf<5H3VO{A5CKRr9+ z01n3`eTS;5b6b(7CKuXYxW+<&3F0u(tXK$L&UCxs<=zJmM_;1pvKe(#c{b;ChHjOF)oK`NDf+xe!EK9r ztCT?2%f?rBYTKBj-?s_BJ^q`e2E1h~Nu`~j{2eC`84E;3Sd0NTid;mOM%+{8rs277 z7qm0P7_Da7}B#ci9*>Xn(3aOO-GY^oK30MXqzfzOoUNQ|f(~zV-&7riLQop(f ztQqQIcvPec6=>Q>r>#yTI2Uc^T6cR8lQk#Yq4w?Wg#2(FoZ4uY^A(ddX>=Nk5B>P_ z#id%e67x03<_ePjDow0(_njS2NuH{YgISd5Yjt1j;1|&-|Q@Gdx zcHL!$rjt6*U=gHS+8;DF;llV0jqL%KJ7~m0%6H4myjO-K#O^at0et9uv!hfYXjb#r z8W8w0zdrBt;+S$$l9|THsKXsxuVQTf;apcwm%cF5Fw*vemYw|Tp9R1T<5t_+k2h6l z4DaR=8)|BHYa@+R`Fwt?j!tuunv)~#iLd_tu3UWjnzK+q1T);fE;xAAM!G|0PsgH8 zbj3YO{62~3r*;511*|h7>M7t?WNsg-Hh=B+8G{f|Y|wr@-iRlYXRZ{*jb>TgOKlKK zo4M8_e&w8B-LTL``LHAbL{)JJTrow2Esxr@4#cSW&f`#x%hN{rv9jq)b0Ei$F1Md& zfCiOrKv^@2YUC0c6z54!+Kq)NuUxl%&!xoLN6uh)2f@^n*9t`J=@8i7v6U?~E7_JX zQc>%T>~)hfq|aZ;)*(Q9WXliQ9mk)jrV<3r+dKaBEl*SZgi8aSD`w-cnv)y_zPAMb1FntrbIg+X&UnP<8Fe~tlF5?grh_+TN)pz58ODo{^VJHprTMRvh$o=ny$buD;q= zsha6x(U-ZfX5Nv?&U;?7_&a+^RCRtg>mQ`yfae?OmmtqMXIhmX3<`s)6n*e#Q?MigG!L*=f>BSb#E>g||yFuFZRgbIH%rDb`kR>p1ZI( zIAC;`(myMX=<;j1Yb8Nao2i)oTVnr*5rnX63uD$<07k+*81*O_(O+pB8p~iM3-WJ2? z=%xv#4jqQjq&nPL0#Uo+*6b96f=VjaSd86#%fR+W0{)(9rjG<@&f=7JsPUt6*;km0 z0mjEfgt56B^sQ$}e}&gw+ulynIM`ihVN6S`AO?LIz?RNQUP9))EWY`3{;}hKU%62Y zNGrBYS1%XDCdj;U0iK&W)2K%e0xi-=ptWG`%(Hezqv*E+-D-HZOK_NElOaxF^AIvF z0Iglk2jOfa6(x><&Bc)oR-*ROa`$2E>2~=S&BlQomjvUbl#*N?l?Sr)G0pR6T`gRK z4=$JD$!&H(Yu3n2TIOJ`Lf1_-TYup#v}3=`t4L1xw6NXQy82ZKZOB(sp4hn5qBxNf zI$62)M``mJ=ba9G%iqjLY=X6El_-d>tv)xu{tDD;F2w2mwI?L+tiz!70}Rb&xNtzL zn4QC-hARj>LFI~q^#RPD!}w5S-zUEML5rLUtCO6y>o*hXMG^Z{gTKfO1h^FyUoJAe zpOdrIfx*Yn(fPM_Nvv54e8h;Rz}CfS`%eQz)!iW8$i=e@GtBc)(MZbWH?OZsOI7ki zq(?zufLW#1ltzBL2X|LzJWvlbEIu?}N(&kA`ZWUoaI#-2(#wn5MY80FW(G8`m4eD} z^blUadKL~Lg1yjhyBPMKdd{Qy!nL__4V{zjIGFEfi49+%m;4=|rG2SXVZgmdg}n&K zx-v*vIArf99ll}9pP=uLAD=_s=0DFsINPt%?F^4vpuLA=st7gJHK*{E6nfpGL_91ctHZ{rr}l>j6ut=3Vgd8?3i4BL3W0yvrE2)lgrZ?<&)&9WeL1WrD2P z?R^m7XGvsz4Dm!axvOSy%PZsgUHz8xyO}B3a~_csfL&$UxYz76j}W-lDv#2R6^X^C zD*`jaM9!z$OTnDYp7JGScOm~S?R6sQx8In+$eHz-*&akw_Sq?bGkU>(s~=j1_satF zagvJ(HP%6db(DfyZJcx(#9;c?zN(X)_SA3`dlw8nt_EDY-mBbP@4xJiMeQiu25HI{ z9oAy+?wvl|xxut`QNzTf9!hBcX{igtXxOs%sq?PwV_r&xYlK%_E6u*S(YPesyyhZN zWX+E`;^cKo00g38b>STbNaJYu+0@l`3l9W)M#)Fsaj8t{kGm)JF4&>r1*N zWz~=%Z<=bC3C$wC|F%CehM*QLm{f2%dMF;OPTKe6`#POENsqXaJ^3>@{kd5dC~TEs zd^W6qp54Cbom;nBKhu}41$Y2$PyEY4$vs!)hTLsj1f>din1pwE_l~4M8q!7p6=3RZ zeUhsY#{?_f;!h^nTVaN+jb+VTMq$O{#mdtIXQh3?LX#&R?!ie2uyPNHB@3HU0g{qv zyeYmBiZ$4v zYJ~yQQSYEieCel0qjok`Ra!*IlMUT8mY$MV01qxqD_c0+y0W#1q~SW{fwn|%#X(dO zYq8bZWGLNEZ!8rmCvcWL+6?ne&>&5$<>{5H^z5CpRSIqY4E7mrD2a~>frK?(UAZK@ z31Pk-`_2Qkin~O;iJ`BAgGD{z0gTQMUmYB#7Lt>T%iwC3<7u$8d4i!gD<@ozA*wvS zaN47)7`|QohBrJUX5{&=Si3EfrZlo4xf9)ag%}0ER*#79!sJd~!;ZvZ51E&?3IpM3 zs~S4${9>t1lmt6wHsKoYz0oA?$wxdX`0Sr+ z6JX^ly2&~blV(h-e0d<`@^8@oo@Ess@QE1Nw0*bf>4SOm^{b%a*~GHoKoujVi{i$d z#Lvdt@>fRuk@Ag2SVD^ZZemxT?41SF))Xn?}fvpSw5V(etqkH?1-#5pl@MbkCMTN$RW*j)2ildovTkR_jXX%=**#&xCxc z69LteJBBR2+isa-36yC$mc`F&R6%T?NFSc(VB8(x&PAC}?^?9j7<6f6hDO=p&%w68|3v32a>c!_ds*ZQh@E~}rJGNi`L z1^&p0yQ1b`8Lo6>IfobWp_9S5uUWCW-M#^?WW@=eS$$SK=Da`_rcSNh%PLBrV9 zqVTW_u^Zs;(8TgBwRj^3Fp|gHRWFrELB($A#4lvDWU?@@>}Z0Vh*T~Yu;od#fi+AZXX0dDy#g@ zfRx=9YIK_N??DZ;n8!pnH6KiCj9rNH--0kuUiG01i%@pSz!PZ;_7+^xV~_LUz;xHd zn9$QYqM2sHN|2g%Ow6y4qgMcWrNhF@3Nz;0woGpAW9;Wea5MaFIzD5jOUT}t*O@1} z;mk2Vz16y?0E4q#{U#CwzB-kgV)_*d&nSh@X~>$&8fA-KoHd*#) zK2cPfiua3gSYlfIq^%fA44X7wAO^p%nt7FYFr8j;t#IZtv_Y8vIJ^zn2f)^VoH$aq zPfyPPweu$uOe&fHDXl5l{eS$zuJB^tq2cm4I<)3hpg-y2!Z2J!Sg=@=zGf_q#sfI& z9=8FqQ`Bj|{$;6`xu;oDS7L8>ikVvHS`-~>gVig1%6UKbGlH-1(Inb=ZNKqu`IgJS z6Mn}p`xL5$L+Aq2&-dEg!)h#gxj_dot~|@l>wW!9kpl!)GZfm{L&;f6p-l!1?&=_4 zsrb{ucHs5;IWs;P@X7yp7p96O+*Oyoi#*#bIE)tV?vf0#iJ$u9R>+`Dg(*_IgT?3i??>M`MM{*!drgu-PVkumt?@t9^?QU_4^QREahy#GxmoGv5<<)1% ziOwg%X$>)y8gxwNG1YC^Bs?H3uCRPuvkOF2j$wUBo@aA7pLR2svsk}`U>B*zno|yV zApu?cxPSadH`dh1UPF21moHYtvwQRE+A_*YYPt(kHR(!JEco-2Gl0FK9G?kekHnxk z<6fF76D@Zo6H*_e&uNo?)HrL7isPeTNIrJQn~zsIIR73;C&0&*`)0ArWP#jn^kU~q z_p5Nos?t49B|mGcj{RkLq>*R(qY&Nec2+KIbKQBdVpOcL`acIRvU~~-u$f~jb&fnu zNztVSQ~o2B2UIr4cfV&D)_k3BXs6rM73r^|R6-9A z@XQUVE?K%EI9Nra{21rN2*$AOWlKq#wKiD@1KYlm3>3(q5~>;SNurdO7{*PMHVnlQ z+aP~n{L^I4%BI5kkKaOxmkzs7u#i}>3+f;E=pon~Fu_JKH}67Lmqwdq06V~wkmb#{ zV?KTKji%LUlEMU`VOd8a5_Bu$8KnxQZMZ25PiwlAl zB6+{LUy25T6wt}LHv_T*it~)i2q+Lo>t0(@g0K_v1GS*&1l+ew=AFQB#Zlj>%GVT> ze(FfCb2`c(-Q7zElgZg>_BlM#yMnSq)=w_MNv~}x%9qq9Es^bFn~@~pzOOZThzmnPyw-o)yTJ2!YmYWdr( zp1n2vvPomglc+~WVn=G2S2M!sfMRALs8mKETLFh0RS5;5pkyp(%c07TpsAiJJpY5Y&QNKlLEn^7tN2 z(1&97pR*?3mZdWe`+BmsF^S~AQ4m9_{v;sSa^#xD2>Y)qXb?=~RP&&PUorD)m`arhb`6wKOZca5rl*SVFmf?kW!@B zHROPYlVpe{fjov#2Y2~@B67`8oi65%t#}OVqdw<*c>tscFfVf))}ZS}5TpfZ9^Cmw*1A^>4L;zT5pp2?CY-PxMuNQ$%#hJqPRQc2;+}u1o3D+iz*K7o()MW{Kdb|}Z3OAHN2%m1dG$*${*57DaskXEgsuW4 z&Wgls=!8hwc3hE7l`e=XKnLKfC~`{fY`g^Qk0cxC@t2Sa&)xkTM#l!AqypOU-UNAh zCXoi;@jE6Bm16)gj)t8vJ-x)b=|$=n`#rhJQ!}NBk@p0+t`Ylj`2IyffFS- z%Wh0jZ1NF?w~X>>j&bNaemQvks(%U84q;SPz75rUKBD(Ca}NFq`J>qT@ejqi!nYjg z-QGvCCZY%2bdwVN{dSx`D!OzE{RoBh$*q4n|4>eLS)CiNDsnVmtS`!8fRtw2W)4BS z%JpD&!%h~W*2o*MCavmXvqm3x7>AoxO64)#K}rw* zf7~@n!Pv1f@_vQJ!m_ZR0hZ%i#vS&4E}Xwi;(PHmu$d ziypYfyDfTz|24oYU&9v@i{rhq^e)k(az2?z6|13);W!8_dT zC=iECyjx?pm&~vC+~nY)!8{_(MhaoUK@Q>!?o5$Q{P<538!if_D<};u)A54cR4zqb z-;p*V@qRfJNps)aZ}Pq*i<761e0ia7W2G@$|}W8v~6Z3ED0+Ai1|<=q+V}Q z!nOUH!x#uls0WeYru4Pl4k~XwEp988v~L(_;{XTxv=(@J$b#_kL;*cVdhhMFON|-z zdnlR%AIcsoR_TY2W1Tr9I9=yH*M4 zedGhArz~bAAq@FD!EbWOudVgKRJrb@!H`Ses^Wu$6MVWA(p0j>m4!BjAuAGGNLT`P z6UyeO*|D#oI|6ADc5UWnm=QnEk4toq#T&=}#l5x(H6x-sZ)z!&Zf+Sbe7@d4XIf2y zPTvA9YHB?{WL%GOhOry&C%6nJ=g9c=Y<}bm z%?hEA_7~aZn*ClTb?GqtU$#(J**08F$+Re1BnB*2gtCshbD~cdWLZv-$=8-Pgs5KN zRVVqcLiXHPlL=eJd#fUCI5Q+acL5J_pe1u|Wvr;H|L^y|cFFNrC7K1ah~=YpG2 z%y!1XIFdB)!rc>>;sQa~pYR}ij}A#jM|Mgwu)ln&lY%iV#c$A}(ABR`t%5~#4`^Rw zBIHM75{SsR#wo|15?g2OGF99VL4P)?3`Vnbv-tI~n=-Gol{PdZy7+z`rAA z?VS}+1AtJ?G4%9D&s=^%Y}(Oj|2o8Xn&rhp!tm1JUnvn_pNrcE<0a|AO1YyK^$V~? zhq5s=U*N@iyDiJ^g3Xe6Fm^d8_&YBFJ_2T>7jRoaKahr5o3}W=;0dUzbD+ z1`hNSs9TxJ$d)L;IWTj&BHd}HYYkpF1y$poAU?ARdY{Dnll}yz@f&gO&nj&`qj4T%C0d18#0C&D}ZWi0N3} zZgwp&uqRNvtJA10srR0wYxX!#7g*p?#SMDz9BcY4PjX*slHt(JLe@r%!@J39wn5&| zsUm5kI}Ok6j%y~)-Tm~IA=p~(wvN>>?4r^-UmUS)L7&}3oOGm%nQHOSjFbGk`()a) z5LH{Ni~pjI(k6E!MWo#QH5CNgZ!YN05v;d!bucqI{(_=0Lrqm zy3mPVeH{o_mfe&4M?Cz*aFZZ^FWrAf;?9nOa7b8T#3emyim?qc;FTR>MrytOUBE-> z;sFZIsTo|Ivn=Bw-)nKem6`ky+;qHy?9pQM$#kbhpch@2Ax%HnpzH_*8(!-&)GQ`v z(I?f0KG!yFllL>URmeihIYo9Jxm}Wq%&5t!>?ma;4^ZAA{aQkvrn;ACxTBUw5vEkR zdtasv7riqwWvLV1Tr!>HkbgotAP#;&UweAFHGj<*PX*sQeXI9&9DLeoa4?`>lq!_$wq!NEdC|> zO~y4VBYMD$2Pv)>t{liKLo>*u7pqx``JmqCc9mp5^YrDlhHfn8r40Jge0ZhauzD%N zD^RRTr1{KK>19qEcl|Nhm8r9=o2Nv3u_X36mtk9wVAa~g>|2Y9vppWc5GJ+^vr_<& z>I2S`*8{fY))YSndE^=i>saC|$9-a4+r)xQCBat=KQye`D@TWY!C_G^;`?ekC?>3t zsLH!fk}Pq?Ln}9{AXOM7o2lE7ZZwSyaD=G@I;<416ddtXu{EcDoY{4{e~F4$i+;!L za8jRR6LmJFymAkWJ+I%~+lu3>@Ch{1Z!z*XCPfhKOTz@ST$Bk_69b;1hu?vIhC*q~}y)a>4B1pj`SsCs136@a8;iWbvquq=#`}q)y zf3khh3aF?g8NmEX(>CUfcBKEz1Q3^jQkLi_ij+bRAmRK1^0uN9 z2=Rj0618V3VN%jzsX$LLXCmKinenJ=4uG4LCWOK?J5HK=$yHjyAqy+lg;}Qq7|5xEOrku-!}c**e@8T6 zWK8m1vn%ov3+@FwXo$A87OnDL=b-?omgpU9b&h3;!(Y#foK}IN9==xGW=JO0R}?n_BikAJ83v~ zCRok`b80SycSlD;NwggYdOg8d;vXx8V<)ZMEY08D(_8>iL#92$qgeWss+HDi;ke#R z_EH6mrNU2VbH3&wlRmAlyxt-faLzwN^w}@<#M}j;H63y3d3GDnig+z2lTvgtyCzVe zj7o{V(J4}}`yuc`aR~>qHi$>~?S>Nrw=Xf?uBMI7?k}1Y(tVeBR5k^=X})4GzDW%t zwc`nqnw_pdgWA9I5iFP_ZFJoylr-Tw#^nPC3G3-?%+OV8ct1DuRif*YkxLQi+#sQc$^f zXtJt8cuY@@yjqN+QfHq3n*R7nRFWVN7HpxNIH+Yemv0XYq;Pj$cM;)CZP1R_rO>G+ zBw{tsDTR9xfvuDu;uLvoA%d-A-wGQx4S0f&&X0m(>z5C0)%qj4!->FLK_mnWi@8)7 z*@C0oMhPO?N`xL8If?v{8VM(DTE!}<kEKK0V{Y!UD|nj?+-L+;0KF9F$&{M}8V1 zSe0dY%45t{E_qKLWC{yr-C8(tZOw&B?{;YCg9MX z-=kliPoJDB9@HR8sN*ZCTMcg`64Le$qTGBD$0`?gKr$W-FuzQ#`BhNaBcj60Q?JD- zu=<|R-3%a;**m71x-ds-@>;`C&Ti8)93X(HfDQ_x^yyHbU{>7Q1ofH#5o1M05r=>Y zx#iv*(JL@+>CL>r2P)_mL{KlCl|s`W z{JVF?u-qFo+a=uMW*koGg0Q-95OgE+E^cV_+tZ**iV2`A^Uj-4#exi#;>7Z7LoWLZ z>t-4`i8$%C5Rhe~tOAPW)`!UT6;#;Xh_v%a0J-e_WS{zi77PwqaE71kzKQ=hg{xmm z?4^czzY;+YkeQ097d^+8!i=jnUQ~wLb-)6(*c}?kn|h?g1`xs&{lW*auj9RIp7^E=j{HZHF~01)jOQc%vM)-e2TexvtiBLaRrwXk z#Ms-N_DPVW8A8zHp&5v5w<=I?${*dzhq*R1;=E`UUw-`ij#>j50~pYit`zr!0@hU) zl+df3lo6&==%SaAy1$4_R90~=0jIQLmt1y)&%Z4ORRTjPdNOX3@K>Y+6&4cGTdD(w zDNV7E+}#UMd3Upl^aV`-+?%I?hB*pU?d%%yG0m+kmM)c)u=8n@hvwd&zb7S3D1zv- z1NW|2eMeg}H3B!4VBX^amchFhpCiI!QA>n8`%ILz^AiX8pQXKCtx0Bb_MQWT0*~y8 zeHbW}H{4pVc>@!$R|EcOwspNn3-h>dh=@81Ez6{tDIW#I#%Clm?ak8}NU}J4KC*~x zf2=5LO z?3fB=*iu-ZkPN}Qr8`-e(l zDZfSL>1n6f$w7t8@)xv&wT6?_9anx6K|1f~Wmv#yy_M}f+kHc625i3co55IlW;1b0 zz?(H<;&i=|xEF->EoKimDUdtcv#YAC=gpj&3rzVHnS$hfNfG6Yj?lcGankao=8K|X z>^gPQE3f)<=Q7Wo`y0h=gACksBWe56D~sTAfnN~AdVnh;Y&!K~O_H!fea8C-tbVX^ zB4H!v0*T_H5IfF6-oR?x)d%H0a z{*LGv< zqmcMhWQ_~)ZBgDvaDXiV?=bp8xa?-vU%QUrfW^Seh9?hOS7;%D)dSO8$*Hg(JM?~t zAYc)2Upu=(xL5C9)<5yM)w_vI-T4?(1}=0_u7C&_9e!p5D7T!yN}R*kP?g;fgHdZb zYyQzOphwf1IyNe!EdP`*z~L~@ok||S;!UQT4roFLxQQpsc;KQhzdqo4HihLIGGXul zuWAS%8=H&LAW53S8as%;4=!j=y*9foXzDE5arH<7FW@~~2ZxU^>Oem|>Iu9O6%`;) z4i?9_zOzQppr#5SI3l-$c*GFc*tYb9gwyNGdITJGuDF5??nQT`<0nDpAUe|sl|m7# ziq`&@?-1r~Jomvy6G78f8){*#^voU*f*3D!%RAz$)QNmFSBEHHqrshq4s7M4AXZn8 zs8Lp1XyG&F`{8<^@PNGBUdLyIBsTiY+H^n5Nm@pNDmQx-O3PjFurzL_60<8L@I{NZ z5&4O6>FH0b60@Bu&StvRQUibjIdMXDU($3Q@x&88N$CFQutAe2&J1#;p_cF6sMA@a zn$RQcmZcM$1)z!7+(3+@upjPBf@C{x{H* zha)*hR#*Hx#f;hMzg)rIwl3!z1_3%@l&ndXn>@Dj_H)i2QAlfr1f#03U=UZ%JD;_j zN4B$(07#wXzM*vuK9lnkLuYB3r`mms(D&chyf(e1P+>@_e{yhbU#w%2VEDrA!0QpE zR7OF=+GMUL^042$I>AeEuUJdZ(%5+VOs>JS>I`>>*Vmry!SyPL%lm ztAvZj_ov*Tv=Zf=HfUw!P)Fx8EFUB>O zQHBOhYn1(*Fe}EtS=0W$xWRda%iPTT!1Ev#yf+j1Ka$ls-~sJDjx}gQ)p8JNY_o+- zcMtPca%)e1f>K~5e2FGy$ok1&8_n)P&&NlV#=8`ytyC291s1NG66Lycb9?Uee0sZO zcvNH-Z&TtrLh8nOyPF9eb3vJS-a@Qy0_Xqfcs z(hTT;odG}GD^O8up02X{=iNXbTUs0!DNyzRr-AadK5joCGb&ju`dnhx09NUZ34%%m zKxTB@zhA0z;zNyr7UGG$&$$7HNla88=N1a~Mp&{yV$pfiY6P$o(@Oz&&J3dHOTG{P zB+VmO_Qkb$we)T2NQ=dBN(H4&nZlNcR?nSjm%yHzHSK&Wv)kAby$hk;57B^N#*31r zEHq4CZZ^Z{KAcV+oBf=X7({hkmXNqHn?3x-CFtj_m{HnCUeg^88aKyCX0lQ0* zwob_K9u&bPfeBTLueVA`0F@QN8iWI!e2;AQi3^mPKodosVyea}GRw+AEIAnYEAHBw z_d4b3)hdUN^;ZG(C1s|@UUG^@TF$c{Q+pRqq+WEpI+r~hz*vN265Lv`Fo}T!H3J!V z8cpC-fT%&4H!HJjGGj=zw}BGA4DJlR zw0`SoFjY4iS&uSQIpnp~bj7K#d{dP2Rbzn4117FR4hpO3*f}`z#-+nR0>Aq_&e~0) z5Ep0=z3r}#0@Vn^(`6X-9^<=R?~)Mlz~zgpp7;jV@5_GG9MThL>xcfEHliL=BlKN0 z!OTy98hPqG4@Dmn*s{jct^03AzZQi@x<|3O?2Ey*IO!jgmV}Zgzxa}Ipr!a#-TOVL z^xZx1m^ywojQmk2I24j;9QNiF0pBo@EU|iYDD6mp;C`EIlzX}c?MCN{U1s%QhQw~0@3OUuAP z@D$LXv3sjcwVnY35)lLgDn___=MwY>i9kU3c^+7o3_( z+0J?TdP_;gOBL~nICi2Qb0+X?eG;x!@bc*Rf>@Rg>1Y|e(5>9`>^jiu8=qBr4-l>scNuNMKD=a4tB zAIECx5g=s=Q6cF!3V?`tDp~jSZZcIP!_F@>0lokr{_Pu&G6e(=(U?lfklaeOXjg*x z8CX(Bh&X0joWRjl3pr_%w3atf1wuO7gdYIPT}(FF@|}TwqO@hQ3+!9yr2p4 zTu54-%kF@H>4==$bJR!u@T6DGB*ni@G)rgWM2V4+e909 ze$bZzlBRwZ&opMlk0SdfU0SR#zxi@v$>7n32sFme!N(~AWw#(QT_TG>?ob9Kqe&Sl ztQ#kuwLaIjTFL}dOiM)#25upAi*vIaVT4rSBi@|P3TGDa%0H(Tx2S1He7s@}Sf@|; zv*x){$h+aZt;Y?7HQ6yPY`0*i6aNl)e5-Gb`OL5YOw^rr$`N^cRH3F)^vejnXkNi# z)t!$7k1uA=mxR|2{sQ$>4DEv?N|9$}PejHZsH4#ZjO&@=lV{Lx&GsK1{$7QS!uS5e zoOew#WQzn=@EydA{8OOj25u=D&G|TQ%tkVNqOw*DZuPa!_-zWr!sID9-fc6L^{L6Zq#?9GWpo_wjO0Xu2v*dQ z%DRZ4`GcUG@Iz6exag59Tksv!zDliY#PKZBw*B0hNaIPBC6qEIcYqq1FHC%17S8B=~8jsXc+|SHr#0r^~Vs^tm$p$i- zSA0Cz0?;-#D9O=swBj%|%xH#1&WbzQsU~6l80u3z zjdEe5bm#!x=rcgZvw>SnmMQIEqu^U;ehISWR;X+UgzMcG4m$J9rc}M?oWrLGE|9Kx zNmMr*y1bC%coENvysHxur-6v?D&+nNn8YX9F=kQv|EMAg5`{k-ny);1hy+;D4K-G< zqc@##z+C>9o87NyS;`D;bLt$)T+7Px{?o;kR$bH%7Fj0Pp}6ZpXi^6tiFPnL6$O`O!*0+=lADgiW3`1e zyPSMdIwR75K=~qv`F?2N>$%2X#9uD0pzbkJElSoTzh+M1ch@JPWJ)4Js!iT;4izZyd8LO~#J36br$-T58BCiRi%5EC^JQZds-M6JLGnWAf zaiPdGA0@`5yHfitVjkql1`i<%`1EC?rs#$0^YfS&R3(L0rVUNd1% zhuhh>ogQ=-1P>J|9@UQt$4*>@Lr*WG`K`R=swZhBT#b#OLm?jJr2mdZ)7&k0;fb{;+tu$ z|G(FStg}EZk?~j&B1988OS8r-FTZ1U%V;d_0Z2Nj($2^>m|JSU3^wc`=P0oT z>XSsnLvWv)%>+O##mrmVD0IpP>~4;xwg4e;8)7<#)wIa(o3 z)e%9PH3!MDp{0T>+2@sECTs6%5JIH~9aHQJ)ax>i$ra;Qt%=)lglmzG%nuOoDkta* zM`f(5I_{Vh^rWv~;m)4gK3H!~x`sCmp9qsNLkjKLEobIQDcPbA@pq7C$wp4R-YqiV z!GKfp(2NQ`fnSl7{?CigIM_pY6+RaeI{F8>)yrs>c8MPg9ozyAGe1~H3m7pz7hrwR z%;i5dxy=A0pR%+H%+eBejHiu8A=^$~-d4UmDrCqLXDhp^k$@`!%-Vf^HO+f|@o%TO zxl*4;M@;U33jDvI2ze;&I$&~6MUlifmv*jLD0JHdA8PY8Q?w-j^i*dZM5vfao&5WS zEIj-do2jVQ^Jnnt6C*~!PTqJsPEL+?G+9gHBj_P1xThr-l^s{)9eH$(hQ%_Lr x-Q`!Y0H6|PbZc&YAn*}rF?LA&S0*~m?q;R;gj;-3Hpm3O(EU9hI)N9+0013Au_pik literal 0 HcmV?d00001 From 679d715085729cf62b65c5a6254f0d99c210468b Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 16 Nov 2022 10:41:05 -0500 Subject: [PATCH 2/3] Tweaks from a second read + code review * Ensure we have a title * Add a small lead-in * Make sure to thank Postman * Reference JSON Path's similar project --- pages/posts/bowtie-intro.md | 42 ++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/pages/posts/bowtie-intro.md b/pages/posts/bowtie-intro.md index 6a0eaed7..e3b30b48 100644 --- a/pages/posts/bowtie-intro.md +++ b/pages/posts/bowtie-intro.md @@ -1,5 +1,5 @@ --- -title: "" +title: "Introducing: Bowtie" date: 2022-11-16 tags: - Update @@ -12,24 +12,44 @@ authors: photo: /img/avatars/julian.webp link: https://twitter.com/JulianWasTaken byline: JSON Schema Test Suite Maintainer & Technical Lead, API Specifications @Postman -excerpt: "Bowtie: a new tool for executing JSON Schema implementations & a call to help improve it" +excerpt: "A new tool for executing JSON Schema implementations & a call to help improve it" --- -*This is the first in what will hopefully be an intermittent series of posts about Bowtie. -I speak here without speaking on behalf of the JSON Schema organization or its members in any official capacity -- Bowtie isn't a tool we The JSON Schema Team are "blessing" in some way today, though I have personal hopes it does become a sort of official tool, and have developed it fully intending for it to be owned by "the community" in whatever sense that means. +*This is the first in what will hopefully be an intermittent series on Bowtie. +I speak here without speaking on behalf of the JSON Schema organization in any official capacity -- Bowtie isn't a tool we The JSON Schema Team are "blessing" in some way today, though I have personal hopes it becomes a sort of official tool, and have developed it intending it to be owned by "the community" in whatever sense that means. For the moment, I speak only on behalf of myself as its author :)* +The JSON Schema + +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "string", + "maxLength": 3 +} +``` + +validates strings of length at most 3. +This behavior is what the specification says *should* happen. +Does every *implementation* of the specification, across the wide spectrum of programming languages, properly *follow* the specification? +What about for other more complicated schema / instance pairs? +This is the key question Bowtie tries to address -- how can we compare behavioral differences between JSON Schema implementations and between the specification, in the hopes that we make it easier to fix implementation issues and clarify any unclear portions of the specification? + ## What It Is [Bowtie](https://github.com/bowtie-json-schema/bowtie/) is what I'm calling a "meta-validator", by which I mean a program which can execute *other* JSON Schema validation implementations and collect results from them. +There's prior art in doing this sort of thing. +The [JSON Path Comparison project](https://cburgmer.github.io/json-path-comparison/) does this extremely well for [JSONPath](https://goessner.net/articles/JsonPath/), and [Nicolas Seriot's "Parsing JSON is a Minefield"](https://seriot.ch/projects/parsing_json.html) is a fantastic example for JSON itself. +Bowtie attempts to bring these ideas to JSON Schema. + From the existing [list of JSON Schema implementations](https://json-schema.org/implementations.html#validators), Bowtie already [supports](https://github.com/orgs/bowtie-json-schema/packages) *12* implementations across *9* programming languages, allowing anyone to run any of these implementations and see what they have to say about schemas and instances. It ships with a [command line program](https://bowtie-json-schema.readthedocs.io/en/latest/cli/), but perhaps more excitingly, ongoing automated runs of this CLI have been set up, such that Bowtie emits a [report across all of its supported implementations](https://bowtie-json-schema.github.io/bowtie/draft2020). -To produce this report, Bowtie runs the (existing) [official JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite), which is our existing set of tests meant to exercise compliance with the JSON Schema specifications. -Many implementations already [use the suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite#who-uses-the-test-suite), but this is the first time both users of JSON Schema as well as implementers can see results of running the suite in a single place, across many implementations. -The test suite already has great coverage of our specifications, meaning it well represents all corners of the *validation* portions of the specification. +To produce this report, Bowtie runs the [official JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite), which is our existing set of tests meant to exercise compliance with the JSON Schema specifications. +Many implementations already [use the suite within their own continuous integration](https://github.com/json-schema-org/JSON-Schema-Test-Suite#who-uses-the-test-suite), but this is the first time both users of JSON Schema as well as implementers can see results of running the suite in a single place, across many implementations. +The test suite already has great coverage of our specifications (specifically the validation portions of them). The suite certainly isn't perfect, but Bowtie's results therefore cover the validation specification really well. ## Why It Might Be Interesting @@ -38,7 +58,7 @@ The most noticeable thing Bowtie enables is an easy way to compare how close an This gives transparency to users of implementations, and also to the community about areas which might be hard to implement, or are commonly misimplemented. Our hope is that this leads to improvement and energy to help fix issues, and overall to a stronger community! -Even beyond the test suite, Bowtie is capable of providing a "uniform" interface to the implementations it supports, meaning you can quickly access results from each one. +Even beyond the test suite, Bowtie is capable of providing a uniform interface to the implementations it supports, meaning you can quickly access results from each one without needing to learn the language-specific API each implementation offers. If you have a schema and instance and want to run it across many implementations, or a single implementation which you're not already familiar with or don't have set up, Bowtie can help. ## How Do I Run It? @@ -52,11 +72,11 @@ If you're just interested in its output (i.e. reports on runs of the test suite) * [draft4](https://bowtie-json-schema.github.io/bowtie/draft4) * [draft3](https://bowtie-json-schema.github.io/bowtie/draft3) -The medium term goal is to combine these onto one nice, unified report, at which point the links may change (though hopefully we'll remember to put a redirect in place). +The medium-term goal is to combine these onto one unified report (at which point the links may change, though hopefully we'll put a redirect in place). If you want to go beyond the test suite reports, you can run Bowtie locally as well, on whatever input you'd like. Bowtie is written in Python and published [on PyPI](https://pypi.org/project/bowtie-json-schema/). -If you have no existing preferred setup for installing Python applications, [install pipx using the platform-specific instructions for your OS](https://pypa.github.io/pipx/#install-pipx), then run: +If you have no existing preferred setup for installing Python applications, [install `pipx` using the platform-specific instructions for your OS](https://pypa.github.io/pipx/#install-pipx), then run: ```sh $ pipx install bowtie-json-schema @@ -176,6 +196,8 @@ Even something like making Bowtie easier to install for those who don't use Pyth ## Conclusion Thanks for taking the time to hear a bit about Bowtie. +Special thanks also must be given to [Postman](https://www.postman.com/) who employs me full-time to be able to do work like this on behalf of the community. +Without Postman, this work would never have happened! I hope there's a lot more to come. Please do share feedback, it's very welcome, and if you do want to get involved, that'd be very much appreciated! From 2faa0e985c8706e70cbd5989fa6a97d2647b1cd2 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 16 Nov 2022 15:24:17 -0500 Subject: [PATCH 3/3] Update the JSONPath link. --- pages/posts/bowtie-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/posts/bowtie-intro.md b/pages/posts/bowtie-intro.md index e3b30b48..3509d7be 100644 --- a/pages/posts/bowtie-intro.md +++ b/pages/posts/bowtie-intro.md @@ -40,7 +40,7 @@ This is the key question Bowtie tries to address -- how can we compare behaviora [Bowtie](https://github.com/bowtie-json-schema/bowtie/) is what I'm calling a "meta-validator", by which I mean a program which can execute *other* JSON Schema validation implementations and collect results from them. There's prior art in doing this sort of thing. -The [JSON Path Comparison project](https://cburgmer.github.io/json-path-comparison/) does this extremely well for [JSONPath](https://goessner.net/articles/JsonPath/), and [Nicolas Seriot's "Parsing JSON is a Minefield"](https://seriot.ch/projects/parsing_json.html) is a fantastic example for JSON itself. +The [JSONPath Comparison project](https://cburgmer.github.io/json-path-comparison/) does this extremely well for [JSONPath](https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base), and [Nicolas Seriot's "Parsing JSON is a Minefield"](https://seriot.ch/projects/parsing_json.html) is a fantastic example for JSON itself. Bowtie attempts to bring these ideas to JSON Schema. From the existing [list of JSON Schema implementations](https://json-schema.org/implementations.html#validators), Bowtie already [supports](https://github.com/orgs/bowtie-json-schema/packages) *12* implementations across *9* programming languages, allowing anyone to run any of these implementations and see what they have to say about schemas and instances.