Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

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

Changeset 32

Show
Ignore:
Timestamp:
11/21/04 00:13:21
Author:
fumanchu
Message:

Made Decompiler less fragile by adding stack sentinels for cannot_represent, table_arg, and kw_arg.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/storage/storeado.py

    r31 r32  
    5858class AdapterFromADO(storage.Adapter): 
    5959    """Coerce incoming values from ADO to Dejavu datatypes.""" 
     60     
    6061    def __init__(self, unit=None): 
    6162        self.unit = unit 
     
    290291 
    291292 
     293# Stack sentinels 
     294cannot_represent = object() 
     295table_arg = object() 
     296kw_arg = object() 
     297 
    292298class ADOSQLDecompiler(codewalk.LambdaDecompiler): 
    293299    """ADOSQLDecompiler(store, unitClass, expr, adapter=AdapterToADOSQL()). 
     
    313319     
    314320    def __init__(self, store, unitClass, expr, adapter=AdapterToADOSQL()): 
    315         self.store = store 
    316         self.unitClass = unitClass 
     321        self.tablename = store.prefix + unitClass.__name__ 
    317322        self.expr = expr 
    318323        self.adapter = adapter 
     
    324329        self.walk() 
    325330        result = self.stack[0] 
    326         if result is None
     331        if result is cannot_represent
    327332            result = 'True' 
    328333        return result, self.imperfect 
     
    333338        while terms: 
    334339            term, operation = terms.pop() 
    335             # All this checking of None is done so that a function 
    336             # (like dejavu.iscurrentweek) can be labeled imperfect-- 
    337             # all Units (which match the rest of the Expression) 
    338             # will be recalled. They can then be compared in 
    339             # expr.evaluate(unit). 
    340             if comp is None
    341                 if term is not None
     340            # All this checking of cannot_represent is done so that a 
     341            # function (like dejavu.iscurrentweek) can be labeled 
     342            # imperfect--all Units (which match the rest of the  
     343            # Expression) will be recalled. They can then be 
     344            # compared in expr.evaluate(unit). 
     345            if term is not cannot_represent
     346                if comp is cannot_represent
    342347                    comp = term 
    343             else: 
    344                 if term is not None: 
     348                else: 
    345349                    comp = "(%s) %s (%s)" % (term, operation, comp) 
    346350        self.stack.append(comp) 
     
    353357     
    354358    def visit_LOAD_FAST(self, lo, hi): 
    355         pass 
     359        if lo + (hi << 8) < self.co_argcount: 
     360            self.stack.append(table_arg) 
     361        else: 
     362            self.stack.append(kw_arg) 
    356363     
    357364    def visit_LOAD_ATTR(self, lo, hi): 
    358365        name = self.co_names[lo + (hi << 8)] 
    359         self.stack.append("[%s%s].[%s]" % 
    360                           (self.store.prefix, self.unitClass.__name__, name)) 
     366        tos = self.stack.pop() 
     367        if tos is table_arg: 
     368            self.stack.append("[%s].[%s]" % (self.tablename, name)) 
     369        else: 
     370            self.stack.append((tos, name)) 
    361371     
    362372    def visit_LOAD_CONST(self, lo, hi): 
     
    377387        self.stack.append("(" + terms + ")") 
    378388     
    379     def visit_BUILD_LIST(self, lo, hi): 
    380         self.visit_BUILD_TUPLE(lo, hi) 
     389    visit_BUILD_LIST = visit_BUILD_TUPLE 
    381390     
    382391    def visit_CALL_FUNCTION(self, lo, hi): 
     
    403412            self.stack.append(self.functions[func](*args)) 
    404413        else: 
    405             if isinstance(func, basestring): 
    406                 if func.endswith("[startswith]"): 
    407                     self.stack[-1] = self.stack[-1] + " Like '" + args[0][1:-1] + "%'" 
     414            if isinstance(func, tuple): 
     415                tos, func = func 
     416                if func == "startswith": 
     417                    self.stack.append(tos + " Like '" + args[0][1:-1] + "%'") 
    408418                    self.imperfect = True 
    409419                    return 
    410                 elif func.endswith("[endswith]")
    411                     self.stack[-1] = self.stack[-1] + " Like '%" + args[0][1:-1] + "'" 
     420                elif func == "endswith"
     421                    self.stack.append(tos + " Like '%" + args[0][1:-1] + "'") 
    412422                    self.imperfect = True 
    413423                    return 
    414                 elif func == '<built-in function len>': 
     424            elif isinstance(func, basestring): 
     425                if func == '<built-in function len>': 
    415426                    self.stack.append("Len(" + args[0] + ")") 
    416427                    return 
    417428            else: 
    418429                if self.stack: 
    419                     self.stack[-1] = None 
     430                    self.stack[-1] = cannot_represent 
    420431                else: 
    421                     self.stack = [None
     432                    self.stack = [cannot_represent
    422433                self.imperfect = True 
    423434     
     
    437448        else: 
    438449            if op2.startswith("'") and op2.endswith("'"): 
    439                 # All ADO comparison operators for strings are case-insensitive 
    440                 # by default. Rather than determine column-by-column which 
     450                # ADO comparison operators for strings are case-insensitive 
     451                # by default. Rather than determine which columns in the DB 
    441452                # might be case-sensitive, just flag them all as imperfect. 
    442453                self.imperfect = True 
     
    448459     
    449460    def visit_BINARY_SUBSCR(self): 
    450         """The only BINARY_SUBSCR used in Expressions should be kwargs[key].""" 
     461        # The only BINARY_SUBSCR used in Expressions should be kwargs[key]. 
    451462        name = self.stack.pop() 
     463        tos = self.stack.pop() 
     464        if tos is not kw_arg: 
     465            raise ValueError(tos, name) 
    452466        # name, since formed in LOAD_CONST, has extraneous single-quotes. 
    453         value = self.expr.kwargs[name[1:-1]] 
     467        name = name[1:-1] 
     468        value = self.expr.kwargs[name] 
    454469        value = self.adapter.coerce(value) 
    455470        self.stack.append(value) 
     
    457472    def visit_UNARY_NOT(self): 
    458473        op = self.stack.pop() 
    459         if op is None
     474        if op is cannot_represent
    460475            # Usually as a result of has(farClassName). 
    461             self.stack.append(None
     476            self.stack.append(cannot_represent
    462477        else: 
    463478            self.stack.append("not (" + op + ")") 
  • trunk/storage/test_storeado.py

    r31 r32  
    6666        sel(lambda x: dejavu.year(x.Event) == 2004, 
    6767            u"SELECT * FROM [djvThings] WHERE Year([djvThings].[Event]) = 2004", False) 
    68 ##         
    69 ##        sel(lambda x: x.has('Animals'), u"SELECT * FROM [djvThings] WHERE True", True) 
    70 ##        # Paradoxically, "not has" should also return True, so 
    71 ##        # we can pass all Units to dejavu for final eval. 
    72 ##        sel(lambda x: not x.has('Animals'), u"SELECT * FROM [djvThings] WHERE True", True) 
    7368     
    7469    def test_multiselect(self): 
     
    8075               u"FROM [djvThings] LEFT JOIN [djvAnimals] ON [djvThings].[Size] " 
    8176               u"= [djvAnimals].[Legs] WHERE [djvThings].[Group] = 3") 
    82         self.assertEqual(testSM.multiselect(Things, f, [(Animals, None)])[0], sql) 
     77        self.assertEqual(testSM.multiselect(Things, f, 
     78                                            [(Animals, None)])[0], sql) 
    8379     
    8480    def test_create_storage(self): 
     
    196192        trial(lambda x: x.DateTo == None, u"[djvThings].[DateTo] Is Null", False) 
    197193     
    198         # Multiple arguments 
     194        # Multiple arguments (? Why should this be supported?) 
    199195        trial(lambda x, y, z: x.Date == 3 and y.Qty > 4 and z.Qty < 20, 
    200196              "([djvThings].[Date] = 3) and (([djvThings].[Qty] > 4) and ([djvThings].[Qty] < 20))", False)