Changeset 6230


Ignore:
Timestamp:
Jan 22, 2009, 1:24:06 PM (16 years ago)
Author:
ole
Message:

Fixed issue with caching of different instances of callable objects
as described in changeset:6229
Also added bytecode determination for classes.

Location:
anuga_core/source/anuga/caching
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/caching/caching.py

    r6222 r6230  
    8686  'bin': 1,              # Use binary format (more efficient)
    8787  'compression': 1,      # Use zlib compression
    88   'bytecode': 0,         # Recompute if bytecode has changed
     88  'bytecode': 1,         # Recompute if bytecode has changed
    8989  'expire': 0            # Automatically remove files that have been accessed
    9090                         # least recently
     
    162162  If the function definition changes after a result has been cached it will be
    163163  detected by examining the functions bytecode (co_code, co_consts,
    164   func_defualts, co_argcount) and it will be recomputed.
     164  func_defaults, co_argcount) and it will be recomputed.
    165165
    166166  LIMITATIONS:
     
    13821382      val = myhash(I, ids)
    13831383  elif type(T) == num.ArrayType:
    1384       T = num.array(T) # Ensure contiguous
     1384      T = num.array(T) # Ensure array is contiguous
    13851385
    13861386      # Use mean value for efficiency
    13871387      val = hash(num.average(T.flat))
    13881388  elif type(T) == InstanceType:
     1389      # Use the attribute values
    13891390      val = myhash(T.__dict__, ids)
    13901391  else:
     
    15471548
    15481549  if type(func) == types.FunctionType:
    1549     bytecode = func.func_code.co_code
    1550     consts = func.func_code.co_consts
    1551     argcount = func.func_code.co_argcount   
    1552     defaults = func.func_defaults     
     1550    return get_func_code_details(func)
    15531551  elif type(func) == types.MethodType:
    1554     bytecode = func.im_func.func_code.co_code
    1555     consts =  func.im_func.func_code.co_consts
    1556     argcount =  func.im_func.func_code.co_argcount   
    1557     defaults = func.im_func.func_defaults         
     1552    return get_func_code_details(func.im_func)
     1553  elif type(func) == types.InstanceType:   
     1554    if callable(func):
     1555      # Get bytecode from __call__ method
     1556      bytecode = get_func_code_details(func.__call__.im_func)
     1557     
     1558      # Add hash value of object to detect attribute changes
     1559      return bytecode + (myhash(func),)
     1560    else:
     1561      msg = 'Instance %s was passed into caching in the role of a function ' % str(func)
     1562      msg = ' but it was not callable.'
     1563      raise Exception, msg
     1564  elif type(func) in [types.BuiltinFunctionType, types.BuiltinMethodType]:     
     1565    # Built-in functions are assumed not to change 
     1566    return None, 0, 0, 0
     1567  elif type(func) == types.ClassType:
     1568      # Get bytecode from __init__ method
     1569      bytecode = get_func_code_details(func.__init__.im_func)   
     1570      return bytecode     
    15581571  else:
    1559     #raise Exception  #Test only
    1560     bytecode = None   #Built-in functions are assumed not to change
    1561     consts = 0
    1562     argcount = 0
    1563     defaults = 0
    1564 
    1565   return (bytecode, consts, argcount, defaults)
     1572    msg = 'Unknown function type: %s' % type(func)
     1573    raise Exception, msg
     1574
     1575
     1576 
     1577 
     1578def get_func_code_details(func):
     1579  """Extract co_code, co_consts, co_argcount, func_defaults
     1580  """
     1581 
     1582  bytecode = func.func_code.co_code
     1583  consts = func.func_code.co_consts
     1584  argcount = func.func_code.co_argcount   
     1585  defaults = func.func_defaults       
     1586 
     1587  return bytecode, consts, argcount, defaults 
    15661588
    15671589# -----------------------------------------------------------------------------
  • anuga_core/source/anuga/caching/test_caching.py

    r6229 r6230  
    366366                                   
    367367           
    368     def Xtest_caching_of_callable_objects(self):
     368    def test_caching_of_callable_objects(self):
    369369        """test_caching_of_callable_objects(self)
    370370       
     
    386386
    387387           
    388            
    389388        f1 = call(2, 3)
    390389        f2 = call(5, 7)
     390       
     391       
     392        # Check that hash value of callable objects don't change
     393        assert myhash(f1) == -758136387
     394        assert myhash(f2) == -11221564     
     395       
     396        bc1 = get_bytecode(f1)
     397        bc2 = get_bytecode(f2)
     398       
     399        #print 'bc1', bc1
     400        #print 'bc2', bc2
     401       
     402        msg = 'Byte code should be different'
     403        assert bc1 != bc2, msg
     404
    391405       
    392406        x = num.arange(10).astype(num.Float)
     
    412426        assert num.allclose(res1, ref1)               
    413427       
    414         # Test that f2(x) is still clear
    415         flag = cache(f2, x, test=True, verbose=False)       
    416         msg = 'Function f2(x) should not be cached here'
    417         assert flag is None, msg               
    418        
    419428        # Run f2(x) and test result
    420429        res2 = cache(f2, x, verbose=False)
     
    803812
    804813      verbose = False
    805 
     814     
    806815      for compression_store in [False, True]:
    807816        for compression_retrieve in [False, True]:       
     
    811820       
    812821          if verbose: print 'cache for first time'
    813           a = cache(Dummy, args=(9,10),
    814                     compression=compression_store,
    815                     verbose=verbose)
     822          a_ref = cache(Dummy, args=(9,10),
     823                        compression=compression_store,
     824                        verbose=verbose)
    816825         
    817826          if verbose: print 'Check that cache is there'
     
    819828                       compression=compression_retrieve,
    820829                       verbose=verbose)
     830                       
     831          if verbose: print 'Check cached result'
     832          a = cache(Dummy, args=(9,10),
     833                    compression=compression_store,
     834                    verbose=verbose)                       
     835          assert a.__dict__ == a_ref.__dict__
    821836
    822837
     
    868883#-------------------------------------------------------------
    869884if __name__ == "__main__":
    870     #suite = unittest.makeSuite(Test_Caching, 'test_hash_collision')
     885    #suite = unittest.makeSuite(Test_Caching, 'test_caching_of_callable_objects')
    871886    suite = unittest.makeSuite(Test_Caching, 'test')
    872887    runner = unittest.TextTestRunner()
Note: See TracChangeset for help on using the changeset viewer.