IBM Bob HackathonMutantHunter

Mutation testing · specification-derived tests · python-validators

MutantHunter

Finds the bugs a test suite misses, writes tests that catch them, and proves the gain on mutants the agents never saw. Generated by mutanthunter report from the files in results/.

Pooled Hold-out Score — main modules

Share of mutants killed, pooled over the main modules. Split B is the hidden half of the mutants; exam C uses mutant operators that did not exist while the tests were written. Whiskers are 95% Wilson intervals.

B0 human testsB1 plain promptMH MutantHunter

Split B

hold-out half

60.3%→78.0%

Human tests → with MutantHunter · plain prompt (B1) 77.3% · 141 mutants · McNemar B1 vs MH: 2 only B1, 3 only MH, p = 1.000

0%25%50%75%100%B0human testsB0 (human tests): 85/141 killed, 60.3% (95% CI 52.0–68.0%)60.3%B1plain promptB1 (plain prompt): 109/141 killed, 77.3% (95% CI 69.7–83.4%)77.3%MHMutantHunterMH (MutantHunter): 110/141 killed, 78.0% (95% CI 70.5–84.1%)78.0%

Exam C

unseen operators

65.8%→82.2%

Human tests → with MutantHunter · plain prompt (B1) 76.7% · 146 mutants · McNemar B1 vs MH: 1 only B1, 9 only MH, p = 0.021

0%25%50%75%100%B0human testsB0 (human tests): 96/146 killed, 65.8% (95% CI 57.7–73.0%)65.8%B1plain promptB1 (plain prompt): 112/146 killed, 76.7% (95% CI 69.2–82.8%)76.7%MHMutantHunterMH (MutantHunter): 120/146 killed, 82.2% (95% CI 75.2–87.5%)82.2%
Extra kills over the plain prompt
+9 / −1
exam C · split B: +3 / −2
Bugs confirmed
5
4 not reported upstream · 13 suspected, 12 logic
Missed historical bugs caught
2/2
by the MH tests · human tests 0/2

Per-module scores

Each module on the hidden split B and on exam C. Hover a bar for the counts; the table below holds every value.

B0 human testsB1 plain promptMH MutantHunter

Split B

hold-out half

0%50%100%croncron · B0 (human tests): 29/44 killed, 65.9%cron · B1 (plain prompt): 37/44 killed, 84.1%cron · MH (MutantHunter): 36/44 killed, 81.8%81.8%emailemail · B0 (human tests): 6/14 killed, 42.9%email · B1 (plain prompt): 10/14 killed, 71.4%email · MH (MutantHunter): 10/14 killed, 71.4%71.4%financefinance · B0 (human tests): 32/57 killed, 56.1%finance · B1 (plain prompt): 44/57 killed, 77.2%finance · MH (MutantHunter): 44/57 killed, 77.2%77.2%urlurl · B0 (human tests): 18/26 killed, 69.2%url · B1 (plain prompt): 18/26 killed, 69.2%url · MH (MutantHunter): 20/26 killed, 76.9%76.9%hostnameextrahostname · B0 (human tests): 16/18 killed, 88.9%hostname · B1 (plain prompt): 16/18 killed, 88.9%hostname · MH (MutantHunter): 16/18 killed, 88.9%88.9%mac_addressextramac_address · B0 (human tests): 1/1 killed, 100.0%mac_address · B1 (plain prompt): 1/1 killed, 100.0%mac_address · MH (MutantHunter): 1/1 killed, 100.0%100.0%

Exam C

unseen operators

0%50%100%croncron · B0 (human tests): 29/34 killed, 85.3%cron · B1 (plain prompt): 32/34 killed, 94.1%cron · MH (MutantHunter): 32/34 killed, 94.1%94.1%emailemail · B0 (human tests): 16/26 killed, 61.5%email · B1 (plain prompt): 23/26 killed, 88.5%email · MH (MutantHunter): 22/26 killed, 84.6%84.6%financefinance · B0 (human tests): 21/36 killed, 58.3%finance · B1 (plain prompt): 26/36 killed, 72.2%finance · MH (MutantHunter): 28/36 killed, 77.8%77.8%urlurl · B0 (human tests): 30/50 killed, 60.0%url · B1 (plain prompt): 31/50 killed, 62.0%url · MH (MutantHunter): 38/50 killed, 76.0%76.0%hostnameextrahostname · B0 (human tests): 12/28 killed, 42.9%hostname · B1 (plain prompt): 20/28 killed, 71.4%hostname · MH (MutantHunter): 21/28 killed, 75.0%75.0%mac_addressextramac_address · B0 (human tests): 2/5 killed, 40.0%mac_address · B1 (plain prompt): 5/5 killed, 100.0%mac_address · MH (MutantHunter): 5/5 killed, 100.0%100.0%
ModuleSetSplit BExam CTestsSuspectedMinBobcoins
B0B1MHB0B1MH
cronmain65.9%84.1%81.8%85.3%94.1%94.1%207011.16.54
emailmain42.9%71.4%71.4%61.5%88.5%84.6%13248.57.9
financemain56.1%77.2%77.2%58.3%72.2%77.8%12049.85.61
urlmain69.2%69.2%76.9%60.0%62.0%76.0%234313.211.07
hostnameextra88.9%88.9%88.9%42.9%71.4%75.0%16615.03.84
mac_addressextra100.0%100.0%100.0%40.0%100.0%100.0%8314.52.54

Not run in this study: between, card, country, crypto_addresses/btc_address, crypto_addresses/trx_address, domain, encoding, hashes, i18n/es, i18n/fi, i18n/fr, i18n/ind, i18n/ru, iban, ip_address, length, slug, uuid

Bugs found

The spec subagents turn every test that fails on the current code into a suspected violation. Each one was reviewed by reading the code and searching the upstream issues.

emailnew2 test entries

Quoted-string local part with space is rejected

Input '" "@example.com'

Code src/validators/email.py:93-95 — the quoted-string character class [... !#-\[\]-\177] omits 0x20 (space), which RFC 5321 qtextSMTP (%d32-33) allows.

Upstream no existing issue found (searched python-validators/validators issues on 2026-09-26); still present on master.

emailnew1 test entry

IPv6 address literal with IPv6: tag is rejected

Input 'user@[IPv6:::1]' with ipv6_address=True / 'user@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]' with ipv6_address=True

Code src/validators/email.py:70 — domain_part.lstrip("[").rstrip("]") keeps the IPv6: tag, so the RFC 5321 form [IPv6:::1] is rejected while the non-standard [::1] is accepted.

Upstream no existing issue found (searched 2026-09-26); still present on master.

financeknown upstream4 test entries

ISIN checksum never accumulates — _isin_checksum loop does not update check

Input "US0378331006" (wrong check digit; correct is "US0378331005")

Code src/validators/finance.py:34-51 — _isin_checksum computes val but never adds it to check, so return (check % 10) == 0 is always True and any check digit is accepted.

Upstream known bug, issue #440 (open) with open fix PRs #464, #468 and #473; still present on master. MutantHunter rediscovered it from the spec, it is not new.

hostnamenew1 test entry

Simple hostname regex caps at 61 characters instead of 63

Input "a" * 62 (and "a" * 63)

Code src/validators/hostname.py:27-29 — [a-z0-9-]{0,59} between the first and last character caps a single-label hostname at 61 characters; RFC 1123 section 2.1 requires up to 63. Labels inside a dotted name are checked by domain() and are not affected.

Upstream no issue for this cap (related feature request #433 on RFC 1123 support); still present on master.

urlnew1 test entry

Empty port (trailing colon) rejected by implementation

Input "http://example.com:"

Code src/validators/hostname.py:18-21 — the port regex requires at least one digit, but RFC 3986 section 3.2.3 defines port = *DIGIT and the WHATWG URL standard also accepts http://example.com:. Minor severity.

Upstream no existing issue found (searched 2026-09-26); still present on master.

Rejected after review (4)
  • email: Single-character TLD is rejected. design choice, not a logic bug. The library requires a TLD of 2-63 letters (see upstream PR #476, which kept that rule), and no single-character TLD exists in the DNS root.
  • mac_address: Dot-grouped notation not supported (three groups of four hex digits). scope choice, not a logic bug. The docstring and regex only promise colon- and hyphen-separated addresses; the spec lists the dotted form as an alternative convention, not the IEEE 802 standard format.
  • url: Port zero rejected by implementation. design choice. src/validators/hostname.py:18-21 deliberately accepts ports 1-65535; port 0 is reserved and cannot be connected to, so rejecting it is a semantic policy beyond RFC 3986 syntax.
  • url: Strict-query rejects RFC-valid pchar characters in query (: and @). policy choice exposed as the strict_query parameter (default True); with strict_query=False the input is accepted. The human tests encode the strict default.
All suspected violations (13), raw entries
email: Quoted-string local part with space is rejected logic · confirmed
## SV-1: Quoted-string local part with space is rejected

- Category: logic
- Spec: RFC 5321 4.1.2 — R6
- Input: `'" "@example.com'`
- Spec says: valid — qtextSMTP is `%d32-33 / %d35-91 / %d93-126`; space (0x20 = %d32) is explicitly permitted inside a quoted-string
- Code returns: `ValidationError` (falsy)
- Test:
  ```python
  from validators import email
  assert email('" "@example.com')
  ```
- Status: confirmed
- Bug: email-quoted-local-part
- Code: `src/validators/email.py:93-95` — the quoted-string character class `[... !#-\[\]-\177]` omits 0x20 (space), which RFC 5321 qtextSMTP (`%d32-33`) allows.
- Upstream: no existing issue found (searched python-validators/validators issues on 2026-09-26); still present on master.
- Same root cause as SV-4 (quoted-string handling); counted once.
- Broad-test removed: `test_quoted_string_with_space` — asserted current behavior
email: Single-character TLD is rejected logic · rejected
## SV-2: Single-character TLD is rejected

- Category: logic
- Spec: RFC 5321 4.1.2 / RFC 1034 — R7
- Input: `'user@example.a'`
- Spec says: valid — neither RFC 5321 nor RFC 1034 imposes a minimum TLD length; a single-label TLD is syntactically legal
- Code returns: `ValidationError` (falsy)
- Test:
  ```python
  from validators import email
  assert email("user@example.a")
  ```
- Status: rejected
- Review: design choice, not a logic bug. The library requires a TLD of 2-63 letters (see upstream PR #476, which kept that rule), and no single-character TLD exists in the DNS root.
email: IPv6 address literal with IPv6: tag is rejected logic · confirmed
## SV-3: IPv6 address literal with `IPv6:` tag is rejected

- Category: logic
- Spec: RFC 5321 4.1.3 — R11
- Input: `'user@[IPv6:::1]'` with `ipv6_address=True` / `'user@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]'` with `ipv6_address=True`
- Spec says: valid — IPv6 literals in email domains MUST use the `IPv6:` prefix inside brackets; `[IPv6:::1]` and `[IPv6:2001:…]` are the correct form
- Code returns: `ValidationError` (falsy) — the implementation strips brackets with `lstrip("[").rstrip("]")`, leaving `IPv6:::1`, but then passes it directly to the `hostname` validator which does not know how to handle the `IPv6:` prefix
- Test:
  ```python
  from validators import email
  assert email("user@[IPv6:::1]", ipv6_address=True)
  assert email("user@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]", ipv6_address=True)
  ```
- Status: confirmed
- Bug: email-ipv6-literal
- Code: `src/validators/email.py:70` — `domain_part.lstrip("[").rstrip("]")` keeps the `IPv6:` tag, so the RFC 5321 form `[IPv6:::1]` is rejected while the non-standard `[::1]` is accepted.
- Upstream: no existing issue found (searched 2026-09-26); still present on master.
email: Quoted-string local part containing @ or special characters is rejected logic · confirmed
## SV-4: Quoted-string local part containing `@` or special characters is rejected

- Category: logic
- Spec: RFC 5322 3.2.4 / RFC 5321 4.1.2 — R6
- Input: `'"user@name"@example.com'` / `'"user name"@example.com'`
- Spec says: valid — any printable ASCII character except unescaped `"` and `\` is allowed inside a quoted-string, including `@`, spaces, and `(`, `)`, `,`, `;`, `<`, `>`, `:`
- Code returns: `ValidationError` (falsy) — for `@` inside quotes, the count-`@` check at line 58 rejects addresses with more than one `@`; for spaces, the quoted-string regex character class omits 0x20
- Test:
  ```python
  from validators import email
  assert email('"user name"@example.com')
  assert email('"user@name"@example.com')
  ```
- Status: confirmed
- Bug: email-quoted-local-part
- Code: `src/validators/email.py:58` — `value.count("@") != 1` rejects any `@` inside a quoted local part before the quoted-string regex runs; spaces fail at `email.py:93-95` (see SV-1).
- Upstream: no existing issue found (searched 2026-09-26); still present on master.
- Same root cause as SV-1; counted once together with SV-1.
finance: ISIN checksum never accumulates — _isin_checksum loop does not update check logic · confirmed
## ISIN checksum never accumulates — `_isin_checksum` loop does not update `check`
- Category: logic
- Spec: wiki-ISIN.txt § Examples — R21
- Input: `"US0378331006"` (wrong check digit; correct is `"US0378331005"`)
- Spec says: invalid (Luhn check digit must be 5, not 6)
- Code returns: True (check is always 0 because the loop never adds val to check)
- Test:
  ```python
  from validators import isin
  def test_isin_invalid_wrong_check_digit_apple():
      """Spec: wiki-ISIN.txt § Examples — Apple, Inc. — R21
      'US0378331006' (check digit 6 instead of 5) must be invalid.
      """
      assert not isin("US0378331006")
  ```
- Status: confirmed
- Bug: isin-check-digit
- Code: `src/validators/finance.py:34-51` — `_isin_checksum` computes `val` but never adds it to `check`, so `return (check % 10) == 0` is always True and any check digit is accepted.
- Upstream: known bug, issue #440 (open) with open fix PRs #464, #468 and #473; still present on master. MutantHunter rediscovered it from the spec, it is not new.
- The other three ISIN entries below have the same root cause; the four entries count as one bug.
- Broad-test removed: `test_isin_wrong_checksum_passes_due_to_bug` — asserted current behavior
finance: ISIN checksum never accumulates — last char letter incorrectly accepted logic · confirmed
## ISIN checksum never accumulates — last char letter incorrectly accepted
- Category: logic
- Spec: wiki-ISIN.txt § Description — R16
- Input: `"US037833100A"` (last character is letter 'A', not a digit)
- Spec says: invalid (last character must be a numerical check digit 0–9)
- Code returns: True (check is always 0 because the loop never adds val to check)
- Test:
  ```python
  from validators import isin
  def test_isin_last_char_letter_is_invalid():
      """Spec: wiki-ISIN.txt § Description — R16
      An ISIN whose last character is a letter rather than a digit must be invalid.
      """
      assert not isin("US037833100A")
  ```
- Status: confirmed
- Bug: isin-check-digit
- Review: same root cause as the first ISIN entry (#440); counted once.
- Broad-test removed: `test_isin_12_letter_string_passes_due_to_bug` — asserted current behavior
finance: ISIN checksum never accumulates — wrong check digit for Treasury Corp Victoria logic · confirmed
## ISIN checksum never accumulates — wrong check digit for Treasury Corp Victoria
- Category: logic
- Spec: wiki-ISIN.txt § Examples — R21
- Input: `"AU0000XVGZA4"` (wrong check digit; correct is `"AU0000XVGZA3"`)
- Spec says: invalid (Luhn check digit must be 3, not 4)
- Code returns: True
- Test:
  ```python
  from validators import isin
  def test_isin_invalid_wrong_check_digit_treasury():
      """Spec: wiki-ISIN.txt § Examples — Treasury Corp Victoria — R21
      'AU0000XVGZA4' (check digit 4 instead of 3) must be invalid.
      """
      assert not isin("AU0000XVGZA4")
  ```
- Status: confirmed
- Bug: isin-check-digit
- Review: same root cause as the first ISIN entry (#440); counted once.
finance: ISIN checksum never accumulates — wrong check digit for BAE Systems logic · confirmed
## ISIN checksum never accumulates — wrong check digit for BAE Systems
- Category: logic
- Spec: wiki-ISIN.txt § Examples — BAE Systems — R21
- Input: `"GB0002634947"` (wrong check digit; correct is `"GB0002634946"`)
- Spec says: invalid (correct check digit is 6)
- Code returns: True
- Test:
  ```python
  from validators import isin
  def test_isin_invalid_wrong_check_digit_bae():
      """Spec: wiki-ISIN.txt § Examples — BAE Systems — R21
      'GB0002634947' (check digit 7 instead of 6) must be invalid.
      """
      assert not isin("GB0002634947")
  ```
- Status: confirmed
- Bug: isin-check-digit
- Review: same root cause as the first ISIN entry (#440); counted once.
hostname: Simple hostname regex caps at 61 characters instead of 63 logic · confirmed
## Simple hostname regex caps at 61 characters instead of 63

- Category: logic
- Spec: rfc1123.pdf Section 2.1 — R8
- Input: `"a" * 62`  (and `"a" * 63`)
- Spec says: valid — RFC 1123 §2.1 states "Host software MUST handle host names of up to 63 characters"
- Code returns: `ValidationError` — the `_simple_hostname_regex` in `hostname.py` uses `{0,59}` for the middle segment which, combined with the mandatory first char and optional last char, caps the total at 61 characters (1 + 59 + 1 = 61). The comment in the source even acknowledges the range should be `{1, 61}` but that is already incorrect per the spec (should be `{1, 63}`).
- Test:
  ```python
  def test_label_63_chars_valid():
      label = "a" * 63
      assert hostname(label)

  def test_label_62_chars_valid():
      label = "a" * 62
      assert hostname(label)

  def test_label_63_chars_with_hyphen_valid():
      label = "a" + "b" * 61 + "c"  # 63 chars total
      assert hostname(label)
  ```
- Broad-test removed: `test_simple_62_chars_invalid` — asserted current behavior (62-char label invalid)
- Status: confirmed
- Bug: hostname-63-characters
- Code: `src/validators/hostname.py:27-29` — `[a-z0-9-]{0,59}` between the first and last character caps a single-label hostname at 61 characters; RFC 1123 section 2.1 requires up to 63. Labels inside a dotted name are checked by `domain()` and are not affected.
- Upstream: no issue for this cap (related feature request #433 on RFC 1123 support); still present on master.
mac_address: Dot-grouped notation not supported (three groups of four hex digits) logic · rejected
## Dot-grouped notation not supported (three groups of four hex digits)

- Category: logic
- Spec: wiki-MAC_address.pdf Notational conventions — R4
- Input: `"0123.4567.89AB"`
- Spec says: valid (three groups of four hexadecimal digits separated by dots is an accepted human-friendly notation)
- Code returns: `ValidationError(func=mac_address, args={'value': '0123.4567.89AB'})`
- Test:
  ```python
  from validators import mac_address

  def test_dot_notation_basic():
      assert mac_address("0123.4567.89AB")

  def test_dot_notation_lowercase():
      assert mac_address("0123.4567.89ab")

  def test_dot_notation_mixed_case():
      assert mac_address("aAbB.cCdD.eEfF")

  def test_dot_notation_all_zeros():
      assert mac_address("0000.0000.0000")

  def test_dot_notation_broadcast():
      assert mac_address("FFFF.FFFF.FFFF")
  ```
- Status: rejected
- Review: scope choice, not a logic bug. The docstring and regex only promise colon- and hyphen-separated addresses; the spec lists the dotted form as an alternative convention, not the IEEE 802 standard format.

---

### Root cause

The validator's regex `^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$` only
matches six 2-digit groups separated by `:` or `-`.  
It does not include a branch for three 4-digit groups separated by `.`
(`^([0-9A-Fa-f]{4}\.){2}([0-9A-Fa-f]{4})$`), which the Wikipedia
Notational conventions section explicitly lists as a valid notation (Cisco
format, e.g. `0123.4567.89AB`).
url: Port zero rejected by implementation logic · rejected
## Port zero rejected by implementation

- Category: logic
- Spec: rfc3986 §3.2.3 — R14
- Input: `"http://example.com:0/path"`
- Spec says: valid — `port = *DIGIT`; port 0 is a single digit and is syntactically legal per the RFC grammar
- Code returns: `ValidationError` — the hostname validator rejects port 0 (treats it as invalid rather than applying a pure syntax check)
- Test:
  ```python
  from validators import url
  def test_port_zero():
      """Spec: rfc3986 §3.2.3 — R14: port 0 is syntactically valid per *DIGIT grammar."""
      assert url("http://example.com:0/path")
  ```
- Status: rejected
- Review: design choice. `src/validators/hostname.py:18-21` deliberately accepts ports 1-65535; port 0 is reserved and cannot be connected to, so rejecting it is a semantic policy beyond RFC 3986 syntax.
url: Empty port (trailing colon) rejected by implementation logic · confirmed
## Empty port (trailing colon) rejected by implementation

- Category: logic
- Spec: rfc3986 §3.2.3 — R14
- Input: `"http://example.com:"`
- Spec says: valid — `port = *DIGIT` allows zero digits; RFC 3986 §3.2.3 says producers SHOULD omit the `:` when port is empty but parsers must accept it
- Code returns: `ValidationError` — the hostname validator rejects a trailing `:` with no port digits
- Test:
  ```python
  from validators import url
  def test_port_empty_is_spec_valid():
      """Spec: rfc3986 §3.2.3 — R14: port = *DIGIT; empty port (host:) is syntactically valid."""
      assert url("http://example.com:")
  ```
- Status: confirmed
- Bug: url-empty-port
- Code: `src/validators/hostname.py:18-21` — the port regex requires at least one digit, but RFC 3986 section 3.2.3 defines `port = *DIGIT` and the WHATWG URL standard also accepts `http://example.com:`. Minor severity.
- Upstream: no existing issue found (searched 2026-09-26); still present on master.
url: Strict-query rejects RFC-valid pchar characters in query (: and @) spec-ambiguous · rejected
## Strict-query rejects RFC-valid pchar characters in query (`:` and `@`)

- Category: spec-ambiguous
- Spec: rfc3986 §3.4 — R19
- Input: `"http://example.com/path?user:name@host"`
- Spec says: valid — `query = *(pchar / "/" / "?")` and `pchar` includes both `:` and `@`; the query string `user:name@host` is syntactically correct per RFC 3986
- Code returns: `ValidationError(reason="bad query field: 'user:name@host'")` — `parse_qs` with `strict_parsing=True` (the default) treats an unquoted field with no `=` separator as a parse error
- Test:
  ```python
  from validators import url
  def test_query_colon_at_allowed():
      """Spec: rfc3986 §3.4 — R19: ':' and '@' (pchar) are allowed in query."""
      assert url("http://example.com/path?user:name@host")
  ```
- Status: rejected
- Review: policy choice exposed as the `strict_query` parameter (default True); with `strict_query=False` the input is accepted. The human tests encode the strict default.
- Note: The `strict_query=True` default is an application-level policy choice, not an RFC grammar rule. The human tests at `tests/test_url.py` are consistent with `strict_query=True` (e.g. they mark `?bar=baz&inga=42&quux` as invalid). This is therefore `spec-ambiguous` rather than a clear logic bug.

Historical bug replay

Caught = at least one test fails on the pre-fix commit and passes on the fix. Reading notes (spec §7.4): tests written today encode today's fixed behaviour, so any test that pins current behaviour "catches" a reverted fix. The meaningful rows are the extra set (highlighted): bugs the human tests still miss. Report B1 as context only. Row 1231f6a is spec-ambiguous (RFC 3986 vs WHATWG) and not counted.

SHADateModuleSetSubjectHumanMHB1Note
41f3d6d2023-09-02hostnameextrafix: simple hostname validation regexmisscaughtcaughtparent rejects single-character labels; RFC 1123 allows them
402b3512025-07-18mac_addressextrafix: reject MAC addresses with mixed separatorsmisscaughtcaughtparent accepts mixed ':' and '-' separators
4015e8e2023-08-18urlmainfix: url validator considers urls with /#/ as validcaughtcaughtcaught
960b48b2023-09-17urlmainfix: Valid URLs failing validation - query and fragment parts (#297)caughtcaughtcaught
15984e82023-10-05urlmainfix: URL fragment check (#305)caughtcaughtmiss
38d196a2023-11-07urlmainallow pct-encoded entities in fragmentscaughtcaughtcaught
c0e29cf2024-03-22domainmainfix: domain name not confirming to rfc_2782miss——
5f6437c2024-03-22domainmainpatch: `domain` & `url` modulescaught——
5f6437c2024-03-22urlmainpatch: `domain` & `url` modulescaughtcaughtcaught
b6cfb432024-03-31domainmainfix: domain validation is now more consistent across rfcsmiss——
af69a682024-04-02emailmainpatch: supported extended latin in usernamecaughtcaughtmiss
af69a682024-04-02urlmainpatch: supported extended latin in usernamemissmissmiss
181f6dc2024-04-18domainmainfix: rfc cases in the `domain` validatorcaught——
7c0e6052024-05-08ip_addressmainfix(ip_address): properly handle private is falsecaught——
0a791b62024-09-15domainmainfix(domain): accept .onion as a valid TLDcaught——
1231f6a2024-10-06urlmainfix(url): add hashtag to allowed fragment charactersmissmissmissspec-ambiguous: RFC 3986 forbids '#' in fragment, WHATWG/browsers allow it (issue #403)
25fcef02025-03-29emailmainFix email regex issue 140 (#411)caughtcaughtcaught
f7aa5932023-09-23betweenreferencefix: bug in `between` modulecaught——
d1a5b222024-03-19betweenreferencefix: `between` and `length` validatorsmiss——API contract change; the spec is the library docstring, not an external standard
d1a5b222024-03-19lengthreferencefix: `between` and `length` validatorsmiss——API contract change; the spec is the library docstring, not an external standard
7c97eca2025-04-26i18n/esreferenceFix: Allow Special DOI Cases Used in Public Administration Tests (#415)caught——

Method and limits