[Python-modules-commits] [yarl] 01/07: Import yarl_0.7.0.orig.tar.gz

Piotr Ożarowski piotr at moszumanska.debian.org
Mon Nov 7 21:51:13 UTC 2016


This is an automated email from the git hooks/post-receive script.

piotr pushed a commit to branch master
in repository yarl.

commit bab09dac17a4a328b1229158dd5aff4d04799945
Author: Piotr Ożarowski <piotr at debian.org>
Date:   Mon Nov 7 22:47:17 2016 +0100

    Import yarl_0.7.0.orig.tar.gz
---
 CHANGES.rst            |   11 +
 PKG-INFO               |   17 +-
 README.rst             |    4 +
 setup.cfg              |    4 +-
 setup.py               |    4 +-
 tests/test_quoting.py  |   32 ++
 tests/test_url.py      |   28 +-
 yarl.egg-info/PKG-INFO |   17 +-
 yarl/__init__.py       |   89 +++-
 yarl/_quoting.c        | 1060 ++++++++++++++++++++++++++++--------------------
 yarl/_quoting.pyx      |   29 +-
 yarl/quoting.py        |   20 +-
 12 files changed, 839 insertions(+), 476 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 7208d3f..64b348f 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,17 @@
 CHANGES
 =======
 
+0.7.0 (2016-11-07)
+------------------
+
+* Accept `int` as value for `.with_query()`
+
+0.6.0 (2016-11-07)
+------------------
+
+* Explicitly use UTF8 encoding in setup.py #20
+* Properly unquote non-UTF8 strings #19
+
 0.5.3 (2016-11-02)
 ------------------
 
diff --git a/PKG-INFO b/PKG-INFO
index 969b0c5..3cd1bf6 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: yarl
-Version: 0.5.3
+Version: 0.7.0
 Summary: Yet another URL library
 Home-page: https://github.com/aio-libs/yarl/
 Author: Andrew Svetlov
@@ -24,6 +24,10 @@ Description: yarl
             :target: https://yarl.readthedocs.io
         
         
+        .. image:: https://img.shields.io/pypi/pyversions/yarl.svg
+            :target: https://pypi.python.org/pypi/yarl
+        
+        
         Introduction
         ------------
         
@@ -160,6 +164,17 @@ Description: yarl
         CHANGES
         =======
         
+        0.7.0 (2016-11-07)
+        ------------------
+        
+        * Accept `int` as value for `.with_query()`
+        
+        0.6.0 (2016-11-07)
+        ------------------
+        
+        * Explicitly use UTF8 encoding in setup.py #20
+        * Properly unquote non-UTF8 strings #19
+        
         0.5.3 (2016-11-02)
         ------------------
         
diff --git a/README.rst b/README.rst
index c7fd138..2e017f8 100644
--- a/README.rst
+++ b/README.rst
@@ -16,6 +16,10 @@ yarl
     :target: https://yarl.readthedocs.io
 
 
+.. image:: https://img.shields.io/pypi/pyversions/yarl.svg
+    :target: https://pypi.python.org/pypi/yarl
+
+
 Introduction
 ------------
 
diff --git a/setup.cfg b/setup.cfg
index 4882edf..b4e7cea 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,7 +2,7 @@
 test = pytest
 
 [egg_info]
-tag_build = 
-tag_date = 0
 tag_svn_revision = 0
+tag_date = 0
+tag_build = 
 
diff --git a/setup.py b/setup.py
index 5dc1da2..7885ec9 100644
--- a/setup.py
+++ b/setup.py
@@ -51,7 +51,7 @@ class ve_build_ext(build_ext):
 here = pathlib.Path(__file__).parent
 fname = here / 'yarl' / '__init__.py'
 
-with codecs.open(str(fname), 'r', 'latin1') as fp:
+with fname.open(encoding='utf8') as fp:
     try:
         version = re.findall(r"^__version__ = '([^']+)'$", fp.read(), re.M)[0]
     except IndexError:
@@ -62,7 +62,7 @@ install_requires = ['multidict>=2.0']
 
 def read(name):
     fname = here / name
-    with fname.open() as f:
+    with fname.open(encoding='utf8') as f:
         return f.read()
 
 
diff --git a/tests/test_quoting.py b/tests/test_quoting.py
index 26d8b1c..bd2514c 100644
--- a/tests/test_quoting.py
+++ b/tests/test_quoting.py
@@ -222,3 +222,35 @@ def test_quote_bad_types(quote):
 def test_unquote_bad_types(unquote):
     with pytest.raises(TypeError):
         unquote(123)
+
+
+def test_quote_lowercase(quote):
+    assert quote('%d1%84') == '%D1%84'
+
+
+def test_quote_unquoted(quote):
+    assert quote('%41') == 'A'
+
+
+def test_unquote_unsafe(unquote):
+    assert unquote('%26', unsafe='&') == '%26'
+
+
+def test_unquote_unsafe2(unquote):
+    assert unquote('%26abc', unsafe='&') == '%26abc'
+
+
+def test_unquote_non_ascii(unquote):
+    assert unquote('%F8') == '%F8'
+
+
+def test_unquote_non_ascii_non_tailing(unquote):
+    assert unquote('%F8ab') == '%F8ab'
+
+
+def test_quote_non_ascii(quote):
+    assert quote('%F8') == '%F8'
+
+
+def test_quote_non_ascii2(quote):
+    assert quote('a%F8b') == 'a%F8b'
diff --git a/tests/test_url.py b/tests/test_url.py
index 8b1853e..f6c42a3 100644
--- a/tests/test_url.py
+++ b/tests/test_url.py
@@ -691,16 +691,11 @@ def test_with_query_kwargs_and_args_are_mutually_exclusive():
             {'a': '2', 'b': '4'}, a='1')
 
 
-def test_with_query_kwargs_should_be_str():
-    url = URL('http://example.com')
-    with pytest.raises(TypeError):
-        url.with_query(b=3)
-
-
 def test_with_query_only_single_arg_is_supported():
     url = URL('http://example.com')
-    with pytest.raises(TypeError):
-        url.with_query(b=3)
+    u1 = url.with_query(b=3)
+    u2 = URL('http://example.com/?b=3')
+    assert u1 == u2
     with pytest.raises(ValueError):
         url.with_query('a=1', 'a=b')
 
@@ -727,10 +722,15 @@ def test_with_query_str_non_ascii_and_spaces():
     assert url2.query_string == 'a=1+2&b=знач'
 
 
+def test_with_query_int():
+    url = URL('http://example.com')
+    assert url.with_query({'a': 1}) == URL('http://example.com/?a=1')
+
+
 def test_with_query_non_str():
     url = URL('http://example.com')
     with pytest.raises(TypeError):
-        url.with_query({'a': 1})
+        url.with_query({'a': 1.1})
 
 
 def test_with_query_multidict():
@@ -1259,3 +1259,13 @@ def test_relative_abs_parts_are_removed():
 def test_relative_fails_on_rel_url():
     with pytest.raises(ValueError):
         URL('/path?a=b#frag').relative()
+
+
+def test_slash_and_question_in_query():
+    u = URL('http://example.com/path?http://example.com/p?a#b')
+    assert u.query_string == 'http://example.com/p?a'
+
+
+def test_slash_and_question_in_fragment():
+    u = URL('http://example.com/path#http://example.com/p?a')
+    assert u.fragment == 'http://example.com/p?a'
diff --git a/yarl.egg-info/PKG-INFO b/yarl.egg-info/PKG-INFO
index 969b0c5..3cd1bf6 100644
--- a/yarl.egg-info/PKG-INFO
+++ b/yarl.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: yarl
-Version: 0.5.3
+Version: 0.7.0
 Summary: Yet another URL library
 Home-page: https://github.com/aio-libs/yarl/
 Author: Andrew Svetlov
@@ -24,6 +24,10 @@ Description: yarl
             :target: https://yarl.readthedocs.io
         
         
+        .. image:: https://img.shields.io/pypi/pyversions/yarl.svg
+            :target: https://pypi.python.org/pypi/yarl
+        
+        
         Introduction
         ------------
         
@@ -160,6 +164,17 @@ Description: yarl
         CHANGES
         =======
         
+        0.7.0 (2016-11-07)
+        ------------------
+        
+        * Accept `int` as value for `.with_query()`
+        
+        0.6.0 (2016-11-07)
+        ------------------
+        
+        * Explicitly use UTF8 encoding in setup.py #20
+        * Properly unquote non-UTF8 strings #19
+        
         0.5.3 (2016-11-02)
         ------------------
         
diff --git a/yarl/__init__.py b/yarl/__init__.py
index 484c1c1..82aabb8 100644
--- a/yarl/__init__.py
+++ b/yarl/__init__.py
@@ -9,7 +9,7 @@ from multidict import MultiDict, MultiDictProxy
 
 from .quoting import quote, unquote
 
-__version__ = '0.5.3'
+__version__ = '0.7.0'
 
 __all__ = ['URL', 'quote', 'unquote']
 
@@ -61,12 +61,75 @@ class cached_property:
 
 
 class URL:
-    # don't derive from str
+    # Don't derive from str
     # follow pathlib.Path design
     # probably URL will not suffer from pathlib problems:
     # it's intended for libraries like aiohttp,
     # not to be passed into standard library functions like os.open etc.
 
+    # URL grammar (RFC 3986)
+    # pct-encoded = "%" HEXDIG HEXDIG
+    # reserved    = gen-delims / sub-delims
+    # gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+    # sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
+    #             / "*" / "+" / "," / ";" / "="
+    # unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+    # URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+    # hier-part   = "//" authority path-abempty
+    #             / path-absolute
+    #             / path-rootless
+    #             / path-empty
+    # scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+    # authority   = [ userinfo "@" ] host [ ":" port ]
+    # userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
+    # host        = IP-literal / IPv4address / reg-name
+    # IP-literal = "[" ( IPv6address / IPvFuture  ) "]"
+    # IPvFuture  = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+    # IPv6address =                            6( h16 ":" ) ls32
+    #             /                       "::" 5( h16 ":" ) ls32
+    #             / [               h16 ] "::" 4( h16 ":" ) ls32
+    #             / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+    #             / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+    #             / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+    #             / [ *4( h16 ":" ) h16 ] "::"              ls32
+    #             / [ *5( h16 ":" ) h16 ] "::"              h16
+    #             / [ *6( h16 ":" ) h16 ] "::"
+    # ls32        = ( h16 ":" h16 ) / IPv4address
+    #             ; least-significant 32 bits of address
+    # h16         = 1*4HEXDIG
+    #             ; 16 bits of address represented in hexadecimal
+    # IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+    # dec-octet   = DIGIT                 ; 0-9
+    #             / %x31-39 DIGIT         ; 10-99
+    #             / "1" 2DIGIT            ; 100-199
+    #             / "2" %x30-34 DIGIT     ; 200-249
+    #             / "25" %x30-35          ; 250-255
+    # reg-name    = *( unreserved / pct-encoded / sub-delims )
+    # port        = *DIGIT
+    # path          = path-abempty    ; begins with "/" or is empty
+    #               / path-absolute   ; begins with "/" but not "//"
+    #               / path-noscheme   ; begins with a non-colon segment
+    #               / path-rootless   ; begins with a segment
+    #               / path-empty      ; zero characters
+    # path-abempty  = *( "/" segment )
+    # path-absolute = "/" [ segment-nz *( "/" segment ) ]
+    # path-noscheme = segment-nz-nc *( "/" segment )
+    # path-rootless = segment-nz *( "/" segment )
+    # path-empty    = 0<pchar>
+    # segment       = *pchar
+    # segment-nz    = 1*pchar
+    # segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
+    #               ; non-zero-length segment without any colon ":"
+    # pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+    # query       = *( pchar / "/" / "?" )
+    # fragment    = *( pchar / "/" / "?" )
+    # URI-reference = URI / relative-ref
+    # relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
+    # relative-part = "//" authority path-abempty
+    #               / path-absolute
+    #               / path-noscheme
+    #               / path-empty
+    # absolute-URI  = scheme ":" hier-part [ "?" query ]
     __slots__ = ('_cache', '_val')
 
     def __new__(cls, val='', *, encoded=False):
@@ -117,7 +180,7 @@ class URL:
             val = SplitResult(val[0],  # scheme
                               netloc,
                               quote(val[2], safe='/'),
-                              query=quote(val[3], safe='=+&', plus=True),
+                              query=quote(val[3], safe='=+&?', plus=True),
                               fragment=quote(val[4]))
 
         self._val = val
@@ -590,9 +653,6 @@ class URL:
                 raise ValueError("Either kwargs or single query parameter "
                                  "must be present")
             query = kwargs
-            for _, value in kwargs.items():
-                if not isinstance(value, str):
-                    raise TypeError("Invalid variable type")
         elif len(args) == 1:
             query = args[0]
         else:
@@ -603,8 +663,16 @@ class URL:
             query = ''
         elif isinstance(query, Mapping):
             quoter = partial(quote, safe='', plus=True)
-            query = '&'.join(quoter(k)+'='+quoter(v)
-                             for k, v in query.items())
+            lst = []
+            for k, v in query.items():
+                if isinstance(v, str):
+                    pass
+                elif type(v) == int:  # no subclasses like bool
+                    v = str(v)
+                else:
+                    raise TypeError("Invalid variable type")
+                lst.append(quoter(k)+'='+quoter(v))
+            query = '&'.join(lst)
         elif isinstance(query, str):
             query = quote(query, safe='=+&', plus=True)
         elif isinstance(query, (bytes, bytearray, memoryview)):
@@ -615,7 +683,10 @@ class URL:
                              for k, v in query)
         else:
             raise TypeError("Invalid query type")
-        return URL(self._val._replace(query=query),
+        path = self._val.path
+        if path == '':
+            path = '/'
+        return URL(self._val._replace(path=path, query=query),
                    encoded=True)
 
     def with_fragment(self, fragment):
diff --git a/yarl/_quoting.c b/yarl/_quoting.c
index 52bd43e..9da1a09 100644
--- a/yarl/_quoting.c
+++ b/yarl/_quoting.c
@@ -629,6 +629,20 @@ static const char *__pyx_f[] = {
 };
 
 /*--- Type declarations ---*/
+struct __pyx_opt_args_4yarl_8_quoting__do_unquote;
+
+/* "yarl/_quoting.pyx":133
+ * 
+ * 
+ * cdef str _do_unquote(str val, str unsafe='', bint plus=False):             # <<<<<<<<<<<<<<
+ *     cdef str pct = ''
+ *     cdef str last_pct = ''
+ */
+struct __pyx_opt_args_4yarl_8_quoting__do_unquote {
+  int __pyx_n;
+  PyObject *unsafe;
+  int plus;
+};
 
 /* --- Runtime support code (head) --- */
 /* Refnanny.proto */
@@ -805,11 +819,9 @@ static CYTHON_INLINE int __Pyx_PyByteArray_Append(PyObject* bytearray, int value
 /* ByteArrayAppendObject.proto */
 static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyObject* value);
 
-/* SliceObject.proto */
-static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(
-        PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop,
-        PyObject** py_start, PyObject** py_stop, PyObject** py_slice,
-        int has_cstart, int has_cstop, int wraparound);
+/* PyUnicode_Substring.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring(
+            PyObject* text, Py_ssize_t start, Py_ssize_t stop);
 
 /* decode_c_bytes.proto */
 static CYTHON_INLINE PyObject* __Pyx_decode_c_bytes(
@@ -838,9 +850,9 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
 #define __Pyx_ExceptionReset(type, value, tb)  PyErr_SetExcInfo(type, value, tb)
 #endif
 
-/* PySequenceContains.proto */
-static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) {
-    int result = PySequence_Contains(seq, item);
+/* PyUnicodeContains.proto */
+static CYTHON_INLINE int __Pyx_PyUnicode_ContainsTF(PyObject* substring, PyObject* text, int eq) {
+    int result = PyUnicode_Contains(text, substring);
     return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
 }
 
@@ -883,6 +895,14 @@ static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int eq
 /* UnicodeEquals.proto */
 static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals);
 
+/* GetException.proto */
+#if CYTHON_FAST_THREAD_STATE
+#define __Pyx_GetException(type, value, tb)  __Pyx__GetException(__pyx_tstate, type, value, tb)
+static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb);
+#else
+static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb);
+#endif
+
 /* Import.proto */
 static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level);
 
@@ -943,6 +963,7 @@ static PyObject *__pyx_v_4yarl_8_quoting_UNRESERVED_QUOTED = 0;
 static CYTHON_INLINE Py_UCS4 __pyx_f_4yarl_8_quoting__hex(uint8_t); /*proto*/
 static CYTHON_INLINE int __pyx_f_4yarl_8_quoting__from_hex(Py_UCS4); /*proto*/
 static PyObject *__pyx_f_4yarl_8_quoting__do_quote(PyObject *, PyObject *, int); /*proto*/
+static PyObject *__pyx_f_4yarl_8_quoting__do_unquote(PyObject *, struct __pyx_opt_args_4yarl_8_quoting__do_unquote *__pyx_optional_args); /*proto*/
 #define __Pyx_MODULE_NAME "yarl._quoting"
 int __pyx_module_is_main_yarl___quoting = 0;
 
@@ -952,18 +973,14 @@ static PyObject *__pyx_builtin_TypeError;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_UnicodeDecodeError;
 static const char __pyx_k_[] = "";
-static const char __pyx_k__5[] = "%";
-static const char __pyx_k__6[] = ":/?#[]@";
-static const char __pyx_k__7[] = "!$&'()*+,;=";
-static const char __pyx_k__8[] = "-._~";
-static const char __pyx_k_ch[] = "ch";
+static const char __pyx_k__4[] = "%";
+static const char __pyx_k__5[] = ":/?#[]@";
+static const char __pyx_k__6[] = "!$&'()*+,;=";
+static const char __pyx_k__7[] = "-._~";
 static const char __pyx_k_02X[] = "%{:02X}";
-static const char __pyx_k_pct[] = "pct";
-static const char __pyx_k_ret[] = "ret";
 static const char __pyx_k_val[] = "val";
 static const char __pyx_k_base[] = "base";
 static const char __pyx_k_main[] = "__main__";
-static const char __pyx_k_pcts[] = "pcts";
 static const char __pyx_k_plus[] = "plus";
 static const char __pyx_k_safe[] = "safe";
 static const char __pyx_k_test[] = "__test__";
@@ -976,7 +993,6 @@ static const char __pyx_k_import[] = "__import__";
 static const char __pyx_k_string[] = "string";
 static const char __pyx_k_unsafe[] = "unsafe";
 static const char __pyx_k_unquote[] = "_unquote";
-static const char __pyx_k_unquoted[] = "unquoted";
 static const char __pyx_k_TypeError[] = "TypeError";
 static const char __pyx_k_ValueError[] = "ValueError";
 static const char __pyx_k_Unallowed_PCT[] = "Unallowed PCT %{}{}";
@@ -992,44 +1008,37 @@ static PyObject *__pyx_n_s_TypeError;
 static PyObject *__pyx_kp_u_Unallowed_PCT;
 static PyObject *__pyx_n_s_UnicodeDecodeError;
 static PyObject *__pyx_n_s_ValueError;
+static PyObject *__pyx_kp_u__4;
 static PyObject *__pyx_kp_u__5;
 static PyObject *__pyx_kp_u__6;
 static PyObject *__pyx_kp_u__7;
-static PyObject *__pyx_kp_u__8;
 static PyObject *__pyx_n_s_append;
 static PyObject *__pyx_n_s_ascii_letters;
 static PyObject *__pyx_n_s_base;
-static PyObject *__pyx_n_s_ch;
 static PyObject *__pyx_n_s_digits;
 static PyObject *__pyx_n_s_format;
 static PyObject *__pyx_kp_s_home_travis_build_aio_libs_yarl;
 static PyObject *__pyx_n_s_import;
 static PyObject *__pyx_n_s_main;
-static PyObject *__pyx_n_s_pct;
-static PyObject *__pyx_n_s_pcts;
 static PyObject *__pyx_n_s_plus;
 static PyObject *__pyx_n_s_quote;
 static PyObject *__pyx_n_s_range;
-static PyObject *__pyx_n_s_ret;
 static PyObject *__pyx_n_s_safe;
 static PyObject *__pyx_n_s_string;
 static PyObject *__pyx_n_s_test;
 static PyObject *__pyx_n_s_unquote;
-static PyObject *__pyx_n_s_unquoted;
 static PyObject *__pyx_n_s_unsafe;
 static PyObject *__pyx_n_s_val;
 static PyObject *__pyx_n_s_yarl__quoting;
 static PyObject *__pyx_pf_4yarl_8_quoting__quote(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_val, PyObject *__pyx_v_safe, int __pyx_v_plus); /* proto */
-static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_val, PyObject *__pyx_v_unsafe, CYTHON_UNUSED PyObject *__pyx_v_plus); /* proto */
-static PyObject *__pyx_int_1;
+static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_val, PyObject *__pyx_v_unsafe, PyObject *__pyx_v_plus); /* proto */
 static PyObject *__pyx_int_16;
-static PyObject *__pyx_slice__4;
 static PyObject *__pyx_tuple__2;
 static PyObject *__pyx_tuple__3;
-static PyObject *__pyx_tuple__9;
-static PyObject *__pyx_tuple__11;
-static PyObject *__pyx_codeobj__10;
-static PyObject *__pyx_codeobj__12;
+static PyObject *__pyx_tuple__8;
+static PyObject *__pyx_tuple__10;
+static PyObject *__pyx_codeobj__9;
+static PyObject *__pyx_codeobj__11;
 
 /* "yarl/_quoting.pyx":24
  * 
@@ -2244,7 +2253,7 @@ static PyMethodDef __pyx_mdef_4yarl_8_quoting_3_unquote = {"_unquote", (PyCFunct
 static PyObject *__pyx_pw_4yarl_8_quoting_3_unquote(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_val = 0;
   PyObject *__pyx_v_unsafe = 0;
-  CYTHON_UNUSED PyObject *__pyx_v_plus = 0;
+  PyObject *__pyx_v_plus = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_unquote (wrapper)", 0);
@@ -2301,28 +2310,13 @@ static PyObject *__pyx_pw_4yarl_8_quoting_3_unquote(PyObject *__pyx_self, PyObje
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_val, PyObject *__pyx_v_unsafe, CYTHON_UNUSED PyObject *__pyx_v_plus) {
-  PyObject *__pyx_v_pct = NULL;
-  PyObject *__pyx_v_pcts = NULL;
-  PyObject *__pyx_v_ret = NULL;
-  PyObject *__pyx_v_ch = NULL;
-  PyObject *__pyx_v_unquoted = NULL;
+static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_val, PyObject *__pyx_v_unsafe, PyObject *__pyx_v_plus) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   int __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
-  Py_ssize_t __pyx_t_4;
-  PyObject *(*__pyx_t_5)(PyObject *);
-  PyObject *__pyx_t_6 = NULL;
-  Py_ssize_t __pyx_t_7;
-  PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
-  int __pyx_t_10;
-  PyObject *__pyx_t_11 = NULL;
-  PyObject *__pyx_t_12 = NULL;
-  PyObject *__pyx_t_13 = NULL;
-  int __pyx_t_14;
+  struct __pyx_opt_args_4yarl_8_quoting__do_unquote __pyx_t_4;
   __Pyx_RefNannySetupContext("_unquote", 0);
 
   /* "yarl/_quoting.pyx":124
@@ -2395,7 +2389,7 @@ static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__py
  *         raise TypeError("Argument should be str")
  *     if not val:             # <<<<<<<<<<<<<<
  *         return ''
- *     pct = ''
+ *     return _do_unquote(<str>val, unsafe, plus)
  */
   __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_val); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
   __pyx_t_2 = ((!__pyx_t_1) != 0);
@@ -2405,8 +2399,8 @@ static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__py
  *         raise TypeError("Argument should be str")
  *     if not val:
  *         return ''             # <<<<<<<<<<<<<<
- *     pct = ''
- *     pcts = bytearray()
+ *     return _do_unquote(<str>val, unsafe, plus)
+ * 
  */
     __Pyx_XDECREF(__pyx_r);
     __Pyx_INCREF(__pyx_kp_u_);
@@ -2418,153 +2412,234 @@ static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__py
  *         raise TypeError("Argument should be str")
  *     if not val:             # <<<<<<<<<<<<<<
  *         return ''
- *     pct = ''
+ *     return _do_unquote(<str>val, unsafe, plus)
  */
   }
 
   /* "yarl/_quoting.pyx":130
  *     if not val:
  *         return ''
- *     pct = ''             # <<<<<<<<<<<<<<
- *     pcts = bytearray()
- *     ret = []
+ *     return _do_unquote(<str>val, unsafe, plus)             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  if (!(likely(PyUnicode_CheckExact(__pyx_v_unsafe))||((__pyx_v_unsafe) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_unsafe)->tp_name), 0))) __PYX_ERR(0, 130, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_plus); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 130, __pyx_L1_error)
+  __pyx_t_4.__pyx_n = 2;
+  __pyx_t_4.unsafe = ((PyObject*)__pyx_v_unsafe);
+  __pyx_t_4.plus = __pyx_t_2;
+  __pyx_t_3 = __pyx_f_4yarl_8_quoting__do_unquote(((PyObject*)__pyx_v_val), &__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 130, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_r = __pyx_t_3;
+  __pyx_t_3 = 0;
+  goto __pyx_L0;
+
+  /* "yarl/_quoting.pyx":123
+ * 
+ * 
+ * def _unquote(val, *, unsafe='', plus=False):             # <<<<<<<<<<<<<<
+ *     if val is None:
+ *         return None
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("yarl._quoting._unquote", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "yarl/_quoting.pyx":133
+ * 
+ * 
+ * cdef str _do_unquote(str val, str unsafe='', bint plus=False):             # <<<<<<<<<<<<<<
+ *     cdef str pct = ''
+ *     cdef str last_pct = ''
+ */
+
+static PyObject *__pyx_f_4yarl_8_quoting__do_unquote(PyObject *__pyx_v_val, struct __pyx_opt_args_4yarl_8_quoting__do_unquote *__pyx_optional_args) {
+  PyObject *__pyx_v_unsafe = ((PyObject*)__pyx_kp_u_);
+  PyObject *__pyx_v_pct = 0;
+  PyObject *__pyx_v_last_pct = 0;
+  PyObject *__pyx_v_pcts = 0;
+  PyObject *__pyx_v_ret = 0;
+  PyObject *__pyx_v_unquoted = 0;
+  PyObject *__pyx_v_ch = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  Py_ssize_t __pyx_t_3;
+  Py_ssize_t __pyx_t_4;
+  void *__pyx_t_5;
+  int __pyx_t_6;
+  int __pyx_t_7;
+  Py_ssize_t __pyx_t_8;
+  int __pyx_t_9;
+  Py_ssize_t __pyx_t_10;
+  PyObject *__pyx_t_11 = NULL;
+  PyObject *__pyx_t_12 = NULL;
+  int __pyx_t_13;
+  PyObject *__pyx_t_14 = NULL;
+  PyObject *__pyx_t_15 = NULL;
+  PyObject *__pyx_t_16 = NULL;
+  int __pyx_t_17;
+  __Pyx_RefNannySetupContext("_do_unquote", 0);
+  if (__pyx_optional_args) {
+    if (__pyx_optional_args->__pyx_n > 0) {
+      __pyx_v_unsafe = __pyx_optional_args->unsafe;
+    }
+  }
+
+  /* "yarl/_quoting.pyx":134
+ * 
+ * cdef str _do_unquote(str val, str unsafe='', bint plus=False):
+ *     cdef str pct = ''             # <<<<<<<<<<<<<<
+ *     cdef str last_pct = ''
+ *     cdef bytearray pcts = bytearray()
  */
   __Pyx_INCREF(__pyx_kp_u_);
   __pyx_v_pct = __pyx_kp_u_;
 
-  /* "yarl/_quoting.pyx":131
- *         return ''
- *     pct = ''
- *     pcts = bytearray()             # <<<<<<<<<<<<<<
- *     ret = []
- *     for ch in val:
+  /* "yarl/_quoting.pyx":135
+ * cdef str _do_unquote(str val, str unsafe='', bint plus=False):
+ *     cdef str pct = ''
+ *     cdef str last_pct = ''             # <<<<<<<<<<<<<<
+ *     cdef bytearray pcts = bytearray()
+ *     cdef list ret = []
  */
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)(&PyByteArray_Type)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_v_pcts = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
+  __Pyx_INCREF(__pyx_kp_u_);
+  __pyx_v_last_pct = __pyx_kp_u_;
 
-  /* "yarl/_quoting.pyx":132
- *     pct = ''
- *     pcts = bytearray()
- *     ret = []             # <<<<<<<<<<<<<<
+  /* "yarl/_quoting.pyx":136
+ *     cdef str pct = ''
+ *     cdef str last_pct = ''
+ *     cdef bytearray pcts = bytearray()             # <<<<<<<<<<<<<<
+ *     cdef list ret = []
+ *     cdef str unquoted
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)(&PyByteArray_Type)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_pcts = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "yarl/_quoting.pyx":137
+ *     cdef str last_pct = ''
+ *     cdef bytearray pcts = bytearray()
+ *     cdef list ret = []             # <<<<<<<<<<<<<<
+ *     cdef str unquoted
  *     for ch in val:
- *         if pct:
  */
-  __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 132, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_v_ret = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 137, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_ret = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
 
-  /* "yarl/_quoting.pyx":133
- *     pcts = bytearray()
- *     ret = []
+  /* "yarl/_quoting.pyx":139
+ *     cdef list ret = []
+ *     cdef str unquoted
  *     for ch in val:             # <<<<<<<<<<<<<<
  *         if pct:
  *             pct += ch
  */
-  if (likely(PyList_CheckExact(__pyx_v_val)) || PyTuple_CheckExact(__pyx_v_val)) {
-    __pyx_t_3 = __pyx_v_val; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
-    __pyx_t_5 = NULL;
-  } else {
-    __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_val); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 133, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 133, __pyx_L1_error)
+  if (unlikely(__pyx_v_val == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' is not iterable");
+    __PYX_ERR(0, 139, __pyx_L1_error)
   }
-  for (;;) {
-    if (likely(!__pyx_t_5)) {
-      if (likely(PyList_CheckExact(__pyx_t_3))) {
-        if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_6 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 133, __pyx_L1_error)
-        #else
-        __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 133, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        #endif
-      } else {
-        if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 133, __pyx_L1_error)
-        #else
-        __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 133, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        #endif
-      }
-    } else {
-      __pyx_t_6 = __pyx_t_5(__pyx_t_3);
-      if (unlikely(!__pyx_t_6)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 133, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_6);
-    }
-    __Pyx_XDECREF_SET(__pyx_v_ch, __pyx_t_6);
-    __pyx_t_6 = 0;
+  __Pyx_INCREF(__pyx_v_val);
+  __pyx_t_2 = __pyx_v_val;
+  __pyx_t_7 = __Pyx_init_unicode_iteration(__pyx_t_2, (&__pyx_t_4), (&__pyx_t_5), (&__pyx_t_6)); if (unlikely(__pyx_t_7 == -1)) __PYX_ERR(0, 139, __pyx_L1_error)
+  for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_4; __pyx_t_8++) {
+    __pyx_t_3 = __pyx_t_8;
+    __pyx_t_1 = PyUnicode_FromOrdinal(__Pyx_PyUnicode_READ(__pyx_t_6, __pyx_t_5, __pyx_t_3)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 139, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_XDECREF_SET(__pyx_v_ch, __pyx_t_1);
+    __pyx_t_1 = 0;
 
-    /* "yarl/_quoting.pyx":134
- *     ret = []
+    /* "yarl/_quoting.pyx":140
+ *     cdef str unquoted
  *     for ch in val:
  *         if pct:             # <<<<<<<<<<<<<<
  *             pct += ch
  *             if len(pct) == 3:  # pragma: no branch   # peephole optimizer
  */
-    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_pct); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 134, __pyx_L1_error)
-    if (__pyx_t_2) {
+    __pyx_t_9 = (__pyx_v_pct != Py_None) && (__Pyx_PyUnicode_IS_TRUE(__pyx_v_pct) != 0);
+    if (__pyx_t_9) {
 
-      /* "yarl/_quoting.pyx":135
+      /* "yarl/_quoting.pyx":141
  *     for ch in val:
  *         if pct:
  *             pct += ch             # <<<<<<<<<<<<<<
  *             if len(pct) == 3:  # pragma: no branch   # peephole optimizer
  *                 pcts.append(int(pct[1:], base=16))
  */
-      __pyx_t_6 = PyNumber_InPlaceAdd(__pyx_v_pct, __pyx_v_ch); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 135, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __Pyx_DECREF_SET(__pyx_v_pct, __pyx_t_6);
-      __pyx_t_6 = 0;
+      __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_pct, __pyx_v_ch); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 141, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!(likely(PyUnicode_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error)
+      __Pyx_DECREF_SET(__pyx_v_pct, ((PyObject*)__pyx_t_1));
+      __pyx_t_1 = 0;
 
-      /* "yarl/_quoting.pyx":136
+      /* "yarl/_quoting.pyx":142
  *         if pct:
  *             pct += ch
  *             if len(pct) == 3:  # pragma: no branch   # peephole optimizer             # <<<<<<<<<<<<<<
  *                 pcts.append(int(pct[1:], base=16))
- *                 pct = ''
+ *                 last_pct = pct
  */
-      __pyx_t_7 = PyObject_Length(__pyx_v_pct); if (unlikely(__pyx_t_7 == -1)) __PYX_ERR(0, 136, __pyx_L1_error)
-      __pyx_t_2 = ((__pyx_t_7 == 3) != 0);
-      if (__pyx_t_2) {
+      if (unlikely(__pyx_v_pct == Py_None)) {
+        PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
+        __PYX_ERR(0, 142, __pyx_L1_error)
+      }
+      __pyx_t_10 = __Pyx_PyUnicode_GET_LENGTH(__pyx_v_pct); if (unlikely(__pyx_t_10 == -1)) __PYX_ERR(0, 142, __pyx_L1_error)
+      __pyx_t_9 = ((__pyx_t_10 == 3) != 0);
+      if (__pyx_t_9) {
 
-        /* "yarl/_quoting.pyx":137
+        /* "yarl/_quoting.pyx":143
  *             pct += ch
  *             if len(pct) == 3:  # pragma: no branch   # peephole optimizer
  *                 pcts.append(int(pct[1:], base=16))             # <<<<<<<<<<<<<<
+ *                 last_pct = pct
  *                 pct = ''
- *             continue
  */
-        __pyx_t_6 = __Pyx_PyObject_GetSlice(__pyx_v_pct, 1, 0, NULL, NULL, &__pyx_slice__4, 1, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 137, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 137, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_6 = PyDict_New(); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 137, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        if (PyDict_SetItem(__pyx_t_6, __pyx_n_s_base, __pyx_int_16) < 0) __PYX_ERR(0, 137, __pyx_L1_error)
-        __pyx_t_9 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_8, __pyx_t_6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 137, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __pyx_t_10 = __Pyx_PyByteArray_AppendObject(__pyx_v_pcts, __pyx_t_9); if (unlikely(__pyx_t_10 == -1)) __PYX_ERR(0, 137, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-
-        /* "yarl/_quoting.pyx":138
+        if (unlikely(__pyx_v_pct == Py_None)) {
+          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+          __PYX_ERR(0, 143, __pyx_L1_error)
+        }
+        __pyx_t_1 = __Pyx_PyUnicode_Substring(__pyx_v_pct, 1, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __pyx_t_11 = PyTuple_New(1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 143, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_11);
+        __Pyx_GIVEREF(__pyx_t_1);
+        PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_1);
+        __pyx_t_1 = 0;
+        __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_base, __pyx_int_16) < 0) __PYX_ERR(0, 143, __pyx_L1_error)
+        __pyx_t_12 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_11, __pyx_t_1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 143, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_12);
+        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __pyx_t_13 = __Pyx_PyByteArray_AppendObject(__pyx_v_pcts, __pyx_t_12); if (unlikely(__pyx_t_13 == -1)) __PYX_ERR(0, 143, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+
+        /* "yarl/_quoting.pyx":144
  *             if len(pct) == 3:  # pragma: no branch   # peephole optimizer
  *                 pcts.append(int(pct[1:], base=16))
+ *                 last_pct = pct             # <<<<<<<<<<<<<<
+ *                 pct = ''
+ *             continue
+ */
+        __Pyx_INCREF(__pyx_v_pct);
+        __Pyx_DECREF_SET(__pyx_v_last_pct, __pyx_v_pct);
+
+        /* "yarl/_quoting.pyx":145
+ *                 pcts.append(int(pct[1:], base=16))
+ *                 last_pct = pct
  *                 pct = ''             # <<<<<<<<<<<<<<
  *             continue
  *         if pcts:
@@ -2572,26 +2647,26 @@ static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__py
         __Pyx_INCREF(__pyx_kp_u_);
         __Pyx_DECREF_SET(__pyx_v_pct, __pyx_kp_u_);
 
-        /* "yarl/_quoting.pyx":136
+        /* "yarl/_quoting.pyx":142
  *         if pct:
  *             pct += ch
  *             if len(pct) == 3:  # pragma: no branch   # peephole optimizer             # <<<<<<<<<<<<<<
  *                 pcts.append(int(pct[1:], base=16))
- *                 pct = ''
+ *                 last_pct = pct
  */
       }
 
-      /* "yarl/_quoting.pyx":139
- *                 pcts.append(int(pct[1:], base=16))
+      /* "yarl/_quoting.pyx":146
+ *                 last_pct = pct
  *                 pct = ''
  *             continue             # <<<<<<<<<<<<<<
  *         if pcts:
  *             try:
  */
-      goto __pyx_L6_continue;
+      goto __pyx_L3_continue;
 
-      /* "yarl/_quoting.pyx":134
- *     ret = []
+      /* "yarl/_quoting.pyx":140
+ *     cdef str unquoted
  *     for ch in val:
  *         if pct:             # <<<<<<<<<<<<<<
  *             pct += ch
@@ -2599,17 +2674,17 @@ static PyObject *__pyx_pf_4yarl_8_quoting_2_unquote(CYTHON_UNUSED PyObject *__py
  */
     }
... 1138 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/yarl.git



More information about the Python-modules-commits mailing list