diff options
| author | natsuoto <[email protected]> | 2026-07-11 17:38:52 +0530 |
|---|---|---|
| committer | natsuoto <[email protected]> | 2026-07-11 17:38:52 +0530 |
| commit | c7a8a902eb86dfec5dd5c4ec77c532f5b920d3ac (patch) | |
| tree | 9eaff3968954dc8f5bf079684dba46b6026e2221 | |
| parent | c7e0fcfbccc3021415a7c5ac170598a7dc6ee7f6 (diff) | |
| download | edify-c7a8a902eb86dfec5dd5c4ec77c532f5b920d3ac.tar.xz edify-c7a8a902eb86dfec5dd5c4ec77c532f5b920d3ac.zip | |
feat(library): add 23 patterns across 12 categories (medical, transport, financial, geo, security, numeric, web, grammar, document, data, contact, software)
36 files changed, 601 insertions, 10 deletions
diff --git a/edify/library/__init__.py b/edify/library/__init__.py index a115b55..460702b 100644 --- a/edify/library/__init__.py +++ b/edify/library/__init__.py @@ -62,6 +62,7 @@ from edify.library.contact import ( address, email, fax, + handle, pager, phone, username, @@ -74,6 +75,8 @@ from edify.library.data import ( ini, json, msgpack, + orc, + parquet, protobuf, toml, tsv, @@ -88,19 +91,23 @@ from edify.library.document import ( pdf, pptx, readme, + rtf, svg, + tex, xlsx, ) -from edify.library.financial import card, crypto, currency, wallet +from edify.library.financial import card, crypto, currency, routing, sortcode, vat, wallet from edify.library.geo import ( altitude, + bearing, coordinate, geohash, + mgrs, place, plus, postal, ) -from edify.library.grammar import abnf, bnf, ebnf, peg, pest +from edify.library.grammar import abnf, antlr, bnf, ebnf, peg, pest from edify.library.identifier import ( arn, asin, @@ -142,11 +149,12 @@ from edify.library.media import ( regex, shebang, ) -from edify.library.medical import medical +from edify.library.medical import blood, dicom, dosage, medical from edify.library.numeric import ( fraction, hash, integer, + natural, number, ordinal, percentage, @@ -162,12 +170,15 @@ from edify.library.security import ( csr, der, keyring, + nonce, pem, pgp, + signature, ssh, x509, ) from edify.library.software import ( + bump, cargo, checksum, component, @@ -207,16 +218,19 @@ from edify.library.text import ( unicode, word, ) -from edify.library.transport import aircraft, vehicle +from edify.library.transport import aircraft, flight, plate, vehicle from edify.library.web import ( apache, captcha, + cookie, + csp, htaccess, humans, manifest, nginx, robots, sitemap, + useragent, ) __all__ = [ @@ -227,6 +241,7 @@ __all__ = [ "alpha", "alphanumeric", "altitude", + "antlr", "apache", "apikey", "arn", @@ -238,8 +253,11 @@ __all__ = [ "barcode", "base", "bearer", + "bearing", "bic", + "blood", "bnf", + "bump", "captcha", "card", "cargo", @@ -251,9 +269,11 @@ __all__ = [ "codec", "color", "component", + "cookie", "coordinate", "cron", "crypto", + "csp", "csr", "csrf", "csv", @@ -262,12 +282,14 @@ __all__ = [ "date", "datetime", "der", + "dicom", "did", "digest", "docker", "docx", "doi", "domain", + "dosage", "duration", "ebnf", "ein", @@ -281,6 +303,7 @@ __all__ = [ "fax", "filename", "filter", + "flight", "fraction", "geohash", "git", @@ -290,6 +313,7 @@ __all__ = [ "gtin", "guid", "hal", + "handle", "hash", "hdf5", "hmac", @@ -324,13 +348,16 @@ __all__ = [ "medical", "meid", "mfa", + "mgrs", "mimetype", "mmsi", "mnemonic", "mobi", "mpn", "msgpack", + "natural", "nginx", + "nonce", "number", "numeric", "oauth", @@ -338,12 +365,14 @@ __all__ = [ "offset", "openapi", "openid", + "orc", "orcid", "ordinal", "otp", "package", "pager", "palette", + "parquet", "passkey", "password", "path", @@ -356,6 +385,7 @@ __all__ = [ "phone", "pin", "place", + "plate", "plus", "pmc", "pmid", @@ -372,7 +402,9 @@ __all__ = [ "regex", "robots", "roman", + "routing", "rss", + "rtf", "saml", "scientific", "script", @@ -381,12 +413,14 @@ __all__ = [ "semver", "session", "shebang", + "signature", "signing", "sitemap", "sku", "slug", "soap", "socket", + "sortcode", "ssh", "ssn", "sso", @@ -395,6 +429,7 @@ __all__ = [ "svg", "swagger", "swatch", + "tex", "time", "timestamp", "timezone", @@ -406,8 +441,10 @@ __all__ = [ "unicode", "uri", "url", + "useragent", "username", "uuid", + "vat", "vehicle", "version", "vin", diff --git a/edify/library/contact/__init__.py b/edify/library/contact/__init__.py index 58f1017..b4393cd 100644 --- a/edify/library/contact/__init__.py +++ b/edify/library/contact/__init__.py @@ -1,8 +1,9 @@ from edify.library.contact.address import address from edify.library.contact.email import email from edify.library.contact.fax import fax +from edify.library.contact.handle import handle from edify.library.contact.pager import pager from edify.library.contact.phone import phone from edify.library.contact.username import username -__all__ = ["address", "email", "fax", "pager", "phone", "username"] +__all__ = ["address", "email", "fax", "handle", "pager", "phone", "username"] diff --git a/edify/library/contact/handle.py b/edify/library/contact/handle.py new file mode 100644 index 0000000..206ec21 --- /dev/null +++ b/edify/library/contact/handle.py @@ -0,0 +1,20 @@ +"""``handle`` — social-media ``@name`` handle shape.""" + +from __future__ import annotations + +from edify import Pattern + +handle = ( + Pattern() + .start_of_input() + .char("@") + .between(1, 30) + .any_of() + .range("a", "z") + .range("A", "Z") + .range("0", "9") + .char("_") + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a social-media ``@handle`` shape.""" diff --git a/edify/library/data/__init__.py b/edify/library/data/__init__.py index cea9539..147f2e2 100644 --- a/edify/library/data/__init__.py +++ b/edify/library/data/__init__.py @@ -5,6 +5,8 @@ from edify.library.data.html import html from edify.library.data.ini import ini from edify.library.data.json import json from edify.library.data.msgpack import msgpack +from edify.library.data.orc import orc +from edify.library.data.parquet import parquet from edify.library.data.protobuf import protobuf from edify.library.data.toml import toml from edify.library.data.tsv import tsv @@ -19,6 +21,8 @@ __all__ = [ "ini", "json", "msgpack", + "orc", + "parquet", "protobuf", "toml", "tsv", diff --git a/edify/library/data/orc.py b/edify/library/data/orc.py new file mode 100644 index 0000000..6c60666 --- /dev/null +++ b/edify/library/data/orc.py @@ -0,0 +1,8 @@ +"""``orc`` — Apache ORC file signature shape.""" + +from __future__ import annotations + +from edify import Pattern + +orc = Pattern().start_of_input().string("ORC").zero_or_more().any_char().end_of_input() +"""Callable :class:`Pattern` for an Apache ORC file (``ORC`` magic prefix).""" diff --git a/edify/library/data/parquet.py b/edify/library/data/parquet.py new file mode 100644 index 0000000..0d51cfb --- /dev/null +++ b/edify/library/data/parquet.py @@ -0,0 +1,8 @@ +"""``parquet`` — Apache Parquet file signature shape.""" + +from __future__ import annotations + +from edify import Pattern + +parquet = Pattern().start_of_input().string("PAR1").zero_or_more().any_char().end_of_input() +"""Callable :class:`Pattern` for an Apache Parquet file (``PAR1`` magic prefix).""" diff --git a/edify/library/document/__init__.py b/edify/library/document/__init__.py index 215845a..4a5142a 100644 --- a/edify/library/document/__init__.py +++ b/edify/library/document/__init__.py @@ -5,7 +5,9 @@ from edify.library.document.odt import odt from edify.library.document.pdf import pdf from edify.library.document.pptx import pptx from edify.library.document.readme import readme +from edify.library.document.rtf import rtf from edify.library.document.svg import svg +from edify.library.document.tex import tex from edify.library.document.xlsx import xlsx __all__ = [ @@ -16,6 +18,8 @@ __all__ = [ "pdf", "pptx", "readme", + "rtf", "svg", + "tex", "xlsx", ] diff --git a/edify/library/document/rtf.py b/edify/library/document/rtf.py new file mode 100644 index 0000000..ebaafdf --- /dev/null +++ b/edify/library/document/rtf.py @@ -0,0 +1,17 @@ +"""``rtf`` — Rich Text Format signature shape.""" + +from __future__ import annotations + +from edify import Pattern + +rtf = ( + Pattern() + .start_of_input() + .string("{\\rtf") + .optional() + .digit() + .zero_or_more() + .any_char() + .end_of_input() +) +"""Callable :class:`Pattern` for an RTF document (``{\\rtfN`` prefix).""" diff --git a/edify/library/document/tex.py b/edify/library/document/tex.py new file mode 100644 index 0000000..add552b --- /dev/null +++ b/edify/library/document/tex.py @@ -0,0 +1,26 @@ +"""``tex`` — LaTeX / TeX source shape.""" + +from __future__ import annotations + +from edify import Pattern + +tex = ( + Pattern() + .start_of_input() + .string("\\documentclass") + .optional() + .group() + .char("[") + .zero_or_more() + .anything_but_chars("]") + .char("]") + .end() + .char("{") + .one_or_more() + .anything_but_chars("}") + .char("}") + .zero_or_more() + .any_char() + .end_of_input() +) +"""Callable :class:`Pattern` for a LaTeX document source (``\\documentclass`` prefix).""" diff --git a/edify/library/financial/__init__.py b/edify/library/financial/__init__.py index 9bf261b..ec3f2e8 100644 --- a/edify/library/financial/__init__.py +++ b/edify/library/financial/__init__.py @@ -1,6 +1,9 @@ from edify.library.financial.card import card from edify.library.financial.crypto import crypto from edify.library.financial.currency import currency +from edify.library.financial.routing import routing +from edify.library.financial.sortcode import sortcode +from edify.library.financial.vat import vat from edify.library.financial.wallet import wallet -__all__ = ["card", "crypto", "currency", "wallet"] +__all__ = ["card", "crypto", "currency", "routing", "sortcode", "vat", "wallet"] diff --git a/edify/library/financial/routing.py b/edify/library/financial/routing.py new file mode 100644 index 0000000..2a11763 --- /dev/null +++ b/edify/library/financial/routing.py @@ -0,0 +1,8 @@ +"""``routing`` — US ABA routing-number shape (9 digits).""" + +from __future__ import annotations + +from edify import Pattern + +routing = Pattern().start_of_input().exactly(9).digit().end_of_input() +"""Callable :class:`Pattern` for a US ABA routing number (9 digits).""" diff --git a/edify/library/financial/sortcode.py b/edify/library/financial/sortcode.py new file mode 100644 index 0000000..269a316 --- /dev/null +++ b/edify/library/financial/sortcode.py @@ -0,0 +1,23 @@ +"""``sortcode`` — UK sort-code shape (``NN-NN-NN`` or 6 digits).""" + +from __future__ import annotations + +from edify import Pattern, any_of + +_dashed = ( + Pattern() + .start_of_input() + .exactly(2) + .digit() + .char("-") + .exactly(2) + .digit() + .char("-") + .exactly(2) + .digit() + .end_of_input() +) +_solid = Pattern().start_of_input().exactly(6).digit().end_of_input() + +sortcode = any_of(_dashed, _solid) +"""Callable :class:`Pattern` for a UK sort code.""" diff --git a/edify/library/financial/vat.py b/edify/library/financial/vat.py new file mode 100644 index 0000000..faa5882 --- /dev/null +++ b/edify/library/financial/vat.py @@ -0,0 +1,8 @@ +"""``vat`` — VAT identification number shape (country prefix + digits).""" + +from __future__ import annotations + +from edify import Pattern + +vat = Pattern().start_of_input().exactly(2).uppercase().between(6, 12).digit().end_of_input() +"""Callable :class:`Pattern` for a VAT identification number.""" diff --git a/edify/library/geo/__init__.py b/edify/library/geo/__init__.py index 624d7b6..1e447bd 100644 --- a/edify/library/geo/__init__.py +++ b/edify/library/geo/__init__.py @@ -1,8 +1,10 @@ from edify.library.geo.altitude import altitude +from edify.library.geo.bearing import bearing from edify.library.geo.coordinate import coordinate from edify.library.geo.geohash import geohash +from edify.library.geo.mgrs import mgrs from edify.library.geo.place import place from edify.library.geo.plus import plus from edify.library.geo.postal import postal -__all__ = ["altitude", "coordinate", "geohash", "place", "plus", "postal"] +__all__ = ["altitude", "bearing", "coordinate", "geohash", "mgrs", "place", "plus", "postal"] diff --git a/edify/library/geo/bearing.py b/edify/library/geo/bearing.py new file mode 100644 index 0000000..deeb88f --- /dev/null +++ b/edify/library/geo/bearing.py @@ -0,0 +1,33 @@ +"""``bearing`` — compass-bearing shape (0-360 degrees).""" + +from __future__ import annotations + +from edify import Pattern + +bearing = ( + Pattern() + .start_of_input() + .any_of() + .subexpression( + Pattern().string("360").optional().group().char(".").one_or_more().char("0").end() + ) + .subexpression( + Pattern() + .any_of() + .subexpression(Pattern().char("3").range("0", "5").digit()) + .subexpression(Pattern().range("1", "2").digit().digit()) + .subexpression(Pattern().between(1, 2).digit()) + .end() + .optional() + .group() + .char(".") + .one_or_more() + .digit() + .end() + ) + .end() + .optional() + .char("°") + .end_of_input() +) +"""Callable :class:`Pattern` for a compass bearing (0-360 degrees).""" diff --git a/edify/library/geo/mgrs.py b/edify/library/geo/mgrs.py new file mode 100644 index 0000000..e14322f --- /dev/null +++ b/edify/library/geo/mgrs.py @@ -0,0 +1,33 @@ +"""``mgrs`` — Military Grid Reference System coordinate shape.""" + +from __future__ import annotations + +from edify import Pattern + +mgrs = ( + Pattern() + .start_of_input() + .between(1, 2) + .digit() + .any_of() + .range("C", "H") + .range("J", "N") + .range("P", "X") + .end() + .exactly(2) + .uppercase() + .any_of() + .exactly(2) + .digit() + .exactly(4) + .digit() + .exactly(6) + .digit() + .exactly(8) + .digit() + .exactly(10) + .digit() + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for an MGRS coordinate.""" diff --git a/edify/library/grammar/__init__.py b/edify/library/grammar/__init__.py index 2b7f067..c31d94b 100644 --- a/edify/library/grammar/__init__.py +++ b/edify/library/grammar/__init__.py @@ -1,7 +1,8 @@ from edify.library.grammar.abnf import abnf +from edify.library.grammar.antlr import antlr from edify.library.grammar.bnf import bnf from edify.library.grammar.ebnf import ebnf from edify.library.grammar.peg import peg from edify.library.grammar.pest import pest -__all__ = ["abnf", "bnf", "ebnf", "peg", "pest"] +__all__ = ["abnf", "antlr", "bnf", "ebnf", "peg", "pest"] diff --git a/edify/library/grammar/antlr.py b/edify/library/grammar/antlr.py new file mode 100644 index 0000000..9eb6523 --- /dev/null +++ b/edify/library/grammar/antlr.py @@ -0,0 +1,26 @@ +"""``antlr`` — ANTLR grammar-source shape.""" + +from __future__ import annotations + +from edify import Pattern + +antlr = ( + Pattern() + .start_of_input() + .string("grammar") + .one_or_more() + .whitespace_char() + .letter() + .zero_or_more() + .any_of() + .range("a", "z") + .range("A", "Z") + .range("0", "9") + .char("_") + .end() + .char(";") + .zero_or_more() + .any_char() + .end_of_input() +) +"""Callable :class:`Pattern` for an ANTLR grammar source (``grammar Name;`` header + rules).""" diff --git a/edify/library/medical/__init__.py b/edify/library/medical/__init__.py index 55f816e..0d1f735 100644 --- a/edify/library/medical/__init__.py +++ b/edify/library/medical/__init__.py @@ -1,3 +1,6 @@ +from edify.library.medical.blood import blood +from edify.library.medical.dicom import dicom +from edify.library.medical.dosage import dosage from edify.library.medical.medical import medical -__all__ = ["medical"] +__all__ = ["blood", "dicom", "dosage", "medical"] diff --git a/edify/library/medical/blood.py b/edify/library/medical/blood.py new file mode 100644 index 0000000..7e05408 --- /dev/null +++ b/edify/library/medical/blood.py @@ -0,0 +1,21 @@ +"""``blood`` — ABO/Rh blood-type shape (``A+``, ``AB-``, ``O+``, etc.).""" + +from __future__ import annotations + +from edify import Pattern + +blood = ( + Pattern() + .start_of_input() + .group() + .any_of() + .string("AB") + .char("A") + .char("B") + .char("O") + .end() + .end() + .any_of_chars("+-") + .end_of_input() +) +"""Callable :class:`Pattern` for an ABO/Rh blood-type shape.""" diff --git a/edify/library/medical/dicom.py b/edify/library/medical/dicom.py new file mode 100644 index 0000000..6d80110 --- /dev/null +++ b/edify/library/medical/dicom.py @@ -0,0 +1,20 @@ +"""``dicom`` — DICOM UID shape (dotted digits).""" + +from __future__ import annotations + +from edify import Pattern + +dicom = ( + Pattern() + .start_of_input() + .one_or_more() + .digit() + .one_or_more() + .group() + .char(".") + .one_or_more() + .digit() + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a DICOM UID: dotted-integer chain.""" diff --git a/edify/library/medical/dosage.py b/edify/library/medical/dosage.py new file mode 100644 index 0000000..23df906 --- /dev/null +++ b/edify/library/medical/dosage.py @@ -0,0 +1,51 @@ +"""``dosage`` — pharmaceutical dosage shape (``10mg``, ``5.5 ml/kg``).""" + +from __future__ import annotations + +from edify import Pattern + + +def _unit() -> Pattern: + return ( + Pattern() + .any_of() + .string("mg") + .char("g") + .string("kg") + .string("ml") + .char("l") + .string("mcg") + .string("iu") + .end() + ) + + +dosage = ( + Pattern() + .start_of_input() + .one_or_more() + .digit() + .optional() + .group() + .char(".") + .one_or_more() + .digit() + .end() + .optional() + .whitespace_char() + .subexpression(_unit()) + .optional() + .group() + .char("/") + .any_of() + .string("kg") + .string("day") + .string("dose") + .end() + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a pharmaceutical dosage shape: +digits with optional decimal + unit (``mg``/``g``/``kg``/``ml``/``l``/``mcg``/``iu``) +and optional per-``kg``/``day``/``dose`` qualifier. +""" diff --git a/edify/library/numeric/__init__.py b/edify/library/numeric/__init__.py index 1a327ba..d2aba35 100644 --- a/edify/library/numeric/__init__.py +++ b/edify/library/numeric/__init__.py @@ -1,6 +1,7 @@ from edify.library.numeric.fraction import fraction from edify.library.numeric.hash import hash from edify.library.numeric.integer import integer +from edify.library.numeric.natural import natural from edify.library.numeric.number import number from edify.library.numeric.ordinal import ordinal from edify.library.numeric.percentage import percentage @@ -12,6 +13,7 @@ __all__ = [ "fraction", "hash", "integer", + "natural", "number", "ordinal", "percentage", diff --git a/edify/library/numeric/natural.py b/edify/library/numeric/natural.py new file mode 100644 index 0000000..72d1253 --- /dev/null +++ b/edify/library/numeric/natural.py @@ -0,0 +1,8 @@ +"""``natural`` — natural-number shape (positive integers, no leading zero).""" + +from __future__ import annotations + +from edify import Pattern + +natural = Pattern().start_of_input().range("1", "9").zero_or_more().digit().end_of_input() +"""Callable :class:`Pattern` for a positive integer with no leading zero.""" diff --git a/edify/library/security/__init__.py b/edify/library/security/__init__.py index f0334f2..8270327 100644 --- a/edify/library/security/__init__.py +++ b/edify/library/security/__init__.py @@ -3,8 +3,10 @@ from edify.library.security.certificate import certificate from edify.library.security.csr import csr from edify.library.security.der import der from edify.library.security.keyring import keyring +from edify.library.security.nonce import nonce from edify.library.security.pem import pem from edify.library.security.pgp import pgp +from edify.library.security.signature import signature from edify.library.security.ssh import ssh from edify.library.security.x509 import x509 @@ -14,8 +16,10 @@ __all__ = [ "csr", "der", "keyring", + "nonce", "pem", "pgp", + "signature", "ssh", "x509", ] diff --git a/edify/library/security/nonce.py b/edify/library/security/nonce.py new file mode 100644 index 0000000..20dbcc0 --- /dev/null +++ b/edify/library/security/nonce.py @@ -0,0 +1,23 @@ +"""``nonce`` — cryptographic nonce shape (base64/hex-safe alphabet).""" + +from __future__ import annotations + +from edify import Pattern + +nonce = ( + Pattern() + .start_of_input() + .between(16, 256) + .any_of() + .range("A", "Z") + .range("a", "z") + .range("0", "9") + .char("+") + .char("/") + .char("=") + .char("_") + .char("-") + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a cryptographic nonce.""" diff --git a/edify/library/security/signature.py b/edify/library/security/signature.py new file mode 100644 index 0000000..1a2003e --- /dev/null +++ b/edify/library/security/signature.py @@ -0,0 +1,23 @@ +"""``signature`` — digital-signature payload shape (base64/hex-safe alphabet).""" + +from __future__ import annotations + +from edify import Pattern + +signature = ( + Pattern() + .start_of_input() + .between(64, 4096) + .any_of() + .range("A", "Z") + .range("a", "z") + .range("0", "9") + .char("+") + .char("/") + .char("=") + .char("_") + .char("-") + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a digital-signature payload.""" diff --git a/edify/library/software/__init__.py b/edify/library/software/__init__.py index aea11f3..b19ef09 100644 --- a/edify/library/software/__init__.py +++ b/edify/library/software/__init__.py @@ -1,3 +1,4 @@ +from edify.library.software.bump import bump from edify.library.software.cargo import cargo from edify.library.software.checksum import checksum from edify.library.software.component import component @@ -12,6 +13,7 @@ from edify.library.software.semver import semver from edify.library.software.version import version __all__ = [ + "bump", "cargo", "checksum", "component", diff --git a/edify/library/software/bump.py b/edify/library/software/bump.py new file mode 100644 index 0000000..c213093 --- /dev/null +++ b/edify/library/software/bump.py @@ -0,0 +1,22 @@ +"""``bump`` — semver bump keyword shape.""" + +from __future__ import annotations + +from edify import Pattern + +bump = ( + Pattern() + .start_of_input() + .any_of() + .string("major") + .string("minor") + .string("patch") + .string("premajor") + .string("preminor") + .string("prepatch") + .string("prerelease") + .string("release") + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a semver bump keyword.""" diff --git a/edify/library/transport/__init__.py b/edify/library/transport/__init__.py index 0cbd39e..b84fdda 100644 --- a/edify/library/transport/__init__.py +++ b/edify/library/transport/__init__.py @@ -1,4 +1,6 @@ from edify.library.transport.aircraft import aircraft +from edify.library.transport.flight import flight +from edify.library.transport.plate import plate from edify.library.transport.vehicle import vehicle -__all__ = ["aircraft", "vehicle"] +__all__ = ["aircraft", "flight", "plate", "vehicle"] diff --git a/edify/library/transport/flight.py b/edify/library/transport/flight.py new file mode 100644 index 0000000..a14494b --- /dev/null +++ b/edify/library/transport/flight.py @@ -0,0 +1,18 @@ +"""``flight`` — flight-number shape (2-letter airline + 1-4 digits, optional suffix).""" + +from __future__ import annotations + +from edify import Pattern + +flight = ( + Pattern() + .start_of_input() + .exactly(2) + .uppercase() + .between(1, 4) + .digit() + .optional() + .uppercase() + .end_of_input() +) +"""Callable :class:`Pattern` for an IATA/ICAO flight-number shape.""" diff --git a/edify/library/transport/plate.py b/edify/library/transport/plate.py new file mode 100644 index 0000000..c97d0b4 --- /dev/null +++ b/edify/library/transport/plate.py @@ -0,0 +1,24 @@ +"""``plate`` — vehicle license-plate shape (permissive alphanumeric).""" + +from __future__ import annotations + +from edify import Pattern + +plate = ( + Pattern() + .start_of_input() + .between(1, 3) + .any_of() + .range("A", "Z") + .range("0", "9") + .end() + .optional() + .any_of_chars("- ") + .between(1, 4) + .any_of() + .range("A", "Z") + .range("0", "9") + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a vehicle license-plate shape.""" diff --git a/edify/library/web/__init__.py b/edify/library/web/__init__.py index 32e29a2..51e7cb9 100644 --- a/edify/library/web/__init__.py +++ b/edify/library/web/__init__.py @@ -1,19 +1,25 @@ from edify.library.web.apache import apache from edify.library.web.captcha import captcha +from edify.library.web.cookie import cookie +from edify.library.web.csp import csp from edify.library.web.htaccess import htaccess from edify.library.web.humans import humans from edify.library.web.manifest import manifest from edify.library.web.nginx import nginx from edify.library.web.robots import robots from edify.library.web.sitemap import sitemap +from edify.library.web.useragent import useragent __all__ = [ "apache", "captcha", + "cookie", + "csp", "htaccess", "humans", "manifest", "nginx", "robots", "sitemap", + "useragent", ] diff --git a/edify/library/web/cookie.py b/edify/library/web/cookie.py new file mode 100644 index 0000000..6f8e1b7 --- /dev/null +++ b/edify/library/web/cookie.py @@ -0,0 +1,28 @@ +"""``cookie`` — HTTP cookie ``name=value`` shape.""" + +from __future__ import annotations + +from edify import Pattern + + +def _value_char() -> Pattern: + return Pattern().assert_not_ahead().any_of().whitespace_char().char(";").end().end().any_char() + + +cookie = ( + Pattern() + .start_of_input() + .one_or_more() + .any_of() + .range("a", "z") + .range("A", "Z") + .range("0", "9") + .char("_") + .char("-") + .end() + .char("=") + .one_or_more() + .subexpression(_value_char()) + .end_of_input() +) +"""Callable :class:`Pattern` for an HTTP ``name=value`` cookie pair.""" diff --git a/edify/library/web/csp.py b/edify/library/web/csp.py new file mode 100644 index 0000000..449559a --- /dev/null +++ b/edify/library/web/csp.py @@ -0,0 +1,43 @@ +"""``csp`` — Content-Security-Policy directive shape.""" + +from __future__ import annotations + +from edify import Pattern + + +def _directive_value() -> Pattern: + return Pattern().assert_not_ahead().char(";").end().any_char() + + +csp = ( + Pattern() + .start_of_input() + .one_or_more() + .any_of() + .range("a", "z") + .char("-") + .end() + .one_or_more() + .whitespace_char() + .one_or_more() + .subexpression(_directive_value()) + .zero_or_more() + .group() + .char(";") + .zero_or_more() + .whitespace_char() + .one_or_more() + .any_of() + .range("a", "z") + .char("-") + .end() + .one_or_more() + .whitespace_char() + .one_or_more() + .subexpression(_directive_value()) + .end() + .optional() + .char(";") + .end_of_input() +) +"""Callable :class:`Pattern` for a Content-Security-Policy directive shape.""" diff --git a/edify/library/web/useragent.py b/edify/library/web/useragent.py new file mode 100644 index 0000000..6996a41 --- /dev/null +++ b/edify/library/web/useragent.py @@ -0,0 +1,29 @@ +"""``useragent`` — User-Agent request-header shape.""" + +from __future__ import annotations + +from edify import Pattern + +useragent = ( + Pattern() + .start_of_input() + .between(4, 1024) + .any_of() + .range("A", "Z") + .range("a", "z") + .range("0", "9") + .char("/") + .char(".") + .char("-") + .char("(") + .char(")") + .char(" ") + .char(";") + .char("+") + .char("_") + .char(",") + .char(":") + .end() + .end_of_input() +) +"""Callable :class:`Pattern` for a permissive User-Agent string.""" |
