@@ -815,9 +815,18 @@ class URL(object):
815815 that starts with a slash.
816816 userinfo (Text): The username or colon-separated
817817 username:password pair.
818- uses_netloc (bool): Indicates whether two slashes appear
819- between the scheme and the host (``http://eg.com`` vs
820- ``mailto:e@g.com``). Set automatically based on scheme.
818+ uses_netloc (Optional[bool]): Indicates whether ``://`` (the "netloc
819+ separator") will appear to separate the scheme from the *path* in
820+ cases where no host is present. Setting this to ``True`` is a
821+ non-spec-compliant affordance for the common practice of having URIs
822+ that are *not* URLs (cannot have a 'host' part) but nevertheless use
823+ the common ``://`` idiom that most people associate with URLs;
824+ e.g. ``message:`` URIs like ``message://message-id`` being
825+ equivalent to ``message:message-id``. This may be inferred based on
826+ the scheme depending on whether :func:`register_scheme` has been
827+ used to register the scheme and should not be passed directly unless
828+ you know the scheme works like this and you know it has not been
829+ registered.
821830
822831 All of these parts are also exposed as read-only attributes of
823832 URL instances, along with several useful methods.
@@ -882,15 +891,28 @@ def __init__(
882891 self ._rooted = _typecheck ("rooted" , rooted , bool )
883892 self ._userinfo = _textcheck ("userinfo" , userinfo , '/?#@' )
884893
885- uses_netloc = scheme_uses_netloc (self ._scheme , uses_netloc )
894+ if uses_netloc is None :
895+ uses_netloc = scheme_uses_netloc (self ._scheme , uses_netloc )
886896 self ._uses_netloc = _typecheck ("uses_netloc" ,
887897 uses_netloc , bool , NoneType )
888- # fixup for rooted consistency
889- if self ._host :
898+ will_have_authority = (
899+ self ._host or
900+ (self ._port and self ._port != SCHEME_PORT_MAP .get (scheme ))
901+ )
902+ if will_have_authority :
903+ # fixup for rooted consistency; if there's any 'authority'
904+ # represented in the textual URL, then the path must be rooted, and
905+ # we're definitely using a netloc (there must be a ://).
890906 self ._rooted = True
891- if (not self ._rooted ) and self ._path and self ._path [0 ] == '' :
907+ self ._uses_netloc = True
908+ if (not self ._rooted ) and self .path [:1 ] == (u'' ,):
892909 self ._rooted = True
893910 self ._path = self ._path [1 :]
911+ if not will_have_authority and self ._path and not self ._rooted :
912+ # If, after fixing up the path, there *is* a path and it *isn't*
913+ # rooted, then we are definitely not using a netloc; if we did, it
914+ # would make the path (erroneously) look like a hostname.
915+ self ._uses_netloc = False
894916
895917 def get_decoded_url (self , lazy = False ):
896918 # type: (bool) -> DecodedURL
@@ -1006,6 +1028,8 @@ def userinfo(self):
10061028 def uses_netloc (self ):
10071029 # type: () -> Optional[bool]
10081030 """
1031+ Indicates whether ``://`` (the "netloc separator") will appear to
1032+ separate the scheme from the *path* in cases where no host is present.
10091033 """
10101034 return self ._uses_netloc
10111035
@@ -1134,14 +1158,28 @@ def replace(
11341158 slash.
11351159 userinfo (Text): The username or colon-separated username:password
11361160 pair.
1137- uses_netloc (bool): Indicates whether two slashes appear between
1138- the scheme and the host
1139- (``http://eg.com`` vs ``mailto:e@g.com``)
1161+ uses_netloc (bool): Indicates whether ``://`` (the "netloc
1162+ separator") will appear to separate the scheme from the *path*
1163+ in cases where no host is present. Setting this to ``True`` is
1164+ a non-spec-compliant affordance for the common practice of
1165+ having URIs that are *not* URLs (cannot have a 'host' part) but
1166+ nevertheless use the common ``://`` idiom that most people
1167+ associate with URLs; e.g. ``message:`` URIs like
1168+ ``message://message-id`` being equivalent to
1169+ ``message:message-id``. This may be inferred based on the
1170+ scheme depending on whether :func:`register_scheme` has been
1171+ used to register the scheme and should not be passed directly
1172+ unless you know the scheme works like this and you know it has
1173+ not been registered.
11401174
11411175 Returns:
11421176 URL: A copy of the current :class:`URL`, with new values for
11431177 parameters passed.
11441178 """
1179+ if scheme is not _UNSET and scheme != self .scheme :
1180+ # when changing schemes, reset the explicit uses_netloc preference
1181+ # to honor the new scheme.
1182+ uses_netloc = None
11451183 return self .__class__ (
11461184 scheme = _optional (scheme , self .scheme ),
11471185 host = _optional (host , self .host ),
0 commit comments