From ahaas at airmail.net Mon May 2 23:50:07 2005 From: ahaas at airmail.net (Art Haas) Date: Mon, 2 May 2005 16:50:07 -0500 Subject: [PythonCAD] Twenty-fourth release of PythonCAD now available In-Reply-To: <200504291651.52075.w.knol@niwa.co.nz> References: <20050428135205.GS11497@artsapartment.org> <200504291651.52075.w.knol@niwa.co.nz> Message-ID: <20050502215007.GA2217@artsapartment.org> On Fri, Apr 29, 2005 at 04:51:52PM +1200, Wilbert Knol wrote: > Whilst R23 worked OK, R24 causes run-time problems: > (best viewed without word-wrap..) > > [wk at wk PythonCAD-DS1-R24]$ ./gtkpycad.py > Traceback (most recent call last): > File "./gtkpycad.py", line 350, in ? > main() > File "./gtkpycad.py", line 328, in main > _image = GTKImage() > File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkimage.py", line 419, in __init__ > self.__mdict = fill_menubar(self.__mb, self) > File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkmenus.py", line 2287, in fill_menubar > _act.connect_proxy(_item) > File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkactions.py", line 294, in connect_proxy > widget.set_no_show_all(True) > AttributeError: 'gtk.MenuItem' object has no attribute 'set_no_show_all' > [wk at wk PythonCAD-DS1-R24]$ > > My system is probably to blame; it has been butchered around a bit. Hi. No, this is a bug in that the code uses the 'set_no_show_all' method which is not available in older PyGTK releases. I'll fix this up probably with a hasattr() test and post a simple patch, but it will need testing, and possibly/probably other bugs of this nature may turn up. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Tue May 3 18:39:39 2005 From: ahaas at airmail.net (Art Haas) Date: Tue, 3 May 2005 11:39:39 -0500 Subject: [PythonCAD] Twenty-fourth release of PythonCAD now available In-Reply-To: <20050502215007.GA2217@artsapartment.org> References: <20050428135205.GS11497@artsapartment.org> <200504291651.52075.w.knol@niwa.co.nz> <20050502215007.GA2217@artsapartment.org> Message-ID: <20050503163939.GA27408@artsapartment.org> On Mon, May 02, 2005 at 04:50:07PM -0500, Art Haas wrote: > On Fri, Apr 29, 2005 at 04:51:52PM +1200, Wilbert Knol wrote: > > Whilst R23 worked OK, R24 causes run-time problems: > > (best viewed without word-wrap..) > > > > [wk at wk PythonCAD-DS1-R24]$ ./gtkpycad.py > > [ ... python backtrace ...] > > [wk at wk PythonCAD-DS1-R24]$ > > > > My system is probably to blame; it has been butchered around a bit. > > Hi. > > No, this is a bug in that the code uses the 'set_no_show_all' method > which is not available in older PyGTK releases. I'll fix this up > probably with a hasattr() test and post a simple patch, but it will need > testing, and possibly/probably other bugs of this nature may turn up. Here's the trivial patch that will only call this method if it is found. Please let me know if this patch is all that is needed to get the latest PythonCAD release running on your system. Art Haas Index: PythonCAD/Interface/Gtk/gtkactions.py =================================================================== --- PythonCAD/Interface/Gtk/gtkactions.py (revision 1791) +++ PythonCAD/Interface/Gtk/gtkactions.py (revision 1792) @@ -291,7 +291,8 @@ widget.show() else: widget.hide() - widget.set_no_show_all(True) + if hasattr(widget, 'set_no_show_all'): + widget.set_no_show_all(True) if isinstance(widget, gtk.MenuItem): if self.__accelpath is not None: self.connect_accelerator() -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From w.knol at niwa.co.nz Wed May 4 01:44:39 2005 From: w.knol at niwa.co.nz (Wilbert Knol) Date: Wed, 4 May 2005 11:44:39 +1200 Subject: [PythonCAD] Twenty-fourth release of PythonCAD now available In-Reply-To: <20050503163939.GA27408@artsapartment.org> References: <20050428135205.GS11497@artsapartment.org> <20050502215007.GA2217@artsapartment.org> <20050503163939.GA27408@artsapartment.org> Message-ID: <200505041144.40023.w.knol@niwa.co.nz> On Wednesday 04 May 2005 04:39, Art Haas wrote: > > On Fri, Apr 29, 2005 at 04:51:52PM +1200, Wilbert Knol wrote: > > > Whilst R23 worked OK, R24 causes run-time problems: > Here's the trivial patch that will only call this method if it is > found. Please let me know if this patch is all that is needed to > get the latest PythonCAD release running on your system. Thanks Art, for the patch. I freshly unpacked R24, patched it, and ran su -c "python setup.py install". This is what I get when I run it up: [wk at wk PythonCAD-DS1-R24]$ ./gtkpycad.py Traceback (most recent call last): File "./gtkpycad.py", line 350, in ? main() File "./gtkpycad.py", line 328, in main _image = GTKImage() File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkimage.py", line 419, in __init__ self.__mdict = fill_menubar(self.__mb, self) File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkmenus.py", line 2289, in fill_menubar _menu = _make_file_menu(_group, gtkimage) File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkmenus.py", line 1222, in _make_file_menu _item = _act.create_menu_item() File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkactions.py", line 266, in create_menu_item self.connect_proxy(_item) File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkactions.py", line 298, in connect_proxy self.connect_accelerator() File "/home/wk/Documents/src/PythonCAD-DS1-R24/PythonCAD/Interface/Gtk/gtkactions.py", line 367, in connect_accelerator self.__accelgroup.connect_by_path(self.__accelpath, AttributeError: 'gtk.AccelGroup' object has no attribute 'connect_by_path' [wk at wk PythonCAD-DS1-R24]$ Hope this is of some use.... Wilbert. From ahaas at airmail.net Wed May 4 19:40:01 2005 From: ahaas at airmail.net (Art Haas) Date: Wed, 4 May 2005 12:40:01 -0500 Subject: [PythonCAD] Need testers for PyGTK compatiblity patch Message-ID: <20050504174001.GF27408@artsapartment.org> Hi. The latest release does not work on PyGTK releases prior to 2.4, and I've made the following minimal patch to hopefully get things going again. Could anyone running a PyGTK prior to 2.4 test this. I believe the Fedora Core 2 release uses PyGTK-2.2, as would Fedora/RedHat releases prior to FC3. I think older SuSE, Mandrake/Mandriva, and Debian releases use PyGTK-2.2, but I don't know which release versions would apply, nor do I know what the various BSD systems have. Hopefully applying this patch will produce a working PythonCAD for the older PyGTK release. Things seem to be working fine for users of PyGTK-2.4 and newer I'm glad to report. Art Index: PythonCAD/Interface/Gtk/gtkactions.py =================================================================== --- PythonCAD/Interface/Gtk/gtkactions.py (revision 1791) +++ PythonCAD/Interface/Gtk/gtkactions.py (revision 1793) @@ -291,7 +291,8 @@ widget.show() else: widget.hide() - widget.set_no_show_all(True) + if hasattr(widget, 'set_no_show_all'): + widget.set_no_show_all(True) if isinstance(widget, gtk.MenuItem): if self.__accelpath is not None: self.connect_accelerator() @@ -363,7 +364,14 @@ if _count == 0: # print "calling accelgroup.connect_by_path()" # print "accelpath: " + self.__accelpath - self.__accelgroup.connect_by_path(self.__accelpath, + if hasattr(self.__accelgroup, 'connect_by_path'): + self.__accelgroup.connect_by_path(self.__accelpath, + self._accel_cb) + else: + _data = gtk.accel_map_lookup_entry(self.__accelpath) + if _data is not None: + _k, _m = _data + self.__accelgroup.connect(_k, _m, gtk.ACCEL_VISIBLE, self._accel_cb) _count = _count + 1 -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Thu May 5 17:07:36 2005 From: ahaas at airmail.net (Art Haas) Date: Thu, 5 May 2005 10:07:36 -0500 Subject: [PythonCAD] Need testers for PyGTK compatiblity patch In-Reply-To: <20050504174001.GF27408@artsapartment.org> References: <20050504174001.GF27408@artsapartment.org> Message-ID: <20050505150736.GE2439@artsapartment.org> Hi. The previous patch is apparently not going to work, so I'm offering this one as a second try. I'm not sure yet how to replace the connect_by_path() method, or actually if the code in the gtkmenus.py file that handles connecting the menu items to the accelgroup will do the job for us. Please test this on a machine using a PyGTK release prior to 2.4 and let me know if things work. Art Index: PythonCAD/Interface/Gtk/gtkactions.py =================================================================== --- PythonCAD/Interface/Gtk/gtkactions.py (revision 1791) +++ PythonCAD/Interface/Gtk/gtkactions.py (revision 1801) @@ -291,7 +291,8 @@ widget.show() else: widget.hide() - widget.set_no_show_all(True) + if hasattr(widget, 'set_no_show_all'): + widget.set_no_show_all(True) if isinstance(widget, gtk.MenuItem): if self.__accelpath is not None: self.connect_accelerator() @@ -363,8 +364,9 @@ if _count == 0: # print "calling accelgroup.connect_by_path()" # print "accelpath: " + self.__accelpath - self.__accelgroup.connect_by_path(self.__accelpath, - self._accel_cb) + if hasattr(self.__accelgroup, 'connect_by_path'): + self.__accelgroup.connect_by_path(self.__accelpath, + self._accel_cb) _count = _count + 1 def disconnect_accelerator(self): -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Fri May 6 18:01:27 2005 From: ahaas at airmail.net (Art Haas) Date: Fri, 6 May 2005 11:01:27 -0500 Subject: [PythonCAD] Need testers for PyGTK compatiblity patch In-Reply-To: <20050505150736.GE2439@artsapartment.org> References: <20050504174001.GF27408@artsapartment.org> <20050505150736.GE2439@artsapartment.org> Message-ID: <20050506160127.GO2439@artsapartment.org> Hi. Here's the latest patch I'm hoping people with older machines can test. The addition of the hasattr() tests has apparently resolved part of the problems on running on older machines, and the get_action() fix at the top of the patch was a genuine bug. Please test this if you are running PythonCAD on a system using PyGTK releases older than 2.4. Thanks. Art Index: PythonCAD/Interface/Gtk/gtkactions.py =================================================================== --- PythonCAD/Interface/Gtk/gtkactions.py (revision 1791) +++ PythonCAD/Interface/Gtk/gtkactions.py (working copy) @@ -82,7 +82,7 @@ self.visible = visible def get_action(self, action): - return self.__actions.get(action.get_name()) + return self.__actions.get(action) def list_actions(self): return self.__actions.values() @@ -291,7 +291,8 @@ widget.show() else: widget.hide() - widget.set_no_show_all(True) + if hasattr(widget, 'set_no_show_all'): + widget.set_no_show_all(True) if isinstance(widget, gtk.MenuItem): if self.__accelpath is not None: self.connect_accelerator() @@ -363,8 +364,9 @@ if _count == 0: # print "calling accelgroup.connect_by_path()" # print "accelpath: " + self.__accelpath - self.__accelgroup.connect_by_path(self.__accelpath, - self._accel_cb) + if hasattr(self.__accelgroup, 'connect_by_path'): + self.__accelgroup.connect_by_path(self.__accelpath, + self._accel_cb) _count = _count + 1 def disconnect_accelerator(self): -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From gdizzy at gmail.com Sat May 7 21:15:54 2005 From: gdizzy at gmail.com (Lukas Musil) Date: Sat, 7 May 2005 21:15:54 +0200 Subject: [PythonCAD] New idea Message-ID: Hi ... I am student in seconmary school industry of building and need CAD system for Linux or *BSD (Windows flustrating me) . I found www.pythoncad.org . PythonCAD is good , but I need (and not only I) and text on vertical dimension was also vertical . It would be nice if zooming on mouse wheel. Thanks bye , Lukas Musil PS.: Sorry for my english . From gdizzy at gmail.com Sun May 8 10:13:52 2005 From: gdizzy at gmail.com (Lukas Musil) Date: Sun, 8 May 2005 10:13:52 +0200 Subject: [PythonCAD] New idea In-Reply-To: <20050507211329.GA7796@artsapartment.org> References: <20050507211329.GA7796@artsapartment.org> Message-ID: >On Sat, May 07, 2005 at 09:15:54PM +0200, Lukas Musil wrote: >> Hi ... I am student in seconmary school industry of building and need >> CAD system for Linux or *BSD (Windows flustrating me) . I found >> www.pythoncad.org . PythonCAD is good , but I need (and not only I) >> and text on vertical dimension was also vertical . It would be nice >> if zooming on mouse wheel. Thanks >The PythonCAD code is already set up for storing and displaying text at >an arbitrary angle; the problem was drawing it on the screen. The latest >GTK+ release (really the Pango library) supports rotating text, but I'm >not sure if PyGTK does or doesn't. If/When a PyQT/PyKDE front end ever >emerges then that front end will be able to display rotated text as that >feature has been available in QT for quite a while. hmm.. ok As for zooming on the mouse wheel, I'm guessing you mean that rolling the wheel in one direction performs a zoom in, and rolling in the other does a zoom out? Yes , Zooming on pulldown-menu is not effect (IMHO) From ahaas at airmail.net Mon May 9 19:16:23 2005 From: ahaas at airmail.net (Art Haas) Date: Mon, 9 May 2005 12:16:23 -0500 Subject: [PythonCAD] RPM packages for twenty-fourth release available Message-ID: <20050509171623.GK7796@artsapartment.org> Hi. Thanks go to D. Scott Barninger for making them. The 'download' page has been adjusted so these packages can be downloaded. http://www.pythoncad.org/download.html Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Thu May 12 22:46:49 2005 From: ahaas at airmail.net (Art Haas) Date: Thu, 12 May 2005 15:46:49 -0500 Subject: [PythonCAD] Updates in repo Message-ID: <20050512204649.GK16065@artsapartment.org> Hi. The latest updates available at the repo contain numerous changes. The display of the various layers in a drawing is now done by the LayerDisplay class in the 'gtkshell.py' file, the first utilization of code in this relatively new file. The code is much cleaner and easier to understand than the hodge-podge that had been in the GTKImage class, so not only are things easier to follow the change allowed the removal of a great deal of code from GTKImage. Also, the GTK event handling code has begun to get a long needed review. PythonCAD has not been a good PyGTK or GTK client in some ways, as often the event handling code returned values unnecessarily. The handling of the 'activate' signal by menuitem widgets was a prime example. The first round of cleanups has removed the unnecessary return statements and I've started fiddling with handlers of 'motion_notify', 'key_press', 'key_release', and the button press/release so they return Boolean values. More of this work is expected over the coming weeks/months. A few bug fixes are also included, especially in the compatability code in the gtkactions.py file. A few quirks were addressed - the undo-ing of a split on a segment entity would usually require two undo menu choices, now it is done (correctly) with one menu choice. Also, stretch operations that selected the stretched entities with a box will now were stored in the undo/redo chain as individual events instead of a single action, and that has been fixed. Other oddments here and there have been addressed as well. Enjoy. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Wed May 18 22:26:48 2005 From: ahaas at airmail.net (Art Haas) Date: Wed, 18 May 2005 15:26:48 -0500 Subject: [PythonCAD] Seeking code suggestions when handling exceptions Message-ID: <20050518202648.GL2592@artsapartment.org> Hi. For the last couple of days I've been puzzling about exception handling in Python. The thing that got me started down this track was the threads on the python-dev mailing list dealing with proposals to enhance and simplify the exception handling in Python. For example, one proposal was to allow for try/except/finally blocks in the code. This change would be a nice addition as it could simplify code that currently nests a try/except block within a try/finally block. Another proposal dealt with anonymous blocks, generator functions, and templates, and this proposal seemed to spawn various others as offshoots, and discussion of these proposals is ongoing. Read the python-dev mailing list archives for more details: http://mail.python.org/pipermail/python-dev/ The exception handling thread made me look a bit at how PythonCAD uses try/finally and try/except blocks, and while doing this I began looking at the code for sending messages between the various entities. Here's some sample code to demonstrate how things currently work - the following is a shortened version of the setThickness() method in the 'graphicobject.py' file: setThickness(self, t): _ot = self.__thickness if abs(_ot - t) > 1e-10: self.__thickness = t self.sendMessage('thickness_changed', _ot) self.modified() # calls self.sendMessage('modified') So, if the abs() test succeeds the new thickness value is stored, and then the object calls sendMessgage() and lets any object that listens to the 'thickness_changed' message via connect() will invoke some method, and finally the modified() method is called which will send out the 'modified' message to objects listening for it. That is all fine and good, but things get sticky if an exception is thrown during the sendMessage() calls. If a exception is thrown during the first sendMessage() call above, then modified() is never invoked, and depending on when the exception is raised some objects listening for 'thickness_changed' messages may not have the appropriate bound method invoked. If the exception is raised during the sending of the 'modified' message, then the problem is just that potentially one or more objects may not get the notification that the entity thickness has changed. A possible solution is to use try/finally: setThickness(self, t): _ot = self.__thickness if abs(_ot - t) > 1e-10: self.__thickness = _t try: self.sendMessage('thickness_changed', _ot) finally: self.modified() Now, the modified() method is guaranteed to be invoked whether or not an exception was raised during the sending of the 'thickness_changed' message. Two potential problems arise when doing this, however. First, there are an unknown number of objects that did not receive the 'thickness_changed' message, and second any exceptions thrown during the invocation of self.modified() would wipe out the original exception and replace it with the new one, making debugging more difficult. A second possible solution is the following: setThickness(self, t): _ot = self.__thickness if abs(_ot - t) > 1e-10: self.__thickness = _t try: self.sendMessage('thickness_changed', _ot) except: raise else: self.modified() Here, self.modified() will only be called if the 'thickness_changed' message was sent successfully, which is what should happen. Any exception occuring during the self.modified() call would not be handled, so some number of entities may not be notified of the change, though. The problems of an exception occurring during the self.modified() call are also still present. A third possibility is this: setThickness(self, t): _ot = self.__thickness if abs(_ot - t) > 1e-10: self.__thickness = _t try: self.sendMessage('thickness_changed', _ot) except: pass try: self.modified() except: pass Any errors are ignored, so for better or worse this method finishes but possibly leaves wreckage behind tripping things up later. I want to ensure in the sample code above that the 'thickness_changed' message is sent to all listeners successfully, and also that the 'modified' message is sent to all listeners successfully, and should something go wrong midway either backout the change or, even better, inform any listeners that had received messages about the change that something went wrong and the change failed. I played around with other try/finally, try/except, and try/except/else blocks, and I could never hit on a nice, clean solution to this objective. The code grew more cumbersome, less clear, and those results indicated I was working in the wrong direction. It seems like this type of problem is something that anyone programming in a language which uses exceptions, like C++ or Java, would encounter. As such, there are probably a variety of strategies that people have used to deal with exception handling during looping constructs, and means of reverting things should a problem occur prior to the desired end point. If we use database terminology, I'd like something like the following: setThickness(self, t): _ot = self.__thickness if abs(_ot - t) > 1e-10: self.__thickness = _t try: self.sendMessage('thickness_changed', _ot) self.modified() except: self.rollback() else: self.commit() The trick is writing the rollback() and commit() routines, as well as constructing a framework where such routines could be made for all the various attribute setting methods in PythonCAD. Writing this note has helped me think about things a little, but I still don't have a good idea as how to solve this problem. Any comments people care to add about an approach to accomplish rollback/commit type behavior would be welcomed. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From noel at peralex.com Thu May 19 07:32:04 2005 From: noel at peralex.com (Noel Grandin) Date: Thu, 19 May 2005 07:32:04 +0200 Subject: [PythonCAD] Seeking code suggestions when handling exceptions In-Reply-To: <20050518202648.GL2592@artsapartment.org> References: <20050518202648.GL2592@artsapartment.org> Message-ID: <428C24D4.6060709@peralex.com> Hi My basic suggestion is either (a) don't do anything. If an exception happens you have already have a problem. A signal being lost is not such a big deal. or (b) have a global application exception handler, which logs the message and perhaps asks the user if the problem is serious enough to abort. then do try: self.sendMessage('thickness_changed', _ot) except: global_ex_handler.log() try: self.modified() except: global_ex_handler.log() And I would probably put all of that into a utility method that all of the setters could use. Art Haas wrote: >Hi. > >For the last couple of days I've been puzzling about exception handling >in Python. The thing that got me started down this track was the threads >on the python-dev mailing list dealing with proposals to enhance and >simplify the exception handling in Python. For example, one proposal >was to allow for try/except/finally blocks in the code. This change >would be a nice addition as it could simplify code that currently nests >a try/except block within a try/finally block. Another proposal dealt >with anonymous blocks, generator functions, and templates, and this >proposal seemed to spawn various others as offshoots, and discussion of >these proposals is ongoing. Read the python-dev mailing list archives >for more details: > >http://mail.python.org/pipermail/python-dev/ > >The exception handling thread made me look a bit at how PythonCAD uses >try/finally and try/except blocks, and while doing this I began looking >at the code for sending messages between the various entities. Here's >some sample code to demonstrate how things currently work - the >following is a shortened version of the setThickness() method >in the 'graphicobject.py' file: > >setThickness(self, t): > _ot = self.__thickness > if abs(_ot - t) > 1e-10: > self.__thickness = t > self.sendMessage('thickness_changed', _ot) > self.modified() # calls self.sendMessage('modified') > >So, if the abs() test succeeds the new thickness value is stored, and >then the object calls sendMessgage() and lets any object that listens >to the 'thickness_changed' message via connect() will invoke some >method, and finally the modified() method is called which will send out >the 'modified' message to objects listening for it. That is all fine and >good, but things get sticky if an exception is thrown during the >sendMessage() calls. If a exception is thrown during the first >sendMessage() call above, then modified() is never invoked, and depending >on when the exception is raised some objects listening for 'thickness_changed' >messages may not have the appropriate bound method invoked. If the >exception is raised during the sending of the 'modified' message, then >the problem is just that potentially one or more objects may not get >the notification that the entity thickness has changed. > >A possible solution is to use try/finally: > >setThickness(self, t): > _ot = self.__thickness > if abs(_ot - t) > 1e-10: > self.__thickness = _t > try: > self.sendMessage('thickness_changed', _ot) > finally: > self.modified() > >Now, the modified() method is guaranteed to be invoked whether or not >an exception was raised during the sending of the 'thickness_changed' >message. Two potential problems arise when doing this, however. First, >there are an unknown number of objects that did not receive the >'thickness_changed' message, and second any exceptions thrown during >the invocation of self.modified() would wipe out the original exception >and replace it with the new one, making debugging more difficult. > >A second possible solution is the following: > >setThickness(self, t): > _ot = self.__thickness > if abs(_ot - t) > 1e-10: > self.__thickness = _t > try: > self.sendMessage('thickness_changed', _ot) > except: > raise > else: > self.modified() > >Here, self.modified() will only be called if the 'thickness_changed' >message was sent successfully, which is what should happen. Any >exception occuring during the self.modified() call would not be handled, >so some number of entities may not be notified of the change, though. >The problems of an exception occurring during the self.modified() call >are also still present. > >A third possibility is this: > >setThickness(self, t): > _ot = self.__thickness > if abs(_ot - t) > 1e-10: > self.__thickness = _t > try: > self.sendMessage('thickness_changed', _ot) > except: > pass > try: > self.modified() > except: > pass > >Any errors are ignored, so for better or worse this method finishes but >possibly leaves wreckage behind tripping things up later. > >I want to ensure in the sample code above that the 'thickness_changed' >message is sent to all listeners successfully, and also that the >'modified' message is sent to all listeners successfully, and should >something go wrong midway either backout the change or, even better, >inform any listeners that had received messages about the change >that something went wrong and the change failed. I played around with >other try/finally, try/except, and try/except/else blocks, and I >could never hit on a nice, clean solution to this objective. The code >grew more cumbersome, less clear, and those results indicated I >was working in the wrong direction. > >It seems like this type of problem is something that anyone programming >in a language which uses exceptions, like C++ or Java, would encounter. >As such, there are probably a variety of strategies that people have >used to deal with exception handling during looping constructs, and >means of reverting things should a problem occur prior to the desired >end point. If we use database terminology, I'd like something like >the following: > >setThickness(self, t): > _ot = self.__thickness > if abs(_ot - t) > 1e-10: > self.__thickness = _t > try: > self.sendMessage('thickness_changed', _ot) > self.modified() > except: > self.rollback() > else: > self.commit() > >The trick is writing the rollback() and commit() routines, as well as >constructing a framework where such routines could be made for all >the various attribute setting methods in PythonCAD. > >Writing this note has helped me think about things a little, but I still >don't have a good idea as how to solve this problem. Any comments people >care to add about an approach to accomplish rollback/commit type behavior >would be welcomed. > >Art > > NOTICE: Please note that this email, and the contents thereof, are subject to the standard Peralex email disclaimer, which may be found at: http://www.peralex.com/disclaimer.html If you cannot access the disclaimer through the URL attached and you wish to receive a copy thereof please send an email to email at peralex.com From ahaas at airmail.net Thu May 19 15:42:13 2005 From: ahaas at airmail.net (Art Haas) Date: Thu, 19 May 2005 08:42:13 -0500 Subject: [PythonCAD] Seeking code suggestions when handling exceptions In-Reply-To: <428C24D4.6060709@peralex.com> References: <20050518202648.GL2592@artsapartment.org> <428C24D4.6060709@peralex.com> Message-ID: <20050519134213.GM2592@artsapartment.org> On Thu, May 19, 2005 at 07:32:04AM +0200, Noel Grandin wrote: > Hi > > My basic suggestion is either > > (a) don't do anything. If an exception happens you have already have a > problem. A signal being lost is not such a big deal. That is certainly an option. If the code isn't changed from its current form this is exactly what happens. > or > > (b) have a global application exception handler, which logs the message > and perhaps asks the user if the problem is serious enough to abort. > then do > > try: > self.sendMessage('thickness_changed', _ot) > except: > global_ex_handler.log() > try: > self.modified() > except: > global_ex_handler.log() > > And I would probably put all of that into a utility method that all of > the setters could use. This idea is a possibility. Thinking more about the problem of handling exceptions during the various sendMessage() calls makes me wonder if it is even possible to solve, or if a solution is possible the cost is complex and expensive, possibly outweighing the benefits. Many programs simply quit if they encounter an error like a memory allocation failure instead of trying to possibly free up some resources and try the allocation again. Making the program as robust as possible is what I'm aiming for, so I would really hope to devise some approach better than an abrupt failure. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From noel at peralex.com Thu May 19 17:43:24 2005 From: noel at peralex.com (Noel Grandin) Date: Thu, 19 May 2005 17:43:24 +0200 Subject: [PythonCAD] Seeking code suggestions when handling exceptions In-Reply-To: <20050519134213.GM2592@artsapartment.org> References: <20050518202648.GL2592@artsapartment.org> <428C24D4.6060709@peralex.com> <20050519134213.GM2592@artsapartment.org> Message-ID: <428CB41C.2080704@peralex.com> >the program as robust as possible is what I'm aiming for, so I would >really hope to devise some approach better than an abrupt failure. > > > That is pretty much what I do - my central exception handler allows the user to click continue and keep working, even if some plugin blew up. This is pretty much OK on virtual machine languages like Python and Java, because the chances of corrupting something important are much lower. In some of my applications the central handler will look at the type and/or the source of the exception and decide on it's own that the exception is not worth worrying about. But I always log it to a file for safety sake :-) NOTICE: Please note that this email, and the contents thereof, are subject to the standard Peralex email disclaimer, which may be found at: http://www.peralex.com/disclaimer.html If you cannot access the disclaimer through the URL attached and you wish to receive a copy thereof please send an email to email at peralex.com From ewilhelm at sbcglobal.net Thu May 19 18:22:32 2005 From: ewilhelm at sbcglobal.net (Eric Wilhelm) Date: Thu, 19 May 2005 09:22:32 -0700 Subject: [PythonCAD] Seeking code suggestions when handling exceptions In-Reply-To: <428CB41C.2080704@peralex.com> References: <20050518202648.GL2592@artsapartment.org> <20050519134213.GM2592@artsapartment.org> <428CB41C.2080704@peralex.com> Message-ID: <200505190922.32921.ewilhelm@sbcglobal.net> # The following was supposedly scribed by # Noel Grandin # on Thursday 19 May 2005 08:43 am: >>the program as robust as possible is what I'm aiming for, so I would >>really hope to devise some approach better than an abrupt failure. > >That is pretty much what I do - my central exception handler >allows the user to click continue and keep working, even if some > plugin blew up. Maybe save a .crash file when you enter the exception handler (then delete it if you make it back out.) So if everything does go down, you can recover if you hadn't saved. You may need to use the undo data, particularly if the error came from the data-structure (e.g. a key error or something.) Or, you could just pickle a brain-dump and then code a recovery function that is able to step through (getting as far as possible if the crash was caused by some kind of data corruption.) --Eric -- [...proprietary software is better than gpl because...] "There is value in having somebody you can write checks to, and they fix bugs." -- Mike McNamara (president of a commercial software company) --------------------------------------------- http://scratchcomputing.com --------------------------------------------- From ahaas at airmail.net Thu May 19 21:33:55 2005 From: ahaas at airmail.net (Art Haas) Date: Thu, 19 May 2005 14:33:55 -0500 Subject: [PythonCAD] Seeking code suggestions when handling exceptions In-Reply-To: <20050519134213.GM2592@artsapartment.org> References: <20050518202648.GL2592@artsapartment.org> <428C24D4.6060709@peralex.com> <20050519134213.GM2592@artsapartment.org> Message-ID: <20050519193355.GO2592@artsapartment.org> On Thu, May 19, 2005 at 08:42:13AM -0500, Art Haas wrote: > On Thu, May 19, 2005 at 07:32:04AM +0200, Noel Grandin wrote: > > Hi > > > > My basic suggestion is either > > > > (a) don't do anything. If an exception happens you have already have a > > problem. A signal being lost is not such a big deal. > > That is certainly an option. If the code isn't changed from its current > form this is exactly what happens. More reading and searching lead to the QT-mailing list archives. The QT-interest list seemed most appropriate, so I did a search on 'exception handling' and found various threads which discuss this topic. The thread below was very interesting and topicwise close to the issue in PythonCAD about handling exceptions during sendMessage() calls: http://lists.trolltech.com/qt-interest/2003-03/thread00680-0.html Many of the points touched on in the thread are valid in PythonCAD - the de-coupling of the entities sending and recieving the signals(QT)/messages(PythonCAD), how an entity sending a signal/message doesn't care how many listeners for that message have been connected, and how notification can be viewed as a one-way message to something like "My value has changed, deal with it". Also, the difficulty in dealing with keeping track of which listeners have been sent a messsage and trying to send another message telling them to ignore the earlier one is brought up. Worth a look for people following this topic here. Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Mon May 23 17:24:06 2005 From: ahaas at airmail.net (Art Haas) Date: Mon, 23 May 2005 10:24:06 -0500 Subject: [PythonCAD] PythonCAD and exception handling in sendMessage() calls Message-ID: <20050523152406.GB2437@artsapartment.org> Hi. More thinking and reading over the last few days has produced no solution to the potential problem regarding handling exceptions during sendMessage() calls. The various strategies people have proposed are all potential areas for development, but for the short term I'm going to leave that work to someone else. The thread on the QT mailing list mentioned in an earlier mail has pushed me to believe that there should not be any sort of rollback or restoration of a changed value in some entity if one of the sendMessage() calls fails. Consider the simplfied setThickness() code I'd posted earlier: def setThickness(self, t): _ot = self.__thickness if abs(_ot - t) > 1e-10: self.__thickness = t self.sendMessage('thickness_changed', _ot) self.modified() # calls self.sendMessage('modified') The object that had the thickness change has no idea what is listening to the 'thickness_changed' or 'modified' messages, nor should it. Once the new value is set the entity is at its new state, and reverting it because some unknown listener had a problem doing who knows what suggests that the entity has some sort of knowledge about what that listener does, and that is not how things work in the messaging system, nor in QT's signal()/slots() implementation for that matter. I'm still going to investigate ways of ensuring that the all sendMessage() calls in some block of code get called if an exception is raised during one of those calls. It may take several releases before any preliminary code emerges, and whatever code does appear will almost certainly change several times before a reasonable approach is finalized. Here's the thread on the QT mailing list once again for those interested: http://lists.trolltech.com/qt-interest/2003-03/thread00680-0.html Art -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From ahaas at airmail.net Thu May 26 21:05:56 2005 From: ahaas at airmail.net (Art Haas) Date: Thu, 26 May 2005 14:05:56 -0500 Subject: [PythonCAD] [ANNOUNCE] Twenty-fifth release of PythonCAD now available Message-ID: <20050526190556.GJ9543@artsapartment.org> I'm pleased to announce the twenty-fifth development release of PythonCAD, a CAD package for open-source software users. As the name implies, PythonCAD is written entirely in Python. The goal of this project is to create a fully scriptable drafting program that will match and eventually exceed features found in commercial CAD software. PythonCAD is released under the GNU Public License (GPL). PythonCAD requires Python 2.2 or newer. The interface is GTK 2.0 based, and uses the PyGTK module for interfacing to GTK. The design of PythonCAD is built around the idea of separating the interface from the back end as much as possible. By doing this, it is hoped that both GNOME and KDE interfaces can be added to PythonCAD through usage of the appropriate Python module. Addition of other PythonCAD interfaces will depend on the availability of a Python module for that particular interface and developer interest and action. The twenty-fifth release consists primarily of bug fixes. The compatibility code for the GTK Action and ActionGroup classes introduced in the previous release had a number of bugs which have been fixed. People running PythonCAD on PyGTK releases prior to 2.4 should find this latest release working correctly due to these fixes. Thanks go to Wilbert Knol for helping identify and test the proposed fixes for this problem. A number of changes to the event handling code also are include in this release. Previously various event handling routines either returned an incorrect value, or returned a value when not needed. This release cleans up many of these issues, making the event handling code easier to follow as well as better conforming to GTK/PyGTK requirements. Various other bug fixes and code enhancements are present in this release as well. A mailing list for the development and use of PythonCAD is available. Visit the following page for information about subscribing and viewing the mailing list archive: http://mail.python.org/mailman/listinfo/pythoncad Visit the PythonCAD web site for more information about what PythonCAD does and aims to be: http://www.pythoncad.org/ Come and join me in developing PythonCAD into a world class drafting program! Art Haas -- Man once surrendering his reason, has no remaining guard against absurdities the most monstrous, and like a ship without rudder, is the sport of every wind. -Thomas Jefferson to James Smith, 1822 From michele.petrazzo at unipex.it Fri May 27 19:59:20 2005 From: michele.petrazzo at unipex.it (Michele Petrazzo) Date: Fri, 27 May 2005 19:59:20 +0200 Subject: [PythonCAD] R25 bug Message-ID: <42975FF8.40108@unipex.it> I have just download the release 25, and I found these three bugs: - when I print: File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Interface/Gtk/gtkmenus.py", line 320, in file_print_screen_cb gtkprinting.print_dialog(gtkimage, _plot) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Interface/Gtk/gtkprinting.py", line 152, in print_dialog if isinstance(_size_widget, gtk.ComboBox): AttributeError: 'module' object has no attribute 'ComboBox' - into PythonCAD/Interface/Gtk/gtkmodify.py at line 393 there is a Truee, not True - I draw an object (line, circle, etc..), I select move (one of the three), I select the first point to move, the second and after I select no objects then the program ask me for select an object (I click two times into the canvas). After I re-click for the distance (first and second point), but now I click over the object, and I receive this error: File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Interface/Gtk/gtkimage.py", line 127, in da_general_event event, _tool) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Interface/Gtk/gtkmodify.py", line 123, in move_elem_button_press_cb move_objects(gtkimage, _objs, tool) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Interface/Gtk/gtkmodify.py", line 83, in move_objects PythonCAD.Generic.move.move_objects(_active_layer, objlist, _dx, _dy) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/move.py", line 341, in move_objects _move_segment(layer, _obj, _dx, _dy) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/move.py", line 86, in _move_segment layer.addObject(_np1) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/layer.py", line 427, in addObject obj.setParent(self) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/entity.py", line 305, in setParent Entity.addChild(parent, self) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/entity.py", line 345, in addChild self.modified() File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/entity.py", line 212, in modified self.sendMessage('modified') File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/message.py", line 114, in sendMessage _method(self, *args) File "/home/michele/PythonCAD-DS1-R25/PythonCAD/Generic/image.py", line 1019, in _objectModified _undo[_i].append((_pid, _oid)) IndexError: list index out of range Hope this help, Michele