Changeset 287
- Timestamp:
- 08/23/06 17:09:46
- Files:
-
- trunk/logic.py (modified) (5 diffs)
- trunk/test/test_codewalk.py (modified) (12 diffs)
- trunk/test/test_logic.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/logic.py
r286 r287 150 150 """ 151 151 152 from dejavu import codewalk 152 from compiler.consts import * 153 import sys 153 154 from types import CodeType, FunctionType 154 155 … … 170 171 pass 171 172 173 from dejavu import codewalk 174 172 175 173 176 class Aggregator(codewalk.Rewriter): … … 199 202 200 203 # Add the **kwargs flag if present 201 if obj.co_flags & 0x08:202 self.co_flags |= 0x08204 if obj.co_flags & CO_VARKEYWORDS: 205 self.co_flags |= CO_VARKEYWORDS 203 206 204 207 # Add the *args flag if present 205 if obj.co_flags & 0x04:206 self.co_flags |= 0x04208 if obj.co_flags & CO_VARARGS: 209 self.co_flags |= CO_VARARGS 207 210 208 211 def and_combine(self, obj): … … 372 375 if not isinstance(attr, str): 373 376 attr = str(attr) 374 names = ('x', attr) 375 376 consts = (None, criteria) 377 378 co_flags = codewalk.CO_NOFREE | codewalk.CO_OPTIMIZED | codewalk.CO_NEWLOCALS 379 380 if sys.version_info >= (2, 5): 381 # 2.5 doesn't include arguments in co_names anymore, 382 idx = 0 383 names = (attr,) 384 # It also stopped prepending None to co_consts... 385 consts = (criteria,) 386 # ...and nested_scopes are now "always on". 387 co_flags |= codewalk.CO_NESTED 388 else: 389 idx = 1 390 names = ('x', attr) 391 consts = (None, criteria) 392 377 393 co = [124, 0, 0, 378 105, 1, 0,379 100, 1, 0,394 105, idx, 0, 395 100, idx, 0, 380 396 106, cmp_op, 0, 381 397 83, … … 386 402 # constants, names, varnames, 387 403 # filename, name, firstlineno, lnotab[, freevars[, cellvars]]) 388 co = CodeType(1, 1, 2, 67, ''.join(map(chr, co)),404 co = CodeType(1, 1, 2, co_flags, ''.join(map(chr, co)), 389 405 consts, names, ('x',), '', '<lambda>', 1, '') 390 406 func = FunctionType(co, {}) trunk/test/test_codewalk.py
r286 r287 4 4 except ImportError: 5 5 fixedpoint = None 6 6 7 import sys 8 if sys.version_info >= (2, 5): 9 # Python 2.5 stopped putting arguments in co_names, 10 # and stopped prepending None to co_consts (except when CO_NESTED?). 11 idx = 0 12 else: 13 idx = 1 14 15 7 16 import unittest 8 17 … … 54 63 r = codewalk.Localizer(f[0]).bytecode() 55 64 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 56 'LOAD_CONST', 1, 0,65 'LOAD_CONST', idx, 0, 57 66 'COMPARE_OP', 6, 0, 58 67 'RETURN_VALUE'])) 59 68 r = codewalk.Localizer(f[1]).bytecode() 60 69 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 61 'LOAD_CONST', 3, 0,62 'LOAD_ATTR', 2, 0,63 'LOAD_CONST', 1, 0,64 'LOAD_CONST', 2, 0,65 'LOAD_CONST', 2, 0,70 'LOAD_CONST', idx + 2, 0, 71 'LOAD_ATTR', idx + 1, 0, 72 'LOAD_CONST', idx, 0, 73 'LOAD_CONST', idx + 1, 0, 74 'LOAD_CONST', idx + 1, 0, 66 75 'CALL_FUNCTION', 3, 0, 67 76 'BINARY_ADD', … … 69 78 r = codewalk.Localizer(f[2]).bytecode() 70 79 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 71 'LOAD_ATTR', 1, 0,72 'LOAD_CONST', 4, 0,73 'LOAD_ATTR', 3, 0,74 'LOAD_CONST', 1, 0,75 'LOAD_CONST', 2, 0,76 'LOAD_CONST', 2, 0,80 'LOAD_ATTR', idx, 0, 81 'LOAD_CONST', idx + 3, 0, 82 'LOAD_ATTR', idx + 2, 0, 83 'LOAD_CONST', idx, 0, 84 'LOAD_CONST', idx + 1, 0, 85 'LOAD_CONST', idx + 1, 0, 77 86 'CALL_FUNCTION', 3, 0, 78 87 'COMPARE_OP', 2, 0, … … 80 89 'POP_TOP', 81 90 'LOAD_FAST', 0, 0, 82 'LOAD_ATTR', 4, 0,91 'LOAD_ATTR', idx + 3, 0, 83 92 'LOAD_FAST', 1, 0, 84 'LOAD_CONST', 3, 0,93 'LOAD_CONST', idx + 2, 0, 85 94 'BINARY_SUBSCR', 86 95 'COMPARE_OP', 0, 0, … … 88 97 89 98 r = codewalk.Localizer(f[3]).bytecode() 90 self.assertEqual(r, nums(['LOAD_CONST', 1, 0,91 'LOAD_FAST', 0, 0, 92 'LOAD_ATTR', 1, 0,99 self.assertEqual(r, nums(['LOAD_CONST', idx, 0, 100 'LOAD_FAST', 0, 0, 101 'LOAD_ATTR', idx, 0, 93 102 'COMPARE_OP', 3, 0, 94 103 'JUMP_IF_TRUE', 14, 0, 95 104 'POP_TOP', 96 105 'LOAD_FAST', 1, 0, 97 'LOAD_CONST', 2, 0,106 'LOAD_CONST', idx + 1, 0, 98 107 'BINARY_MULTIPLY', 99 'LOAD_CONST', 3, 0,108 'LOAD_CONST', idx + 2, 0, 100 109 'COMPARE_OP', 4, 0, 101 110 'RETURN_VALUE'])) … … 104 113 r = codewalk.EarlyBinder(f[1]).bytecode() 105 114 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 106 'LOAD_CONST', 5, 0,115 'LOAD_CONST', idx + 4, 0, 107 116 'BINARY_ADD', 108 117 'RETURN_VALUE'])) 109 118 r = codewalk.EarlyBinder(f[2]).bytecode() 110 119 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 111 'LOAD_ATTR', 1, 0,112 'LOAD_CONST', 6, 0,120 'LOAD_ATTR', idx, 0, 121 'LOAD_CONST', idx + 5, 0, 113 122 'COMPARE_OP', 2, 0, 114 123 'JUMP_IF_FALSE', 17, 0, 115 124 'POP_TOP', 116 125 'LOAD_FAST', 0, 0, 117 'LOAD_ATTR', 4, 0,126 'LOAD_ATTR', idx + 3, 0, 118 127 'LOAD_FAST', 1, 0, 119 'LOAD_CONST', 3, 0,128 'LOAD_CONST', idx + 2, 0, 120 129 'BINARY_SUBSCR', 121 130 'COMPARE_OP', 0, 0, 122 131 'RETURN_VALUE'])) 123 132 r = codewalk.EarlyBinder(f[4]).bytecode() 124 self.assertEqual(r, nums(['LOAD_CONST', 5, 0,133 self.assertEqual(r, nums(['LOAD_CONST', idx + 4, 0, 125 134 'LOAD_FAST', 0, 0, 126 135 'BINARY_MULTIPLY', 127 136 'RETURN_VALUE'])) 128 137 r = codewalk.EarlyBinder(f[5]).bytecode() 129 self.assertEqual(r, nums(['LOAD_CONST', 5, 0,130 'LOAD_FAST', 0, 0, 131 'LOAD_CONST', 3, 0,138 self.assertEqual(r, nums(['LOAD_CONST', idx + 4, 0, 139 'LOAD_FAST', 0, 0, 140 'LOAD_CONST', idx + 2, 0, 132 141 'BINARY_SUBSCR', 133 142 'UNARY_NEGATIVE', … … 135 144 'RETURN_VALUE'])) 136 145 r = codewalk.EarlyBinder(f[6]).bytecode() 137 self.assertEqual(r, nums(['LOAD_CONST', 2, 0,146 self.assertEqual(r, nums(['LOAD_CONST', idx + 1, 0, 138 147 'JUMP_IF_TRUE', 13, 0, 139 148 'POP_TOP', 140 'LOAD_CONST', 1, 0,141 'LOAD_FAST', 0, 0, 142 'LOAD_ATTR', 2, 0,149 'LOAD_CONST', idx, 0, 150 'LOAD_FAST', 0, 0, 151 'LOAD_ATTR', idx + 1, 0, 143 152 'COMPARE_OP', 2, 0, 144 153 'RETURN_VALUE'])) … … 146 155 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 147 156 # 2, since co_names was ('getattr', 'x'). 148 'LOAD_ATTR', 2, 0,149 'LOAD_CONST', 2, 0,157 'LOAD_ATTR', idx + 1, 0, 158 'LOAD_CONST', idx + 1, 0, 150 159 'COMPARE_OP', 2, 0, 151 160 'RETURN_VALUE'])) … … 154 163 r = codewalk.EarlyBinder(e, bind_late=[datetime.date.today]).bytecode() 155 164 self.assertEqual(r, nums(['LOAD_FAST', 0, 0, 156 'LOAD_ATTR', 1, 0,157 'LOAD_CONST', 3, 0,165 'LOAD_ATTR', idx, 0, 166 'LOAD_CONST', idx + 2, 0, 158 167 'CALL_FUNCTION', 0, 0, 159 168 'COMPARE_OP', 5, 0, … … 162 171 # Closures (dereferencing of func_closure) 163 172 r = codewalk.EarlyBinder(f[11]).bytecode() 164 v = sys.version_info 165 if v[0] >= 2 and v[1] >= 4: 166 # This bytecode changed for Python 2.4 173 if sys.version_info >= (2, 4): 174 # This bytecode changed for Python 2.4. 175 # Oddly enough, it didn't change from 2.4 to 2.5 176 # like other LOAD_CONST (because of CO_NESTED?). 167 177 self.assertEqual(r, nums(['LOAD_CONST', 2, 0, 168 178 'RETURN_VALUE'])) 169 179 else: 170 self.assertEqual(r, nums(['LOAD_CONST', 2, 0,180 self.assertEqual(r, nums(['LOAD_CONST', idx + 1, 0, 171 181 'RETURN_VALUE', 172 182 'LOAD_CONST', 0, 0, … … 178 188 "lambda x, **kw: (x.Date == datetime.date(2004, 1, 1)) and (x.Qty < kw['Size'])", 179 189 "lambda x, amount: (4 != x.amount) or (amount * 3 > 20)", 180 "lambda x: 3 * 4 * 5 * x", 190 ] 191 if sys.version_info >= (2, 5): 192 # Python 2.5 collapses constants where possible. 193 s.append("lambda x: 60 * x") 194 else: 195 s.append("lambda x: 3 * 4 * 5 * x") 196 s.extend([ 181 197 "lambda x: a[2:4] == -(x['offset'])", 182 198 "lambda x: (amount == 5) or (amount == x.Qty)", … … 186 202 "lambda x, y, z, **kw: (x.Qty > 1) and ((y.Qty > 20) and (z.Type == 'A'))", 187 203 "", 188 ] 204 ]) 189 205 if fixedpoint: 190 206 s.append("lambda x: x.Amount > fixedpoint.FixedPoint(3, 2)") trunk/test/test_logic.py
r286 r287 17 17 e = logic.Expression(lambda x: dejavu.icontains(x.Status, 'c')) 18 18 self.assertEqual(repr(e), lx + "dejavu.icontains(x.Status, 'c'))") 19 self.assertEqual(e.func.func_code.co_code, 20 'd\x03\x00|\x00\x00i\x03\x00d\x01\x00\x83\x02\x00S') 19 if sys.version_info >= (2, 5): 20 # Python 2.5 stopped including args in co_names, 21 # so the indices into co_names changed. 22 self.assertEqual(e.func.func_code.co_code, 23 'd\x02\x00|\x00\x00i\x02\x00d\x00\x00\x83\x02\x00S') 24 else: 25 self.assertEqual(e.func.func_code.co_code, 26 'd\x03\x00|\x00\x00i\x03\x00d\x01\x00\x83\x02\x00S') 21 27 22 28 # 4/28/04: This one failed in endue.html.nav, … … 48 54 # Test the 'in' operator. 49 55 e = logic.Expression(lambda x: x.Name in ['George', 'John']) 50 self.assertEqual(repr(e), lx + "x.Name in ['George', 'John'])") 56 if sys.version_info >= (2, 5): 57 # Python 2.5 collapses the list into a single tuple CONST 58 self.assertEqual(repr(e), lx + "x.Name in ('George', 'John'))") 59 else: 60 self.assertEqual(repr(e), lx + "x.Name in ['George', 'John'])") 51 61 52 62 # Test varying return values. … … 102 112 a = lambda x: x.Date == 3 103 113 b = lambda x: x.Qty == 5 114 115 if sys.version_info >= (2, 5): 116 # Python 2.5 stopped including args in co_names, 117 # so the indices into co_names changed. 118 i = 0 119 else: 120 i = 1 121 104 122 merged_code = nums(['LOAD_FAST', 0, 0, 105 'LOAD_ATTR', 1, 0,106 'LOAD_CONST', 1, 0,123 'LOAD_ATTR', i, 0, 124 'LOAD_CONST', i, 0, 107 125 'COMPARE_OP', 2, 0, 108 126 'JUMP_IF_FALSE', 13, 0, 109 127 'POP_TOP', 110 128 'LOAD_FAST', 0, 0, 111 'LOAD_ATTR', 2, 0,112 'LOAD_CONST', 2, 0,129 'LOAD_ATTR', i + 1, 0, 130 'LOAD_CONST', i + 1, 0, 113 131 'COMPARE_OP', 2, 0, 114 132 'RETURN_VALUE']) … … 120 138 # Combine another. Change the name of the first arg and add kwargs. 121 139 ag.and_combine(lambda y, **kw: y.Size < kw['Size']) 122 self.assertEqual(ag.bytecode(), nums(['LOAD_FAST', 0, 0, 123 'LOAD_ATTR', 1, 0, 124 'LOAD_CONST', 1, 0, 125 'COMPARE_OP', 2, 0, 126 'JUMP_IF_FALSE', 13, 0, 127 'POP_TOP', 128 'LOAD_FAST', 0, 0, 129 'LOAD_ATTR', 2, 0, 130 'LOAD_CONST', 2, 0, 131 'COMPARE_OP', 2, 0, 132 'JUMP_IF_FALSE', 17, 0, 133 'POP_TOP', 134 'LOAD_FAST', 0, 0, 135 'LOAD_ATTR', 3, 0, 136 'LOAD_FAST', 1, 0, 137 'LOAD_CONST', 3, 0, 138 'BINARY_SUBSCR', 139 'COMPARE_OP', 0, 0, 140 'RETURN_VALUE'])) 140 merged_code = nums(['LOAD_FAST', 0, 0, 141 'LOAD_ATTR', i, 0, 142 'LOAD_CONST', i, 0, 143 'COMPARE_OP', 2, 0, 144 'JUMP_IF_FALSE', 13, 0, 145 'POP_TOP', 146 'LOAD_FAST', 0, 0, 147 'LOAD_ATTR', i + 1, 0, 148 'LOAD_CONST', i + 1, 0, 149 'COMPARE_OP', 2, 0, 150 'JUMP_IF_FALSE', 17, 0, 151 'POP_TOP', 152 'LOAD_FAST', 0, 0, 153 'LOAD_ATTR', i + 2, 0, 154 'LOAD_FAST', 1, 0, 155 'LOAD_CONST', i + 2, 0, 156 'BINARY_SUBSCR', 157 'COMPARE_OP', 0, 0, 158 'RETURN_VALUE']) 159 self.assertEqual(ag.bytecode(), merged_code) 141 160 f = ag.function() 142 161 if sys.hexversion >= (2 << 24 | 4 << 16): … … 160 179 # Assert the mixed code (before renumbering consts) 161 180 self.assertEqual(ag._bytecode, nums(['LOAD_FAST', 0, 0, 162 'LOAD_ATTR', 1, 0,163 'LOAD_CONST', 1, 0,181 'LOAD_ATTR', i, 0, 182 'LOAD_CONST', i, 0, 164 183 'COMPARE_OP', 2, 0, 165 184 'JUMP_IF_FALSE', 13, 0, 166 185 'POP_TOP', 167 186 'LOAD_FAST', 0, 0, 168 'LOAD_ATTR', 1, 0,169 'LOAD_CONST', 1, 0,187 'LOAD_ATTR', i, 0, 188 'LOAD_CONST', i, 0, 170 189 'COMPARE_OP', 2, 0, 171 190 'RETURN_VALUE'])) 172 191 # Assert the final, mixed code 173 192 self.assertEqual(ag.bytecode(), nums(['LOAD_FAST', 0, 0, 174 'LOAD_ATTR', 1, 0,175 'LOAD_CONST', 1, 0,193 'LOAD_ATTR', i, 0, 194 'LOAD_CONST', i, 0, 176 195 'COMPARE_OP', 2, 0, 177 196 'JUMP_IF_FALSE', 13, 0, 178 197 'POP_TOP', 179 198 'LOAD_FAST', 0, 0, 180 'LOAD_ATTR', 2, 0,181 'LOAD_CONST', 2, 0,199 'LOAD_ATTR', i + 1, 0, 200 'LOAD_CONST', i + 1, 0, 182 201 'COMPARE_OP', 2, 0, 183 202 'RETURN_VALUE']))
