The documentation states you must define one of __lt__(), __le__(), __gt__(), or __ge__(), but only should supply an __eq__() method.
In other words, the __eq__ method is optional.
The total_ordering implementation does not require you to specify an __eq__ method; it only tests for the __lt__(), __le__(), __gt__(), or __ge__() methods. It supplies up to 3 missing special methods based of one of those 4.
You can't base the order on just __le__ or __ge__ because you can't assume that you can swap a and b; if b is a different type b.__le__ might not be implemented and so your a < b   <=>   not (b <= a) map can't be guaranteed. The implementation uses (a <= b) and (a != b) if __le__ is not defined but __lt__ has been.
The full table of mappings is:
| comparison | available | alternative | 
| a > b | a < b | (not a < b) and (a != b) | 
|  | a <= b | (not a <= b) | 
|  | a >= b | (a >= b) and (a != b) | 
| a <= b | a < b | (a < b) or (a == b) | 
|  | a > b | (not a > b) | 
|  | a >= b | (not a >= b) or (a == b) | 
| a < b | a <= b | (a <= b) and (a != b) | 
|  | a > b | (not a > b) and (a != b) | 
|  | a >= b | (not a >= b) | 
| a >= b | a < b | (not a < b) | 
|  | a <= b | (not a <= b) or (a == b) | 
|  | a > b | (a > b) or (a == b) | 
 
The __eq__ method is optional because the base object object defines one for you; two instances are considered equal only if they are the same object; ob1 == ob2 only if ob1 is ob2 is True. See the do_richcompare() function in object.c; remember that the == operator in the code there is comparing pointers.