From 014066827c4cb0f6e3fa3c3f00fc0e26edacc737 Mon Sep 17 00:00:00 2001 From: Joe Shochet Date: Mon, 5 Feb 2001 05:26:12 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/directscripts/python-mode.el | 161 ++++++++++++++++++++++-- direct/src/showbase/DirectObject.py | 5 +- direct/src/showbase/EventManager.py | 1 + direct/src/showbase/Finder.py | 102 ++++++++------- direct/src/showbase/Loader.py | 16 +-- direct/src/showbase/ShowBase.py | 18 +-- direct/src/showbase/ShowBaseGlobal.py | 1 + direct/src/task/Task.py | 6 +- 8 files changed, 228 insertions(+), 82 deletions(-) diff --git a/direct/src/directscripts/python-mode.el b/direct/src/directscripts/python-mode.el index 9290f62cd7..94ba81ed6d 100644 --- a/direct/src/directscripts/python-mode.el +++ b/direct/src/directscripts/python-mode.el @@ -106,6 +106,11 @@ See the Python Mode home page for details: :type 'string :group 'python) +(defcustom ppy-python-command "ppython" + "*Shell command used to start Python interpreter." + :type 'string + :group 'python) + (defcustom pyd-python-command "python_d" "*Shell command used to start Python interpreter." :type 'string @@ -136,13 +141,17 @@ mode buffer is visited during an Emacs session. After that, use (const :tag "JPython" jpython)) :group 'python) -(defcustom py-python-command-args '("-i" "-u") +(defcustom py-python-command-args '("-i") "*List of string arguments to be used when starting a Python shell." :type '(repeat string) :group 'python) +(defcustom ppy-python-command-args '("-i") + "*List of string arguments to be used when starting a Python shell." + :type '(repeat string) + :group 'python) -(defcustom pyd-python-command-args '("-i") +(defcustom pyd-python-command-args '("-d -i") "*List of string arguments to be used when starting a Python shell." :type '(repeat string) :group 'python) @@ -472,6 +481,7 @@ Currently-active file is at the head of the list.") (define-key py-mode-map "\C-c>" 'py-shift-region-right) ;; subprocess commands (define-key py-mode-map "\C-c\C-c" 'py-execute-buffer) + (define-key py-mode-map "\C-c\C-v" 'py-redefine-class) (define-key py-mode-map "\C-c\C-m" 'py-execute-import-or-reload) ;; (define-key py-mode-map "\C-c\C-s" 'py-execute-string) ;; VR STUDIO ENHANCEMENT @@ -519,7 +529,7 @@ Currently-active file is at the head of the list.") (define-key py-mode-map "\C-xnd" 'py-narrow-to-defun) ;; information (define-key py-mode-map "\C-c\C-b" 'py-submit-bug-report) - (define-key py-mode-map "\C-c\C-v" 'py-version) + ;(define-key py-mode-map "\C-c\C-v" 'py-version) ;; shadow global bindings for newline-and-indent w/ the py- version. ;; BAW - this is extremely bad form, but I'm not going to change it ;; for now. @@ -727,6 +737,7 @@ package. Note that the latest X/Emacs releases contain this package.") ["Execute region" py-execute-region (mark)] ["Execute def or class" py-execute-def-or-class (mark)] ["Execute string" py-execute-string t] + ["Redefine class" py-redefine-class t] ["Start interpreter..." py-shell t] "-" ["Go to start of block" py-goto-block-up t] @@ -1022,6 +1033,7 @@ py-beep-if-tab-change\t\tring the bell if `tab-width' is changed" (setq local-write-file-hooks 'Use-Undecided-Unix-Mode) ) + (defun Use-Undecided-Unix-Mode() (interactive) (set-buffer-file-coding-system 'undecided-unix) @@ -1153,15 +1165,21 @@ If an exception occurred return t, otherwise return nil. BUF must exist." ;; for toggling between CPython and JPython (defvar py-which-shell nil) +(defvar ppy-which-shell nil) (defvar pyd-which-shell nil) (defvar py-which-args py-python-command-args) +(defvar ppy-which-args ppy-python-command-args) (defvar pyd-which-args pyd-python-command-args) (defvar py-which-bufname "Python") (make-variable-buffer-local 'py-which-shell) +(make-variable-buffer-local 'ppy-which-shell) (make-variable-buffer-local 'pyd-which-shell) (make-variable-buffer-local 'py-which-args) +(make-variable-buffer-local 'ppy-which-args) (make-variable-buffer-local 'pyd-which-args) (make-variable-buffer-local 'py-which-bufname) +(make-variable-buffer-local 'ppy-which-bufname) +(make-variable-buffer-local 'pyd-which-bufname) (defun py-toggle-shells (arg) "Toggles between the CPython and JPython shells. @@ -1190,14 +1208,17 @@ Programmatically, ARG can also be one of the symbols `cpython' or ((< 0 arg) ;; set to CPython (setq py-which-shell py-python-command + ppy-which-shell ppy-python-command pyd-which-shell pyd-python-command py-which-args py-python-command-args + ppy-which-args ppy-python-command-args pyd-which-args pyd-python-command-args py-which-bufname "Python" msg "CPython" mode-name "Python")) ((> 0 arg) (setq py-which-shell py-jpython-command + ppy-which-shell ppy-jpython-command pyd-which-shell pyd-python-command py-which-args py-jpython-command-args py-which-bufname "JPython" @@ -1297,6 +1318,36 @@ filter." (use-local-map py-shell-map) )) + + +(defun ppy-shell (&optional argprompt) + "This is Joe's hacked version of py-shell which runs ppython for linux" + (interactive "P") + ;; Set the default shell if not already set + (when (null ppy-which-shell) + (py-toggle-shells py-default-interpreter)) + (let ((args ppy-which-args)) + (when (and argprompt + (interactive-p) + (fboundp 'split-string)) + ;; TBD: Perhaps force "-i" in the final list? + (setq args (split-string + (read-string (concat py-which-bufname + " arguments: ") + (concat + (mapconcat 'identity py-which-args " ") " ") + )))) + (switch-to-buffer-other-window + (apply 'make-comint py-which-bufname ppy-which-shell nil args)) + (make-local-variable 'comint-prompt-regexp) + (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ") + (add-hook 'comint-output-filter-functions + 'py-comint-output-filter-function) + (set-syntax-table py-mode-syntax-table) + (use-local-map py-shell-map) + )) + + (defun py-clear-queue () "Clear the queue of temporary files waiting to execute." (interactive) @@ -3171,8 +3222,22 @@ These are Python temporary files awaiting execution." (interactive "p") (let ((proc (get-buffer-process (current-buffer)))) (if (and (eobp) proc (= (point) (marker-position (process-mark proc)))) - (python-resume) - (delete-char arg)))) + (let ((current (point))) + (goto-char (- current 4)) + (if (or (search-forward ">>> " current t) + (search-forward "... " current t)) + (python-resume) + (let () + (goto-char current) + (message "End of buffer") + ) + ) + ) + (delete-char arg) + ) + ) + ) + (defun comint-interrupt-subjob-or-maybe-return (arg) "Enter a return (comint-send-input) or send a comint-interrupt-subjob @@ -3190,13 +3255,91 @@ These are Python temporary files awaiting execution." (comint-interrupt-subjob)))) (comint-send-input)))) + ;; Function to try to resume panda mainloop (defun python-resume () (interactive) - (end-of-buffer) - (insert "run()") - (newline 1) - (py-execute-string "try:\n\trun()\nexcept NameError,e:\n\tif e.__str__() == 'run':\n\t\tpass\n\telse:\n\t\traise\nexcept:\n\traise")) + (let* ((curbuf (current-buffer)) + (proc (get-process py-which-bufname)) + (procbuf (process-buffer proc)) + ) + (set-buffer procbuf) + (insert "run()\n") + (py-execute-string "try:\n\trun()\nexcept NameError,e:\n\tif e.__str__() == 'run':\n\t\tpass\n\telse:\n\t\traise\nexcept:\n\traise") + (goto-char (point-max)) + (set-buffer curbuf) + ) + ) + + + +(defun py-redefine-class (&optional async) + (interactive "P") + (save-excursion + (py-mark-def-or-class t) + ;; mark is before point + (py-redefine-class-region (mark) (point) async) + ) + ) + + +(defun py-redefine-class-region (start end &optional async) + (interactive "r\nP") + (or (< start end) + (error "Region is empty")) + (let* ((proc (get-process py-which-bufname)) + (temp (if (memq 'broken-temp-names py-emacs-features) + (let + ((sn py-serial-number) + (pid (and (fboundp 'emacs-pid) (emacs-pid)))) + (setq py-serial-number (1+ py-serial-number)) + (if pid + (format "python-%d-%d" sn pid) + (format "python-%d" sn))) + (make-temp-name "python-"))) + (file (expand-file-name temp py-temp-directory))) + (write-region start end file nil 'nomsg) + (cond + (proc + ;; use the existing python shell + (py-redefine-class-file proc file) + )))) + + +;; Python subprocess utilities and filters +(defun py-redefine-class-file (proc filename) + "Send to Python interpreter process PROC \"execfile('FILENAME')\". +Make that process's buffer visible and force display. Also make +comint believe the user typed this string so that +`kill-output-from-shell' does The Right Thing." + (interactive) + (let ((curbuf (current-buffer)) + (procbuf (process-buffer proc)) + (cmd (format "import Finder; Finder.rebindClass(__builtins__.globals(), r'%s')\n" filename)) + ) + + ;; Goto the python buffer + (set-buffer procbuf) + (goto-char (point-max)) + (let ((current (point))) + (goto-char (- current 4)) + ;; Look for the python prompt + (if (or (search-forward ">>> " current t) + (search-forward "... " current t)) + (let () + ;; We are already at a prompt, no need to interrupt + (process-send-string proc cmd) + ) + (let () + ;; Interrupt the task loop + (interrupt-process procbuf nil) + (process-send-string proc cmd) + ) + ) + ) + ) + ) + (provide 'python-mode) ;;; python-mode.el ends here diff --git a/direct/src/showbase/DirectObject.py b/direct/src/showbase/DirectObject.py index c194a285ed..13d5ffb8b8 100644 --- a/direct/src/showbase/DirectObject.py +++ b/direct/src/showbase/DirectObject.py @@ -11,8 +11,9 @@ class DirectObject: """ try: self.cleanup() - except NameError: - print "No cleanup() method defined!" + except AttributeError: + # No cleanup() method defined + pass # Event Handling diff --git a/direct/src/showbase/EventManager.py b/direct/src/showbase/EventManager.py index 441ce6d990..3a34d51504 100644 --- a/direct/src/showbase/EventManager.py +++ b/direct/src/showbase/EventManager.py @@ -84,6 +84,7 @@ class EventManager: else: EventManager.notify.warning('unnamed event in processEvent') + def restart(self): taskMgr.spawnTaskNamed(Task.Task(self.eventLoop), 'eventManager') diff --git a/direct/src/showbase/Finder.py b/direct/src/showbase/Finder.py index 46c7ef9703..485ced0cec 100644 --- a/direct/src/showbase/Finder.py +++ b/direct/src/showbase/Finder.py @@ -1,42 +1,56 @@ import types +import os -def findClassInModule(module, className, nesting, visited=[]): +def findClassInModule(module, className, visited): # Make sure you have not already visited this module # to prevent recursion if module in visited: return None # Ok, clear to proceed, add this module to the visited list visited.append(module) - print ('visiting: ' + `module`) + # print ('visiting: ' + `module`) + # Look in this module for classes and other modules for key in module.__dict__.keys(): value = module.__dict__[key] - if (type(value) == types.ClassType): + # If this is a class + if ((key != "_") and (type(value) == types.ClassType)): + # See if the name matches if value.__name__ == className: - return value + # It does! We found our class + return [value, module.__dict__] + # Its a module, recursively look into its namespace elif (type(value) == types.ModuleType): - ret = findClassInModule(value, className, nesting+1, visited) + ret = findClassInModule(value, className, visited) + # If that recursion found it, return the goodies if ret: return ret - # otherwise keep looking + # Otherwise keep looking + # Well, after all that we did not find anything return None -def findClass(builtins, className): - for key in builtins.keys(): - value = builtins[key] - if (type(value) == types.ClassType): +# Find a class named className somewhere in this namespace +def findClass(namespace, className): + for key in namespace.keys(): + value = namespace[key] + # If we found a class, see if it matches classname + # Make sure we do not match "_" + if ((key != "_") and (type(value) == types.ClassType)): if value.__name__ == className: - return value + # It does, that was easy! + return [value, namespace] + # Look in all the modules in this namespace elif (type(value) == types.ModuleType): - ret = findClassInModule(value, className, 0) + ret = findClassInModule(value, className, []) + # If we found it return the goodies if ret: return ret - # otherwise keep looking + # Otherwise keep looking + # Nope, not in there return None - def rebindClass(builtins, filename): tempClassName = 'py_temp_class' file = open(filename) @@ -53,7 +67,7 @@ def rebindClass(builtins, filename): parenLoc = classHeader.find('(') if parenLoc > 0: className = classHeader[:parenLoc] - print 'found className: ' + className + # print 'found className: ' + className found = 1 foundLine = i foundChar = parenLoc @@ -62,7 +76,7 @@ def rebindClass(builtins, filename): colonLoc = classHeader.find(':') if colonLoc > 0: className = classHeader[:colonLoc] - print 'found className: ' + className + # print 'found className: ' + className found = 1 foundLine = i foundChar = colonLoc @@ -72,52 +86,52 @@ def rebindClass(builtins, filename): return None # Store the original real class - realClass = findClass(builtins, className) + res = findClass(builtins, className) + if res: + realClass, realNameSpace = res + else: + print ('Error redinifing class: could not find class: ' + className) + return None - tmpfilename = '/usr/local/tmp_py_file' + # Make a temp file in the home directory to execfile from + tmpfilename = os.path.join(os.getenv('HOME'), 'tmp_py_file') tmpfile = open(tmpfilename, 'w') - # newline = 'class ' + tempClassName + lines[foundLine][(6+foundChar):] - newline = 'class ' + tempClassName + ':\012' - +# newline = 'class ' + tempClassName + ':\012' + # now write the class back to the file with the new class name for i in range(len(lines)): - if (i == foundLine): - tmpfile.write(newline) - else: - tmpfile.write(lines[i]) +# if (i == foundLine): +# tmpfile.write(newline) +# else: + tmpfile.write(lines[i]) file.close() tmpfile.close() # Now execute that class def - execfile(tmpfilename, builtins) + execfile(tmpfilename, realNameSpace) + # Remove that temp file + os.remove(tmpfilename) - tmpClass = findClass(builtins, tempClassName) + res = findClass(realNameSpace, className) + if res: + tmpClass, tmpNameSpace = res + else: + print ('Error redinifing class: could not find temp class') + return None - print 'realClass: ' + `realClass` - print 'tmpClass: ' + `tmpClass` + # Copy the functions that we just redefined into the real class + copyFuncs(tmpClass, realClass) - # Reassign the new dict - #copyFuncs(tmpClass, realClass) - copyDict(tmpClass, realClass) + # Now make sure the original class is in that namespace, not our temp one + realNameSpace[className] = realClass def copyFuncs(fromClass, toClass): + # Copy the functions from fromClass into toClass dictionary for key in fromClass.__dict__.keys(): value = fromClass.__dict__[key] if (type(value) == types.FunctionType): toClass.__dict__[key] = value - -def copyDict(fromClass, toClass): - oldModule = toClass.__module__ - toClass.__dict__ = fromClass.__dict__ - toClass.__module__ = oldModule - -class Finder: - def __init__(self): - pass - def tester(self): - pass - diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index 5ec773c13f..cbeaff7dc4 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -3,7 +3,6 @@ from PandaModules import * from DirectNotifyGlobal import * - class Loader: """Loader class: contains method to load models, sounds and code""" @@ -14,11 +13,8 @@ class Loader: def __init__(self, base): """__init__(self) Loader constructor""" - self.__base = base - self.__loader = PandaLoader() - #self.__texturePool = TexturePool() - #self.__modelPool = ModelPool() - #self.__audioPool = AudioPool() + self.base = base + self.loader = PandaLoader() # model loading funcs def loadModel(self, modelPath): @@ -26,9 +22,9 @@ class Loader: Attempt to load a model from given file path, return a nodepath to the model if successful or None otherwise.""" Loader.notify.info("Loading model: %s" % (modelPath) ) - node = self.__loader.loadSync(Filename(modelPath)) + node = self.loader.loadSync(Filename(modelPath)) if (node != None): - nodePath = self.__base.hidden.attachNewNode(node) + nodePath = self.base.hidden.attachNewNode(node) else: nodePath = None return nodePath @@ -41,7 +37,7 @@ class Loader: Loader.notify.info("Loading model once: %s" % (modelPath)) node = ModelPool.loadModel(modelPath) if (node != None): - nodePath = self.__base.hidden.attachNewNode(node) + nodePath = self.base.hidden.attachNewNode(node) else: nodePath = None return nodePath @@ -55,7 +51,7 @@ class Loader: # utilize load once goodness nodePath = self.loadModelOnce(modelPath) if (nodePath != None): - return (nodePath.copyTo(self.__base.hidden)) + return (nodePath.copyTo(self.base.hidden)) else: return None diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index f8452e9f85..43b7a1425d 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -16,12 +16,14 @@ import LinearEulerIntegrator import AngularEulerIntegrator import ClockObject import Transitions +import Loader + globalClock = ClockObject.ClockObject.getGlobalClock() class ShowBase: - notify = None + notify = directNotify.newCategory("ShowBase") def __init__(self): @@ -34,8 +36,6 @@ class ShowBase: self.wantDIRECT = self.config.GetBool('want-directtools', 0) self.wantStats = self.config.GetBool('want-stats', 0) - import Loader - self.initialState = NodeAttributes() # Set a default "off color" (i.e. use poly color) for color transitions self.initialState.setAttribute(ColorTransition.getClassType(), @@ -101,15 +101,9 @@ class ShowBase: self.buttonThrower = self.mouseWatcher.attachNewNode(ButtonThrower()) - if (ShowBase.notify == None): - ShowBase.notify = directNotify.newCategory("ShowBase") - self.loader = Loader.Loader(self) - self.eventMgr = eventMgr - self.messenger = messenger - self.taskMgr = taskMgr # Particle manager @@ -145,7 +139,7 @@ class ShowBase: self.particleMgrEnabled = 1 self.physicsMgrEnabled = 1 self.taskMgr.removeTasksNamed('manager-update') - self.taskMgr.spawnTaskNamed(Task.Task(self.__updateManagers), + self.taskMgr.spawnTaskNamed(Task.Task(self.updateManagers), 'manager-update') def disableParticles(self): @@ -166,8 +160,8 @@ class ShowBase: def isPhysicsMgrEnabled(self): return self.physicsMgrEnabled - def __updateManagers(self, state): - """__updateManagers(self)""" + def updateManagers(self, state): + """updateManagers(self)""" dt = min(globalClock.getDt(), 0.1) if (self.particleMgrEnabled == 1): self.particleMgr.doParticles(dt) diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 4c52cce3e2..30a5df4df3 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -17,3 +17,4 @@ __builtin__.tkroot = base.tkroot __builtin__.taskMgr = base.taskMgr __builtin__.eventMgr = base.eventMgr __builtin__.messenger = base.messenger + diff --git a/direct/src/task/Task.py b/direct/src/task/Task.py index 0af0c6a120..0fde9d9c9b 100644 --- a/direct/src/task/Task.py +++ b/direct/src/task/Task.py @@ -226,8 +226,8 @@ class TaskManager: task.uponDeath(task) def removeTasksNamed(self, taskName): - removedTasks = [] TaskManager.notify.debug('removing tasks named: ' + taskName) + removedTasks = [] # Find the tasks that match by name and make a list of them for task in self.taskList: @@ -247,11 +247,7 @@ class TaskManager: for task in self.taskList: task.setCurrentTimeFrame(self.currentTime, self.currentFrame) # Run the task and check the return value - if task.name == 'test': - print 'before task' ret = task(task) - if task.name == 'test': - print 'after task' if (ret == cont): continue elif (ret == done):