Hi Miles,

I wasn’t around for the first discussion on the topic, but one of the reasons 
(1) doesn’t work terribly well is that it’s not enough to know what changed; 
one also has to know how to group the changes into individual undo/redo steps.  
It sounds like the plugin infrastructure accomplishes this by the 
over-simplification that a plugin does discrete operations (ie: one plugin call 
== one undo step).

Why does the plugin mechanism need to do a diff?  Is that to apply the changes, 
or just to know what to commit?  If it’s the latter, just stop doing that.  
Memory is cheap; commit everything.  So what if undo replaces a bunch of stuff 
that didn’t actually change.

Cheers,
Jeff.


> On 6 Mar 2018, at 09:02, miles mccoo <m...@mmccoo.com> wrote:
> 
> Thanks all for your replies.
> 
> I like the plugin mechanism. It does some nice things for python folks. 
> Refresh, undo, garbage collection (I think). I want to see it succeed.
> 
> From reading Orson's mail, I think I wasn't entirely clear, so let me try to 
> fix that first.
> 
> 
> The plugin mechanism tries to track the changes of a python plugin. In the 
> c++ world, developers are expected to inform BOARD_COMMIT that something has 
> changed. The plugin infrastructure does this for you. One could compare it to 
> garbage collection. My interpretation of how this is done is simple: before a 
> plugin runs, make a list of all design objects. zones, tracks, modules, 
> nets... after the plugin completes, do a "diff".
> 
> This is mostly fine with the exception of removed items.
> 
> The problem with removed items is how do you do a diff on a deleted, memory 
> managed, cleaned up object? Perhaps that memory now contains a different kind 
> of object. Perhaps it's been reallocated to a similar object as before.
> 
> 
> 
> as it stands now, any plugin that removes items from a board item container 
> will likely fail. It's not quite a crash, but it has a similar feel to the 
> user.
> 
> 
> 
> Solutions. I can think of four. 
> 
> solution 1. Why is the plugin mechanism in the business of tracking changes? 
> Shouldn't BOARD_COMMIT just magically happen whenever a c++ instance is 
> modified. I brought this up in a previous thread[1] and various reasons were 
> given why this isn't desirable.
> 
> solution 2. Same as #1 except BC magic only happens on python API calls. The 
> plugin mechanism would no longer do diffs. Just add BC checkpoints. This is 
> probably a lot of work. I might be willing to do this work but it would take 
> time. [2]
> 
> solution 3. easy to implement. turn off deletion on calls to remove if 
> currently running a plugin
> plugin gets a boolean: isPluginActive. set/unset around the call to actual 
> python run code.
> add pcbnew.isPluginActive() to python api. (I could imagine this could have 
> other uses)
> the remove code looks at isPluginActive to decide whether to set isown. (that 
> code is actually python, not swig)
> I have #3 implemented and my plugins no longer crash. See attached patch for 
> if folks agree it is an acceptable stopgap.
> 
> solution 4. probably not the direction I would go but a way to enable python 
> memory management and do the plugin diff thing. Basically, give each object 
> some sort of unique id. (could be useful for other things). In addition to 
> holding a list of object pointers, plugin infrastructure would hold a list of 
> object ids.
> 
> 
> Given the ease with which a plugin can hit this issue and given how long it 
> would take to get #2 right, I guess I'm recommending the changes of that 
> attached patch for #3.
> 
> Miles
> 
> [1] https://lists.launchpad.net/kicad-developers/msg32063.html 
> <https://lists.launchpad.net/kicad-developers/msg32063.html>
> [2] I think my personal opinion is that #1 is superior over #2. Python people 
> shouldn't have to care but why is it that c++ should or want to? Yes, I read 
> the arguments from the previous thread but I'm not convinced. I'm also just a 
> kicad spectator, so there's a lot I don't know.
> 
> 
> 
> 
> 
> On Fri, Mar 2, 2018 at 2:47 PM, Wayne Stambaugh <stambau...@gmail.com 
> <mailto:stambau...@gmail.com>> wrote:
> LOL, I just replied to Miles.  Thanks Orson for helping out!
> 
> On 3/2/2018 8:36 AM, Maciej Sumiński wrote:
> > Hi Miles,
> >
> > I suppose the silence in the thread indicates there are not many
> > developers knowing the Python scripting interface inside out. Since you
> > are both studying the scripting interface and developing own scripts, it
> > is quite possible you are the most competent person to give us an advice
> > on how to proceed. See some comments below, but I am neither a Python
> > script developer nor a scripting interface maintainer, so I might be
> > lacking some basic knowledge here.
> >
> > On 02/28/2018 05:12 PM, miles mccoo wrote:
> >> So I'm plugin-ifying my python scripts (the mechanism is awesome). One of
> >> the plugins deletes some stuff and that is causing trouble.
> >>
> >>
> >>
> >> I'm not sure how to fix the root cause. Hence this mail.
> >>
> >>
> >>
> >> The plugin just deletes Edge.Cuts[1]:
> >> for d in board.GetDrawings():
> >>             if (d.GetLayerName() == 'Edge.Cuts'):
> >>                 board.Remove(d)
> >>
> >>
> >>
> >> in board_item_container.i, I see this (with stuff deleted):
> >> %rename(RemoveNative)    BOARD_ITEM_CONTAINER::Remove;
> >>     def Remove(self,item):
> >>         self.RemoveNative(item)
> >>         item.thisown=1
> >>
> >>
> >> Setting thisown tells, python "you own it". Delete it when you're done.
> >> Which it does.
> >>
> >>
> >> The problem this causes is that the plugin mechanism saves a list of all
> >> objects before running the plugin and then checks if any of them has a null
> >> list after (ie is it still in the design).
> >
> > Is this mechanism implemented to handle memory leaks? If so, would not
> > it be sufficient to stick to 'thisown' flag on Remove() calls or is
> > there another way objects might be destroyed using Python scripts?
> >
> >> Since the object has been deleted by python, the plugin stuff gets 
> >> confused.
> >>
> >>
> >> *So, the question is how to fix this?*
> >>
> >>
> >> It appears that the plugin infrastructure will delete for you (that's what
> >> I'm guessing), so the thisown setting shouldn't be done.
> >>
> >>
> >> On the other hand, if running code from within a standalone script (ie from
> >> regular python shell), now thisown'ing it would yield a memory leak.
> >>
> >>
> >>
> >> Perhaps the plugin stuff should have some sort of flag indicating "you're
> >> in a plugin". Then the thisown setting could be conditional.
> >
> > If the object listing mechanism is required for other reasons, then I
> > suppose it is second best idea. Generally speaking, I would like to make
> > the scripting interface convenient for the users, so they do not need to
> > worry about whether their scripts are run standalone or as a plugin.
> > Let's hide the dirty magic from them and make the coding process enjoyable.
> >
> > Regards,
> > Orson
> >
> >> But I'm just a spectator. *I'm happy to put in the time to fix this but
> >> need guidance on what approach to take.*
> >>
> >>
> >> Miles
> >>
> >>
> >>
> >> [1] full plugin text
> >> import pcbnew
> >>
> >> class RemoveBoundaryPlugin(pcbnew.ActionPlugin):
> >>     def defaults(self):
> >>         self.name <http://self.name/> = "Remove boundary"
> >>         self.category = "A descriptive category name"
> >>         self.description = "This plugin reads a dxf file and converts it to
> >> a zone"
> >>
> >>     def Run(self):
> >>         board = pcbnew.GetBoard()
> >>
> >>         for d in board.GetDrawings():
> >>             print("{}".format(str(d)))
> >>             #print("on layer {} {} {}".format(d.GetLayerName(),
> >>             #                                 str(d.GetStart()),
> >>             #                                 str(d.GetEnd())))
> >>             if (d.GetLayerName() == 'Edge.Cuts'):
> >>                 board.Remove(d)
> >>
> >> RemoveBoundaryPlugin().register()
> >>
> >>
> >>
> >> _______________________________________________
> >> Mailing list: https://launchpad.net/~kicad-developers 
> >> <https://launchpad.net/~kicad-developers>
> >> Post to     : kicad-developers@lists.launchpad.net 
> >> <mailto:kicad-developers@lists.launchpad.net>
> >> Unsubscribe : https://launchpad.net/~kicad-developers 
> >> <https://launchpad.net/~kicad-developers>
> >> More help   : https://help.launchpad.net/ListHelp 
> >> <https://help.launchpad.net/ListHelp>
> >>
> >
> >
> >
> >
> > _______________________________________________
> > Mailing list: https://launchpad.net/~kicad-developers 
> > <https://launchpad.net/~kicad-developers>
> > Post to     : kicad-developers@lists.launchpad.net 
> > <mailto:kicad-developers@lists.launchpad.net>
> > Unsubscribe : https://launchpad.net/~kicad-developers 
> > <https://launchpad.net/~kicad-developers>
> > More help   : https://help.launchpad.net/ListHelp 
> > <https://help.launchpad.net/ListHelp>
> >
> 
> 
> _______________________________________________
> Mailing list: https://launchpad.net/~kicad-developers 
> <https://launchpad.net/~kicad-developers>
> Post to     : kicad-developers@lists.launchpad.net 
> <mailto:kicad-developers@lists.launchpad.net>
> Unsubscribe : https://launchpad.net/~kicad-developers 
> <https://launchpad.net/~kicad-developers>
> More help   : https://help.launchpad.net/ListHelp 
> <https://help.launchpad.net/ListHelp>
> 
> <0001-Fix-for-crash-due-to-pcbnew_action_plugin-object-tra.patch>_______________________________________________
> Mailing list: https://launchpad.net/~kicad-developers
> Post to     : kicad-developers@lists.launchpad.net
> Unsubscribe : https://launchpad.net/~kicad-developers
> More help   : https://help.launchpad.net/ListHelp

_______________________________________________
Mailing list: https://launchpad.net/~kicad-developers
Post to     : kicad-developers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~kicad-developers
More help   : https://help.launchpad.net/ListHelp

Reply via email to