@@ -1517,13 +1517,17 @@ class DecodedURL(object):
1517
1517
handled automatically.
1518
1518
1519
1519
Where applicable, a UTF-8 encoding is presumed. Be advised that
1520
- some interactions, can raise UnicodeEncodeErrors and
1521
- UnicodeDecodeErrors, just like when working with
1522
- bytestrings.
1520
+ some interactions, can raise :exc:`UnicodeEncodeErrors` and
1521
+ :exc:`UnicodeDecodeErrors`, just like when working with
1522
+ bytestrings. Examples of such interactions include handling query
1523
+ strings encoding binary data, and paths containing segments with
1524
+ special characters encoded with codecs other than UTF-8.
1525
+
1526
+ Args:
1527
+ url (URL): A :class:`URL` object to wrap.
1528
+ lazy (bool): Whether to pre-decode all parts of the URL to
1529
+ check for validity. Defaults to True.
1523
1530
1524
- Examples of such interactions include handling query strings
1525
- encoding binary data, and paths containing segments with special
1526
- characters encoded with codecs other than UTF-8.
1527
1531
"""
1528
1532
def __init__ (self , url , lazy = False ):
1529
1533
self ._url = url
@@ -1536,7 +1540,7 @@ def __init__(self, url, lazy=False):
1536
1540
@classmethod
1537
1541
def from_text (cls , text , lazy = False ):
1538
1542
"""\
1539
- Make a DecodedURL instance from any text string containing a URL.
1543
+ Make a ` DecodedURL` instance from any text string containing a URL.
1540
1544
1541
1545
Args:
1542
1546
text (unicode): Text containing the URL
@@ -1567,28 +1571,28 @@ def to_iri(self, *a, **kw):
1567
1571
1568
1572
def click (self , href = u'' ):
1569
1573
"Return a new DecodedURL wrapping the result of :meth:`~hyperlink.URL.click()`"
1570
- return type ( self ) (self ._url .click (href = href ))
1574
+ return self . __class__ (self ._url .click (href = href ))
1571
1575
1572
1576
def sibling (self , segment ):
1573
1577
"""Automatically encode any reserved characters in *segment* and
1574
- return a new DecodedURL wrapping the result of
1578
+ return a new ` DecodedURL` wrapping the result of
1575
1579
:meth:`~hyperlink.URL.sibling()`
1576
1580
"""
1577
- return type ( self ) (self ._url .sibling (_encode_reserved (segment )))
1581
+ return self . __class__ (self ._url .sibling (_encode_reserved (segment )))
1578
1582
1579
1583
def child (self , * segments ):
1580
1584
"""Automatically encode any reserved characters in *segments* and
1581
- return a new DecodedURL wrapping the result of
1585
+ return a new ` DecodedURL` wrapping the result of
1582
1586
:meth:`~hyperlink.URL.child()`.
1583
1587
"""
1584
1588
if not segments :
1585
1589
return self
1586
1590
new_segs = [_encode_reserved (s ) for s in segments ]
1587
- return type ( self ) (self ._url .child (* new_segs ))
1591
+ return self . __class__ (self ._url .child (* new_segs ))
1588
1592
1589
1593
def normalize (self , * a , ** kw ):
1590
- "Return a new DecodedURL wrapping the result of :meth:`~hyperlink.URL.normalize()`"
1591
- return type ( self ) (self ._url .normalize (* a , ** kw ))
1594
+ "Return a new ` DecodedURL` wrapping the result of :meth:`~hyperlink.URL.normalize()`"
1595
+ return self . __class__ (self ._url .normalize (* a , ** kw ))
1592
1596
1593
1597
@property
1594
1598
def absolute (self ):
@@ -1668,11 +1672,13 @@ def uses_netloc(self):
1668
1672
def replace (self , scheme = _UNSET , host = _UNSET , path = _UNSET , query = _UNSET ,
1669
1673
fragment = _UNSET , port = _UNSET , rooted = _UNSET , userinfo = _UNSET ,
1670
1674
uses_netloc = _UNSET ):
1671
- """While the signature is the same, this `replace()` differs a little from
1672
- URL.replace. For instance, it accepts userinfo as a tuple, not
1673
- as a string. As with the rest of the methods on DecodedURL, if
1674
- you pass a reserved character, it will be automatically
1675
- encoded instead of an error being raised.
1675
+ """While the signature is the same, this `replace()` differs a little
1676
+ from URL.replace. For instance, it accepts userinfo as a
1677
+ tuple, not as a string, handling the case of having a username
1678
+ containing a `:`. As with the rest of the methods on
1679
+ DecodedURL, if you pass a reserved character, it will be
1680
+ automatically encoded instead of an error being raised.
1681
+
1676
1682
"""
1677
1683
if path is not _UNSET :
1678
1684
path = [_encode_reserved (p ) for p in path ]
@@ -1695,7 +1701,7 @@ def replace(self, scheme=_UNSET, host=_UNSET, path=_UNSET, query=_UNSET,
1695
1701
rooted = rooted ,
1696
1702
userinfo = userinfo ,
1697
1703
uses_netloc = uses_netloc )
1698
- return type ( self ) (url = new_url )
1704
+ return self . __class__ (url = new_url )
1699
1705
1700
1706
def get (self , name ):
1701
1707
"Get the value of all query parameters whose name matches *name*"
@@ -1766,67 +1772,24 @@ def __dir__(self):
1766
1772
1767
1773
1768
1774
def parse (url , decoded = True , lazy = False ):
1775
+ """Automatically turn text into a structured URL object.
1776
+
1777
+ Args:
1778
+
1779
+ decoded (bool): Whether or not to return a :class:`DecodedURL`,
1780
+ which automatically handles all
1781
+ encoding/decoding/quoting/unquoting for all the various
1782
+ accessors of parts of the URL, or an :class:`EncodedURL`,
1783
+ which has the same API, but requires handling of special
1784
+ characters for different parts of the URL.
1785
+
1786
+ lazy (bool): In the case of `decoded=True`, this controls
1787
+ whether the URL is decoded immediately or as accessed. The
1788
+ default, `lazy=False`, checks all encoded parts of the URL
1789
+ for decodability.
1790
+ """
1769
1791
enc_url = EncodedURL .from_text (url )
1770
1792
if not decoded :
1771
1793
return enc_url
1772
1794
dec_url = DecodedURL (enc_url , lazy = lazy )
1773
1795
return dec_url
1774
-
1775
-
1776
- """Probably turn the properties into normal attributes now that they
1777
- raise exceptions, or at least cachedproperties.
1778
-
1779
- * Decode
1780
- * host
1781
- * userinfo
1782
- * user
1783
- * path
1784
- * query
1785
- * fragment
1786
- * Wrap in encoder
1787
- * replace
1788
- * add()
1789
- * set()
1790
- * child (split and encode?)
1791
- * sibling
1792
- * remove()
1793
- * Passthrough
1794
- * __eq__ / __ne__ / __hash__
1795
- * absolute()
1796
- * Return new DecodedURL with new ._url (the other kind of passthrough)
1797
- * normalize()
1798
- * click()
1799
- * Strict passthrough (doesn't return a DecodedURL)
1800
- * to_uri()
1801
- * to_iri()
1802
-
1803
- # Factoring
1804
-
1805
- Should DecodedURL be a subclass of URL? Inheritance isn't cool
1806
- anymore, so obviously not right? But seriously, it could be:
1807
-
1808
- * Every single method of URL is wrapped with almost an identical API,
1809
- except for __init__
1810
- * A DecodedURL is as much a URL as both `bytes` and `unicode` are
1811
- strings
1812
-
1813
- On the arguments against:
1814
-
1815
- * __init__ differs
1816
- * No real benefit to calling super()
1817
- * Only a few duplicate methods could be reused (Twisted compat,
1818
- .get(), a couple others)
1819
- * Complicates the relationship, as every DecodedURL has an underlying
1820
- EncodedURL and every EncodedURL _may_ have a DecodedURL. Values
1821
- stored within each are actually different, so it's not just
1822
- different methods
1823
-
1824
- # Remaining design questions
1825
-
1826
- * Should _encode_reserved(maximal=False) be used instead?
1827
- * If yes, should the underlying URL have .to_iri() applied to it?
1828
- * Right now DecodedURL needs each part to encode then decode, because
1829
- percent_decode doesn't even try to percent decode if there are any
1830
- non-ascii characters in its argument.
1831
-
1832
- """
0 commit comments