Skip to main content

Program Enhanced Text — documentation automation tool

Project description

🐾 PET — Program Enhanced Text

Write docs once. Automate the rest. Never copy-paste again.

Python License Version


PET turns your documentation into a living document. Instead of manually copying version numbers, pasting code samples, and updating chapter headings by hand, you write a .md.pet template and let PET generate the final Markdown. When your source changes, regenerate — done.

pet  README.md.pet  README.md

Not just Markdown. PET works with any text-based format — AsciiDoc, reStructuredText, LaTeX, HTML, plain text, or anything else. The template extension and output format are entirely up to you. Markdown is the most common use case, which is why the examples here use it.


1 The Idea in 30 Seconds

A .md.pet file is regular Markdown with Python code blocks between {% and %}. PET executes the blocks and splices their output into the document.

Template (docs.md.pet):

{%
use('number')
use('snippet')
n = number(fmt="{:3d}  ")
src = snippet("src")
%}

The core loop:

{% doc | n(src('main_loop')) %}

Output (docs.md):

The core loop:

  1  for item in queue:
  2      process(item)
  3      log(item)

PET replaces every {% ... %} block with whatever that Python code prints. Everything else passes through untouched.


2 Installation

pip install pet-doc

Initialise a project (copies the macro library into .pet/):

cd my-project
pet init                  # first-time setup
pet init                  # safe to re-run — regenerates if macros unchanged, skips if you've edited them
pet init -f               # force regeneration regardless of local edits
pet init for_claude       # also installs the pet skill into Claude Code (.claude/)

Process a template once, or watch it for changes:

pet  my-doc.md.pet  my-doc.md          # one-shot
pet watch my-doc.md.pet my-doc.md      # live reload on every save

3 Built-in Macro Library

Text & Structure

Macro What it does
chapter(header_prefix="#", sep=" ") Hierarchical section counter — # 1, ## 1.1, ### 1.1.1
number(start=1, step=1, fmt="{} ") Prefix each line of a text block with a sequential number
include(filename) Read any file and return its content as a string
snippet(directory) Scan source files for named snippet / end snippet markers
dedent(text) Strip common leading indentation from included code

Data Readers

All data macros expose get("dot.separated.path") for deep value access. Lists support integer indices: get("dependencies.0.name").

Macro Format
toml(file) TOML — great for pyproject.toml, config files
yaml(file) YAML — nested keys, lists, indexed access
json(file) JSON — identical API to yaml
xml(file) XML — xpath queries, attribute access via attr()
properties(file) Java .properties — flat key=value, dotted keys preserved
env(file) .env files — strips surrounding quotes, skips comments

Pipelines

pipe is an identity transformer. Compose steps with |:

use('pipe')
use('dedent')
use('number')

n      = number(fmt="{:3d}  ")
clean  = pipe | dedent | n   # dedent first, then add line numbers

doc | clean(include("src/core.py"))

Apply a transformation line by line with .on_lines():

shout = pipe | str.upper
doc | shout.on_lines()(include("words.txt"))

4 Worked Example — This README

This very document is generated by PET 1.0.2. The version badge above is not hardcoded — it is read live from pyproject.toml:

 1 | use('data/toml')
 2 | proj = toml("pyproject.toml")
 3 | VERSION = proj.get('project.version')

The section headings are auto-numbered by chapter:

 4 | ch = chapter()
 5 | # becomes  ->  # 1 The Idea in 30 Seconds
 6 | # becomes  ->  # 2 Installation
 7 | # etc.

Change the order, add a section, remove one — the numbers update on the next pet README.md.pet README.md.


5 Why PET?

Documentation rots. Code evolves, but the docs that reference it often don't. Copy-pasted version numbers fall behind. Pasted code samples go stale. Chapter numbers break the moment you reorder sections.

PET's answer is deliberately small:

  • No new language — your macros are plain Python classes
  • No build framework — one command, one output file
  • No lock-in — the output is standard Markdown; stop using PET any time
  • Self-documenting — the template is the documentation intent

If information already exists somewhere in your project, humans shouldn't maintain a second copy of it. PET makes the automated copy the only copy.

For the full theory — single-source-of-truth, consistency checks as document unit tests, and why correct docs matter more than ever in the age of LLM RAG — see RATIONALE.md.

To learn how to write your own macros, with every built-in macro explained pattern by pattern, see MACROGUIDE.md.


Generated from README.md.pet by PET 1.0.2 · pet README.md.pet README.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pet_doc-1.0.2.tar.gz (63.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pet_doc-1.0.2-py3-none-any.whl (31.1 kB view details)

Uploaded Python 3

File details

Details for the file pet_doc-1.0.2.tar.gz.

File metadata

  • Download URL: pet_doc-1.0.2.tar.gz
  • Upload date:
  • Size: 63.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pet_doc-1.0.2.tar.gz
Algorithm Hash digest
SHA256 dff41973db5a51d5daa3d6caba3259237765942b6c7766d6ea5da096a25b3d8f
MD5 6d5b96b8757395c717c2f9d30700da58
BLAKE2b-256 243c1850022816ae4340b1edfa51d3f766b25a5a007886e2d990ec0fd1d75431

See more details on using hashes here.

File details

Details for the file pet_doc-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: pet_doc-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 31.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for pet_doc-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a1a5869a846546e3c3ffbb3f73655a547f9e5ec0034acd3c651fa785ea2908eb
MD5 f6957c1abc365a84cbd05ccdc6450a65
BLAKE2b-256 d0785e195cdbc774b087a05b31a14c375de25a958ec2384b2049da9d0e3271b3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page