| #!/usr/bin/env python3 | 
 | # -*- coding: utf-8 -*- | 
 | # | 
 | # Copyright (C) 2017-2020  The Project X-Ray Authors. | 
 | # | 
 | # Use of this source code is governed by a ISC-style | 
 | # license that can be found in the LICENSE file or at | 
 | # https://opensource.org/licenses/ISC | 
 | # | 
 | # SPDX-License-Identifier: ISC | 
 | """ | 
 | Python 3 removed the 'cmp' function and raises a Type error when you try to | 
 | compare different types. This module recreates Python 2 style 'cmp' function | 
 | which produces a "total ordering" for mixed type lists. | 
 | """ | 
 |  | 
 | import functools | 
 | import itertools | 
 |  | 
 |  | 
 | def cmp(a, b): | 
 |     """ | 
 |  | 
 |     >>> cmp(1, 1) | 
 |     0 | 
 |     >>> cmp('A', 'A') | 
 |     0 | 
 |     >>> cmp(None, None) | 
 |     0 | 
 |     >>> cmp(('A', 'B'), ('A', 'B')) | 
 |     0 | 
 |     >>> cmp(['A', 'B'], ('A', 'B')) | 
 |     0 | 
 |     >>> cmp((1, 2), (1, 2)) | 
 |     0 | 
 |     >>> cmp((1, 2), [1, 2]) | 
 |     0 | 
 |  | 
 |     >>> cmp(1, 2) | 
 |     -1 | 
 |     >>> cmp('A', 'B') | 
 |     -1 | 
 |     >>> cmp(('A', 'B'), ('A', 'C')) | 
 |     -1 | 
 |     >>> cmp(['A', 'B'], ('A', 'C')) | 
 |     -1 | 
 |     >>> cmp((1, 2), (1, 3)) | 
 |     -1 | 
 |     >>> cmp((1, 2), [1, 3]) | 
 |     -1 | 
 |  | 
 |     >>> cmp(2, 1) | 
 |     1 | 
 |     >>> cmp('B', 'A') | 
 |     1 | 
 |     >>> cmp(('A', 'C'), ('A', 'B')) | 
 |     1 | 
 |     >>> cmp(['A', 'C'], ('A', 'B')) | 
 |     1 | 
 |     >>> cmp((1, 3), (1, 2)) | 
 |     1 | 
 |     >>> cmp((1, 3), [1, 2]) | 
 |     1 | 
 |  | 
 |     >>> cmp(1, None) | 
 |     1 | 
 |     >>> cmp('A', None) | 
 |     1 | 
 |     >>> cmp(('A', 'B'), None) | 
 |     1 | 
 |     >>> cmp(['A', 'B'], None) | 
 |     1 | 
 |     >>> cmp((1, 2), None) | 
 |     1 | 
 |     >>> cmp((1, 2), None) | 
 |     1 | 
 |  | 
 |     >>> cmp(None, 2) | 
 |     -1 | 
 |     >>> cmp(None, 'B') | 
 |     -1 | 
 |     >>> cmp(None, ('A', 'B')) | 
 |     -1 | 
 |     >>> cmp(None, ('A', 'C')) | 
 |     -1 | 
 |     >>> cmp(None, (1, 2)) | 
 |     -1 | 
 |     >>> cmp(None, [1, 3]) | 
 |     -1 | 
 |  | 
 |     >>> cmp(1, 'A') | 
 |     -1 | 
 |     >>> cmp('A', 1) | 
 |     1 | 
 |  | 
 |     >>> cmp(('A', 'B'), 1) | 
 |     1 | 
 |     >>> cmp(1, ['A', 'B']) | 
 |     -1 | 
 |  | 
 |     >>> cmp((1, 2), 1) | 
 |     1 | 
 |     >>> cmp(1, (1, 2)) | 
 |     -1 | 
 |  | 
 |     >>> cmp('A', 'AA') | 
 |     -1 | 
 |     >>> cmp('AA', 'A') | 
 |     1 | 
 |  | 
 |     >>> cmp(b'A', b'A') | 
 |     0 | 
 |     >>> cmp(b'A', b'AA') | 
 |     -1 | 
 |     >>> cmp(b'AA', b'A') | 
 |     1 | 
 |  | 
 |     >>> def bit(*args): | 
 |     ...   return args | 
 |     >>> a = ('CLBLL', 'L', 'SLICEL', ('X', 0), 'AFFMUX', 'XOR') | 
 |     >>> b = ('CLBLL', 'L', 'SLICEL', ('X', 0), 'AFFMUX', ('F', 7)) | 
 |     >>> cmp(a, b) | 
 |     -1 | 
 |     >>> cmp(b, a) | 
 |     1 | 
 |  | 
 |     """ | 
 |     if not isinstance(a, (str, bytes)) and not isinstance(b, (str, bytes)): | 
 |         try: | 
 |             for i, j in itertools.zip_longest(iter(a), iter(b)): | 
 |                 r = cmp(i, j) | 
 |                 if r != 0: | 
 |                     return r | 
 |             return 0 | 
 |         except TypeError: | 
 |             pass | 
 |     if type(a) == type(b): | 
 |         if a == b: | 
 |             return 0 | 
 |         elif a < b: | 
 |             return -1 | 
 |         elif a > b: | 
 |             return 1 | 
 |         else: | 
 |             raise SystemError | 
 |     return cmp(a.__class__.__name__, b.__class__.__name__) | 
 |  | 
 |  | 
 | cmp_key = functools.cmp_to_key(cmp) | 
 |  | 
 | if __name__ == "__main__": | 
 |     import doctest | 
 |     doctest.testmod() |