classification
Title: urlencode produces bad output from ssl.CERT_NONE and friends that chokes decoders
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: ethan.furman Nosy List: barry, christian.heimes, ethan.furman, vitaly.krug
Priority: normal Keywords:

Created on 2018-03-08 06:57 by vitaly.krug, last changed 2021-06-29 20:16 by barry.

Messages (5)
msg313424 - (view) Author: Vitaly Kruglikov (vitaly.krug) Date: 2018-03-08 06:57
```
In [9]: from urllib.parse import urlencode, parse_qs

In [10]: import ast, ssl

In [11]: d = dict(cert_reqs=ssl.CERT_NONE)

In [12]: urlencode(d)
Out[12]: 'cert_reqs=VerifyMode.CERT_NONE'

In [25]: parse_qs('cert_reqs=VerifyMode.CERT_NONE')
Out[25]: {'cert_reqs': ['VerifyMode.CERT_NONE']}
In [29]: ast.literal_eval('VerifyMode.CERT_NONE')
Traceback (most recent call last)
...
ValueError: malformed node or string: <_ast.Attribute object at 0x105c22358>
```

This used to work fine and produce `'cert_reqs=0'` on Python 2.7, allowing it to be decoded properly downstream. However, `'cert_reqs=VerifyMode.CERT_NONE'` can't be decoded generically. So, something it's that used to work in prior python versions that is breaking now.

Additional information. json.dumps() actually dumps that value as a number instead of 'VerifyMode.CERT_NONE'. 

It appears that urlencode doesn't work properly with enums, where I would expect it to emit the numeric value of the enum.
msg313732 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2018-03-13 08:58
Ethan, please take a look.
msg391439 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2021-04-20 14:20
IIUC, the issue is that

  urlencode( {'cert_reqs': ssl.CERT_NONE} )

no longer produces

  'cert_reqs=0'

?
msg391440 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2021-04-20 14:23
I guess so.

We turned CERT_NONE into an IntFlag enum many years ago. urlencode() uses repr to convert integer enums.
msg391441 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2021-04-20 14:44
Actually, I think it uses str().  An easy fix would be to use format() for all non-bytes objects instead -- the question then becomes how many objects (besides Enums with mixed-in data types) have a different str() vs format() display?
History
Date User Action Args
2021-06-29 20:16:30barrysetnosy: + barry
2021-04-20 14:44:22ethan.furmansetmessages: + msg391441
2021-04-20 14:23:41christian.heimessetnosy: + christian.heimes
messages: + msg391440
2021-04-20 14:20:31ethan.furmansetmessages: + msg391439
2021-04-17 19:02:33christian.heimessetnosy: - christian.heimes

components: - SSL
versions: + Python 3.8, Python 3.9, Python 3.10, - Python 3.6, Python 3.7
2018-07-11 07:53:35serhiy.storchakasettype: crash -> behavior
2018-03-13 08:58:05christian.heimessetassignee: ethan.furman

messages: + msg313732
nosy: + ethan.furman
2018-03-08 12:31:43christian.heimessetassignee: christian.heimes -> (no value)
2018-03-08 06:57:47vitaly.krugcreate