1
0
mirror of https://github.com/django/django.git synced 2025-09-16 14:09:13 +00:00

Make punycode conversion support IDNA 2008

As a new dependency would be required it is kept optional, default would
be to used Python standard IDNA converter.
This commit is contained in:
Julien BERNARD 2022-11-09 14:54:59 -05:00
parent d6fbfea08d
commit 85b066c9f2
3 changed files with 21 additions and 9 deletions

View File

@ -211,7 +211,19 @@ def escape_uri_path(path):
def punycode(domain): def punycode(domain):
"""Return the Punycode of the given domain if it's non-ASCII.""" """Return the Punycode of the given domain if it's non-ASCII."""
return domain.encode("idna").decode("ascii") if not domain:
return domain
try:
# try importing idna package for IDNA 2008 compliance
import idna
# enable uts46 mapping for mapping: uppercase letters, normalization, etc.
return idna.encode(domain, uts46=True, transitional=False).decode("ascii")
except ImportError:
# will fall back to Python IDNA 2003
return domain.encode("idna").decode("ascii")
except idna.IDNAError as e:
raise UnicodeError(e) from e
def repercent_broken_unicode(path): def repercent_broken_unicode(path):

View File

@ -1062,11 +1062,11 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
), ),
# Address with long display name and unicode domain. # Address with long display name and unicode domain.
( (
("To Example very long" * 4, "to@exampl.com"), ("To Example very long" * 4, "to@examplе.com"),
"utf-8", "utf-8",
"To Example very longTo Example very longTo Example very longT" "To Example very longTo Example very longTo Example very longT"
"o Example very\n" "o Example very\n"
" long <to@xn--exampl-nc1c.com>", " long <to@xn--exampl-8of.com>",
), ),
): ):
with self.subTest(email_address=email_address, encoding=encoding): with self.subTest(email_address=email_address, encoding=encoding):

View File

@ -227,18 +227,18 @@ class FunctionTests(SimpleTestCase):
#13704 - Check urlize handles IDN correctly #13704 - Check urlize handles IDN correctly
""" """
self.assertEqual( self.assertEqual(
urlize("http://c✶.ws"), urlize("http://ça.ws"),
'<a href="http://xn--c-lgq.ws" rel="nofollow">http://c✶.ws</a>', '<a href="http://xn--a-5fa.ws" rel="nofollow">http://ça.ws</a>',
) )
self.assertEqual( self.assertEqual(
urlize("www.c✶.ws"), urlize("www.ça.ws"),
'<a href="http://www.xn--c-lgq.ws" rel="nofollow">www.c✶.ws</a>', '<a href="http://www.xn--a-5fa.ws" rel="nofollow">www.ça.ws</a>',
) )
self.assertEqual( self.assertEqual(
urlize("c✶.org"), '<a href="http://xn--c-lgq.org" rel="nofollow">c✶.org</a>' urlize("ça.org"), '<a href="http://xn--a-5fa.org" rel="nofollow">ça.org</a>'
) )
self.assertEqual( self.assertEqual(
urlize("info@c✶.org"), '<a href="mailto:info@xn--c-lgq.org">info@c✶.org</a>' urlize("info@ça.org"), '<a href="mailto:info@xn--a-5fa.org">info@ça.org</a>'
) )
def test_malformed(self): def test_malformed(self):