Skip to content

Commit

Permalink
Add ruff lint commands to github workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
waketzheng committed Aug 26, 2024
1 parent d076221 commit 4a64fc5
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 117 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ jobs:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install dependencies
run: python -m pip install mypy
run: python -m pip install ruff mypy
- name: Check code style with ruff
run: |
ruff format --check idna tests
ruff check idna tests
- name: Check types with mypy
run: mypy --strict idna

Expand Down
68 changes: 14 additions & 54 deletions idna/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,7 @@ def check_bidi(label: str, check_ltr: bool = False) -> bool:
direction = unicodedata.bidirectional(cp)
if direction == "":
# String likely comes from a newer version of Unicode
raise IDNABidiError(
"Unknown directionality in label {} at position {}".format(
repr(label), idx
)
)
raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx))
if direction in ["R", "AL", "AN"]:
bidi_label = True
if not bidi_label and not check_ltr:
Expand All @@ -91,11 +87,7 @@ def check_bidi(label: str, check_ltr: bool = False) -> bool:
elif direction == "L":
rtl = False
else:
raise IDNABidiError(
"First codepoint in label {} must be directionality L, R or AL".format(
repr(label)
)
)
raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label)))

valid_ending = False
number_type: Optional[str] = None
Expand All @@ -116,11 +108,7 @@ def check_bidi(label: str, check_ltr: bool = False) -> bool:
"BN",
"NSM",
]:
raise IDNABidiError(
"Invalid direction for codepoint at position {} in a right-to-left label".format(
idx
)
)
raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx))
# Bidi rule 3
if direction in ["R", "AL", "EN", "AN"]:
valid_ending = True
Expand All @@ -132,17 +120,11 @@ def check_bidi(label: str, check_ltr: bool = False) -> bool:
number_type = direction
else:
if number_type != direction:
raise IDNABidiError(
"Can not mix numeral types in a right-to-left label"
)
raise IDNABidiError("Can not mix numeral types in a right-to-left label")
else:
# Bidi rule 5
if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]:
raise IDNABidiError(
"Invalid direction for codepoint at position {} in a left-to-right label".format(
idx
)
)
raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx))
# Bidi rule 6
if direction in ["L", "EN"]:
valid_ending = True
Expand Down Expand Up @@ -241,11 +223,7 @@ def valid_contexto(label: str, pos: int, exception: bool = False) -> bool:
for cp in label:
if cp == "\u30fb":
continue
if (
_is_script(cp, "Hiragana")
or _is_script(cp, "Katakana")
or _is_script(cp, "Han")
):
if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"):
return True
return False

Expand Down Expand Up @@ -282,9 +260,7 @@ def check_label(label: Union[str, bytes, bytearray]) -> None:
try:
if not valid_contextj(label, pos):
raise InvalidCodepointContext(
"Joiner {} not allowed at position {} in {}".format(
_unot(cp_value), pos + 1, repr(label)
)
"Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
)
except ValueError:
raise IDNAError(
Expand All @@ -295,15 +271,11 @@ def check_label(label: Union[str, bytes, bytearray]) -> None:
elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]):
if not valid_contexto(label, pos):
raise InvalidCodepointContext(
"Codepoint {} not allowed at position {} in {}".format(
_unot(cp_value), pos + 1, repr(label)
)
"Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label))
)
else:
raise InvalidCodepoint(
"Codepoint {} at position {} of {} not allowed".format(
_unot(cp_value), pos + 1, repr(label)
)
"Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label))
)

check_bidi(label)
Expand Down Expand Up @@ -357,9 +329,7 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str:
return label


def uts46_remap(
domain: str, std3_rules: bool = True, transitional: bool = False
) -> str:
def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str:
"""Re-map the characters in the string according to UTS46 processing."""
from .uts46data import uts46data

Expand All @@ -368,11 +338,7 @@ def uts46_remap(
for pos, char in enumerate(domain):
code_point = ord(char)
try:
uts46row = uts46data[
code_point
if code_point < 256
else bisect.bisect_left(uts46data, (code_point, "Z")) - 1
]
uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1]
status = uts46row[1]
replacement: Optional[str] = None
if len(uts46row) == 3:
Expand All @@ -384,18 +350,14 @@ def uts46_remap(
):
output += char
elif replacement is not None and (
status == "M"
or (status == "3" and not std3_rules)
or (status == "D" and transitional)
status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional)
):
output += replacement
elif status != "I":
raise IndexError()
except IndexError:
raise InvalidCodepoint(
"Codepoint {} not allowed at position {} in {}".format(
_unot(code_point), pos + 1, repr(domain)
)
"Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain))
)

return unicodedata.normalize("NFC", output)
Expand All @@ -412,9 +374,7 @@ def encode(
try:
s = str(s, "ascii")
except UnicodeDecodeError:
raise IDNAError(
"should pass a unicode string to the function rather than a byte string."
)
raise IDNAError("should pass a unicode string to the function rather than a byte string.")
if uts46:
s = uts46_remap(s, std3_rules, transitional)
trailing_dot = False
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,13 @@ include = ["tests", "tools", "HISTORY.rst"]
[project.optional-dependencies]
all = [
"ruff >= 0.6.2",
"mypy >= 1.11.2",
"pytest >= 8.3.2",
"flake8 >= 7.1.1",
]

[tool.ruff]
line-length = 127
[tool.ruff.lint]
extend-select = [
"I", # isort
Expand Down
12 changes: 3 additions & 9 deletions tests/test_idna.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,8 @@ def test_encode(self, encode=None, skip_bytes=False):
encode = idna.encode

self.assertEqual(encode("xn--zckzah.xn--zckzah"), b"xn--zckzah.xn--zckzah")
self.assertEqual(
encode("\u30c6\u30b9\u30c8.xn--zckzah"), b"xn--zckzah.xn--zckzah"
)
self.assertEqual(
encode("\u30c6\u30b9\u30c8.\u30c6\u30b9\u30c8"), b"xn--zckzah.xn--zckzah"
)
self.assertEqual(encode("\u30c6\u30b9\u30c8.xn--zckzah"), b"xn--zckzah.xn--zckzah")
self.assertEqual(encode("\u30c6\u30b9\u30c8.\u30c6\u30b9\u30c8"), b"xn--zckzah.xn--zckzah")
self.assertEqual(encode("abc.abc"), b"abc.abc")
self.assertEqual(encode("xn--zckzah.abc"), b"xn--zckzah.abc")
self.assertEqual(encode("\u30c6\u30b9\u30c8.abc"), b"xn--zckzah.abc")
Expand All @@ -262,9 +258,7 @@ def test_encode(self, encode=None, skip_bytes=False):
def test_decode(self, decode=None, skip_str=False):
if decode is None:
decode = idna.decode
self.assertEqual(
decode(b"xn--zckzah.xn--zckzah"), "\u30c6\u30b9\u30c8.\u30c6\u30b9\u30c8"
)
self.assertEqual(decode(b"xn--zckzah.xn--zckzah"), "\u30c6\u30b9\u30c8.\u30c6\u30b9\u30c8")
self.assertEqual(
decode(b"xn--d1acufc.xn--80akhbyknj4f"),
"\u0434\u043e\u043c\u0435\u043d.\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435",
Expand Down
12 changes: 3 additions & 9 deletions tests/test_idna_codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,19 @@ def setUp(self):
self.idnatests.setUp()

def testCodec(self):
self.assertIs(
codecs.lookup(CODEC_NAME).incrementalencoder, idna.codec.IncrementalEncoder
)
self.assertIs(codecs.lookup(CODEC_NAME).incrementalencoder, idna.codec.IncrementalEncoder)

def testDirectDecode(self):
self.idnatests.test_decode(decode=lambda obj: codecs.decode(obj, CODEC_NAME))

def testIndirectDecode(self):
self.idnatests.test_decode(
decode=lambda obj: obj.decode(CODEC_NAME), skip_str=True
)
self.idnatests.test_decode(decode=lambda obj: obj.decode(CODEC_NAME), skip_str=True)

def testDirectEncode(self):
self.idnatests.test_encode(encode=lambda obj: codecs.encode(obj, CODEC_NAME))

def testIndirectEncode(self):
self.idnatests.test_encode(
encode=lambda obj: obj.encode(CODEC_NAME), skip_bytes=True
)
self.idnatests.test_encode(encode=lambda obj: obj.encode(CODEC_NAME), skip_bytes=True)

def testStreamReader(self):
def decode(obj):
Expand Down
4 changes: 1 addition & 3 deletions tests/test_idna_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,4 @@
class OtherUTS46Tests(unittest.TestCase):
def test_std3(self):
self.assertEqual(idna.uts46_remap("A_", std3_rules=False), "a_")
self.assertRaises(
idna.InvalidCodepoint, idna.uts46_remap, "A_", std3_rules=True
)
self.assertRaises(idna.InvalidCodepoint, idna.uts46_remap, "A_", std3_rules=True)
51 changes: 10 additions & 41 deletions tests/test_idna_uts46.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,7 @@
def unicode_fixup(string):
"""Replace backslash-u-XXXX with appropriate unicode characters."""
return _RE_SURROGATE.sub(
lambda match: chr(
(ord(match.group(0)[0]) - 0xD800) * 0x400
+ ord(match.group(0)[1])
- 0xDC00
+ 0x10000
),
lambda match: chr((ord(match.group(0)[0]) - 0xD800) * 0x400 + ord(match.group(0)[1]) - 0xDC00 + 0x10000),
_RE_UNICODE.sub(lambda match: chr(int(match.group(1), 16)), string),
)

Expand Down Expand Up @@ -184,68 +179,42 @@ def runTest(self):
try:
output = idna.decode(source, uts46=True, strict=True)
if to_unicode_status != "[]":
self.fail(
"decode() did not emit required error {} for {}".format(
to_unicode, repr(source)
)
)
self.fail("decode() did not emit required error {} for {}".format(to_unicode, repr(source)))
self.assertEqual(output, to_unicode, "unexpected decode() output")
except (idna.IDNAError, UnicodeError, ValueError) as exc:
if str(exc).startswith("Unknown"):
raise unittest.SkipTest(
"Test requires support for a newer"
" version of Unicode than this Python supports"
)
raise unittest.SkipTest("Test requires support for a newer" " version of Unicode than this Python supports")
if to_unicode_status == "[]":
raise

try:
output = idna.encode(source, uts46=True, strict=True).decode("ascii")
if to_ascii_status != "[]":
self.fail(
"encode() did not emit required error {} for {}".format(
to_ascii_status, repr(source)
)
)
self.fail("encode() did not emit required error {} for {}".format(to_ascii_status, repr(source)))
self.assertEqual(output, to_ascii, "unexpected encode() output")
except (idna.IDNAError, UnicodeError, ValueError) as exc:
if str(exc).startswith("Unknown"):
raise unittest.SkipTest(
"Test requires support for a newer"
" version of Unicode than this Python supports"
)
raise unittest.SkipTest("Test requires support for a newer" " version of Unicode than this Python supports")
if to_ascii_status == "[]":
raise

try:
output = idna.encode(
source, uts46=True, strict=True, transitional=True
).decode("ascii")
output = idna.encode(source, uts46=True, strict=True, transitional=True).decode("ascii")
if to_ascii_t_status != "[]":
self.fail(
"encode(transitional=True) did not emit required error {} for {}".format(
to_ascii_t_status, repr(source)
)
"encode(transitional=True) did not emit required error {} for {}".format(to_ascii_t_status, repr(source))
)
self.assertEqual(output, to_ascii_t, "unexpected encode() output")
except (idna.IDNAError, UnicodeError, ValueError) as exc:
if str(exc).startswith("Unknown"):
raise unittest.SkipTest(
"Test requires support for a newer"
" version of Unicode than this Python supports"
)
raise unittest.SkipTest("Test requires support for a newer" " version of Unicode than this Python supports")
if to_ascii_t_status == "[]":
raise


def load_tests(loader, tests, pattern):
"""Create a suite of all the individual tests."""
suite = unittest.TestSuite()
with open(
os.path.join(os.path.dirname(__file__), "IdnaTestV2.txt"), "rb"
) as tests_file:
suite.addTests(
TestIdnaTest(lineno, fields)
for lineno, fields in parse_idna_test_table(tests_file)
)
with open(os.path.join(os.path.dirname(__file__), "IdnaTestV2.txt"), "rb") as tests_file:
suite.addTests(TestIdnaTest(lineno, fields) for lineno, fields in parse_idna_test_table(tests_file))
return suite

0 comments on commit 4a64fc5

Please sign in to comment.