Pydantic Compiler

Write Pydantic models and run them. Real Pydantic v2 on real CPython, in your browser - no install, no account, nothing sent to a server.

← VizLearn
models.py Pydantic v2
Output

                

What this is

Pydantic v2 — the real library, not a reimplementation — running on CPython compiled to WebAssembly, on your own machine. Your code is never uploaded.

The first Run takes a few seconds: it downloads the interpreter and then Pydantic. Every run after that is immediate, and the library stays loaded for the rest of your visit.

What works

  • BaseModel, Field, and the whole constraint set — ge, le, min_length, pattern.
  • field_validator and model_validator, in both before and after mode.
  • Nested models, List, Dict, Optional, Union, Literal and discriminated unions.
  • model_dump, model_dump_json, model_validate and model_validate_json.
  • ValidationError in full — every error, with its location, type and input value.

What does not

  • input() — there is no stdin to read from.
  • Network calls, so no fetching a schema or a payload from a URL.
  • Packages beyond the standard library and Pydantic itself. pydantic-settings and email-validator are separate distributions and are not loaded here.
  • Reading or writing files on your computer. There is an in-memory filesystem, so open works, but the files vanish with the run.

How it runs

This is not a validator written in JavaScript to look like Pydantic. It is Pydantic 2.7 on CPython 3.12, both compiled to WebAssembly by the Pyodide project, including pydantic-core — the Rust engine that does the actual validating. Behaviour matches a normal install because it is one.

It runs in a worker thread, separate from the page, so an accidental infinite loop freezes the output rather than the tab. A run that has not finished within ten seconds is stopped and reported.

Reading a ValidationError

Pydantic does not stop at the first problem. It checks every field and raises once, so the report you get back is the complete list — which is why the count on the first line is often greater than one.

Each entry has three parts worth reading separately. The location is a path, not a name: address.pin means the failure is one level down, and tags.0 means the first element of a list. The type is a stable machine code such as greater_than_equal or string_too_short, and it is what you match on if you are turning errors into an API response. The input value is what was actually received, which is usually the fastest way to see that a caller sent a string where a number was meant.

e.errors() gives you all of that as a list of dictionaries rather than as text.

Coercion is the thing to test

Most surprises with Pydantic are about what it will quietly convert. In the default lax mode the string "36" becomes the integer 36, but "thirty-six" raises. A float 36.0 becomes 36; 36.5 does not.

This is exactly the sort of thing that is faster to settle by running it than by reading about it. Change a value in the starter, press Run, and see which way it goes. If you want the strict answer instead, try model_config = ConfigDict(strict=True) on the model and run the same inputs again.

Things worth trying

  • Feed a model a JSON string with User.model_validate_json(...) and see the same validation apply.
  • Add model_config = ConfigDict(extra="forbid") and pass a key the model does not declare.
  • Print User.model_json_schema() — the JSON Schema that FastAPI turns into your API documentation.
  • Write a model_validator(mode="after") that compares two fields, which a per-field validator cannot do.
  • Break something deliberately and read the error. Recognising the error types is most of using this library.

Want plain Python?

The Python compiler is the same editor without the library, and the Python track teaches the language one idea at a time — starting at your first print statement.