diff --git a/README.rst b/README.rst index d4bd4e0c7..844ffff69 100644 --- a/README.rst +++ b/README.rst @@ -74,9 +74,9 @@ automatically encoded giving canonical representation as result: .. code-block:: pycon - >>> url = URL('https://www.python.org/путь') + >>> url = URL('https://www.python.org/шлях') >>> url - URL('https://www.python.org/%D0%BF%D1%83%D1%82%D1%8C') + URL('https://www.python.org/%D1%88%D0%BB%D1%8F%D1%85') Regular properties are *percent-decoded*, use ``raw_`` versions for getting *encoded* strings: @@ -84,17 +84,17 @@ getting *encoded* strings: .. code-block:: pycon >>> url.path - '/путь' + '/шлях' >>> url.raw_path - '/%D0%BF%D1%83%D1%82%D1%8C' + '/%D1%88%D0%BB%D1%8F%D1%85' Human readable representation of URL is available as ``.human_repr()``: .. code-block:: pycon >>> url.human_repr() - 'https://www.python.org/путь' + 'https://www.python.org/шлях' For full documentation please read https://yarl.aio-libs.org. diff --git a/benchmark.py b/benchmark.py index e9741af66..a592f6138 100644 --- a/benchmark.py +++ b/benchmark.py @@ -41,14 +41,14 @@ print( "Cython quote: {:.3f} sec".format( - timeit.timeit("q(s)", cython_setup + "s='/путь/файл';q=Quoter()") + timeit.timeit("q(s)", cython_setup + "s='/шлях/файл';q=Quoter()") ) ) print( "Python quote: {:.3f} sec".format( - timeit.timeit("q(s)", python_setup + "s='/путь/файл';q=Quoter()") + timeit.timeit("q(s)", python_setup + "s='/шлях/файл';q=Quoter()") ) ) diff --git a/docs/api.rst b/docs/api.rst index 03284c2e2..5a4c32596 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -54,8 +54,8 @@ But for *non-ascii* case *encoding* is applied. .. doctest:: - >>> str(URL('http://εμπορικόσήμα.eu/путь/這裡')) - 'http://xn--jxagkqfkduily1i.eu/%D0%BF%D1%83%D1%82%D1%8C/%E9%80%99%E8%A3%A1' + >>> str(URL('http://εμπορικόσήμα.eu/шлях/這裡')) + 'http://xn--jxagkqfkduily1i.eu/%D1%88%D0%BB%D1%8F%D1%85/%E9%80%99%E8%A3%A1' The same is true for *user*, *password*, *query* and *fragment* parts of URL. @@ -70,11 +70,11 @@ Use :meth:`~URL.human_repr` for getting human readable representation: .. doctest:: - >>> url = URL('http://εμπορικόσήμα.eu/путь/這裡') + >>> url = URL('http://εμπορικόσήμα.eu/шлях/這裡') >>> str(url) - 'http://xn--jxagkqfkduily1i.eu/%D0%BF%D1%83%D1%82%D1%8C/%E9%80%99%E8%A3%A1' + 'http://xn--jxagkqfkduily1i.eu/%D1%88%D0%BB%D1%8F%D1%85/%E9%80%99%E8%A3%A1' >>> url.human_repr() - 'http://εμπορικόσήμα.eu/путь/這裡' + 'http://εμπορικόσήμα.eu/шлях/這裡' .. note:: @@ -120,8 +120,8 @@ There are two kinds of properties: *decoded* and *encoded* (with >>> URL('http://john@example.com').user 'john' - >>> URL('http://андрей@example.com').user - 'андрей' + >>> URL('http://бажан@example.com').user + 'бажан' >>> URL('http://example.com').user is None True @@ -133,8 +133,8 @@ There are two kinds of properties: *decoded* and *encoded* (with .. doctest:: - >>> URL('http://андрей@example.com').raw_user - '%D0%B0%D0%BD%D0%B4%D1%80%D0%B5%D0%B9' + >>> URL('http://довбуш@example.com').raw_user + '%D0%B4%D0%BE%D0%B2%D0%B1%D1%83%D1%88' >>> URL('http://example.com').raw_user is None True @@ -147,7 +147,7 @@ There are two kinds of properties: *decoded* and *encoded* (with >>> URL('http://john:pass@example.com').password 'pass' - >>> URL('http://андрей:пароль@example.com').password + >>> URL('http://степан:пароль@example.com').password 'пароль' >>> URL('http://example.com').password is None True @@ -265,8 +265,8 @@ There are two kinds of properties: *decoded* and *encoded* (with >>> URL('http://example.com/path/to').path '/path/to' - >>> URL('http://example.com/путь/сюда').path - '/путь/сюда' + >>> URL('http://example.com/шлях/сюди').path + '/шлях/сюди' >>> URL('http://example.com').path '/' @@ -287,8 +287,8 @@ There are two kinds of properties: *decoded* and *encoded* (with .. doctest:: - >>> URL('http://example.com/путь/сюда?ключ=знач').raw_path_qs - '/%D0%BF%D1%83%D1%82%D1%8C/%D1%81%D1%8E%D0%B4%D0%B0?%D0%BA%D0%BB%D1%8E%D1%87=%D0%B7%D0%BD%D0%B0%D1%87' + >>> URL('http://example.com/шлях/сюди?ключ=знач').raw_path_qs + '/%D1%88%D0%BB%D1%8F%D1%85/%D1%81%D1%8E%D0%B4%D0%B8?%D0%BA%D0%BB%D1%8E%D1%87=%D0%B7%D0%BD%D0%B0%D1%87' .. versionadded:: 0.15 @@ -298,8 +298,8 @@ There are two kinds of properties: *decoded* and *encoded* (with .. doctest:: - >>> URL('http://example.com/путь/сюда').raw_path - '/%D0%BF%D1%83%D1%82%D1%8C/%D1%81%D1%8E%D0%B4%D0%B0' + >>> URL('http://example.com/шлях/сюди').raw_path + '/%D1%88%D0%BB%D1%8F%D1%85/%D1%81%D1%8E%D0%B4%D0%B8' .. attribute:: URL.query_string @@ -333,8 +333,8 @@ There are two kinds of properties: *decoded* and *encoded* (with >>> URL('http://example.com/path#fragment').fragment 'fragment' - >>> URL('http://example.com/path#якорь').fragment - 'якорь' + >>> URL('http://example.com/path#якір').fragment + 'якір' >>> URL('http://example.com/path').fragment '' @@ -344,8 +344,8 @@ There are two kinds of properties: *decoded* and *encoded* (with .. doctest:: - >>> URL('http://example.com/path#якорь').raw_fragment - '%D1%8F%D0%BA%D0%BE%D1%80%D1%8C' + >>> URL('http://example.com/path#якір').raw_fragment + '%D1%8F%D0%BA%D1%96%D1%80' @@ -361,8 +361,8 @@ For *path* and *query* *yarl* supports additional helpers: >>> URL('http://example.com/path/to').parts ('/', 'path', 'to') - >>> URL('http://example.com/путь/сюда').parts - ('/', 'путь', 'сюда') + >>> URL('http://example.com/шлях/сюди').parts + ('/', 'шлях', 'сюди') >>> URL('http://example.com').parts ('/',) @@ -373,8 +373,8 @@ For *path* and *query* *yarl* supports additional helpers: .. doctest:: - >>> URL('http://example.com/путь/сюда').raw_parts - ('/', '%D0%BF%D1%83%D1%82%D1%8C', '%D1%81%D1%8E%D0%B4%D0%B0') + >>> URL('http://example.com/шлях/сюди').raw_parts + ('/', '%D1%88%D0%BB%D1%8F%D1%85', '%D1%81%D1%8E%D0%B4%D0%B8') .. attribute:: URL.name @@ -384,8 +384,8 @@ For *path* and *query* *yarl* supports additional helpers: >>> URL('http://example.com/path/to').name 'to' - >>> URL('http://example.com/путь/сюда').name - 'сюда' + >>> URL('http://example.com/шлях/сюди').name + 'сюди' >>> URL('http://example.com/path/').name '' @@ -395,8 +395,8 @@ For *path* and *query* *yarl* supports additional helpers: .. doctest:: - >>> URL('http://example.com/путь/сюда').raw_name - '%D1%81%D1%8E%D0%B4%D0%B0' + >>> URL('http://example.com/шлях/сюди').raw_name + '%D1%81%D1%8E%D0%B4%D0%B8' .. attribute:: URL.suffix @@ -406,8 +406,8 @@ For *path* and *query* *yarl* supports additional helpers: >>> URL('http://example.com/path/to.txt').suffix '.txt' - >>> URL('http://example.com/путь.сюда').suffix - '.сюда' + >>> URL('http://example.com/шлях.сюди').suffix + '.сюди' >>> URL('http://example.com/path').suffix '' @@ -417,8 +417,8 @@ For *path* and *query* *yarl* supports additional helpers: .. doctest:: - >>> URL('http://example.com/путь.сюда').raw_suffix - '.%D1%81%D1%8E%D0%B4%D0%B0' + >>> URL('http://example.com/шлях.сюди').raw_suffix + '.%D1%81%D1%8E%D0%B4%D0%B8' .. attribute:: URL.suffixes @@ -428,8 +428,8 @@ For *path* and *query* *yarl* supports additional helpers: >>> URL('http://example.com/path/to.tar.gz').suffixes ('.tar', '.gz') - >>> URL('http://example.com/путь.тут.да').suffixes - ('.тут', '.да') + >>> URL('http://example.com/шлях.тут.ось').suffixes + ('.тут', '.ось') >>> URL('http://example.com/path').suffixes () @@ -439,8 +439,8 @@ For *path* and *query* *yarl* supports additional helpers: .. doctest:: - >>> URL('http://example.com/путь.тут.да').raw_suffixes - ('.%D1%82%D1%83%D1%82', '.%D0%B4%D0%B0') + >>> URL('http://example.com/шлях.тут.ось').raw_suffixes + ('.%D1%82%D1%83%D1%82', '.%D0%BE%D1%81%D1%8C') .. attribute:: URL.query @@ -546,8 +546,8 @@ section generates a new :class:`URL` instance. >>> URL('http://user:pass@example.com').with_user('new_user') URL('http://new_user:pass@example.com') - >>> URL('http://user:pass@example.com').with_user('вася') - URL('http://%D0%B2%D0%B0%D1%81%D1%8F:pass@example.com') + >>> URL('http://user:pass@example.com').with_user('олекса') + URL('http://%D0%BE%D0%BB%D0%B5%D0%BA%D1%81%D0%B0:pass@example.com') >>> URL('http://user:pass@example.com').with_user(None) URL('http://example.com') @@ -739,8 +739,8 @@ section generates a new :class:`URL` instance. >>> URL('http://example.com/path#frag').with_fragment('anchor') URL('http://example.com/path#anchor') - >>> URL('http://example.com/path#frag').with_fragment('якорь') - URL('http://example.com/path#%D1%8F%D0%BA%D0%BE%D1%80%D1%8C') + >>> URL('http://example.com/path#frag').with_fragment('якір') + URL('http://example.com/path#%D1%8F%D0%BA%D1%96%D1%80') >>> URL('http://example.com/path#frag').with_fragment(None) URL('http://example.com/path') @@ -755,8 +755,8 @@ section generates a new :class:`URL` instance. >>> URL('http://example.com/path/to?arg#frag').with_name('new') URL('http://example.com/path/new') - >>> URL('http://example.com/path/to').with_name('имя') - URL('http://example.com/path/%D0%B8%D0%BC%D1%8F') + >>> URL('http://example.com/path/to').with_name("ім'я") + URL('http://example.com/path/%D1%96%D0%BC%27%D1%8F') .. method:: URL.with_suffix(suffix) @@ -769,8 +769,8 @@ section generates a new :class:`URL` instance. >>> URL('http://example.com/path/to?arg#frag').with_suffix('.doc') URL('http://example.com/path/to.doc') - >>> URL('http://example.com/path/to').with_suffix('.cуффикс') - URL('http://example.com/path/to.c%D1%83%D1%84%D1%84%D0%B8%D0%BA%D1%81') + >>> URL('http://example.com/path/to').with_suffix('.cуфікс') + URL('http://example.com/path/to.c%D1%83%D1%84%D1%96%D0%BA%D1%81') .. attribute:: URL.parent @@ -816,9 +816,9 @@ The path is encoded if needed. URL('http://example.com/path/to/subpath') >>> url.parts ('/', 'path', 'to', 'subpath') - >>> url = URL('http://example.com/path?arg#frag') / 'сюда' + >>> url = URL('http://example.com/path?arg#frag') / 'сюди' >>> url - URL('http://example.com/path/%D1%81%D1%8E%D0%B4%D0%B0') + URL('http://example.com/path/%D1%81%D1%8E%D0%B4%D0%B8') .. method:: URL.joinpath(*other, encoded=False) @@ -835,12 +835,12 @@ The path is encoded if needed. URL('http://example.com/path/to/subpath') >>> url.parts ('/', 'path', 'to', 'subpath') - >>> url = URL('http://example.com/path?arg#frag').joinpath('сюда') + >>> url = URL('http://example.com/path?arg#frag').joinpath('сюди') >>> url - URL('http://example.com/path/%D1%81%D1%8E%D0%B4%D0%B0') - >>> url = URL('http://example.com/path').joinpath('%D1%81%D1%8E%D0%B4%D0%B0', encoded=True) + URL('http://example.com/path/%D1%81%D1%8E%D0%B4%D0%B8') + >>> url = URL('http://example.com/path').joinpath('%D1%81%D1%8E%D0%B4%D0%B8', encoded=True) >>> url - URL('http://example.com/path/%D1%81%D1%8E%D0%B4%D0%B0') + URL('http://example.com/path/%D1%81%D1%8E%D0%B4%D0%B8') .. versionadded:: 1.9 diff --git a/docs/index.rst b/docs/index.rst index 50c930f24..1e4e64b6a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -61,9 +61,9 @@ automatically encoded giving canonical representation as result: .. doctest:: - >>> url = URL('https://www.python.org/путь') + >>> url = URL('https://www.python.org/шлях') >>> url - URL('https://www.python.org/%D0%BF%D1%83%D1%82%D1%8C') + URL('https://www.python.org/%D1%88%D0%BB%D1%8F%D1%85') Regular properties are *percent-decoded*, use ``raw_`` versions for getting *encoded* strings: @@ -71,17 +71,17 @@ getting *encoded* strings: .. doctest:: >>> url.path - '/путь' + '/шлях' >>> url.raw_path - '/%D0%BF%D1%83%D1%82%D1%8C' + '/%D1%88%D0%BB%D1%8F%D1%85' Human readable representation of URL is available as :meth:`~yarl.URL.human_repr`: .. doctest:: >>> url.human_repr() - 'https://www.python.org/путь' + 'https://www.python.org/шлях' For full documentation please read :ref:`yarl-api` section. diff --git a/tests/test_url.py b/tests/test_url.py index 295c0639c..725e9465b 100644 --- a/tests/test_url.py +++ b/tests/test_url.py @@ -64,8 +64,8 @@ def test_origin(): def test_origin_nonascii(): - url = URL("http://user:password@историк.рф:8888/path/to?a=1&b=2") - assert str(url.origin()) == "http://xn--h1aagokeh.xn--p1ai:8888" + url = URL("http://user:password@оун-упа.укр:8888/path/to?a=1&b=2") + assert str(url.origin()) == "http://xn----8sb1bdhvc.xn--j1amh:8888" def test_origin_ipv6(): @@ -117,8 +117,8 @@ def test_raw_user(): def test_raw_user_non_ascii(): - url = URL("http://вася@example.com") - assert "%D0%B2%D0%B0%D1%81%D1%8F" == url.raw_user + url = URL("http://бажан@example.com") + assert "%D0%B1%D0%B0%D0%B6%D0%B0%D0%BD" == url.raw_user def test_no_user(): @@ -127,8 +127,8 @@ def test_no_user(): def test_user_non_ascii(): - url = URL("http://вася@example.com") - assert "вася" == url.user + url = URL("http://бажан@example.com") + assert "бажан" == url.user def test_raw_password(): @@ -164,13 +164,13 @@ def test_raw_host(): def test_raw_host_non_ascii(): - url = URL("http://историк.рф") - assert "xn--h1aagokeh.xn--p1ai" == url.raw_host + url = URL("http://оун-упа.укр") + assert "xn----8sb1bdhvc.xn--j1amh" == url.raw_host def test_host_non_ascii(): - url = URL("http://историк.рф") - assert "историк.рф" == url.host + url = URL("http://оун-упа.укр") + assert "оун-упа.укр" == url.host def test_localhost(): @@ -210,12 +210,13 @@ def test_authority_short() -> None: def test_authority_full_nonasci() -> None: - url = URL("http://ваня:пароль@айдеко.рф:8080/path") + url = URL("http://степан:пароль@слава.укр:8080/path") assert url.raw_authority == ( - "%D0%B2%D0%B0%D0%BD%D1%8F:%D0%BF%D0%B0%D1%80%D0%BE%D0%BB%D1%8C@" - "xn--80aidohy.xn--p1ai:8080" + "%D1%81%D1%82%D0%B5%D0%BF%D0%B0%D0%BD:" + "%D0%BF%D0%B0%D1%80%D0%BE%D0%BB%D1%8C@" + "xn--80aaf8a3a.xn--j1amh:8080" ) - assert url.authority == "ваня:пароль@айдеко.рф:8080" + assert url.authority == "степан:пароль@слава.укр:8080" def test_lowercase(): @@ -225,9 +226,9 @@ def test_lowercase(): def test_lowercase_nonascii(): - url = URL("http://Айдеко.Рф") - assert url.raw_host == "xn--80aidohy.xn--p1ai" - assert url.host == "айдеко.рф" + url = URL("http://Слава.Укр") + assert url.raw_host == "xn--80aaf8a3a.xn--j1amh" + assert url.host == "слава.укр" def test_compressed_ipv6(): @@ -294,13 +295,13 @@ def test_raw_path(): def test_raw_path_non_ascii(): - url = URL("http://example.com/путь/сюда") - assert "/%D0%BF%D1%83%D1%82%D1%8C/%D1%81%D1%8E%D0%B4%D0%B0" == url.raw_path + url = URL("http://example.com/шлях/сюди") + assert "/%D1%88%D0%BB%D1%8F%D1%85/%D1%81%D1%8E%D0%B4%D0%B8" == url.raw_path def test_path_non_ascii(): - url = URL("http://example.com/путь/сюда") - assert "/путь/сюда" == url.path + url = URL("http://example.com/шлях/сюди") + assert "/шлях/сюди" == url.path def test_path_with_spaces(): @@ -352,8 +353,8 @@ def test_raw_path_qs(): assert url.raw_path_qs == "/?%D0%B1=%D0%B2&%D1%8E=%D0%BA" url = URL("http://example.com/path?б=в&ю=к") assert url.raw_path_qs == "/path?%D0%B1=%D0%B2&%D1%8E=%D0%BA" - url = URL("http://example.com/путь?a=1&b=2") - assert url.raw_path_qs == "/%D0%BF%D1%83%D1%82%D1%8C?a=1&b=2" + url = URL("http://example.com/шлях?a=1&b=2") + assert url.raw_path_qs == "/%D1%88%D0%BB%D1%8F%D1%85?a=1&b=2" def test_query_string_spaces(): @@ -375,8 +376,8 @@ def test_raw_fragment(): def test_raw_fragment_non_ascii(): - url = URL("http://example.com/path#якорь") - assert "%D1%8F%D0%BA%D0%BE%D1%80%D1%8C" == url.raw_fragment + url = URL("http://example.com/path#якір") + assert "%D1%8F%D0%BA%D1%96%D1%80" == url.raw_fragment def test_raw_fragment_safe(): @@ -385,8 +386,8 @@ def test_raw_fragment_safe(): def test_fragment_non_ascii(): - url = URL("http://example.com/path#якорь") - assert "якорь" == url.fragment + url = URL("http://example.com/path#якір") + assert "якір" == url.fragment def test_raw_parts_empty(): @@ -435,17 +436,17 @@ def test_parts_for_empty_url(): def test_raw_parts_non_ascii(): - url = URL("http://example.com/путь/сюда") + url = URL("http://example.com/шлях/сюди") assert ( "/", - "%D0%BF%D1%83%D1%82%D1%8C", - "%D1%81%D1%8E%D0%B4%D0%B0", + "%D1%88%D0%BB%D1%8F%D1%85", + "%D1%81%D1%8E%D0%B4%D0%B8", ) == url.raw_parts def test_parts_non_ascii(): - url = URL("http://example.com/путь/сюда") - assert ("/", "путь", "сюда") == url.parts + url = URL("http://example.com/шлях/сюди") + assert ("/", "шлях", "сюди") == url.parts def test_name_for_empty_url(): @@ -489,8 +490,8 @@ def test_relative_raw_name_slash(): def test_name_non_ascii(): - url = URL("http://example.com/путь") - assert url.name == "путь" + url = URL("http://example.com/шлях") + assert url.name == "шлях" def test_suffix_for_empty_url(): @@ -534,8 +535,8 @@ def test_relative_raw_suffix_dot(): def test_suffix_non_ascii(): - url = URL("http://example.com/путь.суффикс") - assert url.suffix == ".суффикс" + url = URL("http://example.com/шлях.суфікс") + assert url.suffix == ".суфікс" def test_suffix_with_empty_name(): @@ -594,8 +595,8 @@ def test_relative_raw_suffixes_dot(): def test_suffixes_non_ascii(): - url = URL("http://example.com/путь.суффикс") - assert url.suffixes == (".суффикс",) + url = URL("http://example.com/шлях.суфікс") + assert url.suffixes == (".суфікс",) def test_suffixes_with_empty_name(): @@ -753,15 +754,15 @@ def test_div_for_relative_url_started_with_slash(): def test_div_non_ascii(): - url = URL("http://example.com/сюда") - url2 = url / "туда" - assert url2.path == "/сюда/туда" - assert url2.raw_path == "/%D1%81%D1%8E%D0%B4%D0%B0/%D1%82%D1%83%D0%B4%D0%B0" - assert url2.parts == ("/", "сюда", "туда") + url = URL("http://example.com/сюди") + url2 = url / "туди" + assert url2.path == "/сюди/туди" + assert url2.raw_path == "/%D1%81%D1%8E%D0%B4%D0%B8/%D1%82%D1%83%D0%B4%D0%B8" + assert url2.parts == ("/", "сюди", "туди") assert url2.raw_parts == ( "/", - "%D1%81%D1%8E%D0%B4%D0%B0", - "%D1%82%D1%83%D0%B4%D0%B0", + "%D1%81%D1%8E%D0%B4%D0%B8", + "%D1%82%D1%83%D0%B4%D0%B8", ) @@ -846,13 +847,13 @@ def test_joinpath_relative(url, to_join, expected): "url,to_join,encoded,e_path,e_raw_path,e_parts,e_raw_parts", [ pytest.param( - "http://example.com/сюда", - ("туда",), + "http://example.com/сюди", + ("туди",), False, - "/сюда/туда", - "/%D1%81%D1%8E%D0%B4%D0%B0/%D1%82%D1%83%D0%B4%D0%B0", - ("/", "сюда", "туда"), - ("/", "%D1%81%D1%8E%D0%B4%D0%B0", "%D1%82%D1%83%D0%B4%D0%B0"), + "/сюди/туди", + "/%D1%81%D1%8E%D0%B4%D0%B8/%D1%82%D1%83%D0%B4%D0%B8", + ("/", "сюди", "туди"), + ("/", "%D1%81%D1%8E%D0%B4%D0%B8", "%D1%82%D1%83%D0%B4%D0%B8"), id="non-ascii", ), pytest.param( @@ -1093,11 +1094,11 @@ def test_with_name_empty(): def test_with_name_non_ascii(): - url = URL("http://example.com/path").with_name("путь") - assert url.path == "/путь" - assert url.raw_path == "/%D0%BF%D1%83%D1%82%D1%8C" - assert url.parts == ("/", "путь") - assert url.raw_parts == ("/", "%D0%BF%D1%83%D1%82%D1%8C") + url = URL("http://example.com/path").with_name("шлях") + assert url.path == "/шлях" + assert url.raw_path == "/%D1%88%D0%BB%D1%8F%D1%85" + assert url.parts == ("/", "шлях") + assert url.raw_parts == ("/", "%D1%88%D0%BB%D1%8F%D1%85") def test_with_name_percent_encoded(): @@ -1185,11 +1186,11 @@ def test_with_suffix_empty(): def test_with_suffix_non_ascii(): - url = URL("http://example.com/path").with_suffix(".путь") - assert url.path == "/path.путь" - assert url.raw_path == "/path.%D0%BF%D1%83%D1%82%D1%8C" - assert url.parts == ("/", "path.путь") - assert url.raw_parts == ("/", "path.%D0%BF%D1%83%D1%82%D1%8C") + url = URL("http://example.com/path").with_suffix(".шлях") + assert url.path == "/path.шлях" + assert url.raw_path == "/path.%D1%88%D0%BB%D1%8F%D1%85" + assert url.parts == ("/", "path.шлях") + assert url.raw_parts == ("/", "path.%D1%88%D0%BB%D1%8F%D1%85") def test_with_suffix_percent_encoded(): @@ -1340,8 +1341,8 @@ def test_from_ascii_login(): def test_from_non_ascii_login(): - url = URL("http://вася@host:1234/") - assert ("http://" "%D0%B2%D0%B0%D1%81%D1%8F" "@host:1234/") == str(url) + url = URL("http://бажан@host:1234/") + assert ("http://%D0%B1%D0%B0%D0%B6%D0%B0%D0%BD@host:1234/") == str(url) def test_from_ascii_login_and_password(): @@ -1360,10 +1361,10 @@ def test_from_ascii_login_and_password(): def test_from_non_ascii_login_and_password(): - url = URL("http://вася:пароль@host:1234/") + url = URL("http://бажан:пароль@host:1234/") assert ( "http://" - "%D0%B2%D0%B0%D1%81%D1%8F" + "%D0%B1%D0%B0%D0%B6%D0%B0%D0%BD" ":%D0%BF%D0%B0%D1%80%D0%BE%D0%BB%D1%8C" "@host:1234/" ) == str(url) @@ -1384,16 +1385,16 @@ def test_from_ascii_path_lower_case(): def test_from_non_ascii_path(): - url = URL("http://example.com/путь/туда") + url = URL("http://example.com/шлях/туди") assert ( - "http://example.com/" "%D0%BF%D1%83%D1%82%D1%8C/%D1%82%D1%83%D0%B4%D0%B0" + "http://example.com/%D1%88%D0%BB%D1%8F%D1%85/%D1%82%D1%83%D0%B4%D0%B8" ) == str(url) def test_bytes(): - url = URL("http://example.com/путь/туда") + url = URL("http://example.com/шлях/туди") assert ( - b"http://example.com/%D0%BF%D1%83%D1%82%D1%8C/%D1%82%D1%83%D0%B4%D0%B0" + b"http://example.com/%D1%88%D0%BB%D1%8F%D1%85/%D1%82%D1%83%D0%B4%D0%B8" == bytes(url) ) @@ -1610,23 +1611,23 @@ def test_split_result_non_decoded(): def test_human_repr(): - url = URL("http://вася:пароль@хост.домен:8080/путь/сюда?арг=вал#фраг") + url = URL("http://бажан:пароль@хост.домен:8080/шлях/сюди?арг=вал#фраг") s = url.human_repr() assert URL(s) == url - assert s == "http://вася:пароль@хост.домен:8080/путь/сюда?арг=вал#фраг" + assert s == "http://бажан:пароль@хост.домен:8080/шлях/сюди?арг=вал#фраг" def test_human_repr_defaults(): - url = URL("путь") + url = URL("шлях") s = url.human_repr() - assert s == "путь" + assert s == "шлях" def test_human_repr_default_port(): - url = URL("http://вася:пароль@хост.домен/путь/сюда?арг=вал#фраг") + url = URL("http://бажан:пароль@хост.домен/шлях/сюди?арг=вал#фраг") s = url.human_repr() assert URL(s) == url - assert s == "http://вася:пароль@хост.домен/путь/сюда?арг=вал#фраг" + assert s == "http://бажан:пароль@хост.домен/шлях/сюди?арг=вал#фраг" def test_human_repr_ipv6(): @@ -1667,20 +1668,20 @@ def test_human_repr_delimiters(): def test_human_repr_non_printable(): url = URL.build( scheme="http", - user="вася\n\xad\u200b", + user="бажан\n\xad\u200b", password="пароль\n\xad\u200b", host="хост.домен", port=8080, - path="/путь\n\xad\u200b", + path="/шлях\n\xad\u200b", query={"арг\n\xad\u200b": "вал\n\xad\u200b"}, fragment="фраг\n\xad\u200b", ) s = url.human_repr() assert URL(s) == url assert ( - s == "http://вася%0A%C2%AD%E2%80%8B:пароль%0A%C2%AD%E2%80%8B" + s == "http://бажан%0A%C2%AD%E2%80%8B:пароль%0A%C2%AD%E2%80%8B" "@хост.домен:8080" - "/путь%0A%C2%AD%E2%80%8B" + "/шлях%0A%C2%AD%E2%80%8B" "?арг%0A%C2%AD%E2%80%8B=вал%0A%C2%AD%E2%80%8B" "#фраг%0A%C2%AD%E2%80%8B" ) diff --git a/tests/test_url_build.py b/tests/test_url_build.py index ed077368a..5aecbc585 100644 --- a/tests/test_url_build.py +++ b/tests/test_url_build.py @@ -101,8 +101,10 @@ def test_build_with_authority_and_host(): def test_build_with_authority(): - url = URL.build(scheme="http", authority="ваня:bar@host.com:8000", path="path") - assert str(url) == "http://%D0%B2%D0%B0%D0%BD%D1%8F:bar@host.com:8000/path" + url = URL.build(scheme="http", authority="степан:bar@host.com:8000", path="path") + assert ( + str(url) == "http://%D1%81%D1%82%D0%B5%D0%BF%D0%B0%D0%BD:bar@host.com:8000/path" + ) def test_build_with_authority_without_encoding(): @@ -125,23 +127,33 @@ def test_query_dict(): def test_build_path_quoting(): u = URL.build( - scheme="http", host="127.0.0.1", path="/файл.jpg", query=dict(arg="Привет") + scheme="http", + host="127.0.0.1", + path="/фотографія.jpg", + query=dict(arg="Привіт"), ) - assert u == URL("http://127.0.0.1/файл.jpg?arg=Привет") + assert u == URL("http://127.0.0.1/фотографія.jpg?arg=Привіт") assert str(u) == ( - "http://127.0.0.1/%D1%84%D0%B0%D0%B9%D0%BB.jpg?" - "arg=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82" + "http://127.0.0.1/" + "%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%8F.jpg?" + "arg=%D0%9F%D1%80%D0%B8%D0%B2%D1%96%D1%82" ) def test_build_query_quoting(): - u = URL.build(scheme="http", host="127.0.0.1", path="/файл.jpg", query="arg=Привет") + u = URL.build( + scheme="http", + host="127.0.0.1", + path="/фотографія.jpg", + query="arg=Привіт", + ) - assert u == URL("http://127.0.0.1/файл.jpg?arg=Привет") + assert u == URL("http://127.0.0.1/фотографія.jpg?arg=Привіт") assert str(u) == ( - "http://127.0.0.1/%D1%84%D0%B0%D0%B9%D0%BB.jpg?" - "arg=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82" + "http://127.0.0.1/" + "%D1%84%D0%BE%D1%82%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D1%96%D1%8F.jpg?" + "arg=%D0%9F%D1%80%D0%B8%D0%B2%D1%96%D1%82" ) @@ -159,14 +171,14 @@ def test_build_drop_dots(): def test_build_encode(): u = URL.build( scheme="http", - host="историк.рф", - path="/путь/файл", + host="оун-упа.укр", + path="/шлях/криївка", query_string="ключ=знач", fragment="фраг", ) expected = ( - "http://xn--h1aagokeh.xn--p1ai" - "/%D0%BF%D1%83%D1%82%D1%8C/%D1%84%D0%B0%D0%B9%D0%BB" + "http://xn----8sb1bdhvc.xn--j1amh" + "/%D1%88%D0%BB%D1%8F%D1%85/%D0%BA%D1%80%D0%B8%D1%97%D0%B2%D0%BA%D0%B0" "?%D0%BA%D0%BB%D1%8E%D1%87=%D0%B7%D0%BD%D0%B0%D1%87" "#%D1%84%D1%80%D0%B0%D0%B3" ) @@ -177,13 +189,13 @@ def test_build_already_encoded(): # resulting URL is invalid but not encoded u = URL.build( scheme="http", - host="историк.рф", - path="/путь/файл", + host="оун-упа.укр", + path="/шлях/криївка", query_string="ключ=знач", fragment="фраг", encoded=True, ) - assert str(u) == "http://историк.рф/путь/файл?ключ=знач#фраг" + assert str(u) == "http://оун-упа.укр/шлях/криївка?ключ=знач#фраг" def test_build_percent_encoded(): diff --git a/tests/test_url_update_netloc.py b/tests/test_url_update_netloc.py index cf0cc1c44..47d13bcd6 100644 --- a/tests/test_url_update_netloc.py +++ b/tests/test_url_update_netloc.py @@ -33,11 +33,11 @@ def test_with_user(): def test_with_user_non_ascii(): url = URL("http://example.com") - url2 = url.with_user("вася") - assert url2.raw_user == "%D0%B2%D0%B0%D1%81%D1%8F" - assert url2.user == "вася" - assert url2.raw_authority == "%D0%B2%D0%B0%D1%81%D1%8F@example.com" - assert url2.authority == "вася@example.com:80" + url2 = url.with_user("бажан") + assert url2.raw_user == "%D0%B1%D0%B0%D0%B6%D0%B0%D0%BD" + assert url2.user == "бажан" + assert url2.raw_authority == "%D0%B1%D0%B0%D0%B6%D0%B0%D0%BD@example.com" + assert url2.authority == "бажан@example.com:80" def test_with_user_percent_encoded(): @@ -159,11 +159,11 @@ def test_with_host_empty(): def test_with_host_non_ascii(): url = URL("http://example.com:123") - url2 = url.with_host("историк.рф") - assert url2.raw_host == "xn--h1aagokeh.xn--p1ai" - assert url2.host == "историк.рф" - assert url2.raw_authority == "xn--h1aagokeh.xn--p1ai:123" - assert url2.authority == "историк.рф:123" + url2 = url.with_host("оун-упа.укр") + assert url2.raw_host == "xn----8sb1bdhvc.xn--j1amh" + assert url2.host == "оун-упа.укр" + assert url2.raw_authority == "xn----8sb1bdhvc.xn--j1amh:123" + assert url2.authority == "оун-упа.укр:123" def test_with_host_percent_encoded(): diff --git a/yarl/_url.py b/yarl/_url.py index d5202db16..9cca27ef8 100644 --- a/yarl/_url.py +++ b/yarl/_url.py @@ -509,7 +509,7 @@ def host(self): return None if "%" in raw: # Hack for scoped IPv6 addresses like - # fe80::2%Проверка + # fe80::2%Перевірка # presence of '%' sign means only IPv6 address, so idna is useless. return raw return _idna_decode(raw)