Skip to content

Commit e2073db

Browse files
authored
Merge pull request #272 from kjd/condense-exception-attrs-doc
Condense the README section on machine-readable exception attributes
2 parents a5d90c6 + cba1f53 commit e2073db

2 files changed

Lines changed: 9 additions & 57 deletions

File tree

README.md

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -74,47 +74,13 @@ base class. The more specific exceptions are:
7474
codepoint appears in a position whose contextual requirements are
7575
not satisfied.
7676

77-
Exceptions carry machine-readable attributes so that applications
78-
do not need to parse the message: `code` is a short, stable identifier
79-
for the rule that failed (listed below); and, when the failure can be
80-
attributed to a particular character, `text` (the label, or domain for
81-
UTS #46 processing, being validated), `codepoint` (the offending
82-
codepoint as an integer) and `position` (its 1-based index within
83-
`text`, as quoted in the message) are set. Each is `None` when it does
84-
not apply. Message wording is not part of the API and may change.
85-
86-
```pycon
87-
>>> try:
88-
... idna.encode('Königsgäßchen')
89-
... except idna.IDNAError as err:
90-
... print(err.code, err.codepoint, err.position, err.text)
91-
disallowed_codepoint 75 1 Königsgäßchen
92-
```
93-
94-
| `code` | Meaning |
95-
|---|---|
96-
| `input_too_long` | Input exceeds the library's defensive length limit and was not processed |
97-
| `label_too_long` | A label exceeds 63 octets |
98-
| `domain_too_long` | The domain exceeds 253 octets |
99-
| `empty_label` | A label is empty (e.g. consecutive dots) |
100-
| `empty_domain` | The domain is empty |
101-
| `not_nfc` | The label is not in Unicode Normalization Form C |
102-
| `hyphen_3_4` | The label has hyphens in the 3rd and 4th positions |
103-
| `hyphen_start_end` | The label starts or ends with a hyphen |
104-
| `leading_combiner` | The label starts with a combining mark |
105-
| `disallowed_codepoint` | A codepoint is DISALLOWED or UNASSIGNED under IDNA 2008 |
106-
| `contextj` | A CONTEXTJ codepoint (joiner) appears in an invalid context |
107-
| `contexto` | A CONTEXTO codepoint appears in an invalid context |
108-
| `unknown_codepoint` | A codepoint next to a joiner is unknown to this Python's Unicode database |
109-
| `bidi_rule_1``bidi_rule_6` | The corresponding rule of RFC 5893 (the Bidi Rule) is violated |
110-
| `bidi_unknown_direction` | A codepoint's directionality is unknown to this Python's Unicode database |
111-
| `invalid_alabel` | An `xn--` label is malformed or is not valid Punycode |
112-
| `non_canonical_alabel` | An `xn--` label is not the canonical Punycode encoding of its U-label (a "fake A-label") |
113-
| `invalid_ascii` | Byte input is not ASCII |
114-
| `invalid_utf8` | Byte input is not UTF-8 |
115-
| `uts46_disallowed` | A codepoint is disallowed by the UTS #46 mapping table |
116-
| `uts46_std3` | An ASCII character is rejected by the UTS #46 STD3 rules |
117-
| `unsupported_errors` | The codec was given an `errors` handler other than `strict` |
77+
Exceptions carry machine-readable attributes so that applications do
78+
not need to parse the message: `code` is a short, stable identifier
79+
for the rule that failed (such as `disallowed_codepoint` or
80+
`label_too_long`); and, when the failure can be attributed to a
81+
particular character, `text` (the label or domain being validated),
82+
`codepoint` (the offending codepoint as an integer) and `position`
83+
are set.
11884

11985

12086
## Command-line tool

tests/test_idna_errors.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import pickle
55
import re
66
import unittest
7-
from pathlib import Path
87
from typing import get_args
98
from unittest import mock
109

@@ -53,9 +52,8 @@ def test_attributes_are_populated(self):
5352
if match:
5453
self.assertEqual(int(match.group(1)), err.position)
5554

56-
def test_every_error_code_is_documented_and_raisable(self):
57-
"""Each code has an input that produces it, and vice versa; the README
58-
table must list exactly this set."""
55+
def test_every_error_code_is_raisable(self):
56+
"""Each code has an input that produces it, and vice versa."""
5957
r = "\u05d0"
6058
an = "\u0660"
6159
triggers = {
@@ -94,18 +92,6 @@ def test_every_error_code_is_documented_and_raisable(self):
9492
with self.assertRaises(idna.IDNAError) as ctx:
9593
trigger()
9694
self.assertEqual(ctx.exception.code, code)
97-
readme = Path(__file__).resolve().parent.parent / "README.md"
98-
if not readme.is_file():
99-
self.skipTest("README.md not present")
100-
documented = set()
101-
for first, last in re.findall(r"^\| `([a-z0-9_]+)`(?: \u2026 `([a-z0-9_]+)`)? \|", readme.read_text(), re.MULTILINE):
102-
if last: # a `x_1` … `x_6` range row
103-
stem, lo = first.rsplit("_", 1)
104-
documented.update(f"{stem}_{i}" for i in range(int(lo), int(last.rsplit("_", 1)[1]) + 1))
105-
else:
106-
documented.add(first)
107-
documented.discard("code") # the table header
108-
self.assertEqual(documented, codes)
10995

11096
# Conditions that depend on the host's Unicode database being older than
11197
# the input cannot be triggered portably (from Python 3.15,

0 commit comments

Comments
 (0)