From 701d807b4a3a486adbe7ea21b21fd24c4a464d68 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Sat, 8 Feb 2025 09:36:24 +0100 Subject: [PATCH 1/3] Accept valid unicode identifiers as class parameter to make_class Related to #1404 --- src/attr/_make.py | 4 ++++ tests/test_make.py | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/attr/_make.py b/src/attr/_make.py index e3e31ffc2..9491057ad 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -13,6 +13,7 @@ import sys import types import typing +import unicodedata from operator import itemgetter @@ -2908,6 +2909,9 @@ def make_class( .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. .. versionchanged:: 23.2.0 *class_body* """ + # Class identifiers are converted into the normal form NFKC while parsing + name = unicodedata.normalize("NFKC", name) + if isinstance(attrs, dict): cls_dict = attrs elif isinstance(attrs, (list, tuple)): diff --git a/tests/test_make.py b/tests/test_make.py index cc78cb3a4..432a912fa 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -10,6 +10,7 @@ import inspect import itertools import sys +import unicodedata from operator import attrgetter from typing import Generic, TypeVar @@ -1100,6 +1101,44 @@ def test_attr_args(self): assert repr(C(1)).startswith(" Date: Sun, 9 Feb 2025 08:03:36 +0100 Subject: [PATCH 2/3] Test code style --- tests/test_make.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_make.py b/tests/test_make.py index 432a912fa..f5e3b3178 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -1103,12 +1103,14 @@ def test_attr_args(self): def test_normalized_unicode_attr_args(self): """ - Unicode identifiers are valid in Python + Unicode identifiers are valid in Python. """ clsname = "ü" + assert clsname == unicodedata.normalize("NFKC", clsname) attrname = "ß" + assert attrname == unicodedata.normalize("NFKC", attrname) C = make_class(clsname, [attrname], repr=False) @@ -1118,17 +1120,19 @@ def test_normalized_unicode_attr_args(self): kwargs = {"ß": 1} c = C(**kwargs) - assert c.ß == 1 + assert 1 == c.ß def test_unnormalized_unicode_attr_args(self): """ - Unicode identifiers are normalized to NFKC form in Python + Unicode identifiers are normalized to NFKC form in Python. """ clsname = "Ŀ" + assert clsname != unicodedata.normalize("NFKC", clsname) attrname = "ㅁ" + assert attrname != unicodedata.normalize("NFKC", attrname) C = make_class(clsname, [attrname], repr=False) @@ -1137,7 +1141,7 @@ def test_unnormalized_unicode_attr_args(self): kwargs = {unicodedata.normalize("NFKC", attrname): 1} c = C(**kwargs) - assert c.ㅁ == 1 + assert 1 == c.ㅁ def test_catches_wrong_attrs_type(self): """ From fc8b9c6af03e812b1609a3ec0c4e873573e18ad2 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Sun, 9 Feb 2025 08:06:50 +0100 Subject: [PATCH 3/3] Add changelog --- changelog.d/1406.change.md | 1 + src/attr/_make.py | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog.d/1406.change.md diff --git a/changelog.d/1406.change.md b/changelog.d/1406.change.md new file mode 100644 index 000000000..4eae78acd --- /dev/null +++ b/changelog.d/1406.change.md @@ -0,0 +1 @@ +`attrs.make_class()` now allows for Unicode class names. diff --git a/src/attr/_make.py b/src/attr/_make.py index 9491057ad..a7a4075af 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -2908,6 +2908,7 @@ def make_class( .. versionadded:: 17.1.0 *bases* .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. .. versionchanged:: 23.2.0 *class_body* + .. versionchanged:: 25.2.0 Class names can now be unicode. """ # Class identifiers are converted into the normal form NFKC while parsing name = unicodedata.normalize("NFKC", name)