i.e. something like the following:
Code: Select all
r = Register(addr, layout)
r.FIELD1 = 0x2
r.FIELD2 = 0x1
(etc...)
Code: Select all
class Register:
def __init__(self, addr, layout):
self.addr = addr
self._buf = bytearray(sizeof(layout))
self._struct = uctypes.struct(uctypes.addressof(self._buf), layout)
def __getattr__(self, name):
# I2C bus read code goes here
return getattr(self._struct, name)
def __setattr__(self, name, value):
# this obviously doesn't work, but I'm not sure what to put here???
if hasattr(self.struct, name):
setattr(self._struct, name, value)
# I2C bus write code goes here
else:
setattr(self, name, value)
Here's a very simple example highlighting the issue. Instantiating Test1 leads to infinite recursion because the self._storage assignment calls __setattr__:
Code: Select all
class Storage:
def __init__(self):
self.x = 1
self.y = 2
self.z = 3
class Test1:
def __init__(self):
self._storage = Storage()
def __getattr__(self, name):
return getattr(self._storage, name)
def __setattr__(self, name, value):
setattr(self._storage, name, value)
t1 = Test1() # RuntimeError: maximum recursion depth exceeded
Code: Select all
class Test2:
def __init__(self):
object.__setattr__(self, '_storage', Storage()) # avoids infinite recursion
def __getattr__(self, name):
return getattr(self._storage, name)
def __setattr__(self, name, value):
setattr(self._storage, name, value)
t2 = Test2()
t2.x = 10
Code: Select all
class Test3:
def __init__(self):
self.__dict__['_storage'] = Storage() # avoids infinite recursion
def __getattr__(self, name):
return getattr(self._storage, name)
def __setattr__(self, name, value):
setattr(self._storage, name, value)
t3 = Test3()
t2.x = 10