python/samba: Add cmp_fn and cmp_to_key_fn functions for py2/py3
[samba.git] / python / samba / compat.py
1 # module which helps with porting to Python 3
2 #
3 # Copyright (C) Lumir Balhar <lbalhar@redhat.com> 2017
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 """module which helps with porting to Python 3"""
19
20 import sys
21
22 PY3 = sys.version_info[0] == 3
23
24 if PY3:
25     def cmp_fn(x, y):
26         """
27         Replacement for built-in function cmp that was removed in Python 3
28
29         Compare the two objects x and y and return an integer according to
30         the outcome. The return value is negative if x < y, zero if x == y
31         and strictly positive if x > y.
32         """
33
34         return (x > y) - (x < y)
35     # compat functions
36     from  urllib.parse import quote as urllib_quote
37     from urllib.request import urlopen as urllib_urlopen
38     from functools import cmp_to_key as cmp_to_key_fn
39
40     # compat types
41     integer_types = int,
42     string_types = str
43     text_type = str
44     binary_type = bytes
45
46     # alias
47     import io
48     StringIO = io.StringIO
49 else:
50
51     if sys.version_info < (2, 7):
52         def cmp_to_key_fn(mycmp):
53
54             """Convert a cmp= function into a key= function"""
55             class K(object):
56                 __slots__ = ['obj']
57
58                 def __init__(self, obj, *args):
59                     self.obj = obj
60
61                 def __lt__(self, other):
62                     return mycmp(self.obj, other.obj) < 0
63
64                 def __gt__(self, other):
65                     return mycmp(self.obj, other.obj) > 0
66
67                 def __eq__(self, other):
68                     return mycmp(self.obj, other.obj) == 0
69
70                 def __le__(self, other):
71                     return mycmp(self.obj, other.obj) <= 0
72
73                 def __ge__(self, other):
74                     return mycmp(self.obj, other.obj) >= 0
75
76                 def __ne__(self, other):
77                     return mycmp(self.obj, other.obj) != 0
78
79                 def __hash__(self):
80                     raise TypeError('hash not implemented')
81             return K
82     else:
83         from functools import cmp_to_key as cmp_to_key_fn
84     # compat functions
85     from urllib import quote as urllib_quote
86     from urllib import urlopen as urllib_urlopen
87
88     # compat types
89     integer_types = (int, long)
90     string_types = basestring
91     text_type = unicode
92     binary_type = str
93
94     # alias
95     import StringIO
96     StringIO = StringIO.StringIO
97     cmp_fn = cmp