473,396 Members | 1,998 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Wrapping a class set method

Hi there,

I have the following simplified classes:

class Project:
def __init__(self,pname):
self.devices = {} # Dictionary of Device objects
self.pname = pname

def setpname(self,pname):
self.pname = pname

def adddevice(self,dname):
self.devices[dname] = Device(self,dname)

class Device:
def __init__(self,parent,dname):
self.parent = parent
self.dname = dname

def setdname(self,dname):
self.dname = dname

Now, what I would like to do is wrap all of the set/add methods in a
function that pickles the Project object. I would then save the pickled
objects and use them to undo any changes to the above data structures.

I have a suspicion that there's an easier way to do this than
explicitly adding a Project.pickleme() call to the beginning of all of
my set/add methods.

So is there a way to wrap methods for this type of functionality or is
there another way of doing this, maybe without using setter methods?

Jul 27 '05 #1
3 1360
On 27 Jul 2005 11:42:24 -0700, "snoe" <ca*********@gmail.com> wrote:
Hi there,

I have the following simplified classes:

class Project:
def __init__(self,pname):
self.devices = {} # Dictionary of Device objects
self.pname = pname

def setpname(self,pname):
self.pname = pname

def adddevice(self,dname):
self.devices[dname] = Device(self,dname)

class Device:
def __init__(self,parent,dname):
self.parent = parent
self.dname = dname

def setdname(self,dname):
self.dname = dname

Now, what I would like to do is wrap all of the set/add methods in a
function that pickles the Project object. I would then save the pickled
objects and use them to undo any changes to the above data structures.

I have a suspicion that there's an easier way to do this than
explicitly adding a Project.pickleme() call to the beginning of all of
my set/add methods.

So is there a way to wrap methods for this type of functionality or is
there another way of doing this, maybe without using setter methods?

I would look into using properties with the same names as attributes of interest,
to store changes for possible undo/redo. For the devices attribute, you are not changing the
attribute per se, so you need a dict-like object that will do the state tracking when
you add devices. A dict subclass overriding __setitem__ should suffice for the usage you show.
Then you can give the classes undo/redo methods, or whatever. You could also use a special object
instead of a dict subclass, if you wanted some other interface.

Regards,
Bengt Richter
Jul 27 '05 #2
snoe wrote:

I have a suspicion that there's an easier way to do this than
explicitly adding a Project.pickleme() call to the beginning of all of
my set/add methods. So is there a way to wrap methods for this type of functionality or is
there another way of doing this, maybe without using setter methods?

I guess you are pointing to decorators, anyway you have to explicitly
wrap methods that are supposed to pickle.
Another way around is implement a metaclass and give the pickling
methods a special start name like set_ or add_ ,so having a protocol for
writing methods names.I paste the __metaclass__ solution

#### this is a skeleton

def saveStateWrapper(method,states):
from copy import copy
def wrapper(self,*_,**__):
self.__undoings.append(map(copy,[getattr(self,state) for state in
states])) # copy can not be idoneous
return method(self,*_,**__)
return wrapper

def initWrapper(init):
def wrapper(self,*_,**__):
self.__undoings=[]
init(self,*_,**__)
return wrapper

def undo(self): # an undoing method
if self.__undoings:
for state,was in zip(self.states,self.__undoings.pop(-1)):
setattr(self,state,was)

class Undoable(type): # the metaclass
def __init__(cls,name,bases,attrs):
cls.__init__=initWrapper(cls.__init__) # wrap init to add an
attribute __undoings to the instances
for attr in dir(cls):
if attr.split('_')[0] in ('add','set'): # look for attributes
protocolleds

setattr(cls,attr,saveStateWrapper(getattr(cls,attr ),cls.states)) # wrap
methods
cls.undo=undo #add the undo method

class Project(object):
__metaclass__=Undoable
states=['pname','devices']

def __init__(self,pname):
self.devices = set()
self.pname = pname
def set_pname(self,pname):
self.pname = pname
def lookFor(self,dname): # names can change in the devices instances
for device in self.devices: # add exceptions checkings
if device.dname==dname:
return device
def add_device(self,dname):
self.devices.add(Device(self,dname))

class Device(object):
__metaclass__=Undoable
states=['dname']
def __init__(self,parent,dname):
self.parent = parent
self.dname = dname
def set_dname(self,dname):
self.dname = dname

project=Project('pippo')
project.set_pname('pupo')
assert project.pname=='pupo'
project.undo()
assert project.pname=='pippo'
project.add_device('aargh')
device=project.lookFor('aargh')
device.set_dname('sperem')
assert device==project.lookFor('sperem')
device.undo()
assert device==project.lookFor('aargh') ## :)
project.undo()


___________________________________
Yahoo! Mail: gratis 1GB per i messaggi e allegati da 10MB
http://mail.yahoo.it
Jul 27 '05 #3
snoe wrote:

I have a suspicion that there's an easier way to do this than
explicitly adding a Project.pickleme() call to the beginning of all of
my set/add methods. So is there a way to wrap methods for this type of functionality or is
there another way of doing this, maybe without using setter methods?

I guess you are pointing to decorators, anyway you have to explicitly
wrap methods that are supposed to pickle.
Another way around is implement a metaclass and give the pickling
methods a special start name like set_ or add_ ,so having a protocol for
writing methods names.I paste the __metaclass__ solution

#### this is a skeleton

def saveStateWrapper(method,states):
from copy import copy
def wrapper(self,*_,**__):
self.__undoings.append(map(copy,[getattr(self,state) for state in
states])) # copy can not be idoneous
return method(self,*_,**__)
return wrapper

def initWrapper(init):
def wrapper(self,*_,**__):
self.__undoings=[]
init(self,*_,**__)
return wrapper

def undo(self): # an undoing method
if self.__undoings:
for state,was in zip(self.states,self.__undoings.pop(-1)):
setattr(self,state,was)

class Undoable(type): # the metaclass
def __init__(cls,name,bases,attrs):
cls.__init__=initWrapper(cls.__init__) # wrap init to add an
attribute __undoings to the instances
for attr in dir(cls):
if attr.split('_')[0] in ('add','set'): # look for attributes
protocolleds

setattr(cls,attr,saveStateWrapper(getattr(cls,attr ),cls.states)) # wrap
methods
cls.undo=undo #add the undo method

class Project(object):
__metaclass__=Undoable
states=['pname','devices']

def __init__(self,pname):
self.devices = set()
self.pname = pname
def set_pname(self,pname):
self.pname = pname
def lookFor(self,dname): # names can change in the devices instances
for device in self.devices: # add exceptions checkings
if device.dname==dname:
return device
def add_device(self,dname):
self.devices.add(Device(self,dname))

class Device(object):
__metaclass__=Undoable
states=['dname']
def __init__(self,parent,dname):
self.parent = parent
self.dname = dname
def set_dname(self,dname):
self.dname = dname

project=Project('pippo')
project.set_pname('pupo')
assert project.pname=='pupo'
project.undo()
assert project.pname=='pippo'
project.add_device('aargh')
device=project.lookFor('aargh')
device.set_dname('sperem')
assert device==project.lookFor('sperem')
device.undo()
assert device==project.lookFor('aargh') ## :)
project.undo()

Jul 27 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Jeremy Sanders | last post by:
Is it possible to implement some sort of "lazy" creation of objects only when the object is used, but behaving in the same way as the object? For instance: class Foo: def __init__(self, val):...
0
by: sklett | last post by:
I'm having a really hard time with wrapping an unmanaged class with a managed class, then calling that managed class from my C# code. I will show you the three pieces, then explain: --------...
2
by: Andrzej Kaczmarczyk | last post by:
Hi I am experiencing something weird. maybe you could help me. I have two ineditable classes from outsource libraries: DataColumn and GridColumn I have built a wrapper class around...
0
by: Lokkju | last post by:
I am pretty much lost here - I am trying to create a managed c++ wrapper for this dll, so that I can use it from c#/vb.net, however, it does not conform to any standard style of coding I have seen....
5
by: Lee Crabtree | last post by:
More fun wrapping unmanaged code... I have a class heirarchy that I need to expose to C#, so I need to wrap all the classes. That's not a big deal, except for the base class, which is abstract....
4
by: Lawrence Oluyede | last post by:
I've never used metaclasses in real life before and while searching through the online Cookbook I found this gorgeous example: "Wrapping method calls (meta-class example)"...
8
by: Nathan | last post by:
I am trying to prevent a horizontal list from wrapping. Each list item is floated with "float: left". Currently I use an ugly hack. I set the width of the list to a large number which is...
3
by: gabriel.becedillas | last post by:
Hi, I'm having problems wrapping a hierarchy of classes, actually having problems wrapping the base class. I don't need to use the WrapClass mechanism since I don't want to override classes in...
3
by: Paul Anton Letnes | last post by:
Hello guys, (related to previous thread on wrapping C/C++ in Python, trying the SWIG approach.) Trying to map a C++ class to python, one method for now. Running the following commands to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.