classification
Title: urlparse gives no method to build a url with a port
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.5
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: Amir, James Allsopp, eric.smith, gvanrossum
Priority: normal Keywords:

Created on 2019-10-08 09:51 by James Allsopp, last changed 2019-10-09 16:16 by gvanrossum. This issue is now closed.

Messages (8)
msg354180 - (view) Author: James Allsopp (James Allsopp) Date: 2019-10-08 09:51
Hi,
I like to build my Url's using url unparse, e.g.
site_to_test = urllib.parse.urlunparse((scheme, host, page, '', '', ''))
r = requests.get(site_to_test)

However, we reach a lot of sites through SSH tunnels, as our network is heavily locked down, and need to specify a port. Unfortunately, we can parse a url with a port, and get site_to_test.port = '9097' we can't run it the other way, e.g. this fails.
site_to_test = urllib.parse.urlunparse((scheme, host, page, '', '', '',port=9097))

This should be easy to fix and there's a use case for it.
Thanks
msg354185 - (view) Author: Amir Mohamadi (Amir) * Date: 2019-10-08 11:23
Hi!
I'm a newbie but I'd like to work on this issue
can I work on it???
msg354196 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-10-08 12:34
One way I can think of doing this in a backward compatible way is to add keyword parameters to urlunparse, like:

def urlunparse(components, *, username=None, password=None, hostname=None, port=None):

Which would make your call:
site_to_test = urllib.parse.urlunparse((scheme, host, page, '', '', ''), port=9097)

I think that's a horrible interface, but it is backward compatible.

A better interface would be have all 10 URL parameters passed in as keyword arguments, with reasonable defaults. If you want to keep this named "urlunparse", you'd need to say you can't pass in both "components" and any other named parameter (other than maybe the 4  parameters that are unnamed in ParseResult).

Something like:
def urlunparse(components=None, scheme=None, netloc=None, path=None, params=None, query=None, fragment=None, *, username=None, password=None, hostname=None, port=None):

Then error if components is set and any of scheme, netloc, path, params, query, or fragment is also set.

We could bikeshed about which would be keyword-only, if any, all, or only some as I've shown here.

Another option would be to leave urlunparse alone, and add a new function entirely, which wouldn't have to worry about backward compatibility.

It might be worthwhile to raise this on python-ideas.
msg354274 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-10-09 14:35
Does it work if you pass a string of the form "host:port" as the host field?

I'd rather not change this antiquated interface too much, and I don't like proliferating additional functions.
msg354275 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-10-09 14:44
Yes, that does work:

>>> urllib.parse.urlunparse(("http", f"{host}:{port}", "/", "", "", ""))
'http://hostname:1234/'



The only problem is that your code now needs to look like

>>> port=None
>>> urllib.parse.urlunparse(("http", f"{host}{(':' + str(port)) if port else ''}", "/", "", "", ""))
'http://hostname/'
msg354276 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-10-09 15:01
Then I find insufficient reason to change the API. Users who need this
frequently can make their own wrapper.
-- 
--Guido (mobile)
msg354283 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-10-09 15:30
Okay, then I'll close this.
msg354285 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2019-10-09 16:16
@Amir maybe you can update the docs to add an example of how to do this (if there isn't already one there).
History
Date User Action Args
2019-10-09 16:16:17gvanrossumsetmessages: + msg354285
2019-10-09 15:30:59eric.smithsetstatus: open -> closed
type: behavior
messages: + msg354283

resolution: wont fix
stage: resolved
2019-10-09 15:01:34gvanrossumsetmessages: + msg354276
2019-10-09 14:44:33eric.smithsetmessages: + msg354275
2019-10-09 14:35:36gvanrossumsetnosy: + gvanrossum
messages: + msg354274
2019-10-08 12:34:38eric.smithsetnosy: + eric.smith
messages: + msg354196
2019-10-08 11:23:57Amirsetnosy: + Amir
messages: + msg354185
2019-10-08 09:51:03James Allsoppcreate