def attributeLocation(self, name): #bruce 090302 renamed from self.attribute() """ Return location of an attribute (per-vertex input) shader variable. If it's not found, return -1 and warn once per session for end users, or raise an AssertionError for developers. @see: _has_shader_attribute """ loc = glGetAttribLocationARB(self.progObj, name) if loc == -1: msg = "Invalid or unused attribute variable name '%s'." % name if EndUser.enableDeveloperFeatures(): # Developers want to know of a mismatch between their Python # and shader programs as soon as possible. Not doing so causes # logic errors, or at least incorrect assumptions, to silently # propagate through the code and makes debugging more difficult. assert 0, msg else: # End users on the other hand, may value program stability more. # Just print a warning if the program is released. Do it only # once per session, since this will be in the inner draw loop! global _warnedVars if name not in _warnedVars: print "Warning:", msg _warnedVars += [name] pass pass pass return loc
def initialize(): # called from startup_misc.py if EndUser.enableDeveloperFeatures(): register_debug_menu_command("Import all source files", import_all_modules_cmd) register_debug_menu_command("Export command table", export_command_table_cmd) return
def reload_once(module): """ This function is used to support automatic runtime reloading of modules within this package, for developer convenience. To use it, add this code before any import of symbols from a module (or use this code in place of any direct import of a module): # import module # reload_once(module) Warning: not all modules support runtime reload. Those that don't should say so in their docstrings. Warning: this system does not yet properly handle indirect imports, when only the inner module has been modified. See code comments for details, especially the docstring of debug.reload_once_per_event(). As a workaround, if A imports B and you edit B.py, also edit A.py in order to trigger the desired runtime reload of B.py. """ # this comment become obsolete when exprs.basic was split into separate files: ##Note: this function's module (exprs.basic itself) is fast and harmless enough to reload that it can be ##reloaded on every use, without bothering to use reload_once. Therefore, external callers of anything ##in the exprs package can always "import basic;reload(basic)" first, and if they do, all modules within ##exprs can just start with "from basic import *". But for clarity, some of them call reload_once on basic too. if ( not EndUser.enableDeveloperFeatures() ): #070627 precaution; should improve by making this only affect default value of a debug_pref ###TODO return if not ENABLE_RELOAD: def printfyi( msg ): # WARNING: dup code, inlining py_utils version since not yet imported msg = "fyi (printonce): " + msg from foundation.env import seen_before if not seen_before(msg): print msg if 1: ## printfyi( "exprs modules won't be reloaded during this session" ) # 070627 removed this return reload_once_per_event(module, always_print=True, never_again=False, counter=exprs_globals.reload_counter, check_modtime=True) return
def reload_once(module): """ This function is used to support automatic runtime reloading of modules within this package, for developer convenience. To use it, add this code before any import of symbols from a module (or use this code in place of any direct import of a module): # import module # reload_once(module) Warning: not all modules support runtime reload. Those that don't should say so in their docstrings. Warning: this system does not yet properly handle indirect imports, when only the inner module has been modified. See code comments for details, especially the docstring of debug.reload_once_per_event(). As a workaround, if A imports B and you edit B.py, also edit A.py in order to trigger the desired runtime reload of B.py. """ # this comment become obsolete when exprs.basic was split into separate files: ##Note: this function's module (exprs.basic itself) is fast and harmless enough to reload that it can be ##reloaded on every use, without bothering to use reload_once. Therefore, external callers of anything ##in the exprs package can always "import basic;reload(basic)" first, and if they do, all modules within ##exprs can just start with "from basic import *". But for clarity, some of them call reload_once on basic too. if (not EndUser.enableDeveloperFeatures()): #070627 precaution; should improve by making this only affect default value of a debug_pref ###TODO return if not ENABLE_RELOAD: def printfyi(msg): # WARNING: dup code, inlining py_utils version since not yet imported msg = "fyi (printonce): " + msg from foundation.env import seen_before if not seen_before(msg): print msg if 1: ## printfyi( "exprs modules won't be reloaded during this session" ) # 070627 removed this return reload_once_per_event(module, always_print = True, never_again = False, counter = exprs_globals.reload_counter, check_modtime = True) return
def make_dialog_if_needed(self): """ Create self.dialog if necessary. """ # For developers, remake the dialog from its description file each time that file changes. # (The point of only remaking it then is not speed, but to test the code when it doesn't get remade, # since that's what always happens for non-developers.) # (Someday, when remaking it, copy its window geometry from the old one. Then put that code into the MMKit too. ###e) # For others, only make it the first time. if (EndUser.enableDeveloperFeatures() or env.debug()) and self.dialog: # For developers, remake the dialog if its description file changed (by zapping the old dialog here). zapit = False modtime = os.stat(self.param_desc_path).st_mtime if modtime != self.param_desc_path_modtime: zapit = True self.param_desc_path_modtime = modtime if zapit: #e save geometry? self.dialog.hide() self.dialog.destroy() ###k self.dialog = None pass if not self.dialog: if debug_run(): print "making dialog from", self.parameter_set_filename dialog_env = self # KLUGE... it needs to be something with an imagename_to_pixmap function that knows our icon_path. # the easiest way to make one is self... in future we want our own env, and to modify it by inserting that path... if use_property_pane(): # experimental, doesn't yet work [060623] parent = self.win.vsplitter2 ###@@@ could this parent be wrong? it acted like parent was self.win or so. clas = ParameterPane ###@@@ worked internally, buttons printed debug msgs, but didn't have any effects in GBC. else: # usual case parent = self.win clas = ParameterDialog self.dialog = clas( self.win, self.param_desc_path, env = dialog_env ) # this parses the description file and makes the dialog, # but does not show it and does not connect a controller to it. #e set its geometry if that was saved (from above code or maybe in prefs db) return
def _uniform(self, name): #bruce 090302 renamed from self.uniform() """ Return location of a uniform (input) shader variable. If it's not found, return -1 and warn once per session for end users, or raise an AssertionError for developers. @see: _has_uniform """ loc = glGetUniformLocationARB(self.progObj, name) if loc == -1: # The glGetUniformLocationARB man page says: # "name must be an active uniform variable name in program that is # not a structure, an array of structures, or a subcomponent of a # vector or a matrix." # # It "returns -1 if the name does not correspond to an active # uniform variable in program". Then getUniform ignores it: "If # location is equal to -1, the data passed in will be silently # ignored and the specified uniform variable will not be changed." # # Lets not be so quiet. msg = "Invalid or unused uniform shader variable name '%s'." % name if EndUser.enableDeveloperFeatures(): # Developers want to know of a mismatch between their Python # and shader programs as soon as possible. Not doing so causes # logic errors, or at least incorrect assumptions, to silently # propagate through the code and makes debugging more difficult. assert 0, msg else: # End users on the other hand, may value program stability more. # Just print a warning if the program is released. Do it only # once per session, since this will be in the inner draw loop! global _warnedVars if name not in _warnedVars: print "Warning:", msg _warnedVars += [name] pass pass pass return loc
def enter_example_command(widget, example_command_classname): ## assert isinstance(widget, GLPane) # assumed by _reinit_modes; assertion disabled to fix an import cycle glpane = widget if 0 and EndUser.enableDeveloperFeatures(): ###during devel only; broken due to file splitting # reload before use (this module only) if 0 and 'try reloading preqs too': ### can't work easily, glpane stores all the mode classes (not just their names)... glpane._reinit_modes() # just to get out of current mode safely import command_support.modes as modes reload(modes) ## from selectAtomsMode import selectAtomsMode # commented so it doesn't affect import dependency tools _superclass = 'Undefined variable' # FIX if _superclass is selectAtomsMode: import commands.Select.selectMode as selectMode reload(selectMode) import commands.SelectAtoms.selectAtomsMode as selectAtomsMode reload(selectAtomsMode) ## glpane.mode = glpane.nullmode = modes.nullMode() # revised 071010 (glpane == commandSequencer == modeMixin), new code UNTESTED: glpane._recreate_nullmode() glpane.use_nullmode() glpane._reinit_modes() # try to avoid problems with changing to other modes later, caused by those reloads # wrong: uses old classes from glpane import prototype.test_command_PMs as test_command_PMs reload(test_command_PMs) Initialize.forgetInitialization(__name__) import prototype.test_commands_init as test_commands_init reload(test_commands_init) test_commands_init.initialize() # (note: reload code is untested since the change [bruce 071030] # to call initialize explicitly rather than as import side effect, # done together with splitting this module out of test_commands) from prototype.test_commands_init import enter_example_command_doit else: from prototype.test_commands_init import enter_example_command_doit enter_example_command_doit(glpane, example_command_classname) return
DEBUG_PRINT_UNDO = False # DO NOT COMMIT with True -- causes lots of debug prints regardless of atom_debug DEBUG_FEWER_ARGS_RETRY = True # debug prints for fewer-args retries; now True since these are deprecated [bruce 071004] DEBUG_GETARGSPEC = False # DO NOT COMMIT with True -- debug prints related to USE_GETARGSPEC (only matters when that's true) DEBUG_USE_GETARGSPEC_TypeError = False # print the few cases which args_info can't yet handle (### TODO: fix it for these ASAP) # options that change behavior USE_GETARGSPEC = True # bruce 071004 _use_hcmi_hack = True # enable signal->slot call intercepting code, to check for bugs that mess up other things [bruce 050922] # i suspect this now has to be true (undo won't work without it) -- if true, remove this [bruce 071003 comment] if not EndUser.enableDeveloperFeatures(): # end user case DISABLE_SLOT_ARGCOUNT_RETRY = False # be looser for end-users until we're sure we fixed all the bugs # this would expose and turn into exceptions, as explained in the # long comment in the other case. # [bruce 071004, per team call] NONERROR_STDERR_OK = False # in case we're on a Windows install for which prints to sys.stderr cause exceptions # (that issue ought to be fixed more generally than in this file) else: # developer case DISABLE_SLOT_ARGCOUNT_RETRY = True # bruce 071004 -- WHEN True, THIS WILL EXPOSE SOME BUGS as new TypeError exceptions. # # (see also a change to this for endusers, below.) # # To fix the bugs this exposes, add the proper argument declarations to slot
sys.path.append("./experimental/pyrex-opengl") binPath = os.path.normpath(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../bin') if binPath not in sys.path: sys.path.append(binPath) quux_module_import_succeeded = False try: import quux # can't be toplevel quux_module_import_succeeded = True if "experimental" in os.path.dirname(quux.__file__): # Should never happen for end users, but if it does we want to print the # warning. if env.debug() or not EndUser.enableDeveloperFeatures(): print "debug: fyi:", \ "Loaded experimental version of C rendering code:", \ quux.__file__ except: quux = None quux_module_import_succeeded = False if env.debug(): #bruce 060323 added condition print "WARNING: unable to import C rendering code (quux module).", \ "Only Python rendering will be available." pass # == class ShapeList_inplace: """
sys.path.append("./experimental/pyrex-opengl") binPath = os.path.normpath( os.path.dirname(os.path.abspath(sys.argv[0])) + '/../bin') if binPath not in sys.path: sys.path.append(binPath) quux_module_import_succeeded = False try: import quux # can't be toplevel quux_module_import_succeeded = True if "experimental" in os.path.dirname(quux.__file__): # Should never happen for end users, but if it does we want to print the # warning. if env.debug() or not EndUser.enableDeveloperFeatures(): print "debug: fyi:", \ "Loaded experimental version of C rendering code:", \ quux.__file__ except: quux = None quux_module_import_succeeded = False if env.debug(): #bruce 060323 added condition print "WARNING: unable to import C rendering code (quux module).", \ "Only Python rendering will be available." pass # == class ShapeList_inplace:
def before_most_imports( main_globals ): """ Do things that should be done before most imports occur. main_globals should be the value of globals() in the __main__ module. """ # user-specific debug code to be run before any other imports [bruce 040903] # gpl_only check at startup [bruce 041217] try: import platform_dependent.gpl_only as _gpl_only # if this module is there, this lets it verify it should be there, # and if not, complain (to developers) whenever the program starts print "(running a GPL distribution)" #e retain or zap this? except ImportError: print "(running a non-GPL distribution)" #e retain or zap this? [should never happen for Qt4, as of 070425] pass # this is normal for non-GPL distributions try: rc = "~/.atom-debug-rc" rc = os.path.expanduser(rc) if os.path.exists(rc): ## execfile(rc) -- not allowed! import utilities.debug as _debug _debug.legally_execfile_in_globals(rc, main_globals, error_exception = False) # might fail in non-GPL versions; prints error message but # does not raise an exception. # (doing it like this is required by our licenses for Qt/PyQt) except: print """exception in execfile(%r); traceback printed to stderr or console; exiting""" % (rc,) raise # Figure out whether we're run by a developer from cvs sources # (EndUser.enableDeveloperFeatures() returns True), or by an # end-user from an installer-created program (it returns False). # Use two methods, warn if they disagree, and if either one # think's we're an end user, assume we are (so as to turn off # certain code it might not be safe for end-users to run). # [bruce 050902 new feature; revised 051006 to work in Windows # built packages] # [Russ 080905: Fixed after this file moved into ne1_startup. # bruce 080905 slightly revised that fix. # Note: see also NE1_Build_Constants.py, which has constants # that might be useable for this.] _OUR_PACKAGE = "ne1_startup" # should be this file's package inside cad/src # todo: this could be derived entirely from __name__. our_basename = __name__.split('.')[-1] # e.g. startup_before_most_imports assert _OUR_PACKAGE == __name__.split('.')[-2], \ "need to revise this code for moved file" # this will fail if _OUR_PACKAGE has more than one component, or no # components; that's intentional, since some of the code below would # also fail in that case. If it fails, generalize this and that code. # Method 1. As of 050902, package builders on all platforms reportedly move main.py # (the __main__ script) into a higher directory than the compiled python files. # But developers running from cvs leave them all in cad/src. # So we compare the directories. endUser = True # conservative initial assumption (might be changed below) import __main__ ourdir = None # hack for print statement test in except clause # this is still being imported, but we only need its __file__ attribute, which should be already defined [but see below] try: # It turns out that for Windows (at least) package builds, __main__.__file__ is either never defined or not yet # defined at this point, so we have no choice but to silently guess endUser = True in that case. I don't know whether # this module's __file__ is defined, whether this problem is Windows-specific, etc. What's worse, this problem disables # *both* guessing methods, so on an exception we just have to skip the whole thing. Further study might show that there is # no problem with ourdir, only with maindir, but I won't force us to test that right now. [bruce 051006] # REVIEW: is this still correct now that this code is in a non-toplevel module? [bruce 080111 question] ourdir = os.path.split(__file__)[0] maindir = os.path.split(__main__.__file__)[0] except: # unfortunately it's not ok to print the exception or any error message, in case endUser = True is correct... # but maybe I can get away with printing something cryptic (since our code is known to print things sometimes anyway)? # And I can make it depend on whether ourdir was set, so we have a chance of finding out whether this module defined __file__. # [bruce 051006] if ourdir is not None: print "end-user build" else: print "end user build" # different text -- no '-' else: # we set maindir and ourdir; try both guess-methods, etc def canon(path): #bruce 050908 bugfix in case developer runs python with relative (or other non-canonical) path as argument return os.path.normcase(os.path.abspath(path)) maindir = canon(maindir) ourdir = canon(ourdir) guess1 = (os.path.join(maindir, _OUR_PACKAGE) != ourdir) # Russ 080905: Loaded from package subdirectory. # Method 2. As of 050902, package builders on all platforms remove the .py files, leaving only .pyc files. guess2 = not os.path.exists(os.path.join(ourdir, our_basename + ".py")) endUser = guess1 or guess2 if EndUser.getAlternateSourcePath() != None: # special case when using ALTERNATE_CAD_SRC_PATH feature # (which can cause these guesses to differ or be incorrect): # assume anyone using it is a developer [bruce 070704] endUser = False else: if guess1 != guess2: print "Warning: two methods of guessing whether we're being run by an end-user disagreed (%r and %r)." % (guess1, guess2) print "To be safe, assuming we are (disabling some developer-only features)." print "If this ever happens, it's a bug, and the methods need to be updated." if guess1: print "(debug info: guess1 is true because %r != %r)" % (maindir, ourdir) #bruce 050908 to debug Linux bug in guess1 reported by Ninad (it's True (i.e. wrong) when he runs nE-1 from source) print pass EndUser.setDeveloperFeatures(not endUser) if EndUser.enableDeveloperFeatures(): print "enabling developer features" # The actual enabling is done by other code which checks the value of EndUser.enableDeveloperFeatures(). # Note: most code should NOT behave differently based on that value! # (Doing so might cause bugs to exist in the end-user version but not the developer version, # which would make them very hard to notice or debug. This risk is only justified in a few # special cases.) return # from before_most_imports
def initialize(): # called from startup_misc.py if EndUser.enableDeveloperFeatures(): register_debug_menu_command( "Import all source files", import_all_modules_cmd ) register_debug_menu_command( "Export command table", export_command_table_cmd ) return