1 #!/usr/bin/env python 2 3 """ 4 Operator support. 5 6 Copyright (C) 2010 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 def binary_op(a, b, left_name, right_name): 23 24 """ 25 A single parameterised function providing the binary operator mechanism for 26 arguments 'a' and 'b' using methods of the given 'left_name' and 27 'right_name'. 28 """ 29 30 # First, try and get a method for the left argument, and then call it with 31 # the right argument. 32 33 try: 34 fn = getattr(a, left_name) 35 except AttributeError: 36 pass 37 else: 38 result = fn(b) 39 if result is not NotImplemented: 40 return result 41 42 # Otherwise, try and get a method for the right argument, and then call it 43 # with the left argument. 44 45 try: 46 fn = getattr(b, right_name) 47 except AttributeError: 48 pass 49 else: 50 result = fn(a) 51 if result is not NotImplemented: 52 return result 53 54 # Where no methods were available, or if neither method could support the 55 # operation, raise an exception. 56 57 raise TypeError 58 59 def add(a, b): 60 return binary_op(a, b, "__add__", "__radd__") 61 62 def and_(a, b): 63 return binary_op(a, b, "__and__", "__rand__") 64 65 def div(a, b): 66 return binary_op(a, b, "__div__", "__rdiv__") 67 68 def floordiv(a, b): 69 return binary_op(a, b, "__floordiv__", "__rfloordiv__") 70 71 def lshift(a, b): 72 return binary_op(a, b, "__lshift__", "__rlshift__") 73 74 def mod(a, b): 75 return binary_op(a, b, "__mod__", "__rmod__") 76 77 def mul(a, b): 78 return binary_op(a, b, "__mul__", "__rmul__") 79 80 def or(a, b): 81 return binary_op(a, b, "__or__", "__ror__") 82 83 def pow(a, b): 84 return binary_op(a, b, "__pow__", "__rpow__") 85 86 def rshift(a, b): 87 return binary_op(a, b, "__rshift__", "__rrshift__") 88 89 def sub(a, b): 90 return binary_op(a, b, "__sub__", "__rsub__") 91 92 def xor(a, b): 93 return binary_op(a, b, "__xor__", "__rxor__") 94 95 # vim: tabstop=4 expandtab shiftwidth=4