I was talking to Anders about it the other day when it occurred to me that it could be a quite powerful environment.
The main problem with the Python shell is that it lacks easy reload support. So you start it up, import the module you're writing and run a couple of functions to test it. Discover an error, fix it with Emacs, save, and then you're in trouble because you can't reload the module in the shell. You have to quit the shell, restart it and reimport the module. History helps but it's still silly (well, actually it's a blatantly stupid oversight, maybe in the top 3 of things to fix in Python to speed up development time).
But with a shell integrated in Emacs, I could solve this problem, right? So I set out to write the necessary Elisp. Dump the following in your
.emacs, and it should magically work:
;; run Django shell when editing Django Python code
(defun get-file-in-upstream-dir (location filename)
(let* ((dir (file-name-directory location))
(path (concat dir filename)))
(if (file-exists-p path)
(if (not (equal dir "/"))
(get-file-in-upstream-dir (expand-file-name (concat dir "../")) filename)))))
(defadvice run-python (before possibly-setup-django-project-environment)
(let* ((settings-py (get-file-in-upstream-dir buffer-file-name "settings.py"))
(project-dir (file-name-directory settings-py)))
(setenv "DJANGO_SETTINGS_MODULE" "settings")
(setenv "PYTHONPATH" project-dir)))))
When the Python interpreter is started, the hook above looks for a settings.py file in the parent directories. If one is found, it sets up Django and also sets the PYTHONPATH to the project toplevel.
Use the code with
C-c C-zto show interpreter window,
C-c C-cto evaluate buffer,
C-c C-rto evaluate region, etc. (they're in the Python menu at top).
You'll probably want the following snippet too, it disables the warning that a Python process is still active when you quit Emacs:
(set-process-query-on-exit-flag (get-process "Python") nil)))
python-modeshould do this by itself, but in the end I didn't have the energy to report a bug and fight with the Emacs maintainers.
So did it fix the import problem in Python? Of course not. The shell inside Emacs still can't reimport a module. Sigh. But at least it's easier to test the current module because you can easily evaluate the whole buffer (which works fine).