Example #1
0
 def _debug_print_object_counts(self):
     #bruce 060327 for debugging memory leaks: report Atom & Bond refcounts, and objs that might refer to them
     # Note: these counts include not only instances, but imports of classes into modules.
     # That's probably why the initial counts seem too high:
     # 40 Atoms, 24 Bonds, 40 Chunks, 34 Groups, 8 Parts, 10 Assemblies
     # [as of 080403]
     from utilities.Log import _graymsg
     msglater = ""  # things to print all in one line
     for clasname, modulename in (
             #bruce 080403 fixed modulenames (since the modules were moved into
             # packages); the dotted names seem to work.
         ('Atom', 'model.chem'),
         ('Bond', 'model.bonds'),
             # ('Node', 'Utility'), # Node or Jig is useless here, we need the specific subclasses!
         ('Chunk', 'model.chunk'),
             # DnaLadderRailChunk
             ## ('PiBondSpChain', 'pi_bond_sp_chain'), # no module pi_bond_sp_chain -- due to lazy load or atom-debug reload??
         (
             'Group', 'foundation.Group'
         ),  # doesn't cover subclasses PartGroup, ClipboardItemGroup, RootGroup(sp?), Dna groups
         ('Part', 'model.part'),
         ('Assembly', 'model.assembly')):
         # should also have a command to look for other classes with high refcounts
         if sys.modules.has_key(modulename):
             module = sys.modules[modulename]
             clas = getattr(module, clasname, None)
             if clas:
                 msg = "%d %ss" % (sys.getrefcount(clas), clasname)
                 msg = msg.replace("ys",
                                   "ies")  # for spelling of Assemblies
                 # print these things all at once
                 if msglater:
                     msglater += ', '
                 msglater += msg
                 msg = None
             else:
                 msg = "%s not found in %s" % (clasname, modulename)
         else:
             msg = "no module %s" % (modulename, )
         if msg:
             env.history.message(_graymsg(msg))
     if msglater:
         env.history.message(_graymsg(msglater))
     return
Example #2
0
 def _debug_print_object_counts(self):
     #bruce 060327 for debugging memory leaks: report Atom & Bond refcounts, and objs that might refer to them
     # Note: these counts include not only instances, but imports of classes into modules.
     # That's probably why the initial counts seem too high:
     # 40 Atoms, 24 Bonds, 40 Chunks, 34 Groups, 8 Parts, 10 Assemblies
     # [as of 080403]
     from utilities.Log import _graymsg
     msglater = "" # things to print all in one line
     for clasname, modulename in (
         #bruce 080403 fixed modulenames (since the modules were moved into
         # packages); the dotted names seem to work.
         ('Atom', 'model.chem'),
         ('Bond', 'model.bonds'),
         # ('Node', 'Utility'), # Node or Jig is useless here, we need the specific subclasses!
         ('Chunk', 'model.chunk'),
         # DnaLadderRailChunk
         ## ('PiBondSpChain', 'pi_bond_sp_chain'), # no module pi_bond_sp_chain -- due to lazy load or atom-debug reload??
         ('Group', 'foundation.Group'), # doesn't cover subclasses PartGroup, ClipboardItemGroup, RootGroup(sp?), Dna groups
         ('Part', 'model.part'),
         ('Assembly', 'model.assembly')):
         # should also have a command to look for other classes with high refcounts
         if sys.modules.has_key(modulename):
             module = sys.modules[modulename]
             clas = getattr(module, clasname, None)
             if clas:
                 msg = "%d %ss" % (sys.getrefcount(clas), clasname)
                 msg = msg.replace("ys","ies") # for spelling of Assemblies
                 # print these things all at once
                 if msglater:
                     msglater += ', '
                 msglater += msg
                 msg = None
             else:
                 msg = "%s not found in %s" % (clasname, modulename)
         else:
             msg = "no module %s" % (modulename,)
         if msg:
             env.history.message( _graymsg( msg))
     if msglater:
         env.history.message( _graymsg( msglater))
     return
Example #3
0
def debug_run_command(command,
                      source="user debug input"
                      ):  #bruce 040913-16 in GLPane.py; modified 040928
    """
    Execute a python command, supplied by the user via some sort of debugging interface (named by source),
    in debug.py's globals. Return 1 for ok (incl empty command), 0 for any error.

    Caller should not print exception diagnostics -- this function does that
    (and does not reraise the exception).
    """
    #e someday we might record time, history, etc
    command = "" + command  # i.e. assert it's a string
    #k what's a better way to do the following?
    while command and command[0] == '\n':
        command = command[1:]
    while command and command[-1] == '\n':
        command = command[:-1]
    if not command:
        print "empty command (from %s), nothing executed" % (source, )
        return 1
    if '\n' not in command:
        msg = "will execute (from %s): %s" % (source, command)
    else:
        nlines = command.count('\n') + 1
        msg = "will execute (from %s; %d lines):\n%s" % (source, nlines,
                                                         command)
    print msg
    try:
        # include in history file, so one can search old history files for useful things to execute [bruce 060409]
        from utilities.Log import _graymsg, quote_html
        env.history.message(_graymsg(quote_html(msg)))
    except:
        print_compact_traceback("exception in printing that to history: ")
    command = command + '\n'  #k probably not needed
    try:
        ## exec command in globals()
        legally_exec_command_in_globals(command, globals())
    except:
        print_compact_traceback("exception from that: ")
        return 0
    else:
        print "did it!"
        return 1
    pass
Example #4
0
def debug_run_command(command, source = "user debug input"): #bruce 040913-16 in GLPane.py; modified 040928
    """
    Execute a python command, supplied by the user via some sort of debugging interface (named by source),
    in debug.py's globals. Return 1 for ok (incl empty command), 0 for any error.

    Caller should not print exception diagnostics -- this function does that
    (and does not reraise the exception).
    """
    #e someday we might record time, history, etc
    command = "" + command # i.e. assert it's a string
    #k what's a better way to do the following?
    while command and command[0] == '\n':
        command = command[1:]
    while command and command[-1] == '\n':
        command = command[:-1]
    if not command:
        print "empty command (from %s), nothing executed" % (source,)
        return 1
    if '\n' not in command:
        msg = "will execute (from %s): %s" % (source, command)
    else:
        nlines = command.count('\n')+1
        msg = "will execute (from %s; %d lines):\n%s" % (source, nlines, command)
    print msg
    try:
        # include in history file, so one can search old history files for useful things to execute [bruce 060409]
        from utilities.Log import _graymsg, quote_html
        env.history.message( _graymsg( quote_html( msg)))
    except:
        print_compact_traceback("exception in printing that to history: ")
    command = command + '\n' #k probably not needed
    try:
        ## exec command in globals()
        legally_exec_command_in_globals( command, globals() )
    except:
        print_compact_traceback("exception from that: ")
        return 0
    else:
        print "did it!"
        return 1
    pass
Example #5
0
def editClearUndoStack(win):
    """
    This is called from MWsemantics.editClearUndoStack,
    which is documented as:

      "Slot for clearing the Undo Stack.  Requires the user to confirm."
    """
    #bruce 060304, modified from Mark's prototype in MWsemantics
    
    #e the following message should specify the amount of data to be lost...
    #e and the menu item text also should
    msg = "Please confirm that you want to clear the Undo/Redo Stack.<br>" + \
          _graymsg("(This operation cannot be undone.)")
    confirmed = PleaseConfirmMsgBox( msg)
        # TODO: I bet this needs a "don't show this again" checkbox...
        # with a prefs key...
    if not confirmed:
        env.history.message("Clear Undo Stack: Cancelled.") #k needed??
        return
    # do it
    env.history.message(greenmsg("Clear Undo Stack"))
        # no further message needed if it works, I think
    try:
        ##e Note: the following doesn't actually free storage.
        # [update, 060309 -- i think as of a few days ago it does try to... ##k]
        # Once the UI seems to work, we'll either add that to it,
        # or destroy and remake assy.undo_manager itself before doing this
        # (and make sure destroying it frees storage).
        ##e Make sure this can be called with or without auto-checkpointing
        # enabled, and leaves that setting unchanged. #####@@@@@
        win.assy.clear_undo_stack()
    except:
        print_compact_traceback("exception in clear_undo_stack: ")
        msg = "Internal error in Clear Undo Stack. " \
              "Undo/Redo might be unsafe until a new file is opened."
        env.history.message(redmsg(msg))
            #e that wording assumes we can't open more than one file at a time...
    return
Example #6
0
def editClearUndoStack(win):
    """
    This is called from MWsemantics.editClearUndoStack,
    which is documented as:

      "Slot for clearing the Undo Stack.  Requires the user to confirm."
    """
    #bruce 060304, modified from Mark's prototype in MWsemantics

    #e the following message should specify the amount of data to be lost...
    #e and the menu item text also should
    msg = "Please confirm that you want to clear the Undo/Redo Stack.<br>" + \
          _graymsg("(This operation cannot be undone.)")
    confirmed = PleaseConfirmMsgBox(msg)
    # TODO: I bet this needs a "don't show this again" checkbox...
    # with a prefs key...
    if not confirmed:
        env.history.message("Clear Undo Stack: Cancelled.")  #k needed??
        return
    # do it
    env.history.message(greenmsg("Clear Undo Stack"))
    # no further message needed if it works, I think
    try:
        ##e Note: the following doesn't actually free storage.
        # [update, 060309 -- i think as of a few days ago it does try to... ##k]
        # Once the UI seems to work, we'll either add that to it,
        # or destroy and remake assy.undo_manager itself before doing this
        # (and make sure destroying it frees storage).
        ##e Make sure this can be called with or without auto-checkpointing
        # enabled, and leaves that setting unchanged. #####@@@@@
        win.assy.clear_undo_stack()
    except:
        print_compact_traceback("exception in clear_undo_stack: ")
        msg = "Internal error in Clear Undo Stack. " \
              "Undo/Redo might be unsafe until a new file is opened."
        env.history.message(redmsg(msg))
        #e that wording assumes we can't open more than one file at a time...
    return
    def raytrace_scene(self, tmpscene=False):
        """
        Render scene. 
        If tmpscene is False, the INI and pov files are written to the 'POV-Ray Scene Files' directory.
        If tmpscene is True, the INI and pov files are written to a temporary directory (~/Nanorex/POV-Ray).
        Callers should set <tmpscene> = True when they want to render the scene but don't need to 
        save the files and create a POV-Ray Scene node in the MT (i.e. 'View > POV-Ray').
        The caller is responsible for adding the POV-Ray Scene node (self) to the model tree, if desired.
        Prints any necessary error messages to history; returns nothing.
        """
        #bruce 060710 corrected inaccuracies in docstring
        cmd = greenmsg("POV-Ray: ")
        if env.debug():
            #bruce 060707 (after Windows A8, before Linux/Mac A8)
            # compromise with what's best, so it can be ok for A8 even if only on some platforms
            env.history.message(_graymsg("POV-Ray: "))
            env.history.h_update()
            env.history.widget.update(
            )  ###@@@ will this help? is it safe? should h_update do it?

        ini, pov, out = self.get_povfile_trio(tmpscene)

        if not ini:
            ## return 1, "Problem getting POV-Ray filename trio."
            # [bruce 060710 replaced the above with the following, since it no longer matches the other return statements, or any calls]
            env.history.message(
                cmd + redmsg("Problem getting POV-Ray filename trio."))
            ###e should fix this to improve the message, by including errortext from get_povfile_trio retval (which is nim)
            return

        if tmpscene or not os.path.isfile(self.povrayscene_file):
            # write a new .pov file and save its name in self
            #
            #bruce 060711 comment (about a bug, not yet reported): ###@@@
            #   If an existing pov file has unexpectedly gone missing,
            # this code (I think) rerenders the current model, without even informing the user of the apparent error.
            #   That is extremely bad behavior, IMHO. What it ought to do is put up a dialog to inform the
            # user that the file is missing, and allow one of three actions: cancel, rerender current model,
            # or browse for the file to try to find it. If that browse is cancelled, it should offer the other
            # options, or if that finds the file but it's external, it should offer to copy it or make an
            # external link (or cancel), and then to continue or do no more. All this is desirable for any kind
            # of file node, not just PovrayScene. As it is, this won't be fixed for Mac A8; don't know about 8.1.
            self.povrayscene_file = pov
            writepovfile(self.assy.part, self.assy.o, self.povrayscene_file)
            # bruce 060711 question (possible bug): what sets self.width, self.height,  self.output_type in this case,
            # if the ones used by writepovfile differ from last time they were set in this node?
            # Guess: nothing does (bug, not yet reported). ###@@@

        # figure out renderer to use (POV-Ray or MegaPOV), its path, and its include_dir
        # (note: this contains most of the error checks that used to be inside launch_povray_or_megapov)
        # [bruce 060711 for Mac A8]
        win = self.assy.w
        ask_for_help = True  # give user the chance to fix problems in the prefs dialog
        errorcode, errortext_or_info = decode_povray_prefs(win,
                                                           ask_for_help,
                                                           greencmd=cmd)
        if errorcode:
            errortext = errortext_or_info
            env.history.message(
                cmd + redmsg(errortext)
            )  # redmsg in Mac A8, orangemsg in Windows A8 [bruce 060711]
            return
        info = errortext_or_info
        (program_nickname, program_path, include_dir) = info

        pov = self.povrayscene_file  ###k btw, is this already true?

        #k is out equal to whatever in self might store it, if anything? maybe it's not stored in self.

        write_povray_ini_file(ini, pov, out, info, self.width, self.height,
                              self.output_type)

        if tmpscene:
            msg = "Rendering scene. Please wait..."
        else:
            msg = "Rendering raytrace image from POV-Ray Scene file. Please wait..."
        env.history.message(cmd + msg)
        env.history.h_update(
        )  #bruce 060707 (after Windows A8, before Linux/Mac A8): try to make this message visible sooner
        # (doesn't work well enough, at least on Mac -- do we need to emit it before write_povray_ini_file?)
        env.history.widget.update(
        )  ###@@@ will this help? is it safe? should h_update do it?
        ###e these history widget updates fail to get it to print. Guess: we'd need qapp process events. Fix after Mac A8.
        # besides, we need this just before the launch call, not here.

        if os.path.exists(
                out
        ):  #bruce 060711 in Mac A8 not Windows A8 (probably all of Mac A8 code will also be in Linux A8)
            #e should perhaps first try moving the file to a constant name, so user could recover it manually if they wanted to
            #e (better yet, we should also try to avoid this situation when choosing the filename)
            msg = "Warning: image file already exists; removing it first [%s]" % out
            env.history.message(cmd + orangemsg(msg))
            try:
                os.remove(out)
            except:
                # this code was tested with a fake exception [060712 1041am]
                msg1 = "Problem removing old image file"
                msg2a = " [%s]" % out
                msg2b = "-- will try to overwrite it, "\
                      "but undetected rendering errors might leave it unchanged [%s]" % out
                print_compact_traceback("%s: " % (msg1 + msg2a))
                msg = redmsg(msg1) + msg2b
                #e should report the exception text in the history, too
                env.history.message(msg)
            pass

        # Launch raytrace program (POV-Ray or MegaPOV)
        errorcode, errortext = launch_povray_or_megapov(win, info, ini)

        if errorcode:
            env.history.message(
                cmd + redmsg(errortext)
            )  # redmsg in Mac A8, orangemsg in Windows A8 [bruce 060711]
            return

        #bruce 060707 (after Windows A8, before Linux/Mac A8): make sure the image file exists.
        # (On Mac, on that date [not anymore, 060710], we get this far (no error return, or maybe another bug hid one),
        # but the file is not there.)
        if not os.path.exists(out):
            msg = "Error: %s program finished, but failed to produce expected image file [%s]" % (
                program_nickname, out)
            env.history.message(cmd + redmsg(msg))
            return

        env.history.message(cmd + "Rendered image: " + out)

        # Display image in a window.
        imageviewer = ImageViewer(out, win)
        #bruce 060707 comment: if the file named <out> doesn't exist, on Mac,
        # this produces a visible and draggable tiny window, about 3 pixels wide and maybe 30 pixels high.
        imageviewer.display()

        return  # from raytrace_scene out
Example #8
0
    def raytrace_scene(self, tmpscene = False):
        """
        Render scene. 
        If tmpscene is False, the INI and pov files are written to the 'POV-Ray Scene Files' directory.
        If tmpscene is True, the INI and pov files are written to a temporary directory (~/Nanorex/POV-Ray).
        Callers should set <tmpscene> = True when they want to render the scene but don't need to 
        save the files and create a POV-Ray Scene node in the MT (i.e. 'View > POV-Ray').
        The caller is responsible for adding the POV-Ray Scene node (self) to the model tree, if desired.
        Prints any necessary error messages to history; returns nothing.
        """
        #bruce 060710 corrected inaccuracies in docstring
        cmd = greenmsg("POV-Ray: ")
        if env.debug():
            #bruce 060707 (after Windows A8, before Linux/Mac A8)
            # compromise with what's best, so it can be ok for A8 even if only on some platforms
            env.history.message(_graymsg("POV-Ray: "))
            env.history.h_update()
            env.history.widget.update() ###@@@ will this help? is it safe? should h_update do it?
        
        ini, pov, out = self.get_povfile_trio(tmpscene)
        
        if not ini:
            ## return 1, "Problem getting POV-Ray filename trio."
            # [bruce 060710 replaced the above with the following, since it no longer matches the other return statements, or any calls]
            env.history.message(cmd + redmsg("Problem getting POV-Ray filename trio."))
                ###e should fix this to improve the message, by including errortext from get_povfile_trio retval (which is nim)
            return

        if tmpscene or not os.path.isfile(self.povrayscene_file):
            # write a new .pov file and save its name in self
            #
            #bruce 060711 comment (about a bug, not yet reported): ###@@@
            #   If an existing pov file has unexpectedly gone missing,
            # this code (I think) rerenders the current model, without even informing the user of the apparent error.
            #   That is extremely bad behavior, IMHO. What it ought to do is put up a dialog to inform the
            # user that the file is missing, and allow one of three actions: cancel, rerender current model,
            # or browse for the file to try to find it. If that browse is cancelled, it should offer the other
            # options, or if that finds the file but it's external, it should offer to copy it or make an
            # external link (or cancel), and then to continue or do no more. All this is desirable for any kind
            # of file node, not just PovrayScene. As it is, this won't be fixed for Mac A8; don't know about 8.1.
            self.povrayscene_file = pov
            writepovfile(self.assy.part, self.assy.o, self.povrayscene_file)
                # bruce 060711 question (possible bug): what sets self.width, self.height,  self.output_type in this case,
                # if the ones used by writepovfile differ from last time they were set in this node?
                # Guess: nothing does (bug, not yet reported). ###@@@

        # figure out renderer to use (POV-Ray or MegaPOV), its path, and its include_dir
        # (note: this contains most of the error checks that used to be inside launch_povray_or_megapov)
        # [bruce 060711 for Mac A8]
        win = self.assy.w
        ask_for_help = True # give user the chance to fix problems in the prefs dialog
        errorcode, errortext_or_info = decode_povray_prefs(win, ask_for_help, greencmd = cmd)
        if errorcode:
            errortext = errortext_or_info
            env.history.message(cmd + redmsg(errortext)) # redmsg in Mac A8, orangemsg in Windows A8 [bruce 060711]
            return
        info = errortext_or_info
        (program_nickname, program_path, include_dir) = info

        pov = self.povrayscene_file ###k btw, is this already true?

        #k is out equal to whatever in self might store it, if anything? maybe it's not stored in self.

        write_povray_ini_file(ini, pov, out, info, self.width, self.height, self.output_type)
        
        if tmpscene:
            msg = "Rendering scene. Please wait..."
        else:
            msg = "Rendering raytrace image from POV-Ray Scene file. Please wait..."
        env.history.message(cmd + msg)
        env.history.h_update() #bruce 060707 (after Windows A8, before Linux/Mac A8): try to make this message visible sooner
            # (doesn't work well enough, at least on Mac -- do we need to emit it before write_povray_ini_file?)
        env.history.widget.update() ###@@@ will this help? is it safe? should h_update do it?
        ###e these history widget updates fail to get it to print. Guess: we'd need qapp process events. Fix after Mac A8.
        # besides, we need this just before the launch call, not here.

        if os.path.exists(out): #bruce 060711 in Mac A8 not Windows A8 (probably all of Mac A8 code will also be in Linux A8)
            #e should perhaps first try moving the file to a constant name, so user could recover it manually if they wanted to
            #e (better yet, we should also try to avoid this situation when choosing the filename)
            msg = "Warning: image file already exists; removing it first [%s]" % out
            env.history.message(cmd + orangemsg(msg))
            try:
                os.remove(out)
            except:
                # this code was tested with a fake exception [060712 1041am]
                msg1 = "Problem removing old image file"
                msg2a = " [%s]" % out
                msg2b = "-- will try to overwrite it, "\
                      "but undetected rendering errors might leave it unchanged [%s]" % out
                print_compact_traceback("%s: " % (msg1 + msg2a))
                msg = redmsg(msg1) + msg2b
                #e should report the exception text in the history, too
                env.history.message(msg)
            pass
        
        # Launch raytrace program (POV-Ray or MegaPOV)
        errorcode, errortext = launch_povray_or_megapov(win, info, ini)
        
        if errorcode:
            env.history.message(cmd + redmsg(errortext)) # redmsg in Mac A8, orangemsg in Windows A8 [bruce 060711]
            return
        
        #bruce 060707 (after Windows A8, before Linux/Mac A8): make sure the image file exists.
        # (On Mac, on that date [not anymore, 060710], we get this far (no error return, or maybe another bug hid one),
        # but the file is not there.)
        if not os.path.exists(out):
            msg = "Error: %s program finished, but failed to produce expected image file [%s]" % (program_nickname, out)
            env.history.message(cmd + redmsg(msg))
            return
        
        env.history.message(cmd + "Rendered image: " + out)
        
        # Display image in a window.
        imageviewer = ImageViewer(out, win)
            #bruce 060707 comment: if the file named <out> doesn't exist, on Mac,
            # this produces a visible and draggable tiny window, about 3 pixels wide and maybe 30 pixels high.
        imageviewer.display()
        
        return # from raytrace_scene out