This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Add MixedTypeKey to reprlib
Type: enhancement Stage: needs patch
Components: Library (Lib) Versions: Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, ncoghlan, serhiy.storchaka
Priority: normal Keywords:

Created on 2013-06-09 13:54 by ncoghlan, last changed 2022-04-11 14:57 by admin.

Messages (3)
msg190855 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2013-06-09 13:54
Armin Ronacher pointed out that one downside of the removal of implicit cross-type comparisons in Python 3 is that it makes it harder to produce a stable repr for mixed-type containers.

This seems like a valid point to me, so I propose adding a suitable "MixedTypeKey" definition to reprlib. Passing "key=reprlib.MixedTypeKey" would then reproduce the old Python 2. sorting behaviour.

We can actually improve on the Python 2 approach by basing the fallback comparison on fully qualified type names rather than on the type id.

Proposed implementation (see https://gist.github.com/ncoghlan/5743523):

>>> class MixedTypeKey:
...     """Sort key for mixed type lists in Python 3
... 
...     >>> sorted([None, ..., 1, 1j, "", (), {}, []])
...     Traceback (most recent call last):
...       File "<stdin>", line 1, in <module>
...     TypeError: unorderable types: ellipsis() < NoneType()
...     >>> sorted([None, ..., 1, 1j, "", (), {}, []], key=MixedTypeKey)
...     [None, Ellipsis, 1, 1j, '', (), {}, []]
...     """
...     def __init__(self, k):
...         self._sort_key = k
...         self._type_name = self._get_fully_qualified_name(k)
...     def _get_fully_qualified_name(self, k):
...         k_type = type(k)
...         # Use __qualname__ if available, __name__ otherwise
...         try:
...             k_name = k_type.__qualname__
...         except AttributeError:
...             k_name = k_type.__name__
...         return k_type.__module__ + "." + k_name
...     def __lt__(self, other):
...         # Try standard sorting first
...         sort_key = self._sort_key
...         try:
...             other_sort_key = other._sort_key
...         except AttributeError:
...             other_sort_key = other
...         try:
...             return sort_key < other_sort_key
...         except TypeError:
...             pass
...         # If that fails, sort by the fully qualified type names
...         try:
...             other_type_name = other._type_name
...         except AttributeError:
...             other_type_name = self._get_fully_qualified_name(other)
...         return self._type_name < other_type_name
... 
>>> sorted([None, ..., 1, 1j, "", (), {}, []])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: ellipsis() < NoneType()
>>> sorted([None, ..., 1, 1j, "", (), {}, []], key=MixedTypeKey)
[None, 1j, {}, Ellipsis, 1, [], '', ()]
>>> MixedTypeKey(None) < ...
True

The stdlib version could omit the fallback to __name__ (since it doesn't need to cope with old versions of Python)

Support for other comparisons could theoretically be added, but I advise against it without a solid use case (sorting only needs __lt__).
msg228598 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2014-10-05 17:42
Just a gentle reminder guys.
msg237535 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-03-08 13:44
See also issue22721.
History
Date User Action Args
2022-04-11 14:57:46adminsetgithub: 62373
2019-02-24 22:59:21BreamoreBoysetnosy: - BreamoreBoy
2015-07-21 07:23:46ethan.furmansetnosy: - ethan.furman
2015-03-08 13:44:25serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg237535
2015-03-08 13:36:47berker.peksagsetnosy: + berker.peksag
2014-10-05 17:42:17BreamoreBoysetnosy: + BreamoreBoy

messages: + msg228598
versions: + Python 3.5, - Python 3.4
2013-06-27 01:04:30ethan.furmansetnosy: + ethan.furman
2013-06-09 13:54:32ncoghlancreate