Skip to main content
Edify — simple regular expressions

Edify builds regular expressions you can actually read. It’s a fluent, immutable regex builder for Python: you describe a pattern step by step in plain English, and Edify hands you a compiled regex — one your teammates can review in a pull request instead of squinting at.

Why Edify

A regular expression is easy to write and hard to read. Six months later nobody remembers what ^(?:0x)?([0-9a-fA-F]{4})$ was meant to accept, and the person reviewing the change that touches it has no way to be sure either. The syntax gives you nowhere to put a name, a comment, or a seam.

Edify moves the pattern into ordinary Python, where all three fit:

  • Methods say what they do. .one_or_more().digit() needs no decoding.

  • The quantity comes before the thing it counts, the way you say it aloud — .exactly(4).digit() is exactly four digits.

  • Every call returns a new builder, so a pattern you share can be extended in two directions without either one disturbing the other.

  • A mistake raises an error that points at the call that caused it and names the fix, rather than emitting a regex that is subtly wrong.

A first pattern

from edify import RegexBuilder

# A 16-bit hex literal like "0xC0DE" — with the four hex digits captured.
hex_literal = (
    RegexBuilder()
    .start_of_input()
    .optional().string("0x")
    .capture()
        .exactly(4).any_of().range("0", "9").range("a", "f").range("A", "F").end()
    .end()
    .end_of_input()
)

hex_literal.to_regex_string()   # '^(?:0x)?([0-9a-fA-F]{4})$'
hex_literal.test("0xC0DE")      # True
hex_literal.test("0xZZZZ")      # False

Read the chain top to bottom and it tells you what it accepts.

Patterns you don’t have to write

Edify ships 228 ready-made validators. Each is a callable pattern, so checking a value is a function call:

from edify.library import email, ipv4, semver

email("a@b.com")      # True
semver("1.4.0")       # True
ipv4("10.0.0.1")      # True
ipv4("999.1.1.1")     # False — the octet range is enforced

They are assembled from 83 named fragments you can build with too, so a pattern of your own inherits the same range checks rather than approximating them:

from edify import Pattern, atoms

endpoint = (
    Pattern().start_of_input()
    .named_capture("host").use(atoms.ipv4).end()
    .char(":")
    .named_capture("port").use(atoms.port).end()
    .end_of_input()
)

endpoint.to_regex().match("10.0.0.1:8080").groupdict()
# {'host': '10.0.0.1', 'port': '8080'}
endpoint("10.0.0.1:99999")   # False — 99999 is not a port

Ask a pattern what it means

Because Edify keeps the structure rather than a string, it can describe a pattern back to you — in prose, as a diagram, or as an annotated verbose regex:

from edify import RegexBuilder

year = RegexBuilder().start_of_input().exactly(4).digit().end_of_input()
print(year.to_regex().explain())

# - The text must start with exactly 4 digits (0-9).
#
# Text this pattern accepts:
#     1234

That same structure is what lets Edify warn you at build time about a pattern shaped for catastrophic backtracking, and round-trip a pattern through JSON.

Install

Edify requires Python 3.11+:

pip install edify

Optional extras add the alternate regex engine and the framework integrations: edify[regex], edify[pydantic], edify[fastapi], edify[django], or edify[all].

Also in the box

  • Introspection — a plain-English explanation, an ASCII or rendered diagram, or an annotated re.VERBOSE form of any pattern.

  • Serialization — round-trip a pattern through a dict or JSON and keep a first-class pattern on the other side, not a flattened string.

  • Integrations — pydantic, FastAPI, and Django validators from a pattern.

  • Testing helpers — assert a pattern’s contract beside its definition, and snapshot what it emits.

  • Reverse parsing — turn an existing regex string back into a chain and read what it does.

Documentation

edify.readthedocs.io has the guide, a page for every validator, and the full API reference. Examples throughout the site are live — edit the chain and the emitted regex and match results update as you type, with Edify running in your browser.

License and contributing

Edify is released under the MIT License. Contributions are welcome — see CONTRIBUTING.rst to get set up.

Download files

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

Source Distribution

edify-1.0.0.tar.gz (524.5 kB view details)

Uploaded Source

Built Distribution

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

edify-1.0.0-py3-none-any.whl (271.2 kB view details)

Uploaded Python 3

File details

Details for the file edify-1.0.0.tar.gz.

File metadata

  • Download URL: edify-1.0.0.tar.gz
  • Upload date:
  • Size: 524.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for edify-1.0.0.tar.gz
Algorithm Hash digest
SHA256 79db6dd0734c444ee543d01340ad7b983dfe2cc1df5d7d05e34687c9c5d77fba
MD5 d1c7b67a6712d5bdecd41f9e20b56d2d
BLAKE2b-256 8ef3d16f33fd3350036246be9c6a9bb0a75562b8adff58186681037732d3d498

See more details on using hashes here.

Provenance

The following attestation bundles were made for edify-1.0.0.tar.gz:

Publisher: python-publish.yml on luciferreeves/edify

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file edify-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: edify-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 271.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for edify-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9a6c1118f8ebd7ebfd087a1b2b1d078cdf77e55a4fc0137f6096ca8b972559b
MD5 66c44a2d0330d92b10f02af336223348
BLAKE2b-256 3d64b495e85cc96ac9a386db00275124b97035dbbff062a5b4eefc8ff368f323

See more details on using hashes here.

Provenance

The following attestation bundles were made for edify-1.0.0-py3-none-any.whl:

Publisher: python-publish.yml on luciferreeves/edify

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.1.1

2 files

1.1.0

2 files

This release

1.0.0 This release

2 files

0.3.0

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page