From d02e3e1f4501a9d1a5ce201b31fb2dbcdc2226ee Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 29 May 2026 15:47:08 +0100 Subject: [PATCH 1/2] Add PyScript examples for jiter Generated by apply_llm_response.py from prompts/jiter/response.toml. Examples included: - from_json_basics: Parsing JSON with jiter - partial_json_streaming: Partial JSON for streaming - precision_and_duplicates: Precision and strict parsing Generated-By: apply_llm_response.py --- examples/jiter/README.md | 18 ++++++ examples/jiter/from_json_basics/code.py | 51 +++++++++++++++++ examples/jiter/from_json_basics/config.toml | 1 + examples/jiter/from_json_basics/setup.py | 44 +++++++++++++++ examples/jiter/order.json | 5 ++ examples/jiter/partial_json_streaming/code.py | 46 +++++++++++++++ .../jiter/partial_json_streaming/config.toml | 1 + .../jiter/partial_json_streaming/setup.py | 20 +++++++ .../jiter/precision_and_duplicates/code.py | 56 +++++++++++++++++++ .../precision_and_duplicates/config.toml | 1 + .../jiter/precision_and_duplicates/setup.py | 21 +++++++ 11 files changed, 264 insertions(+) create mode 100644 examples/jiter/README.md create mode 100644 examples/jiter/from_json_basics/code.py create mode 100644 examples/jiter/from_json_basics/config.toml create mode 100644 examples/jiter/from_json_basics/setup.py create mode 100644 examples/jiter/order.json create mode 100644 examples/jiter/partial_json_streaming/code.py create mode 100644 examples/jiter/partial_json_streaming/config.toml create mode 100644 examples/jiter/partial_json_streaming/setup.py create mode 100644 examples/jiter/precision_and_duplicates/code.py create mode 100644 examples/jiter/precision_and_duplicates/config.toml create mode 100644 examples/jiter/precision_and_duplicates/setup.py diff --git a/examples/jiter/README.md b/examples/jiter/README.md new file mode 100644 index 0000000..16eeab7 --- /dev/null +++ b/examples/jiter/README.md @@ -0,0 +1,18 @@ +# jiter Examples + +Each sub-directory contains a self-contained example. The order in +which the examples are to appear is specified in `order.json` (an +array of directory names in the expected order). + +In each example directory you'll find: + +* `config.toml` - must conform to the specification outlined here: + https://docs.pyscript.net/latest/user-guide/configuration/ This is + parsed and ultimately turned into a JSON representation as part of + the package's API object. +* `setup.py` - Python code for contextual and environmental setup, + NOT SEEN BY THE END USER, but is run before the `code.py` code is + evaluated. Allows us to create useful (IPython) shims, avoid + repeating boilerplate and whatnot. +* `code.py` - the actual code added to the editor which forms the + practical example of using the package. diff --git a/examples/jiter/from_json_basics/code.py b/examples/jiter/from_json_basics/code.py new file mode 100644 index 0000000..ba7e14b --- /dev/null +++ b/examples/jiter/from_json_basics/code.py @@ -0,0 +1,51 @@ +""" +A first look at jiter, a fast JSON parser from the Pydantic team. + +The whole API is essentially one function: `jiter.from_json`. It takes +a `bytes` object (not a `str`) and returns native Python values, just +like the standard library's `json.loads`. See the project page for +details: https://github.com/pydantic/jiter +""" +from IPython.core.display import display, HTML + +# jiter.from_json expects bytes -- note the leading `b`. +weather_report = b""" +{ + "station": "Kew Gardens", + "recorded_at": "2026-04-12T09:00:00Z", + "temperature_c": 14.2, + "humidity_pct": 71, + "observers": ["Ada", "Grace", "Lin"], + "is_raining": false +} +""" + +heading("1. Parse JSON bytes into a Python dict") +note( + "jiter returns ordinary Python values: dicts, lists, strings, " + "numbers, booleans, and None. Below, we parse a small weather " + "report and pull values out by key." +) + +report = jiter.from_json(weather_report) + +display(report, append=True) +note( + f"Station: {report['station']}. " + f"Temperature: {report['temperature_c']} °C. " + f"Observers: {', '.join(report['observers'])}." +) + +heading("2. The string cache") +note( + "By default, jiter caches parsed strings to speed up repeated " + "keys and values. You can inspect and reset that cache." +) + +# Parse a few records that share keys, so the cache gets a workout. +for _ in range(5): + jiter.from_json(weather_report) + +note(f"String cache size after parsing: {jiter.cache_usage()} bytes.") +jiter.cache_clear() +note(f"After cache_clear(): {jiter.cache_usage()} bytes.") diff --git a/examples/jiter/from_json_basics/config.toml b/examples/jiter/from_json_basics/config.toml new file mode 100644 index 0000000..9fecf48 --- /dev/null +++ b/examples/jiter/from_json_basics/config.toml @@ -0,0 +1 @@ +packages = ["jiter"] diff --git a/examples/jiter/from_json_basics/setup.py b/examples/jiter/from_json_basics/setup.py new file mode 100644 index 0000000..081d020 --- /dev/null +++ b/examples/jiter/from_json_basics/setup.py @@ -0,0 +1,44 @@ +""" +Shim IPython's display API onto PyScript so example code written in a +Jupyter/IPython idiom runs unmodified in the browser. +""" + +import sys +import types +import js +from pyscript import window, HTML, display as _display + +js.alert = window.alert + + +def display(*args, **kwargs): + """Wrap pyscript.display so output lands in the example target.""" + return _display( + *args, **kwargs, target=__pyscript_display_target__, + ) + + +ipython = types.ModuleType("IPython") +core = types.ModuleType("IPython.core") +core_display = types.ModuleType("IPython.core.display") +core_display.display = display +core_display.HTML = HTML +ipython.core = core +core.display = core_display +ipython.get_ipython = lambda: None +ipython.display = core_display +sys.modules["IPython"] = ipython +sys.modules["IPython.core"] = core +sys.modules["IPython.core.display"] = core_display +sys.modules["IPython.display"] = core_display + + +def heading(text, level=2): + display(HTML(f"{text}"), append=True) + + +def note(text): + display(HTML(f"

{text}

"), append=True) + + +import jiter diff --git a/examples/jiter/order.json b/examples/jiter/order.json new file mode 100644 index 0000000..f2acbe0 --- /dev/null +++ b/examples/jiter/order.json @@ -0,0 +1,5 @@ +[ + "from_json_basics", + "partial_json_streaming", + "precision_and_duplicates" +] diff --git a/examples/jiter/partial_json_streaming/code.py b/examples/jiter/partial_json_streaming/code.py new file mode 100644 index 0000000..8bd0859 --- /dev/null +++ b/examples/jiter/partial_json_streaming/code.py @@ -0,0 +1,46 @@ +# --------------------------------------------------------------------- +# Partial JSON: parsing a stream that hasn't finished arriving. +# --------------------------------------------------------------------- + +heading("Parsing partial JSON as it streams in") +note( + "When you're reading JSON from a network response (think: an LLM " + "token stream), you often want to render what you have so far. " + "jiter's partial_mode handles a truncated payload " + "without raising." +) + +# Imagine these are progressively longer prefixes of a single response +# arriving over the wire, one chunk at a time. +full_response = ( + b'{"model": "demo-1", "choices": [' + b'{"role": "assistant", "content": "Hello, traveller! Welcome to jiter."}' + b']}' +) +checkpoints = [full_response[:n] for n in (20, 55, 95, len(full_response))] + +heading("Default: incomplete input is an error", level=3) +try: + jiter.from_json(checkpoints[1]) +except ValueError as exc: + note(f"Got ValueError: {exc}") + +heading("partial_mode=True: drop the trailing incomplete value", level=3) +note( + "Useful when you want a clean, fully-formed object so far. The " + "still-arriving last field is silently omitted." +) +for i, chunk in enumerate(checkpoints, start=1): + parsed = jiter.from_json(chunk, partial_mode=True) + display(HTML(f"After chunk {i} ({len(chunk)} bytes):"), append=True) + display(parsed, append=True) + +heading('partial_mode="trailing-strings": keep the in-flight string', level=3) +note( + "Perfect for showing a token-by-token assistant reply: the " + "partially-received string is included as-is." +) +for i, chunk in enumerate(checkpoints, start=1): + parsed = jiter.from_json(chunk, partial_mode="trailing-strings") + display(HTML(f"After chunk {i}:"), append=True) + display(parsed, append=True) diff --git a/examples/jiter/partial_json_streaming/config.toml b/examples/jiter/partial_json_streaming/config.toml new file mode 100644 index 0000000..9fecf48 --- /dev/null +++ b/examples/jiter/partial_json_streaming/config.toml @@ -0,0 +1 @@ +packages = ["jiter"] diff --git a/examples/jiter/partial_json_streaming/setup.py b/examples/jiter/partial_json_streaming/setup.py new file mode 100644 index 0000000..cedc558 --- /dev/null +++ b/examples/jiter/partial_json_streaming/setup.py @@ -0,0 +1,20 @@ +"""Lighter setup for the second example: same names, no IPython shim.""" +import js +from pyscript import window, HTML, display as _display + +js.alert = window.alert + + +def display(*args, **kwargs): + return _display(*args, **kwargs, target=__pyscript_display_target__) + + +def heading(text, level=2): + display(HTML(f"{text}"), append=True) + + +def note(text): + display(HTML(f"

{text}

"), append=True) + + +import jiter diff --git a/examples/jiter/precision_and_duplicates/code.py b/examples/jiter/precision_and_duplicates/code.py new file mode 100644 index 0000000..a1810e5 --- /dev/null +++ b/examples/jiter/precision_and_duplicates/code.py @@ -0,0 +1,56 @@ +# --------------------------------------------------------------------- +# Numeric precision and strict-mode options. +# --------------------------------------------------------------------- + +heading("Decimals and duplicate-key detection") +note( + "When JSON carries money or scientific values, the default " + "float conversion can lose precision. jiter lets " + "you opt into Decimal output. Separately, " + "catch_duplicate_keys turns a silent overwrite " + "into a loud error." +) + +# A ledger entry whose amount has more digits than a 64-bit float +# can faithfully store. +ledger_entry = b'{"account": "ACME-001", "amount": 1234567890.1234567890}' + +heading("Default: amount comes back as a float", level=3) +default_parse = jiter.from_json(ledger_entry) +display(default_parse, append=True) +note( + f"Type: {type(default_parse['amount']).__name__}. " + f"Notice the trailing digits have been rounded." +) + +heading('float_mode="decimal": exact decimal arithmetic', level=3) +decimal_parse = jiter.from_json(ledger_entry, float_mode="decimal") +display(decimal_parse, append=True) +note( + f"Type: {type(decimal_parse['amount']).__name__}. " + f"Now we can sum many of these without drift." +) + +# Add up 1000 copies to show Decimal stays exact. +total = sum( + jiter.from_json(ledger_entry, float_mode="decimal")["amount"] + for _ in range(1000) +) +note(f"Sum of 1000 entries (Decimal): {total}") + +heading("Catching duplicate keys", level=3) +note( + "By default, JSON parsers silently let later keys win. That can " + "hide bugs in upstream data. Pass catch_duplicate_keys=True " + "to fail fast instead." +) + +suspect_payload = b'{"user_id": 1, "user_id": 2, "name": "Robin"}' + +permissive = jiter.from_json(suspect_payload) +note(f"Permissive parse (last value wins): {permissive}") + +try: + jiter.from_json(suspect_payload, catch_duplicate_keys=True) +except ValueError as exc: + note(f"Strict parse raised ValueError: {exc}") diff --git a/examples/jiter/precision_and_duplicates/config.toml b/examples/jiter/precision_and_duplicates/config.toml new file mode 100644 index 0000000..9fecf48 --- /dev/null +++ b/examples/jiter/precision_and_duplicates/config.toml @@ -0,0 +1 @@ +packages = ["jiter"] diff --git a/examples/jiter/precision_and_duplicates/setup.py b/examples/jiter/precision_and_duplicates/setup.py new file mode 100644 index 0000000..d05a280 --- /dev/null +++ b/examples/jiter/precision_and_duplicates/setup.py @@ -0,0 +1,21 @@ +"""Lighter setup: same names, no IPython shim.""" +import js +from pyscript import window, HTML, display as _display + +js.alert = window.alert + + +def display(*args, **kwargs): + return _display(*args, **kwargs, target=__pyscript_display_target__) + + +def heading(text, level=2): + display(HTML(f"{text}"), append=True) + + +def note(text): + display(HTML(f"

{text}

"), append=True) + + +import jiter +from decimal import Decimal From a27b84e9060b1e33ce2b2dcf141632812eec0cb3 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 4 Jun 2026 15:24:43 +0100 Subject: [PATCH 2/2] Fix imports. --- examples/jiter/from_json_basics/code.py | 3 +++ examples/jiter/from_json_basics/setup.py | 3 --- examples/jiter/precision_and_duplicates/code.py | 3 +++ examples/jiter/precision_and_duplicates/setup.py | 3 --- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/jiter/from_json_basics/code.py b/examples/jiter/from_json_basics/code.py index ba7e14b..1c051b5 100644 --- a/examples/jiter/from_json_basics/code.py +++ b/examples/jiter/from_json_basics/code.py @@ -8,6 +8,9 @@ """ from IPython.core.display import display, HTML +import jiter + + # jiter.from_json expects bytes -- note the leading `b`. weather_report = b""" { diff --git a/examples/jiter/from_json_basics/setup.py b/examples/jiter/from_json_basics/setup.py index 081d020..b4f3ee1 100644 --- a/examples/jiter/from_json_basics/setup.py +++ b/examples/jiter/from_json_basics/setup.py @@ -39,6 +39,3 @@ def heading(text, level=2): def note(text): display(HTML(f"

{text}

"), append=True) - - -import jiter diff --git a/examples/jiter/precision_and_duplicates/code.py b/examples/jiter/precision_and_duplicates/code.py index a1810e5..9e08eb4 100644 --- a/examples/jiter/precision_and_duplicates/code.py +++ b/examples/jiter/precision_and_duplicates/code.py @@ -1,6 +1,9 @@ # --------------------------------------------------------------------- # Numeric precision and strict-mode options. # --------------------------------------------------------------------- +import jiter +from decimal import Decimal + heading("Decimals and duplicate-key detection") note( diff --git a/examples/jiter/precision_and_duplicates/setup.py b/examples/jiter/precision_and_duplicates/setup.py index d05a280..0bf3fc9 100644 --- a/examples/jiter/precision_and_duplicates/setup.py +++ b/examples/jiter/precision_and_duplicates/setup.py @@ -16,6 +16,3 @@ def heading(text, level=2): def note(text): display(HTML(f"

{text}

"), append=True) - -import jiter -from decimal import Decimal