Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

I think I've seen this ORM somewhere before...

Changeset 92

Show
Ignore:
Timestamp:
11/16/05 03:32:07
Author:
fumanchu
Message:

An ugly first fix for #25 (Python 2.4's JUMP changes). Could be inlined, but needs some improvement regardless. Probably needs more tests too.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/codewalk.py

    r91 r92  
    120120     
    121121    def __init__(self, obj): 
     122        self.verbose = False 
     123         
    122124        # Distill supplied 'obj' arg to a code block string. 
    123125        if isinstance(obj, FunctionType): 
     
    135137         
    136138        self._bytecode = obj 
     139     
     140    def debug(self, *messages): 
     141        if self.verbose: 
     142            for term in messages: 
     143                print term, 
     144        else: 
     145            pass 
    137146     
    138147    def walk(self): 
     
    243252     
    244253    def __init__(self, obj): 
     254        self.verbose = False 
     255         
    245256        if isinstance(obj, FunctionType): 
    246257            self._func = obj 
     
    387398            pos = self.const_index(value) 
    388399            self.tail(3, 'LOAD_CONST', pos & 0xFF, pos >> 8) 
    389             if self.verbose: 
    390                 print name, '-->', value 
     400            self.debug(name, ' --> ', value) 
    391401 
    392402 
     
    678688     
    679689    def __init__(self, obj): 
     690        self.verbose = False 
     691         
    680692        # Distill supplied 'obj' arg to a code block string. 
    681693        if isinstance(obj, FunctionType): 
     
    723735        self.newcode = [] 
    724736         
    725         # Add a list of 'and' and 'or' mappings {target: [(previous TOS, and/or)...]
     737        self.jump_values = {
    726738        self.targets = {} 
    727739        b = self._bytecode 
     740        self.debug("\nWALKING: ", b) 
    728741        while self.cursor < len(b): 
    729             if self.cursor in self.targets: 
    730                 self.visit_target(self.targets[self.cursor]) 
     742            self.debug("\n") 
     743             
     744            ip = self.cursor 
     745            if ip in self.targets: 
     746                self.debug(">>") 
     747             
     748            self.debug(self.cursor) 
     749             
    731750            op = b[self.cursor] 
    732751            self.cursor += 1 
     
    740759                args = () 
    741760             
     761            self.debug("visit (%s, %s)" % (op, repr(args))) 
    742762            self.visit_instruction(op, *args) 
    743763             
    744764            name = 'visit_' + opname[op] 
    745765            name = name.replace('+', '_PLUS_') 
    746              
    747766            if hasattr(self, name): 
     767                self.debug("=> %s(%s)" % (name, repr(args))) 
    748768                getattr(self, name)(*args) 
    749      
    750     def visit_target(self, terms): 
    751         comp = self.stack.pop() 
    752         while terms: 
    753             term, operation = terms.pop() 
    754             comp = "(%s) %s (%s)" % (term, operation, comp) 
    755         self.stack.append(comp) 
     769         
     770        # Combine any targets into a single clause 
     771        self.debug(self.targets) 
     772        targets = [(k, v) for k, v in self.targets.iteritems()] 
     773        if targets: 
     774            targets.sort() 
     775            for target_ip, sources in targets: 
     776                sources.sort() 
     777                sources.reverse() 
     778                for jump_ip, op in sources: 
     779                    # Find term1 at the jump. 
     780                    term1 = self.jump_values[jump_ip] 
     781                    # Find term2 at or just before the target. 
     782                    ip2, term2 = None, None 
     783                    jumps = [(k, v) for k, v in self.jump_values.iteritems()] 
     784                    jumps.sort() 
     785                    for temp_ip, temp_val in jumps: 
     786                        if temp_ip > target_ip: 
     787                            break 
     788                        ip2 = temp_ip 
     789                        term2 = temp_val 
     790                    self.debug("###", target_ip, jump_ip, ip2, "#") 
     791                    clause = "(%s) %s (%s)" % (term1, op, term2) 
     792                    # Replace term2 with the new clause, so that further 
     793                    # combinations have access to it. 
     794                    self.jump_values[ip2] = clause 
     795                    # Just for fun and debuggability, delete term1 
     796                    if jump_ip != ip2: 
     797                        del self.jump_values[jump_ip] 
     798                    self.debug("\n", self.jump_values) 
     799            self.stack = [self.jump_values[ip2]] 
     800        self.debug("stack:", self.stack) 
    756801     
    757802    def visit_BUILD_TUPLE(self, lo, hi): 
     
    789834     
    790835    def visit_JUMP_IF_FALSE(self, lo, hi): 
     836        # Note that self.cursor has already advanced to the next instruction. 
     837        ip = self.cursor - 3 
     838        self.jump_values[ip] = self.stack[-1] 
     839         
    791840        target = self.cursor + (lo + (hi << 8)) 
    792         targetstack = self.targets.setdefault(target, []) 
    793         targetstack.append((self.stack.pop(), 'and')) 
     841        bucket = self.targets.setdefault(target, []) 
     842        bucket.append((ip, 'and')) 
    794843     
    795844    def visit_JUMP_IF_TRUE(self, lo, hi): 
     845        # Note that self.cursor has already advanced to the next instruction. 
     846        ip = self.cursor - 3 
     847        self.jump_values[ip] = self.stack[-1] 
     848         
    796849        target = self.cursor + (lo + (hi << 8)) 
    797         targetstack = self.targets.setdefault(target, []) 
    798         targetstack.append((self.stack.pop(), 'or')) 
     850        bucket = self.targets.setdefault(target, []) 
     851        bucket.append((ip, 'or')) 
    799852     
    800853    def visit_LOAD_ATTR(self, lo, hi): 
     
    819872        self.stack.append(self.co_names[lo + (hi << 8)]) 
    820873     
     874    def visit_POP_TOP(self): 
     875        self.stack.pop() 
     876     
     877    def visit_RETURN_VALUE(self): 
     878        # Note that self.cursor is already the next instruction. 
     879        ip = self.cursor - 1 
     880        self.jump_values[ip] = self.stack[-1] 
     881     
    821882    def visit_SLICE_PLUS_0(self): 
    822883        arg = self.stack.pop() 
  • trunk/test_logic.py

    r91 r92  
    5959                         "lambda x: (x.TripStatus != 'Inquiry') and ((x.Field " 
    6060                         "== 'BC') and (x.StartDate >= 3))") 
    61      
     61         
    6262        # Test Expression pickling 
    6363        e = logic.Expression(lambda x: x.LastDate > datetime.date(2004, 3, 1)) 
     
    7070        f = pickle.loads(p) 
    7171        self.assertEqual(repr(e), repr(f)) 
    72  
    7372     
    7473    def test_Expression_addition(self): 
     
    7877        e += logic.Expression(b) 
    7978        self.assertEqual(e.code(), "lambda x: (x.Date == 3) and (x.Qty == 5)") 
     79         
     80        # This failed in endue.price_filter on 11/14/2005 
     81        f = logic.Expression(lambda x: ((x.DateFrom == None or x.DateFrom <= datetime.date(2005, 11, 17)) 
     82                                        and (x.DateTo == None or x.DateTo >= datetime.date(2005, 11, 17)))) 
     83        f += logic.Expression(lambda x: x.DirectoryID == None or x.DirectoryID == 0) 
     84        self.assertEqual(f.code(), 
     85            'lambda x: (((x.DateFrom == None) or (x.DateFrom <= datetime.date(2005, 11, 17))) ' 
     86            'and ((x.DateTo == None) or (x.DateTo >= datetime.date(2005, 11, 17)))) ' 
     87            'and ((x.DirectoryID == None) or (x.DirectoryID == 0))') 
    8088     
    8189    def test_Aggregator(self):