-
Kirill Smelkov authored
In 54c2a3cf (golang_str: Teach bstr/ustr to compare wrt any string with automatic coercion) I've added __eq__, __ne__, __lt__ etc methods to our strings, but __lt__ and other comparison to raise TypeError against any non-string type. My idea was to mimic user-visible py3 behaviour such as >>> "abc" > 1 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '>' not supported between instances of 'str' and 'int' However it turned out that the implementation was not exactly matching what Python is doing internally which lead to incorrect behaviour when bstr or ustr is compared wrt another type with its own __cmp__. In the general case for `a op b` Python first queries a.__op__(b) and b.__op'__(a) and sometimes other methods before going to .__cmp__. This relies on the methods to return NotImplemented instead of raising an exception and if a trial raises TypeError everything is stopped and that TypeError is returned to the caller. Jérome reports a real breakage due to this when bstr is compared wrt distutils.version.LooseVersion . LooseVersion is basically class LooseVersion(Version): def __cmp__ (self, other): if isinstance(other, StringType): other = LooseVersion(other) return cmp(self.version, other.version) but due to my thinko on `LooseVersion < bstr` the control flow was not getting into that LooseVersion.__cmp__ because bstr.__gt__ was tried first and raised TypeError. -> Fix all comparison operations to return NotImplemented instead of raising TypeError and make sure in the tests that this behaviour exactly matches what native str type does. The fix is needed not only for py2 because added test_strings_cmp_wrt_distutils_LooseVersion was failing on py3 as well without the fix. /reported-by @jerome /reported-on nexedi/slapos!1575 (comment 206080)
09694757