Progressive Formalization for Markdown using Pydantic and Pytest
Project description
Typedown: Progressive Formalization for Markdown
Typedown is a new document format, toolchain, and product experience designed to bridge the gap between free-form Markdown and strict data schemas. It integrates Markdown, Pydantic, Pytest, and Assets into a cohesive package, reducing the cognitive friction in the process of "Progressive Formalization."
The Vision
You don't know it until you model it. — Read the full Typedown Manifesto
In software engineering and complex system design, knowledge often evolves from vague concepts to strict specifications. Current tools force a binary choice: unstructured text (Markdown/Google Docs) or rigid structures (Database/JSON/Code).
Typedown allows you to treat Markdown as the primary interface while gradually imposing constraints via Python's ecosystem:
- Markdown is the host language.
- Pydantic defines the structure (Schema) and local validation.
- Pytest defines global constraints and relationship verification.
Core Concepts
1. The Trinity: Markdown + Pydantic + Pytest
- Markdown: The human-readable layer.
- Pydantic: The schema layer. Defines classes and field-level validation.
- Pytest: The logic layer. Defines constraints that require access to the global variable table (e.g., "Referenced ID must exist").
2. Configuration & Inheritance
- Front Matter: Used for file metadata (e.g., title, author, status).
- Scoped Configuration: Each directory can contain a
config.td. Code blocks tagged withconfig:pythoninconfig.tdare executed to build context (e.g. importing models) and are inherited by subdirectories. - Override Rule: Deepest (most specific) definition wins.
3. Entities & Data Blocks
Variables are expressed using code blocks with a specific language identifier: entity:<class_name>.
# User Definition
Here we define the admin user.
```model
class User(BaseModel):
id: str
name: str
role: str
```
```entity:User
id: "u_001"
name: "Alice"
role: "admin"
```
4. Evolution & Derivation (The "Desugar" Process)
Typedown supports minimal writing for evolving data.
former: Represents the same entity (conceptually) at a different point in time or state.derived_from: Represents a variant of a base object.
Input (Syntactic Sugar):
# Version 2
```entity:User
former: "u_001" # References the previous object
email: "alice@example.com" # Only new/changed fields needed
```
Output (Desugared/Materialized): The compiler merges the previous state with the new fields to create a complete object for validation.
5. Compilation & Materialization
The CLI supports a "compile" operation that can:
- Validate: Check all Pydantic models and Pytest constraints.
- Materialize: Rewrite documents to fill in missing fields from
formerorderived_fromsources, optimizing the reading experience for consumers while keeping the writing experience minimal.
6. Directory Structure
A standard Typedown project looks like this:
.
├── docs/ # The content. Markdown files (.md / .td)
│ ├── arch/
│ │ ├── config.td # Scoped config for this dir
│ │ └── design.md
│ └── ...
├── models/ # The Schema. Python Pydantic classes
│ └── user.py
├── specs/ # The Constraints. Pytest files
│ └── test_consistency.py
└── assets/ # Images, diagrams, static files
Documentation
For more detailed information, please refer to the following directories:
- Specs: Formal language specifications, RFCs, and data models.
- Docs: User guides and feature documentation.
- Dev Docs: Architecture decisions (ADRs) and implementation details.
Architecture & Toolchain
The ecosystem consists of several decoupled components:
1. Typedown Compiler (tdc)
The core library responsible for processing the project.
- Analyze: Parse Markdown AST, resolve imports, build the symbol table, and handle
config.tdinheritance. - Desugar: Resolve
former(temporal) andderived_from(inheritance) links, flattening the data into pure Pydantic instances. - Lint: Static analysis for broken links, unused imports, and style conventions.
- Validate: Execute Pydantic validators and invoke Pytest runner on the extracted dataset.
2. Typedown CLI (td)
The user interface for the terminal.
td init: Scaffold a new project.td build: Compile docs to static HTML/PDF (optional integration).td check: Run the full Validate pipeline.td materialize: Update source files to expand "sugared" blocks.
3. Typedown LSP (Language Server)
Provides the IDE experience (VS Code extension).
- Autocompletion: For
entity:Classfields based on Pydantic definitions. - Go to Definition: Jump from a usage in Markdown to the Python class definition.
- Real-time Diagnostics: Show validation errors (red squiggles) directly in the Markdown editor.
Installation & Usage
Typedown is built with Python. We recommend using uv for lightning-fast environment management.
Method 1: Run directly with uvx
You can run the Typedown CLI directly without manual installation using uvx (part of the uv toolchain). This is great for trying it out or running one-off commands.
# Run in any directory
uvx typedown check
Method 2: Development Setup
If you want to contribute or use it in a local project:
-
Install
uv:curl -LsSf https://astral.sh/uv/install.sh | sh
-
Initialize Virtual Environment & Install:
# In the project root uv sync
-
Run the CLI:
uv run td --help
License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file typedown-0.1.0.tar.gz.
File metadata
- Download URL: typedown-0.1.0.tar.gz
- Upload date:
- Size: 200.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
286d85c0a2e5e5fd9b8eba6fc87b2b9a2129e2c3417fcff6c02275d62ad59b06
|
|
| MD5 |
4ce774fc2a97fca8f6dcbefc5f01a5cf
|
|
| BLAKE2b-256 |
e086ea65f4fa1da86a642b7ca73edefab9bb48fe37f506dd26ec9658a021ff34
|
Provenance
The following attestation bundles were made for typedown-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on IndenScale/Typedown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
typedown-0.1.0.tar.gz -
Subject digest:
286d85c0a2e5e5fd9b8eba6fc87b2b9a2129e2c3417fcff6c02275d62ad59b06 - Sigstore transparency entry: 774049455
- Sigstore integration time:
-
Permalink:
IndenScale/Typedown@9b7dfec7d8a7ef6b4b285572c0edd7bfb06c5989 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/IndenScale
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@9b7dfec7d8a7ef6b4b285572c0edd7bfb06c5989 -
Trigger Event:
push
-
Statement type:
File details
Details for the file typedown-0.1.0-py3-none-any.whl.
File metadata
- Download URL: typedown-0.1.0-py3-none-any.whl
- Upload date:
- Size: 49.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2dd20636fab29f4d22a8612157cc15eb1f70e35b91dec70cbb5cf0e126bd2c3
|
|
| MD5 |
6fb7008a00aef0c330ae9a9dd81e34ca
|
|
| BLAKE2b-256 |
f55dfb88291d94223d1775a35067d2c9aa022fde4168adba702225c59d87f693
|
Provenance
The following attestation bundles were made for typedown-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on IndenScale/Typedown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
typedown-0.1.0-py3-none-any.whl -
Subject digest:
f2dd20636fab29f4d22a8612157cc15eb1f70e35b91dec70cbb5cf0e126bd2c3 - Sigstore transparency entry: 774049456
- Sigstore integration time:
-
Permalink:
IndenScale/Typedown@9b7dfec7d8a7ef6b4b285572c0edd7bfb06c5989 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/IndenScale
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@9b7dfec7d8a7ef6b4b285572c0edd7bfb06c5989 -
Trigger Event:
push
-
Statement type: