cfd5d659d737

vim: sadness
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Mon, 22 Nov 2010 14:32:21 -0500
parents 8bd0f75b7689
children 372fdd7888c9
branches/tags (none)
files vim/.vimrc vim/colors/molokai.vim vim/sadness/bike/AUTHORS vim/sadness/bike/COPYING vim/sadness/bike/ChangeLog vim/sadness/bike/INSTALL vim/sadness/bike/NEWS vim/sadness/bike/PKG-INFO vim/sadness/bike/README vim/sadness/bike/README.emacs vim/sadness/bike/README.idle vim/sadness/bike/README.vim vim/sadness/bike/bike/__init__.py vim/sadness/bike/bike/bikefacade.py vim/sadness/bike/bike/globals.py vim/sadness/bike/bike/log.py vim/sadness/bike/bike/logging.py vim/sadness/bike/bike/mock.py vim/sadness/bike/bike/parsing/__init__.py vim/sadness/bike/bike/parsing/constants.py vim/sadness/bike/bike/parsing/fastparser.py vim/sadness/bike/bike/parsing/fastparserast.py vim/sadness/bike/bike/parsing/load.py vim/sadness/bike/bike/parsing/newstuff.py vim/sadness/bike/bike/parsing/parserutils.py vim/sadness/bike/bike/parsing/pathutils.py vim/sadness/bike/bike/parsing/setpath.py vim/sadness/bike/bike/parsing/test_fastparser.py vim/sadness/bike/bike/parsing/test_fastparserast.py vim/sadness/bike/bike/parsing/test_load.py vim/sadness/bike/bike/parsing/test_newstuff.py vim/sadness/bike/bike/parsing/test_parserutils.py vim/sadness/bike/bike/parsing/test_pathutils.py vim/sadness/bike/bike/parsing/test_utils.py vim/sadness/bike/bike/parsing/test_visitor.py vim/sadness/bike/bike/parsing/testall.py vim/sadness/bike/bike/parsing/utils.py vim/sadness/bike/bike/parsing/visitor.py vim/sadness/bike/bike/query/__init__.py vim/sadness/bike/bike/query/common.py vim/sadness/bike/bike/query/findDefinition.py vim/sadness/bike/bike/query/findReferences.py vim/sadness/bike/bike/query/getAllRelatedClasses.py vim/sadness/bike/bike/query/getPackageDependencies.py vim/sadness/bike/bike/query/getReferencesToModule.py vim/sadness/bike/bike/query/getTypeOf.py vim/sadness/bike/bike/query/relationships.py vim/sadness/bike/bike/query/setpath.py vim/sadness/bike/bike/query/test_common.py vim/sadness/bike/bike/query/test_findDefinition.py vim/sadness/bike/bike/query/test_findReferences.py vim/sadness/bike/bike/query/test_getPackageDependencies.py vim/sadness/bike/bike/query/test_getReferencesToClass.py vim/sadness/bike/bike/query/test_getReferencesToMethod.py vim/sadness/bike/bike/query/test_getReferencesToModule.py vim/sadness/bike/bike/query/test_getTypeOf.py vim/sadness/bike/bike/query/test_relationships.py vim/sadness/bike/bike/query/testall.py vim/sadness/bike/bike/refactor/__init__.py vim/sadness/bike/bike/refactor/extractMethod.py vim/sadness/bike/bike/refactor/extractVariable.py vim/sadness/bike/bike/refactor/inlineVariable.py vim/sadness/bike/bike/refactor/moveToModule.py vim/sadness/bike/bike/refactor/rename.py vim/sadness/bike/bike/refactor/setpath.py vim/sadness/bike/bike/refactor/test_extractMethod.py vim/sadness/bike/bike/refactor/test_extractVariable.py vim/sadness/bike/bike/refactor/test_inlineVariable.py vim/sadness/bike/bike/refactor/test_moveToModule.py vim/sadness/bike/bike/refactor/test_rename.py vim/sadness/bike/bike/refactor/test_renameClass.py vim/sadness/bike/bike/refactor/test_renameFunction.py vim/sadness/bike/bike/refactor/test_renameMethod.py vim/sadness/bike/bike/refactor/testall.py vim/sadness/bike/bike/refactor/utils.py vim/sadness/bike/bike/setpath.py vim/sadness/bike/bike/test_bikefacade.py vim/sadness/bike/bike/test_testutils.py vim/sadness/bike/bike/testall.py vim/sadness/bike/bike/testdata.py vim/sadness/bike/bike/testutils.py vim/sadness/bike/bike/transformer/WordRewriter.py vim/sadness/bike/bike/transformer/__init__.py vim/sadness/bike/bike/transformer/save.py vim/sadness/bike/bike/transformer/setpath.py vim/sadness/bike/bike/transformer/testall.py vim/sadness/bike/bike/transformer/undo.py vim/sadness/bike/ide-integration/BicycleRepairMan_Idle.py vim/sadness/bike/ide-integration/Pymacs-0.20/ChangeLog vim/sadness/bike/ide-integration/Pymacs-0.20/ChangeLog-rebox vim/sadness/bike/ide-integration/Pymacs-0.20/Makefile vim/sadness/bike/ide-integration/Pymacs-0.20/PKG-INFO vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/.cvsignore vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/__init__.py vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/pymacs.py vim/sadness/bike/ide-integration/Pymacs-0.20/Pymacs/rebox.py vim/sadness/bike/ide-integration/Pymacs-0.20/README vim/sadness/bike/ide-integration/Pymacs-0.20/README.html vim/sadness/bike/ide-integration/Pymacs-0.20/THANKS vim/sadness/bike/ide-integration/Pymacs-0.20/THANKS-rebox vim/sadness/bike/ide-integration/Pymacs-0.20/TODO vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs-services vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs-services.bat vim/sadness/bike/ide-integration/Pymacs-0.20/pymacs.el vim/sadness/bike/ide-integration/Pymacs-0.20/rebox vim/sadness/bike/ide-integration/Pymacs-0.20/setup-emacs.py vim/sadness/bike/ide-integration/Pymacs-0.20/setup.py vim/sadness/bike/ide-integration/bike.vim vim/sadness/bike/ide-integration/bikeemacs.py vim/sadness/bike/ide-integration/test/README vim/sadness/bike/ide-integration/test/extractmethod.py vim/sadness/bike/ide-integration/test/scrap.py vim/sadness/bike/ide-integration/test/scrap2.py vim/sadness/bike/setup.py vim/sadness/bike/testall.py vim/sadness/ropevim/rope.vim vim/sadness/sadness.vim

Changes

--- a/vim/.vimrc	Tue Nov 16 17:53:55 2010 -0500
+++ b/vim/.vimrc	Mon Nov 22 14:32:21 2010 -0500
@@ -272,8 +272,10 @@
 map <F4> :TlistToggle<cr>
 map <leader>T :!/usr/local/bin/ctags --exclude='**/ckeditor' -R . $(test -f .venv && echo ~/lib/virtualenvs/`cat .venv`)<CR>
 
-" Rope
-source $HOME/.vim/sadness/ropevim/rope.vim
+" Rope and Bike.
+let g:bike_exceptions=1
+source $HOME/.vim/sadness/sadness.vim
+
 let ropevim_enable_shortcuts = 0
 let ropevim_guess_project = 1
 noremap <leader>rr :RopeRename<CR>
--- a/vim/colors/molokai.vim	Tue Nov 16 17:53:55 2010 -0500
+++ b/vim/colors/molokai.vim	Mon Nov 22 14:32:21 2010 -0500
@@ -58,7 +58,7 @@
 hi Macro           guifg=#C4BE89               gui=italic
 hi SpecialKey      guifg=#66D9EF               gui=italic
 
-hi MatchParen      guifg=#E4E400 guibg=NONE    gui=bold
+hi MatchParen      guifg=#E4E400 guibg=#232728 gui=bold
 hi ModeMsg         guifg=#E6DB74
 hi MoreMsg         guifg=#E6DB74
 hi Operator        guifg=#F92672
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/AUTHORS	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,24 @@
+Authors
+-------
+
+Phil Dawes       <pdawes@users.sourceforge.net> - Current Maintainer 
+                                                  and Main Author
+Shae Erisson     <shae@lapland.fi>              - Original Maintainer
+
+
+The following people have contributed code, bugfixes and patches:
+
+Jürgen Hermann   <jh@web.de>
+Canis Lupus      
+Syver Enstad     <syver-en@online.no>           Windows emacs patches
+Mathew Yeates    <mathew@comma.jpl.nasa.gov>    VIM support and bug fixes
+Marius Gedminas  <mgedmin@delfi.lt>             More VIM support
+François Pinard  <pinard@iro.umontreal.ca>      Pymacs + help with 
+                                                emacs integration
+Ender            <ender@objectrealms.net>
+Jonathan         <jonathan@infogen.net.nz>
+Steve            <thepindropper@yahoo.com.au>
+Peter Astrand    <peter@cendio.se>
+
+See ChangeLog for more details.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/COPYING	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,32 @@
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 2000 by Shae Erisson <shae@lapland.fi>
+Copyright (c) 2001 by Phil Dawes <pdawes@users.sourceforge.net>
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/ChangeLog	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,2034 @@
+2004-02-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added feature to
+	resolveImportedModuleOrPackage that searches the package hierarchy
+	of the scope even if it isn't in the pythonpath.
+
+2004-02-11  Phil Dawes  <pdawes@users.sf.net>
+
+	* bike/query/getTypeOf.py: rewrote resolveImportedModuleOrPackage
+	to use purely getModuleOrPackageUsingFQN searches. (doesnt use
+	getTypeOf Root searching any more)
+	
+	* bike/query/common.py: rewrote getLogicalLine to handle
+	multilines that parse seperately. (But was submitted by Peter
+	Astrand)
+
+2004-02-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added functionality to search from the
+	current directory if looking for an import and scope is a module
+
+2004-02-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/moveToModule.py: Added handling of individual
+	'from a.foo import theFunction'.
+
+	* bike/parsing/fastparserast.py: Added Peter Astrand's patch to
+	fix following bug:
+	'Find-References (and probably others) fails if there is more
+	whitespace than a single space between the "class"/"def" keyword
+	and the class/def name.'
+
+	* bike/query/common.py: fixed bug in just-written-code where no
+	dest in Printnl causes npe.
+	
+	* bike/query/common.py: Fixed a bug in MatchFinder. Printnl ast
+	nodes (print >>foo, bah) look at there children the opposito way
+	to the way the text comes. (i.e. they do visit(bah), visit(foo) in
+	the example above). Wrote code to get round this.
+
+2004-02-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/moveToModule.py: added more functionality to
+	moveFunction
+
+	* bike/bikefacade.py: added expanduser to normalizeFilename so
+	that ~/src/foo gets turned into a proper full path.
+
+	* bike/bikefacade.py: exposed moveClassToNewModule.
+
+	* bike/refactor/moveClass.py: started move-class-to-new-module
+	refactoring.
+
+2004-02-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/pathutils.py: new module containing all the
+	functions that search all the files in the pythonpath.
+
+	* bike/parsing/extended_ast.py: Removed this module. SourceFile is
+	now in load.py, the rest is in fastparserast.py
+
+	* ide-integration/BicycleRepairMan_Idle.py : Added patch from
+	Steve <thepindropper@yahoo.com.au> to allow easier saving of files
+	before refactoring in IDLE
+
+2004-02-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: lots of cleanup. Renamed Source
+	class to SourceFile. Slimmed down Package and Root. Am planning on
+	removing this module completely, and moving the classes into other
+	modules.
+
+
+	* bike/refactor/extractVariable.py: refactored and removed
+	extractLocalVariable_old
+
+	* bike/refactor/extractMethod.py: refactored and removed
+	extractMethod_old
+
+	* bike/refactor/test_rename*.py: Removed the 'rename twice'
+	tests. They are no longer applicable (since BRM saves to disk
+	after each refactoring)
+
+	* bike/transformer/: Moved save.py and undo.py into the
+	transformer package
+
+	* bike/parsing/newstuff.py: moved generatePackageDependencies into
+	the parsing package, because it needs to be used by other modules
+	in the parsing package.
+
+2004-02-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/relationships.py: Added generatePackageDependencies
+	which given a file in a package hierarchy, yields a list of
+	external packages and modules used by the package.
+
+	* bike/parsing/newstuff.py: Rewrote
+	generateModuleFilenamesInPythonPath wrt new ref search scheme.
+	Scheme: If the module you are searching from is in a package
+	hierarchy, scan every module in the hierarchy, and the files in
+	the directory above it (since they can reach the package without
+	including it in PYTHONPATH).
+	If the module is in a non-package directory, search in all files
+	in the directory, and in any packages below that directory.
+	N.B. this is in addition to directories in the PYTHONPATH.
+
+2004-02-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/newstuff.py: Removed getRegexMatchesInPythonPath
+
+	* bike/parsing/newstuff.py: Modified getSourceNodesContainingRegex
+	to search the pythonpath + the set of python files in the
+	directory above the root package of the current file. This should
+	remove the requirement to add the root directory to the python
+	path, and thus prevent BRM from finding references in other
+	package structures.
+
+	* bike/query/common.py: Removed scanASTSourceNodesForMatches and walkSourceNodes
+
+	* bike/globals.py: Added True/False declaration for python 2.2
+	back-compatibility.
+
+2004-01-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Added code to check for \ in a previous
+	line when locating logical lines
+
+2004-01-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Added a test and fixed a bug that meant
+	find-definitions from multiline statements wouldn't work if the
+	braces were equalised on the following line. 
+	(thanks again to Detlev for reporting this bug)
+
+2004-01-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Added a test and fixed a bug that meant
+	find-definitions from multiline statements wouldn't work. 
+	(thanks to Detlev for reporting this bug)
+
+2004-01-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Added Detlevs patch to not recurse into
+	subversion directories.
+
+2004-01-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/newstuff.py: Added code in
+	generateModuleFilenamesInPythonPath to ensure each filename is
+	generated once. (and added test to check for it)
+	(Thanks to Detlev & Syver for this bug report)
+
+	* bike/query/common.py (globalScanForMatches): Removed old
+	ast-based code from globalScanForMatches
+
+2004-01-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Fixed bug where 'from foo import aou'
+	would cause an assert to fail if foo didn't exist. (Thanks Syver)
+
+2004-01-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added code to normalize paths coming into
+	BRM. (hopefully fixes Syver's problems on windows - Thanks Syver)
+
+	
+2003-09-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed bug in
+	Bicyclerepair_idle.
+
+----------------------- 0.9 BETA4 -------------------------------
+
+2003-09-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed bug where brmctx
+	was being tested for a __nonzero__ operator due to new wrapper
+	stuff.
+	Also made the matches window a singleton
+
+	* bike/query/findReferences.py: Rewrote attribute reference
+	finding algorithm to locate a possible match, and then check if
+	the match class shares a common ancestor with the target. (rather
+	than finding all classes in the target hierarchy and then testing
+	each match class against the hierarchy).
+	This results in a 10000% 
+
+2003-09-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/relationships.py: Added buildClassHierarchy
+	functionality to guess a class hierarchy, but found that it's
+	still much too slow to handle the wxpython class hierarchy of 1900
+	odd classes under 1 root!
+
+
+2003-09-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/fastparserast.py: Added maskedsrc to the cache
+
+	* bike/query/getTypeOf.py: Added caching of type lookups
+
+	* bike/bikefacade.py: Added a generic wrapper which purges the
+	caches before and after each brm ctx call
+
+2003-08-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/newstuff.py: Added simple caching mechanism for
+	sourceNodes
+
+2003-08-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Removed some crufty methods and
+	base classes for managing the ast tree hierarchy
+
+	* bike/bikefacade.py: Removed a couple of ast related methods
+
+	* bike/query/findReferences.py: Modified the findRefs
+	functionality to exclude matches where the confidence is high that
+	it's *not* the right type.
+
+	* bike/parsing/load.py: removed the load function (and made
+	necessary refactorings to remove it)
+
+2003-08-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added setWarningLogger
+
+2003-08-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Fixed bug where "../.." was being
+	added to sys.path. This was because extended_ast.py was adding
+	importing setpath.py.
+
+2003-08-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added warning code to print message if
+	sys.path is changed by setpath.py
+
+	* ide-integration/test/README: Added ide tests for inline and
+	extract variable
+
+	* bike/bikefacade.py: Removed the load() function, and fixed
+	inline and extract local variable
+
+----------------------- 0.9 BETA3 -------------------------------
+
+2003-08-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Fixed removeLibdirsFromPath to work with
+	windows python lib directories
+
+----------------------- 0.9 BETA2 -------------------------------
+
+2003-08-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/*: Made it backward compatible with python 2.2
+
+	* ide-integration/bike.vim: Adapted vim plugin to work with new
+	api.
+
+----------------------- 0.9 BETA1 -------------------------------
+
+2003-08-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/test_*: Misc fixes for windows paths
+
+	* ide-integration/BicycleRepairMan_Idle.py: Cleaned up error
+	handling for undo stack
+
+	* bike/query/*: Misc fixes for tests
+
+	* bike/refactor/extractMethod.py: Updated to work with new
+	non-tree system
+
+2003-08-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/testutils.py: Converted createSourceNodeAt to create a
+	directory structure rather than an ast. (and broke a load of tests)
+
+2003-08-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/testutils.py: added test setup fixture to change directory
+	before executing tests
+
+2003-08-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Fixed bug which was stopping sub
+	packages from being found properly
+
+	* bike/query/relationships.py: Fixed getAllClassesInHierarchy and
+	getAllDerivedClasses to work without AST. Uses a smart algorithm
+	which scans the text of files with regexes for baseclassnames and
+	import aliases to narrow down the likely candidates.
+	
+
+2003-08-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.idle: Updated docs for python2.3/idlefork
+
+2003-08-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added code to just use
+	1 window for matches, and to reopen it if needed after it is closed
+
+2003-08-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Fixed bug which cause BRM to descend into
+	non-package directorys
+
+	* bike/parsing/extended_ast.py: Added a couple of new functions to
+	handle pythonpaths for queries and refactorings
+
+2003-08-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: modified globalScanForMatches to scan
+	files in addition to walking the ast.
+
+	* bike/query/findReferences.py: Added code to work with new
+	stateless design.
+
+2003-07-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Removed module locating code from
+	findDefinition, and made it use resolveImportedModuleOrPackage
+	instead.
+
+	* bike/query/getTypeOf.py: Modified resolveImportedModuleOrPackage
+	to use the newstuff function getModuleOrPackageUsingFQN if it cant
+	locate the module in the AST tree.
+
+	* bike/parsing/newstuff.py: modified getModuleUsingFQN
+	to handle packages. renamed to getModuleOrPackageUsingFQN 
+
+2003-07-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Made necessary modifications 
+	enable finding of function definitions without importing code
+	(uses the python path to determine where to look). Doesnt work for
+	methods yet.
+
+2003-07-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/inlineVariable.py: Applied Jonathan's patch which
+	fixes bug when multiple instances of a variable are on one line.
+
+2003-06-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: changed findReferences interface
+	to take a filename instead of a srcnode
+
+	* bike/query/findReferences.py: Fixed bug where error wasnt being
+	reported properly
+
+2003-06-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: renamed findReferences to
+	findReferences_old, and created a new findReferences which takes a
+	filename instead of the srcnode
+
+	* bike/bikefacade.py: Removed getFullyQualifiedNameOfScope - it's
+	not used anywhere, and relies on the fqn stuff working.
+
+	* all tests: attempted to remove all usage of fqn from
+	tests. Instead, replaced with name and filename tests. This is
+	because fqn is one of the major things binding the scopes
+	together. 
+
+	* bike/bikefacade.py: removed getTypeOfExpression. It's not used
+	anywhere. Will reinstate when it is required again.
+
+	* bike/query/getTypeOf.py: Fixed bug where a recursive function
+	could cause BRM to stack overflow
+
+2003-06-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added resolveImportedModuleOrPackage fn
+	to try and split the number of calls to getTypeOf()
+
+	* bike/query/getTypeOf.py: Fixed bug where a[0].theMethod() would
+	cause brm to barf.
+
+	* bike/parsing/fastparserast.py: Beefed up the __str__ members for
+	fastparser nodes
+
+2003-06-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Removed output.py. (functionality now in
+	save.py)
+
+2003-06-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: removed the ismodified stuff, in
+	an attempt to make the xast hierarchy a read-only resource.
+	Added a hook in save.py to update the xast whenever somebody
+	queues an update to be saved.
+
+	* bike/parsing/save.py: Added new save module which maintains its
+	own queue of src to be written back to disk. Replaces output.py
+
+2003-05-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/undo.py (UndoStack.undo): refactored to use dictionary
+
+	* bike/query/findDefinition.py: Refactored main function to have a
+	'stateless' interface (i.e. no need to pass a context).
+	findAllPossibleDefinitionsByCoords(filepath,lineno,col)	
+
+2003-05-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py (getRoot): Made the Root object a
+	singleton. Use the getRoot() method to get it. This is an
+	intermediate step in making the parser stateless. (idea is to make
+	it pretend to be stateless by being a singleton, then once the
+	interfaces have changed, transition the parser code to actually
+	make it stateless)
+
+2003-04-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added exception catching and error
+	reporting to bike-emacs integration
+
+2003-03-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* Applied Jonathan's patches
+	    - InlineVariable handles multiline statements
+	    - Fix to bike vim integration
+	
+2003-03-31  Marius Gedminas  <mgedmin@delfi.lt>
+
+	* ide-integration/bike.vim: Removed unnecessary argument
+	to BikeRename().
+
+	* bike/query/common.py: Fixed handling of lambdas in MatchFinder.
+
+2003-03-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractVariable.py: Made a start on the
+	extract-local-variable refactoring
+
+2003-03-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/inlineVariable.py: Made a start on the
+	inline-local-variable refactoring
+
+----------------------- 0.8 BETA2 -------------------------------
+
+2003-03-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed bug where
+	paths with spaces meant that you couldn't select a reference when
+	doing a findReferences. (Thanks to Andy Bulka for the report)
+
+	* bike/query/getTypeOf.py: Added infinite recursion protection to
+	getTypeOf
+
+	* bike/query/relationships.py: Added some performance improving
+	code when searching for a classhierarchy. Rather than doing a
+	getTypeOf() on every base class, it finds the strings likely to be
+	base classes (i.e. the name of the base class, and any 'import
+	name as foo' lines) to narrow the search.
+
+2003-03-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed bug in extract method,
+	where blank lines were messing up the indentation in the resultant
+	block
+
+
+----------------------- 0.8 BETA1 -------------------------------
+	
+2003-03-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Fixed bug in brm with emacs on
+	windows, where the mark can be active and nil at the same time.
+
+	* bike/bikefacade.py (BRMContext_impl.load): Fixed bug which
+	affected windows users. Path needs to be saved after it's been
+	normalized.
+
+2003-03-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: fixed bug in attribute finding
+	code - was only searching the first function
+
+	* bike/query/getTypeOf.py: Fixed bug where x = x.bah() would cause
+	recursion error. (just catches the stack overflow)
+
+2003-03-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/*: implemented automatic importing of changed files. This
+	means that ide integration stuff no longer has to import code into
+	brm whenever it is saved.
+
+2003-02-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.vim: Consolidated RenameMethod,
+	RenameFunction and RenameClass into 1 menu option. This is because
+	brm now supports renaming of variables and attributes and I didn't
+	want to add another 2 menu items.
+	
+
+2003-02-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Fixed rename 'prompt'
+	bug. Consolidated all the rename stuff into 1 menu option.
+
+2003-02-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/*: removed getReferencesToClass/Function/Method and
+	replaced with findReferences
+
+2003-02-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: Added findReferencesIncludingDefn
+	and made 'vanilla' findReferences not return the definition.  This
+	paves the way for a unified rename that can be used to rename
+	anything.	
+
+2003-02-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Fixed bug reported by Marius - if
+	class is declared in __init__.py, it blows up.
+
+	* bike/query/findReferences.py: Fixed bugs in
+	'getDefinitionAndScope' logic, so can handle nested classes etc..
+
+2003-02-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getReferencesToClass.py: Replaced module logic
+	with call to findReferences()
+
+	* tests: modified or removed tests that tested for the erroneous
+	'import a.b.bah.TheClass'. (A class or function can't be imported
+	- only a module)
+
+2003-01-24  Marius Gedminas <mgedmin@delfi.lt>
+
+	* ide-integration/bike.vim: Show the line itself after finding
+	references/definition.
+
+2003-01-23  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/query/common.py: Fixed a trivial NameError in
+	MatchFinder.visitGlobal().
+
+2003-01-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Refactored and cleaned up the code in
+	this module.
+
+2003-01-22  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/query/common.py: Fixed another ValueError, this time on
+	"from foo import bar" lines.
+
+2003-01-20  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/query/common.py, bike/query/findDefinition.py,
+	bike/query/findReferences.py: Fixed ValueError: list.index(x): x not
+	in list" error caused by several visitFunction methods visiting
+	their child nodes (argument names and default values) out-of-order.
+
+2003-01-16  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/refactor/extractMethod.py: Now puts spaces after commas in
+	generated code.
+
+2003-01-15  Marius Gedminas <mgedmin@delfi.lt>
+
+	* ide-integration/bike.vim: Better load failure diagnostics.
+
+2003-01-14  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/bikefacade.py, bike/parsing/fastparserast.py,
+	ide-integration/BicycleRepairMan_Idle.py: CRLF -> LF translation
+
+2003-01-13  Marius Gedminas <mgedmin@delfi.lt>
+
+	* bike/bikefacade.py: Added a function to check whether a given file
+	was ever imported.
+
+	* bike/test_bikefacade.py: Unit test for the above.
+
+	* ide-integration/bike.vim: Added code to watch for modified files
+	and reimport them into if they had been imported previously.
+
+2003-01-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getReferencesToModule.py: Added Ender's
+	getReferencesToModule module (and test module)
+
+2003-01-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Added some find class attribute
+	definition functionality
+
+2003-01-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: fixed bug where 'import'
+	statements in fn scopes weren't being searched
+
+	* ide-integration/bike.vim: Modified Marius' bike.vim vi
+	integration to support new rename and findReferences calls.
+	
+2003-01-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added fix to redisplay frame in
+	emacs, and to test for mark correctly in emacs.
+
+2003-01-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* AUTHORS: Added Mathew and Marius
+
+2003-01-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.emacs: Added simple instructions for installing pymacs.
+
+	* ide-integration/Pymacs-0.20: I'm going to ship pymacs-0.20 with
+	bicyclerepairman. I've modified it a little to make installation
+	easier.
+
+	* ide-integration/bikeemacs.py: Moved bikeemacs back to its
+	original place.
+	
+
+2003-01-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Cleaned this up a bit
+
+	* bike/parsing/fastparser.py: Fixed bug reported by Mathew Yeates
+	where more than one space between 'class' and the name foxed the
+	parser.
+
+2002-12-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findReferences.py: Started work on unified
+	findReferences code. (uses findDefinition to compare matches)
+
+	* ide-integration/emacs/bikeemacs.py: Rewrote emacs integration
+	using the excellent pymacs package
+
+2002-12-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Fixed findDefinition
+	cosmetic bug
+
+	* ide-integration/bike.el, bikeemacs: Added Syver Enstad's patch
+	for allowing filenames with spaces
+
+2002-12-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Completed support for
+	findDefinition
+
+	* ide-integration/bike.el: added code to handle the fact that if
+	you select a region, the point is one greater than the end of the
+	region and so misses it.
+
+2002-12-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/findDefinition.py: Added code to scan for other
+	method matches after locating the 100% one
+
+2002-12-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added basic
+	finddefinition support to idle
+
+	* ide-integration/bikeemacs.py: Added finddefinition support to xemacs
+
+	* bike/bikefacade.py: Exposed findDefinition through bikefacade
+
+	* bike/query/findDefinition.py: Added new query interface for
+	finding the definition of a reference, given its line/col position
+	in a module. Just supports function, method, and class references
+	for now.
+
+---------------------- 0.7 ---------------------------------------
+
+2002-11-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Fixed bug where saving buffers caused
+	the new emacs protocol to get in a tangle. My solution was to add
+	a disableMessages capability
+
+---------------------- 0.7RC3 ------------------------------------
+
+2002-11-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added acknowledgement protocol, to
+	get round synchronisation problems in windows emacs
+
+2002-11-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing: decommissioned addtypeinfo, typeinfo, tokenutils,
+	tokenhandler, matchTokensToAST, doublelinkedlist, testdata 
+
+	* bike/query/getReferencesToClass.py: Fixed bug where 
+	'from foo import *' would cause an exception if searching for a
+	class called 'foo'
+
+	* bike/*/test_*.py: Removed dependency on brmtransformer.
+
+2002-11-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Rewrote extract method module to
+	use all the new cool stuff (and operate or strings). Doesnt use
+	linked lists, iterators, tokens, brmtransformer or any of that
+	shite any more.
+
+2002-11-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Fixed bug where classscope was being
+	searched if the name wasnt found in methodscope. This is incorrect
+	because class scope isn't visible except through 'self' or a fully
+	qualified classname.
+
+2002-11-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Re-wrote MatchFinder to scan along the
+	source code text when visiting ast nodes. This removes the need to
+	match tokens in order to find the source code location of an ast
+	node.
+
+---------------------- 0.7RC1 ------------------------------------
+
+	
+2002-11-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/relationships.py: Added performance enhancement to
+	getAllDerivedClasses. Now does string search on file before ast
+	searching the classes.
+
+2002-10-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Finished
+	findReferencesByCoordinates support in idle.
+
+2002-10-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added trace
+	console. Started integration of findReferencesByCoordinates into
+	idle.
+
+	* ide-integration/bike-emacs.py: Added xemacs support for
+	getFullyQualifiedNameOfScope, getTypeOfExpression and
+	findReferencesByCoordinates
+
+
+2002-10-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added getFullyQualifiedNameOfScope,
+	getTypeOfExpression and findReferencesByCoordinates
+
+2002-10-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: changed promptForRename callback signature
+	to be linenumbers and columnnumbers
+
+	* bike/refactor/renameMethod.py: Added prompt
+	functionality. 
+
+2002-10-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Added functionality to handle scanning
+	for types of references (needed by getReferencesToMethod)
+
+	* bike/query/getReferencesToMethod.py: Implemented to use
+	common.py stuff
+
+2002-09-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/common.py: Split out common query code into common.py
+
+2002-09-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameFunction.py: Now uses the getReferences stuff
+	
+2002-09-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/transformer/WordRewriter.py: Split this class out of the
+	renameClass module.	
+
+	* bike/transformer: Added new transformer package to contain code
+	which rewrites the internal representation of the sourcecode
+
+	* bike/bikefacade.py: Implemented locateNode to use the new
+	fastparserast stuff.
+
+	* bike/parsing/extended_ast.py: Added code to set fqn (fully
+	qualified name) attributes on the fastparser ast
+
+2002-09-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameClass.py: Finished modification to use
+	getReferencesToClass. 
+
+2002-09-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getTypeOf.py: Refactored getType() functionality out
+	of ast classes and into a query module.
+
+	* bike/parsing/fastparser.py: Added parsing of import and from
+	lines to fastparser, and optimised a little.
+
+2002-09-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameClass.py: Started modification to use
+	getReferencesToClass. 
+
+2002-08-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/query/getReferencesToClass.py: New module which returns a
+	sequence of references to a class
+
+	* bike/parsing/fastparser.py: Wrote new parser which builds a tree
+	of functions and classes, very quickly.
+
+2002-08-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenutils.py: Fixed bug where attempting to
+	tokenize small strings would result in attributeerror
+
+2002-08-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/logging.py: Logging module. Eventually will be replaced by
+	import logging, but for now is a copy of the code by Vinay Sajip
+	(to save people from having to download the module)
+
+	* bike/parsing/brmtransformer.py: Added simple fix - tuple being
+	concatinated to list was causing problems
+
+
+---------------------- 0.6.7 ------------------------------------
+	
+2002-07-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added Canis fix for
+	the bug which stopped brm from displaying the menu when starting
+	idle via right-click file.
+
+	* bike/bikefacade.py: Added Canis windows compatability fix for
+	dealing with .pyw files
+
+	
+2002-07-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed bug where extracting an
+	expression from a line just below a block opener (e.g. if foo:)
+	would cause a parse error.
+
+2002-07-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.idle: Doc about problems on windows
+
+---------------------- 0.6.6 ------------------------------------
+	
+2002-07-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/doublelinkedlist.py: Optimised to use a list rather
+	than a class instance for each link element.
+
+2002-07-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/typeinfo.py: Fixed bug - package wasn't checking
+	parent packages (and Root) for types. This meant that modules
+	imported from higher up the tree weren't being found.
+
+	* bike/parsing/extended_ast.py: Renamed 'Top' to 'Root'
+
+---------------------- 0.6.5 ------------------------------------
+
+2002-07-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Minor bug fix
+
+2002-07-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bikeemacs.py: Added code so that it waits for
+	buffer to be reloaded in emacs before sending the request to
+	update the next one.
+
+	* ide-integration/bike.el: Added bug fix - if prompt for rename
+	was on file not loaded, emacs would send a message back to brm
+	when it ran find-file, which buggered up the 'rename-this-method?' 
+	interaction.
+
+2002-07-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Added support for GNU emacs
+
+	* README.emacs: renamed from README.xemacs
+
+	* 
+
+2002-07-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Added code to handle more windows filename
+	brokenness
+
+2002-07-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added same optimisation to
+	renameMethod.
+
+	* bike/refactor/renameClass.py: Added optimisation: source string
+	is scanned for classname before visiting ast. (with the lazy ast
+	creation this means that files aren't parsed unless they contain
+	the keyword (or are linked to the source via function call).
+
+	* bike/parsing/extended_ast.py: Refactored .source member into
+	.getSource() method and implemented so that tokens are
+	synchronised with source if they're modified. 
+
+2002-07-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Added lazy parsing of ast when
+	source.getModule() is called.
+
+	* bike/parsing/typeinfo.py: Added PackageTypeInfo which deduces
+	child types by interrogating the package rather than relying on
+	children to register themselves in the typeinfo. This was required
+	to facilitate lazy parsing of ast. (since parse would have had to
+	be done to add module node to package). A lookup of a module now
+	causes getModule() to be called on the sourcefile, thus triggering
+	parse of source into ast.
+
+---------------------- 0.6.4 ------------------------------------
+
+2002-06-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenutils.py: Added bug fix for superflous
+	brackets. Basically, if brackets are unecessary (e.g. '(a).foo()')
+	then they aren't in the parse tree but are in the token
+	stream. This buggers up the token matching.
+	This fix just ignores unmatching ')'s. It was the simplist thing
+	that could possibly work, but may cause problems later - needs
+	lots of testing.
+
+---------------------- 0.6.3 ------------------------------------
+	
+2002-06-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Fixed bug where getattr renamed
+	all occurences of the methodattr in the rest of the tokens
+
+2002-06-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed bug where commend before
+	the extracted block would make brm think it should be extracting
+	an expression rather than a block.
+
+	* bike/parsing/addtypeinfo.py: Fixed the same bug in _getImportedType
+
+	* bike/refactor/renameClass.py: Fixed bug where the module search
+	routine in the 'From foo import *' code was using the parent scope
+	as the search position. This doesnt work if 'from' is nested in a
+	class since parent scope is a module, not a package. Added method
+	_getParentPackage() to handle this correctly.
+
+2002-06-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed the 'loop' bug. extract
+	method will now recognise variables assigned to by the extracted
+	function and used in a loop by the calling function.
+
+2002-06-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Lots of refactoring prior to
+	fixing a bug.
+
+2002-06-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/doublelinkedlist.py: Rewrote 'insert' so that it
+	doesnt move the iterator. Renamed old method to
+	insertAndPositionIteratorOnNewElement.
+
+2002-06-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Fixed the parse error when
+	extracting code from an if...else... block. The problem was that
+	the code below the extraction contained the 'else', but not the
+	'if'. This is hacked around by inserting an 'if 1: <indent>
+	pass'. This seems to work, but I welcome a better way of handling
+	this.
+
+	* bike/parsing/output.py: Added code to ensure that indent never
+	dips below 0. This fixes a bug in parsing during method extracts
+	out of nested blocks.
+
+	* bike/refactor/extractMethod.py: Fixed the 'don't know what type
+	this isAssAttr(Name('item'), 'decl', 'OP_ASSIGN')' bug
+
+---------------------- 0.6 --------------------------------------
+	
+2002-05-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/test/*: Added manual test script for testing ide
+	integration before a release
+	
+	* ide-integration/BicycleRepairMan_Idle.py: Now imports code into
+	brm when loaded, or saved for the first time.
+
+	* ide-integration/bike.el: Now imports all loaded python files
+	into brm. Also checks to see if file was just updated to avoid
+	superflous reloads.
+
+2002-05-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/bike.el: Added menu for brm
+
+	* bike/parsing/undo.py: Added an internal undo buffer size
+
+	* ide-integration/BicycleRepairMan_Idle.py: Added generic
+	exception reporting to idle
+
+	* ide-integration/bikeemacs.py: Added generic exception
+	reporting. All exceptions are handled and reported back to the
+	user.
+
+2002-05-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ide-integration/BicycleRepairMan_Idle.py: Exposed undo to idle
+
+	* ide-integration/bikeemacs.py: Exposed undo to emacs
+
+	* bike/bikefacade.py: Exposed undo functionality to facade
+
+	* bike/parsing/undo.py: Added undo functionality
+
+2002-05-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/test_extractMethod.py: Fixed bug in expression
+	extracting code (which caused a parse exception with correct code)
+
+	* bike/bikefacade.py: Added public interface
+
+---------------------- 0.5 --------------------------------------
+
+	* ide-integration: Created new directory for integration modules 
+
+2002-05-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Exposed extract function to idle
+
+	* bike/ui/bikeemacs.py: Exposed extract function to emacs
+
+	* bike/refactor/extractMethod.py: Added support for extracting
+	expressions into methods (e.g.  a = 1+2   ->  a = self.oneplustwo())
+	Added support for extracting functions.
+
+2002-05-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Extract Method pretty much
+	finished. Now on with the testing...
+
+2002-05-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Added extract method support
+	for idle
+
+2002-05-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bike.el: implemented extract-method for emacs
+
+	* bike/bikefacade.py: Exposed extract-method to the outside world
+
+	
+2002-05-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/extractMethod.py: Implemented simple extract
+	method
+
+2002-04-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/matchTokensToAST.py: The 'new' addtokens. Instead
+	of each AST node getting its own slice of tokens, there is only
+	one token list and each node has 2 linked list iterators pointing
+	to the start and end of its tokens in within it.
+	Thus the process of calculating the position of these iterators is
+	now called 'token matching' rather than 'adding tokens to ast'.
+
+	Having only 1 token stream vastly simplifies things. There are no
+	consistency problems when renaming or moving tokens, and no need
+	to 'divide' the comments amongst the AST nodes. 
+	This enables one matching algorithm to be able to cater for all
+	ast nodes without specialized logic.
+	
+	* bike/parsing/vector.py, bike/parsing/doublelinkedlist.py:
+	containers which support the same bi-directional iterator
+	interface. Used in refactoring the parsing module to use a linked
+	list of tokens
+
+2002-04-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/bikefacade.py: Removed use of tokens
+
+---------------------- 0.4.3 ------------------------------------
+
+2002-04-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: fixed import problem in
+	windows
+
+	* bike/parsing/load.py: Added code so that if you select a
+	directory it will load all the modules and packages in it even if
+	it isnt a package (i.e. doesnt have a __init__.py), but would
+	recurse into non-package sub directories.
+
+	* bike/ui/*: This is no longer a package, since the only 2 files
+	are installed elsewhere.
+
+	* setup.py: Made BicycleRepairMan_Idle.py a root level
+	module. This means it can be used with idle by just adding
+	[BicycleRepairMan_Idle] to your .idle file.
+	
+
+2002-04-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtokens.py: Addtokens class now takes tokens in
+	constructor. The addTokens function is renamed to
+	addTokensToASTFromSrc. This will pave the way for Source nodes to
+	hold tokens rather than the source as a string
+
+	* bike/parsing/tokenhandler.py: Fixed bug which caused name ast
+	node to not be tokenized
+
+	* bike/parsing/load.py: Added check for __init__.py before
+	recursing into sub directories. This means that non-package sub
+	directories will not be recursed into. (i.e. the user must load
+	those seperately)
+
+	
+2002-03-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* NEWS: consolidated all README-version files into one NEWS file
+
+	* README*: updated documentation
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed another windows filename
+	isnt normalized bug
+
+	* bike/ui/bike.el: Added same functionality as for idle
+
+	* bike/ui/BicycleRepairMan_Idle.py: Added load on save
+	functionality - means each saved python file gets automatically
+	imported into bicyclerepairman.
+
+2002-03-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Added functionality to deduce the package
+	of the loaded module/package by inspecting parent directories for
+	__init__.py modules. This allows adding of new modules to an
+	existing AST.
+
+2002-03-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* README.idle: Added Evelyn's ammendment to doc 
+
+---------------------- 0.4.2 ------------------------------------
+
+2002-03-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* setup.py: Removed Icons stuff from setup
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed some bugs with idle
+	integration in windows:
+		- Ask if should rename dialogs dont take focus (which
+	makes selection disappear in windows)
+		- Filename normalizing means that filenames get compared correctly.
+
+2002-03-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/testutils.py: Changed the test package structure generation
+	code to add __init__.py modules to the packages. This will be used
+	to work with the new loader code (when I write it).
+
+2002-03-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed bug which was stopping
+	changed files from being reloaded on windows
+
+---------------------- 0.4.1 ------------------------------------
+
+2002-03-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/BicycleRepairMan_Idle.py: Fixed bug where rename method
+	prompts weren't visible to the user.
+
+	* bike/parsing/addtypeinfo.py: Fixed a bug which meant that
+	sourcenode wasnt getting added to default arguments, which caused
+	brm to crash when attempting to tokenize these. 
+
+
+---------------------- 0.4 --------------------------------------
+
+2002-03-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* setup.py: Removed bikegui and pyxmi from the setup
+	program. These are now deprecated.
+
+	* bike/ui/BicycleRepairMan_Idle.py: Added the idle support module
+	to cvs.
+
+	* bike/parsing/tokenhandler.py: Simplified SimpleTokenHandler
+
+	* bike/parsing/extended_ast.py: Removed ExtendedNode base class -
+	it isnt needed (thanks Evelyn)
+
+	* bike/parsing/tokenutils.py: fixed bug in
+	_getOffsetOfTokensCorrespondingToParseTree which was including the
+	NL token in the offset it returned.
+
+	* bike/bikefacade.py: Changed signature of rename method
+	callback. It now sends filename and coords as args rather than
+	exposing the ast nodes to the client.
+
+2002-03-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/__init__.py: Moved bikefacade.py (from the ui package) into
+	the bike package. This is now referenced from __init__.py so a
+	client can do:   
+	import bike;  ctx = bike.load("mypath"); ctx.renameMethod()
+	
+
+	* bike/parsing/typeinfo.py: ModuleTypeinfo.getTypeOf()
+	functionality now uses the imported module *name* to check other
+	modules, rather than a reference to the module itself. This is to
+	allow module reloading.
+
+	* bike/parsing/extended_ast.py: Added 'addtypeinfo' call to Source
+	node. This is now done when the sourcenode is added to the parent
+	node rather than being run once over the whole tree. This
+	facilitates adding additional trees to the ast without having to
+	run the whole addtypeinfo step again.
+
+	* bike/parsing/addtypeinfo.py: Removed the subclasses stuff from
+	the classtypeinfo functionality. Doing this at initial-parse time
+	is too brittle, since a reload of a child source node could remove
+	(or add) a subclass from a base class.
+	Instead, subclasses are calculated at refactoring time.
+
+	
+
+2002-03-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: Removed addfqn,
+	addparentscopeToNode and addSourcenode to nodes functionality from
+	the SourceModule, and integrated them with the first 'addtypeinfo'
+	pass. This almost halves the initial parsing time.
+
+
+2002-03-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Changed renameMethod signature to
+	take a method fqn rather than class and method parameters. This
+	allows the tests to take advantage of the same signature for
+	renameMethod,renameFunction and renameClass.
+
+	* bike/ui/bikeemacs.py: refactored to use the new bikefacade module
+
+	* bike/ui/bikefacade.py: New module which provides easy interface
+	into brm, for integrating into IDEs.
+
+	* bike/parsing/test_addtypeinfo.py: Added recursion handling for
+	things like a=a() (just catches the runtime error)
+
+2002-02-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: found a problem with lambdas - they
+	take the reference from the outer scope. If the reference is a
+	loop variable (e.g. for i in blah) then it is reassigned which
+	knackers the closure.
+	Solution -  lambda i=i: doSomethingWith(i)
+
+	* bike/ui/bikegui.py: removed reliance on tokens
+
+	* bike/parsing/tokenhandler.py: added getStartCoords() and
+	getEndCoords() functions.
+	
+
+2002-02-27  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* */setpath.py: code which insures pythonpath includes path
+	to the bike module (used for running test scripts). This is
+	imported by most modules.
+	
+	* bike/parsing/extended_ast.py: moved addParentScopeToNodes()
+	functionality from addtypeinfo into Source class.
+
+	* bike/parsing/addtypeinfo.py: For deduced types (e.g. types got
+	from function calls), the closure of the type deducing function is
+	put in the typeinfo rather than the type itself. The closure is
+	then run at lookup.
+	This facilitates lazy loading, and means source modules can be
+	reloaded without invalidating the typeinfo objects.
+	
+2002-02-18  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikeemacs.py: Added reload source functionality
+
+	* bike/ui/bike.el: Added support for renameMethod - prompts user
+	for types that brm can't deduce
+
+2002-02-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikeemacs.py: New support for emacs
+
+	* bike/parsing/addtypeinfo.py: Fixed bug which was causing
+	inheritance specs not to be renamed
+
+	* bike/parsing/output.py: Added some code to preserve level of
+	indent in multiline (comma ended) statements (e.g. function
+	arguments, class inheritence args etc...). This really needs
+	reworking into a general solution, but works 70% of the time for
+	now.
+
+2002-01-31  Phil Dawes  <pdawes@bea.com>
+
+	* bike/parsing/output.py: Added comment indenting code which
+	should preserve the indent level of comments
+
+2002-01-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameClass.py: Added functionality to rename the
+	function and class ref in 'import a.b.theFunction and from a
+	import theClass' type statements
+
+	* bike/parsing/renameFunction.py: new refactoring
+	
+	* bike/parsing/tokenhandler.py: Added code to update the typeinfo
+	objects of the parent scope and the Top node. This enables renames
+	to be carried out more than once on the same ast
+
+	* bike/parsing/addtypeinfo.py: Removed node.typeinfo.fqn. refactor
+	code should now use node.fqn
+
+2002-01-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Added token functionality to
+	Name. Removed the getPreceedingTokens() stuff - the getTokens()
+	now returns all tokens including preceeding comments, tokens
+	etc... getNodeTokens() returns just the tokens associated with the
+	node. This is consistent across all the tokenhandler base classes.
+
+	* bike/parsing/tokenutils.py: Fixed bug in _appendTokens where
+	the src 'raise foo' would result in 'raise' being picked up when
+	searching for 'foo' because both tokens are of the same type (name).
+
+2002-01-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtokens.py: Added code to class tokenizer to
+	delegate tokens to the baseclass spec (i.e. bah in 
+	'class foo(bah):'). 
+	
+	* bike/parsing/tokenhandler.py: Class handler stuff to output
+	tokens (see above). This means that renameClass now renames class
+	refs in baseclass specs.
+	
+2002-01-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Fixed a bug which stopped classes
+	that inherited from classes not in the ast from having method
+	declarations renamed.
+
+2002-01-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Added support for handling line breaks.
+   	    i.e.   if foo and \
+	              bah:
+
+	* bike/refactor/renameClass.py: Started new refactoring -
+	renameClass
+
+	* bike/parsing/addtypeinfo.py: removed 'typing indirect recursive
+	functions causes stack overflow' bug
+
+	* bike/refactor/renameMethod.py: Refactored the code so that the
+	renameMethodReferences is done once, with a list of all the
+	classes (in the hierarchy) to match.
+	
+
+2002-01-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Now renames methods on all
+	related classes (base classes and sub classes).
+
+	* doc/*: added some html documentation
+	
+2002-01-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Did some major refactoring and
+	removed all the code which is functionally duplicated in the
+	addtypeinfo module.
+
+	* bike/parsing/addtypeinfo.py: Spruced up the type inference
+	stuff.
+	ModuleTypeInfo now handles from foo import * by storing a list of
+	other modules to search.
+
+2002-01-17  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Save now returns a list of the files modified
+
+2002-01-16  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/extended_ast.py: Added lazy tokenization. Source
+	node now parses the source (rather than being handed the ast).
+
+2002-01-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: Added lazy saving. Files are only saved
+	if source modified.
+ 
+	* bike/testutils.py: Added new utility to find an ast node in a
+	tree based on attributes of the node. 
+	e.g. getMatchingASTNode(ast,"Function",name="foo")
+ 
+2002-01-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added functionality to look for
+	method and ref renames in sub classes
+
+2002-01-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: Added support for imports, import
+	from and import as statements
+
+2002-01-09  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenutils.py: Fixed bug where method call was
+	split over 2 lines. The problem is that the tokenlist contains the
+	NL, but the parsetree doesnt, so the matching wasnt working. See
+	addtokens test_doesntBarfWhenMethodCallSplitOverTwoLines for details.
+
+	* bike/parsing/brmtransformer.py: Added 2 classes which override
+	Print and Println, and return the child nodes in the desired order
+	(they are the wrong way round as they come out of
+	ast.py). The print_stmt method returns these.
+
+	* bike/parsing/output.py: Added code to handle spacing with commas
+	and stream operators
+
+2002-01-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/test_renameMethod.py: Refactored tests so that
+	BikeGUI can use them (through template method).  Tests are now
+	split into RenameMethodTests,
+	RenameMethodReferenceTests_ImportsClass and
+	RenameMethodReferenceTests_doesntImportClass. This is because
+	bikegui 
+	
+2002-01-07  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikegui.py: Added dialog to ask user if want to rename
+	method reference (for cases where the type engine can't deduce the
+	type of the instance)
+
+2002-01-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikegui.py: Added a simple gui for renameMethod
+
+2002-01-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load.py: Added functionality to strip of preceeding
+	directories from package structures. (so if you load
+	'/usr/local/python2.2/compiler', the root package is 'compiler')
+	
+	* bike/parsing/load.py: Added load_readonly(), which doesn't do the
+	addtokens step. 
+	Also added code to enable load() to be called more than once, to
+	add new files and packages to the tree.
+	Moved ui messages into constants module
+	
+2002-01-02  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/brmtransformer.py: removed addTokens() step from
+	parse(), so that it must be called seperately. This is because it
+	isn't complete, and imposes quite a performance penalty. (and it's
+	not needed by pyxmi). Updated all the tests to reflect this.
+
+2002-01-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py :  Added getSubClasses()
+	functionality to class typeinfo.
+
+2001-12-30  Phil Dawes  <pdawes@users.sourceforge.net>
+	* bike/*: Fixed path bugs for windows platform. All tests run on
+	win32 python now.
+	
+2001-12-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: Added 'self' type to function
+	typeinfo. This means renameMethod can handle self.theMethod()
+	automatically.
+
+2001-12-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* pyxmi: Wrote little tool to create xmi representation of python
+	code. Suitable for loading into argouml.
+	
+	* bike/ui/bikecli.py: Added progress meter support. (also in
+	addtokens.py, renameMethod.py, load.py and output.py
+
+2001-12-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Fixed bug where function call
+	returning instance resulted in crash. 'e.g. e().f()'
+
+2001-12-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtokens.py: Reworked addtokens scheme to 'get all
+	tokens for node, and then pass them to children to take their
+	nodes'. This makes for a much easier time processing tokens.
+
+2001-12-16  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Changed Getattr rename
+	functionality to work when attribute token isn't second token of
+	node tokenlist
+
+	* bike/refactor/test_renameMethod.py: refactored renameMethod
+	tests into generic abstract base class. These are now used by the
+	ui package (rather than vice versa)
+
+	* bike/ui/bikecli.py: Added code to tell you how many changes have
+	been made, and advice on what might be wrong if this number is 0.
+
+2001-12-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/tokenhandler.py: Added getNodeTokens()
+	implementation to miss out any preceeding cruft not picked up by
+	addtoken functionality on previous nodes.
+
+2001-12-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Changed renameMethodDefinition to
+	work with nested methods (utilising the new typeinfo.fqn stuff).
+	Removed findclass and findmethod.
+
+2001-12-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikecli.py: Modified prompt message a bit. Added actual
+	standard io stuff so that it works with a user input as well as
+	through the test harness.
+
+	* bike/refactor/renameMethod.py: Modified RenameMethodReferences
+	to create a stack of scopes. The code uses the typeinfo from each
+	scope to determine the type of references, and if it can't find
+	the type there, it checks its own references deduced from the
+	classname passed in. I.e. it assumes that the classname is a
+	class, even if it can't find the definition, and renames instances
+	derived from it.
+
+	Also ammended the 'prompt user callback' code to only ask the user
+	if the type engine doesnt know the type of the instance
+	expression. (before now it was prompting if the type was not the
+	same as the input classname)
+
+2001-12-11  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/ui/bikecli.py: Added code to handle prompting the user for
+	whether the method reference should be renamed.
+
+	* bike/refactor/renameMethod.py: Added code to prompt user when
+	type of object instance isn't known
+
+2001-12-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor.py: now takes advantage of typeinfo stuff to
+	deduce types of references
+	
+2001-12-03  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/addtypeinfo.py: New classes to deduce the types of
+	references. Adds a typeinfo attribute to each scope ast node,
+	which maps reference names to their types (currently as strings).
+
+2001-11-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added stack to maintain
+	references to object instances while visiting package structure
+
+2001-11-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added support for 'from foo
+	import *'
+	
+	* bike/ui/test_bikecli.py: Refactored tests so that all the single
+	file tests are exercised in a package hierarchy context.
+
+2001-11-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Added support to rename methods
+	based on imported classes
+
+2001-11-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/refactor/renameMethod.py: Refactored code (took out
+	RenameMethod class, since wasnt using instance state). Added
+	support for compound references (a.b.c.foo)
+
+2001-11-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load_application.py: removed. (see load.py instead)
+
+	* bike/refactor/renameMethod.py: Added support for fully qualified
+	classnames in _findClass. e.g. a.b.bah.foo. This means that the ui
+	now supports renaming package nested methods (but not their
+	references).
+
+2001-11-20  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing: Added fixes to parser module to reflect changes in
+	python 2.2 compiler module
+
+2001-11-16  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/output.py: new function 'save' saves an entire ast
+	tree
+
+	* bike/refactor/renameMethod.py: Adapted to take an ast rather
+	than source file
+
+2001-11-14  Phil Dawes  <pdawes@bea.com>
+
+	* bike/parsing/load.py: Replacement for load_application.py using
+	Juergen's pythius loader code. load() hierarchically loads a bunch
+	of packages and modules into a big AST.
+
+	* bike/parsing/extended_ast.py: Fleshed out Package and Top nodes
+	to support hierarchical module ast
+
+
+2001-11-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load_application.py: Fixed import visitor code to
+	handle comma seperated imports. (i.e. import foo,bar). Added code
+	to recognise imports via a from clause (i.e. from foo import bar)
+
+	Removed Imports.py. Integrated code into load_application
+	
+
+2001-11-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/load_application.py: Added load_application and
+	Imports modules back into build. Started writing tests for them.
+
+	
+2001-11-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* bike/parsing/brmtransformer.py : Rewrote this to override the
+	methods which create nodes at the root of the parse. This means
+	that a few methods adding parser nodelists to ast nodes should
+	cater for practically all the AST nodes.
+
+	* bike/parsing/tokenhandler.py (GetattrTokenHander.renameAttr):
+	added renameAttr method which renames the attribute in the object
+	state, and in the corresponding tokens.  This is a very brittle
+	implementation, but will be fixed as new functionality is
+	added. (it's the simplist thing right now)
+
+	* bike/parsing/addtokens.py (AddTokens.visitGetattr): added
+	token support for getattr
+
+	* bike/parsing/tokenutils.py: Added getTokensPreceedingNodes,
+	which takes a parsetree of nodes and returns all the tokens before
+	the node represented by the parsetree. This is important because
+	until there is an token-handling implementation of all the ast
+	nodes, some tokens will be missed. By eating the tokens in between
+	the implemented ast nodes, this ensures all the tokens will be
+	outputted at the end.
+
+	
+2001-10-30  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	Created new CVS module, which makes use of distutils much more
+	uniform.
+	
+	* setup.py: Created distutils setup stript: 
+
+2001-10-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: Code to handle spacing in inline comments
+
+	* refactor/renameMethod.py: Started code to handle references when
+	object is created in same scope
+
+
+2001-10-24  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: spaces in conditionals (a == b etc..)
+
+	* parsing/tokenutils.py: Refactored code in TokenList to handle
+	rearranging indent/dedent tokens so that whole-line comments are
+	indented with the things they comment. The transformations are now
+	done after the initial scan (slower, but easier to follow)
+	
+	
+2001-10-23  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: ensured a.b not seperated by spaces. 
+
+	
+2001-10-22  Phil Dawes  <pdawes@users.sourceforge.net>
+	
+	* parsing/output.py: Code to seperate a=b with spaces (a = b)
+
+	* ui/test_cli.py: Merged cli tests with renameMethod tests to
+	ensure all tests work through the cli
+
+2001-10-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* */testall.py: unified testing scripts so that all tests can be
+	run from one place
+	
+2001-10-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ui/cli.py: Added simple command line interface.
+
+2001-10-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: Finished simple ast->string functionality
+	
+2001-10-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* testall.py: added master test script
+
+	* parsing/tokenhandler.py (FunctionTokenHandler.rename): added
+	rename a function and keep tokens in sync functionality
+
+
+2001-10-12  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/output.py: started tokens -> string functionality
+
+2001-10-07  Phil Dawes  <pdawes@users.sourceforge.net>
+	* refactor/renameMethod.py: very basic findClass, findMethod
+	functionality. Needs refactoring into analysis package, and
+	merging with existing code
+	
+2001-10-05  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* refactor/simplediff.py: wrote a simple diff utility to support
+	writing top down tests. (i.e. do a renameMethod, then assert that
+	the diff is correct)
+
+	
+2001-10-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* refactor/renameMethod.py: Got fedup with trying to secondguess
+	what the parser module should do. Decided to do some top-down
+	proper XP style development. Started with implementing the
+	renameMethod story.
+
+2001-10-01  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/test_addtokens.py: refactored tests so that they use
+	brmtransformer to get a node, rather than mocking it.
+
+2001-09-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/brmtransformer.py: Added nodelist to pass_stmt
+	
+2001-09-28  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/addtokens.py (AddTokens.visitModule): finished method
+
+	* parsing/tokenutils.py
+	(TokenConverter.getTokensUptoLastNewlineBeforeCode): method added
+
+2001-09-27  Phil Dawes  <pdawes@users.sourceforge.net>
+	
+	* parsing/addtokens.py: started visitmodule() impl 
+
+	* parsing/extended_ast.py: Added tokens support to Module
+
+2001-09-26  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/test_addtokens.py Refactored tests. Made up better names.
+
+2001-09-25  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	Laptop broke. Continuing with an older version of the code (hence
+	the gap in changelog)
+
+	* parsing/tokenutils.py (TokenConverter.getTokensToColon): Added
+	function which just gobbles tokens to the next colon. Refactored
+	getTokensStartBlock() to use this instead of walking the nodelist,
+	since I think all 
+
+	* parsing/addtokens.py (AddTokens.visitFunction): Now that
+	function and class no longer need to pass in partial nodelists,
+	the code is common. Refactored common code into
+	visitCompoundNode().
+
+	(hence the gap in the changelog)
+	
+	* parsing/tokenhandler.py: removed the preceeding tokens code -
+	you ain't gonna need it!
+
+	* parsing/test_addtokens.py: changed visitclass tests to use
+	mockobjects
+
+2001-09-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* parsing/tokenhandler.py: 
+
+	* parsing/*: Integrated code with bike parsing package
+
+	Split tokenhandler base classes into seperate module
+	Merged brmast stuff into extended_ast package
+	
+	
+2001-09-08  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_tokenutils.py: Added more unit tests 
+
+2001-09-06  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_tokenutils.py: Added more unit tests 
+
+
+2001-09-04  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_addtokens.py: Added some mock objects and tests
+	
+2001-08-31  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* test_tokenutils.py: beefed up the unit tests a bit
+
+2001-08-29  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* brmtransformer.py: This module now just contains code to add the
+	nodelist member to each ast node as the compiler generates
+	it. This is so the code in addtokens has access to the original
+	python parser nodes to generate tokens from.
+
+	* addtokens.py: Moved the code to add the tokens to the ast nodes
+	to this module. It now relies on there being a 'nodelist' member
+	on each ast object, containing the original python parser
+	nodelist.
+
+	* brmast.py: Added hack to retrofit TokenHandler base class to
+	existing compiler.ast classes. This means that we no longer have
+	to include compiler classes with the distribution. 
+	Not sure if this is completely legal - doesn't work with jython.
+
+	Removed stock Python compiler classes from src tree.
+	
+
+2001-08-27  Phil Dawes  <pdawes@users.sourceforge.net>
+	Set about reimplementing the token stuff - will now add tokens to
+	ast objects *after* the nodes have been processed by the compiler
+	module.
+	
+2001-08-22  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* tokenutils.py: Added support for tokenising strings as well as
+	files.
+
+	* test_tokenutils.py: removed testdata directory, and moved all
+	the testdata into this module, now that the tokenutils stuff can
+	take strings as well as files
+
+	* brmtransformer.py: Renamed TransformerWithTokens to Transformer,
+	now that it's in a seperate module.
+
+	* brmast.py: Refactored the added token code out of ast module
+	into this one. Created a seperate mixin called TokenHandler rather
+	than sticking this code in the Node base class. Each class now
+	re-inherits this baseclass.
+	Unfortunately this means that I had to modify the transformer.py
+	file to import brmast rather than ast. Need to think of a better
+	way of doing this.
+
+2001-08-21  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* brmtransformer.py: Created new brmtransformer module and
+	refactored token code from transformer.Transformer into seperate
+	class TransformerWithTokens.  Refactored common code from
+	funcdef() and classdef() into do_compound_stmt()
+
+	* transformer.py: Now that all new code is factored out, reverted
+	to original transformer module from Python-2.1/Tools/compiler.
+
+	* tokenutils.py: Added code to alter DEDENT token line numbers
+	when they are rearranged
+
+2001-08-19  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* tokenutils.py: Added code to do token reordering to ensure that
+	comments immediately before a block of code are placed after the
+	previous block DEDENT token.
+
+2001-08-15  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* transformer.py: tidied up code, and released prototype
+
+2001-08-14  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ast.py: Refactored management of tokens into base Node
+	class. Removed code from Class, and moved node->token conversion
+	to transformer.py
+
+	* transformer.py: See above
+	
+2001-08-13  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* ast.py: Added support for tokens in 'Class' nodes. 'Class' uses
+	nodes passed to convert to tokens using TokenConverter.
+
+	
+2001-08-10  Phil Dawes  <pdawes@users.sourceforge.net>
+
+	* tokenutils.py: Started TokenConverter class to convert python
+	parser nodes to tokens.
+
+	* test_tokenutils.py: unit tests for above
+
+------------------  One year later... -------------------------
+
+
+2000-10-21 19:02  gwilder
+
+	* context.py, refactor/.cvsignore, refactor/NewClass.py,
+	refactor/Refactor.py, refactor/__init__.py:
+	
+	first refactoring: NewClass
+
+2000-10-21 18:56  gwilder
+
+	* kickstand/: test_HasFromStar.py, test_IsClass.py,
+	test_IsGlobal.py, test_all.py, test_context.py,
+	test_load_application.py, testdata/HasFromStar_tf1.py,
+	testdata/HasFromStar_tf2.py, testdata/IsGlobal_tf1.py,
+	testdata/load_application_tf1.expected,
+	testdata/load_application_tf1.py,
+	testdata/rf_addclass_tf1.expected, testdata/rf_addclass_tf1.py:
+	
+	more tests
+
+2000-10-21 18:55  gwilder
+
+	* analysis/: HasFromStar.py, IsClass.py, IsGlobal.py,
+	Superclasses.py, TODO:
+	
+	more analysis functions
+
+2000-10-21 18:38  gwilder
+
+	* parsing/: .cvsignore, Imports.py, README, TODO, __init__.py,
+	extended_ast.py, load_application.py:
+	
+	parse and load a whole app.
+
+2000-10-13 19:32  gwilder
+
+	* INSTALL, analysis/.cvsignore, analysis/IsClass.py,
+	analysis/IsGlobal.py, analysis/README, analysis/TODO,
+	analysis/__init__.py, assembly/genpy.py, kickstand/test_IsClass.py,
+	kickstand/test_IsGlobal.py, kickstand/test_all.py,
+	kickstand/testdata/.cvsignore, kickstand/testdata/IsClass_tf1.py,
+	kickstand/testdata/IsGlobal_tf1.py:
+	
+	new analysis functions; install instructions; testsuite additions.
+
+2000-09-28 00:59  eris
+
+	* .cvsignore, CHANGES, README, assembly/.cvsignore,
+	disassembly/.cvsignore, kickstand/.cvsignore,
+	kickstand/test_common.py, kickstand/treefailtest.py,
+	kickstand/treematchtest.py, kickstand/unequalvars.py,
+	sprocket/.cvsignore, sprocket/common.py, sprocket/common.txt:
+	
+	
+	added .cvsignore files in each dir got the unit test for
+	sprocket/common.py working, added files for that test.
+
+2000-09-06 01:21  jhermann
+
+	* CHANGES, INSTALL, README, TODO:
+	
+	Added administrative files
+
+2000-09-05 22:13  jhermann
+
+	* assembly/__init__.py, disassembly/__init__.py,
+	kickstand/__init__.py, sprocket/__init__.py:
+	
+	Made the inits non-empty
+
+2000-09-05 22:11  jhermann
+
+	* __init__.py:
+	
+	Minor correction
+
+2000-09-01 18:33  jhermann
+
+	* kickstand/__init__.py, kickstand/test_fsm.py,
+	kickstand/test_regast.py, sprocket/__init__.py, sprocket/common.py,
+	sprocket/fsm.py, sprocket/regast.py:
+	
+	Initial source checkin (2000-09-01)
+
+2000-09-01 18:26  jhermann
+
+	* .cvsignore, __init__.py, assembly/__init__.py, assembly/genpy.py,
+	disassembly/__init__.py, disassembly/ast.py, disassembly/consts.py,
+	disassembly/transformer.py:
+	
+	Initial source checkin (2000-09-01)
+
+2000-09-01 18:22  jhermann
+
+	* README:
+	
+	Additions by shae
+
+2000-08-19 01:35  eris
+
+	* README:
+	
+	
+	new dir structure by snibril aka Jürgen Herrman first stab at a
+	tree matcher in common.py
+
+2000-08-01 01:44  jhermann
+
+	* README:
+	
+	Added a readme dummy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/INSTALL	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,17 @@
+Bicycle Repair Man - a Python Refactoring Browser
+=================================================
+
+$Id: INSTALL,v 1.4 2002/03/29 13:10:49 pdawes Exp $
+
+-----------------------------------------------------------------------------
+
+Bicycle Repair Man requires Python 2.2 and above. 
+
+Run 
+% python setup.py install
+
+
+Then look for at the relevant README file to integrate Bicycle Repair
+Man with your IDE.
+
+-----------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/NEWS	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,98 @@
+Main highlights of each new version. See ChangeLog for a more detailed
+description of changes.
+
+Version 0.9
+-----------
+
+This version removes the requirement to load files into
+bicyclerepairman before refactoring. Instead, it searches the
+PYTHONPATH (and the path in which the file being queried is in). This
+allows 'findDefinition' queries to be made on references
+(e.g. classes, methods) where the definition is in the python library.
+
+
+Version 0.8
+-----------
+
+This release improves on the internal type-deduction engine to handle
+variables and attributes. To reflect this, 'rename' now works on
+variables and attributes, in addition to methods, functions and
+classes. This release also adds vim support (thanks to Marius Gedminas
+and Matt Yeates for this)
+
+Version 0.7
+-----------
+
+This release includes a totally re-written type querying engine, which
+is much faster and paves the way for new refactorings. It also adds
+the 'FindReferences' and 'FindDefinition' query to emacs and idle. 
+
+
+Version 0.6
+-----------
+
+This release adds undo functionality to the mix, and beefs up the idle
+and emacs integration so that code is automatically imported into brm
+when you load a file into a buffer.
+
+
+Version 0.5
+-----------
+
+This release adds the ExtractMethod refactoring
+
+
+Version 0.4
+-----------
+
+This release adds support for IDLE (see README.idle), and fixes a few
+bugs. The CLI and GUI interfaces are now deprecated and have been
+removed from this release.
+
+
+
+Version 0.3
+-----------
+
+This release adds the RenameClass and RenameFunction refactorings.
+It also contains the initial xemacs integration functionality (see
+README.xemacs).
+
+
+
+Version 0.2
+-----------
+
+This release adds a simple GUI for renaming methods - run bikegui.py
+after installation.
+
+There's also some upgrades to pyxmi. It should now be able to generate
+xmi to model all generalizations (including cross-package ones).
+N.B. pyxmi.py is now called py2xmi.py. See changelog for reasons!
+
+
+
+Version 0.1
+-----------
+
+This is the first release of Bicycle Repair Man. It requires python
+version 2.2 and above.
+
+This version supports a partial implementation of the RenameMethod
+refactoring through a command line interface. 
+
+It automatically renames the method and references to the method that
+it can deduce. It asks you about method references it can't deduce the
+instance type of.
+
+This software should be considered alpha, and may damage your source
+files - backup your sources before use!
+
+See INSTALL for installation and usage instructions.
+
+
+N.B. This package also contains pyxmi - a little python -> xmi tool I
+cobbled together out of the bicycle repair man parsing package. It
+generates an xmi file out of a source-file or package-structure,
+suitable for loading into the argouml tool. See
+http://argouml.tigris.org.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/PKG-INFO	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: bicyclerepair
+Version: 0.9
+Summary: Bicycle Repair Man, the Python refactoring tool
+Home-page: http://bicyclerepair.sourceforge.net
+Author: Phil Dawes
+Author-email: pdawes@users.sourceforge.net
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,70 @@
+Bicycle Repair Man - a Python Refactoring Browser
+=================================================
+
+Copyright (c) 2000 by Shae Erisson <shae@lapland.fi>
+Copyright (c) 2001-3 by Phil Dawes <pdawes@users.sourceforge.net>
+
+All rights reserved, see COPYING for details.
+
+$Id: README,v 1.7 2003/08/24 19:48:43 pdawes Exp $
+
+-----------------------------------------------------------------------------
+
+Bicycle Repair Man is the Python Refactoring Browser, helping
+Pythonistas everywhere glide over the gory details of refactoring their
+code. Watch him extract jumbled code into well ordered classes. Gasp, as
+he renames all occurrences of a method. Thank You, Bicycle Repair Man!
+
+execute ./testall.py to run all the tests
+
+see INSTALL for installation instructions (uses distutils).
+
+see README.idle, README.emacs etc.. for instructions on how to
+integrate bicyclerepairman into supported IDEs.
+
+-----------------------------------------------------------------------------
+
+
+What's Python? 
+
+Python is a programming language. To find out more
+about it, go to the Python Homepage at http://www.python.org/
+  
+
+What's a Refactoring Browser? 
+
+A Refactoring Browser is an editor that automates Refactorings. The
+first Refactoring Browser was written by Dr. Don Roberts and Dr. John
+Brant at the University of Illinois in Urbana-Champagne. Dr. Don
+Roberts wrote his Ph.D. thesis on the design and implementation of the
+Refactoring Browser. For more detail, read the aforementioned thesis
+at http://st-www.cs.uiuc.edu/~droberts/thesis.pdf
+  
+
+What's a Refactoring? 
+
+A Refactoring is a behaviour preserving change to source code. Some
+Refactorings are RenameVariable, RenameClass, RenameMethod,
+PullUpMethod, and PushDownVariable. Lots of people say it's very easy
+to just type a different name in where your class, method, or variable
+is defined. That's not always a refactoring though.  The Refactoring
+Browser is smart enough to rename every reference to your class,
+method or variable. If you've ever renamed a variable and broken
+classes in widely scattered parts of your system, you might be happier
+using a Refactoring Browser. A Refactoring Browser operates on any of
+method, function, class, or variable. It can add, delete, rename, move
+up down or sideways, inline and abstract. There are some operations
+that are specific to one of the three types, such as abstracting a
+variable into accessors, or turing several lines of code into a
+separate method.
+
+For more information on Refactoring, check out the websites of Martin
+Fowler at http://www.martinfowler.com/ and his Refactoring Site at
+http://www.refactoring.com/ .  
+
+
+Why Bicycle Repair Man?
+
+The Bicycle Repair Man was a superhero in a Monty Python skit, his
+special power was repairing bicycles. 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README.emacs	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,115 @@
+Instructions for running Bicycle Repair Man through emacs/xemacs
+----------------------------------------------------------------
+
+N.B. You need xemacs / emacs 21 or above.
+
+The emacs integration utilises the excellent 'Pymacs' package, written
+by François Pinard, which integrates python with emacs. A copy of this
+software is included with this package.
+
+
+There are 3 steps to installing bicyclerepairman for emacs:
+
+1) Install the base bicyclerepairman package
+
+2) Install the Pymacs package (if you haven't already got it)
+
+3) Modify your .emacs to active the bicyclerepairman functionality
+
+See the sections below for instructions on doing each of these.
+
+WINDOWS USERS: 
+You need to have both the python executable and the scripts directory
+(e.g. c:\Python22/Scripts) in your path for Bicyclerepairman to work.
+
+There are a couple of niggles with brm/emacs on
+windows. See the comments at the end of this file.
+
+
+
+
+
+
+
+1) Installation of Base Bicyclerepairman:
+-----------------------------------------
+
+- install bicyclerepair man as per INSTALL
+
+
+2) Installation of Pymacs:
+--------------------------
+
+(You can skip this if you already have pymacs installed.
+
+- Go to the ide-integration/Pymacs-0.20 directory
+- Run 
+      python setup.py install
+- Run 
+      python setup-emacs.py -l <LISP DIR>    
+  OR  
+      python setup-emacs.py -E xemacs -l <LISP DIR>
+  Depending on your version of emacs.
+
+- Add the following into your .emacs or .xemacs/init.el:
+
+;; pymacs
+(autoload 'pymacs-load "pymacs" nil t)
+(autoload 'pymacs-eval "pymacs" nil t)
+(autoload 'pymacs-apply "pymacs")
+(autoload 'pymacs-call "pymacs")
+
+- Check that it has installed correctly:
+  (Taken from the pymacs README)
+
+
+    To check that `pymacs.el' is properly installed, start Emacs and give
+    it the command `M-x load-library RET pymacs': you should not receive
+    any error.  
+
+    To check that `pymacs.py' is properly installed, start
+    an interactive Python session (e.g. from a command shell) and type
+    `from Pymacs import lisp': you should not receive any error.  
+
+	To check that `pymacs-services' is properly installed, type
+	`pymacs-services' in a shell; you should then get a line ending
+	with "(pymacs-version VERSION)". Press ctrl-c to exit.
+
+
+If you have any problems, consult the README file included with the
+pymacs distribution. N.B. I renamed the setup script to setup-emacs.py
+to make it more intuitive and easier for windows users. I've also
+added a pymacs-services.bat file to allow it to run on windows.
+
+
+3) Activating the Bike/Emacs integration
+----------------------------------------
+
+Add the following to your .emacs or .xemacs/init.el, after the pymacs
+stuff:
+
+(pymacs-load "bikeemacs" "brm-")
+(brm-init)
+
+
+You need to be using python-mode for the bicyclerepairman menu to
+appear. If you haven't already, enable this with:
+
+(autoload 'python-mode "python-mode" "Python editing mode." t)
+(setq auto-mode-alist
+      (cons '("\\.py$" . python-mode) auto-mode-alist))
+
+
+
+Usage:
+------
+
+Load a python file into emacs. A BicycleRepairMan menu should appear.
+
+
+Windows GNU-Emacs users
+-----------------------
+
+The load dialog in windows GNU-Emacs doesn't seem to allow selection
+of directories. If this is the case for you, use 'M-x brm-load' to
+import a package hierarchy.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README.idle	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,47 @@
+BicycleRepairMan_Idle.py is the name of the idle integration module.
+
+
+Installation on Python 2.3 or idlefork
+--------------------------------------
+1) Install Bicycle Repair Man (see INSTALL)
+
+2) Add the following to your ~/.idlerc/config-extensions.cfg:
+(NOTE - I had to put this in my
+<PYTHONLIBDIR>/idlelib/config-extensions.def for it to work correctly)
+
+[BicycleRepairMan_Idle]
+enable=1
+trace=0
+[BicycleRepairMan_Idle_cfgBindings]
+brm-find-references=
+brm-find-definition=
+brm-rename=
+brm-extract-method=
+brm-undo=
+
+Python sourcefile editor windows will now have a 'BicycleRepairMan'
+menu.
+
+
+
+Installation on python 2.2 version of idle
+------------------------------------------
+
+1) Install Bicycle Repair Man (see INSTALL)
+
+2) Add the following line to your <idle-installation>/config.txt or
+~/.idle:
+
+[BicycleRepairMan_Idle]
+
+
+Python sourcefile editor windows will now have a 'BicycleRepairMan'
+menu.
+
+
+
+Caveats
+-------
+
+Sometimes dialogs get lost behind windows. If things seem to have
+paused in a rename-method, try looking for a dialog.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/README.vim	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,2 @@
+Instructions for installing bike.vim are in the file itself.
+See ide-integration/bike.vim
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+# The root bicyclerepairman package
+# do:
+# ---------------------
+# import bike
+# ctx = bike.load()
+# ---------------------
+# to instantiate a bicyclerepairman context object
+
+
+from bikefacade import init, NotAPythonModuleOrPackageException, CouldntLocateASTNodeFromCoordinatesException, UndoStackEmptyException
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/bikefacade.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,274 @@
+import os
+import sys
+import compiler
+from parser import ParserError
+from bike.parsing.pathutils import getRootDirectory
+from bike.refactor import extractMethod
+from bike.refactor.rename import rename
+from bike.refactor.extractMethod import coords
+from bike.transformer.save import save as saveUpdates
+from bike.parsing.utils import fqn_rcar, fqn_rcdr
+from bike.parsing import visitor
+from bike.transformer.undo import getUndoStack, UndoStackEmptyException
+from bike.parsing.fastparserast import getRoot, Class, Function
+from bike.query.common import getScopeForLine
+from bike.query.getTypeOf import getTypeOfExpr, UnfoundType
+from bike.query.findReferences import findReferences
+from bike.query.findDefinition import findAllPossibleDefinitionsByCoords
+from bike.refactor import inlineVariable, extractVariable, moveToModule
+from bike.parsing.load import Cache
+from bike import log
+
+def init():
+    #context = BRMContext_impl()
+    context = BRMContext_wrapper()
+    return context
+
+# the context object public interface
+class BRMContext(object):
+
+
+    def save(self):
+        """ save the changed files out to disk """
+
+    def setRenameMethodPromptCallback(self, callback):
+        """
+        sets a callback to ask the user about method refs which brm
+        can't deduce the type of. The callback must be callable, and
+         take the following parameters:
+          - filename
+          - linenumber
+          - begin column
+          - end column
+         (begin and end columns enclose the problematic method call)
+        """
+        
+    def renameByCoordinates(self, filename_path, line, col, newname):
+        """ an ide friendly method which renames a class/fn/method
+        pointed to by the coords and filename"""
+
+    def extract(self, filename_path, 
+                begin_line, begin_col,
+                end_line, end_col, 
+                name):
+        """ extracts the region into the named method/function based
+        on context"""
+
+    def inlineLocalVariable(self,filename_path, line, col):
+        """ Inlines the variable pointed to by
+        line:col. (N.B. line:col can also point to a reference to the
+        variable as well as the definition) """
+
+
+    def extractLocalVariable(self,filename_path, begin_line, begin_col,
+                             end_line, end_col, variablename):
+        """ Extracts the region into a variable """
+
+    def setProgressLogger(self,logger):
+        """ Sets the progress logger to an object with a write method
+        """
+        
+    def setWarningLogger(self,logger):
+        """ Sets the warning logger to an object with a write method
+        """
+
+    def undo(self):
+        """ undoes the last refactoring. WARNING: this is dangerous if
+        the user has modified files since the last refactoring.
+        Raises UndoStackEmptyException"""
+
+    def findReferencesByCoordinates(self, filename_path, line, column):
+        """ given the coords of a function, class, method or variable
+        returns a generator which finds references to it.
+        """
+
+    def findDefinitionByCoordinates(self,filename_path,line,col):        
+        """ given the coordates to a reference, tries to find the
+        definition of that reference """
+
+    def moveClassToNewModule(self,filename_path, line, 
+                             newfilename):
+        """ moves the class pointed to by (filename_path, line)
+        to a new module """
+
+        
+class NotAPythonModuleOrPackageException: pass
+class CouldntLocateASTNodeFromCoordinatesException: pass
+
+
+# Wrapper to ensure that caches are purged on each request
+class BRMContext_wrapper:
+    def __init__(self):
+        self.brmctx = BRMContext_impl()
+
+    def __getattr__(self,name):
+        return BRMContext_callWrapper(self.brmctx,name)
+
+
+class BRMContext_callWrapper:
+    def __init__(self,brmctx,methodname):
+        self.name = methodname
+        self.brmctx = brmctx
+
+    def __call__(self,*args):
+        Cache.instance.reset()
+        try:
+            return getattr(self.brmctx,self.name)(*args)
+        finally:
+            Cache.instance.reset()
+
+
+class BRMContext_impl(BRMContext):
+    
+    def __init__(self):
+        self.ast = getRoot()
+
+        # Used because some refactorings delegate back to the user.
+        # this flag ensures that code isnt imported during those times
+        self.readyToLoadNewCode = 1 
+        self.paths = []
+        getUndoStack(1)  # force new undo stack
+        if not getRoot().unittestmode:
+            log.warning = sys.stderr            
+        self.promptUserClientCallback = None
+
+    def _getAST(self):
+        return self.ast
+
+    # returns a list of saved filenames
+    def save(self):
+        savedfiles = saveUpdates()
+        return savedfiles
+
+    def setRenameMethodPromptCallback(self, callback):
+        self.promptUserClientCallback = callback
+
+
+    def normalizeFilename(self,filename):
+        filename = os.path.expanduser(filename)
+        filename = os.path.normpath(os.path.abspath(filename))
+        return filename
+
+    def extractMethod(self, filename_path, 
+                        begin_line, begin_column, 
+                        end_line, end_column, 
+                        methodname):
+        self.extract(filename_path, begin_line, begin_column,
+                     end_line, end_column,methodname)
+
+    def extractFunction(self, filename_path, 
+                        begin_line, begin_column, 
+                        end_line, end_column, 
+                        methodname):
+        self.extract(filename_path, begin_line, begin_column,
+                     end_line, end_column,methodname)
+
+    # does it based on context
+    def extract(self, filename_path, 
+                begin_line, begin_col,
+                end_line, end_col, 
+                name):
+        filename_path = self.normalizeFilename(filename_path)
+        extractMethod.extractMethod(filename_path,
+                                    coords(begin_line, begin_col), 
+                                    coords(end_line, end_col), name)
+
+    def inlineLocalVariable(self,filename_path, line, col):
+        filename_path = self.normalizeFilename(filename_path)
+        inlineVariable.inlineLocalVariable(filename_path,line,col)
+
+    def extractLocalVariable(self,filename_path, begin_line, begin_col,
+                             end_line, end_col, variablename):
+        filename_path = self.normalizeFilename(filename_path)
+        extractVariable.extractLocalVariable(filename_path,
+                                             coords(begin_line, begin_col),
+                                             coords(end_line, end_col),
+                                             variablename)
+
+    def moveClassToNewModule(self,filename_path, line, 
+                             newfilename):
+        filename_path = self.normalizeFilename(filename_path)
+        newfilename = self.normalizeFilename(newfilename)
+        moveToModule.moveClassToNewModule(filename_path, line, 
+                                       newfilename)
+
+    def undo(self):
+        getUndoStack().undo()
+
+    def _promptUser(self, filename, lineno, colbegin, colend):
+        return self.promptUserClientCallback(filename, lineno, colbegin, colend)
+
+
+    # must be an object with a write method
+    def setProgressLogger(self,logger):
+        log.progress = logger
+
+    # must be an object with a write method
+    def setWarningLogger(self,logger):
+        log.warning = logger
+
+
+    # filename_path must be absolute
+    def renameByCoordinates(self, filename_path, line, col, newname):
+        filename_path = self.normalizeFilename(filename_path)
+        Cache.instance.reset()
+        try:
+            self._setNonLibPythonPath(filename_path)
+            rename(filename_path,line,col,newname,
+                   self.promptUserClientCallback)
+        finally:
+            Cache.instance.reset()
+
+    def _reverseCoordsIfWrongWayRound(self, colbegin, colend):
+        if(colbegin > colend):
+            colbegin,colend = colend,colbegin
+        return colbegin,colend
+
+
+    def findDefinitionByCoordinates(self,filename_path,line,col):
+        filename_path = self.normalizeFilename(filename_path)
+        self._setCompletePythonPath(filename_path)
+        return findAllPossibleDefinitionsByCoords(filename_path,line,col)
+
+        
+    # filename_path must be absolute
+    def findReferencesByCoordinates(self, filename_path, line, column):
+        filename_path = self.normalizeFilename(filename_path)
+        self._setNonLibPythonPath(filename_path)
+        return findReferences(filename_path,line,column)
+        
+    def refreshASTFromFileSystem(self):
+        for path in self.paths:
+            self.ast = loadast(path, self.ast)
+
+    def _setCompletePythonPath(self,filename):
+        pythonpath = [] + sys.path  # make a copy
+        self.ast.pythonpath = pythonpath
+        
+    def _setNonLibPythonPath(self,filename):
+        if getRoot().unittestmode:
+            return
+        pythonpath = self._removeLibdirsFromPath(sys.path)
+        pythonpath = [os.path.abspath(p) for p in pythonpath]
+        self.ast.pythonpath = pythonpath
+
+    def _getCurrentSearchPath(self):
+        return self.ast.pythonpath
+    
+    def _removeLibdirsFromPath(self, pythonpath):
+        libdir = os.path.join(sys.prefix,"lib").lower()
+        pythonpath = [p for p in pythonpath
+                      if not p.lower().startswith(libdir)]
+        return pythonpath
+
+        
+def _deducePackageOfFile(filename):
+    package = ""
+    dot = ""
+    dir = os.path.dirname(filename)
+    while dir != ""and \
+          os.path.exists(os.path.join(dir, "__init__.py")):
+        dir, dirname = os.path.split(dir)
+        package = dirname+dot+package
+        dot = "."
+    return package
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/globals.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,6 @@
+try:
+    True = 1
+    False = 0
+except:
+    pass
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/log.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,8 @@
+import sys
+class SilentLogger:
+    def write(*args):
+        pass
+
+progress = SilentLogger()
+warning = SilentLogger()
+#warning = sys.stderr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/logging.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1995 @@
+#! /usr/bin/env python
+#
+# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# For the change history, see README.txt in the distribution.
+#
+# This file is part of the Python logging distribution. See
+# http://www.red-dove.com/python_logging.html
+#
+
+"""
+Logging module for Python. Based on PEP 282 and comments thereto in
+comp.lang.python, and influenced by Apache's log4j system.
+
+Should work under Python versions >= 1.5.2, except that source line
+information is not available unless 'inspect' is.
+
+Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
+
+To use, simply 'import logging' and log away!
+"""
+
+import sys, os, types, time, string, socket, cPickle, cStringIO
+
+from SocketServer import ThreadingTCPServer, StreamRequestHandler
+
+
+try:
+    import thread
+except ImportError:
+    thread = None
+try:
+    import inspect
+except ImportError:
+    inspect = None
+
+__author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
+__status__  = "alpha"
+__version__ = "0.4.5"
+__date__    = "4 June 2002"
+
+#---------------------------------------------------------------------------
+#   Miscellaneous module data
+#---------------------------------------------------------------------------
+
+#
+#_srcfile is used when walking the stack to check when we've got the first
+# caller stack frame.
+#If run as a script, __file__ is not bound.
+#
+if __name__ == "__main__":
+    _srcfile = None
+else:
+    if string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
+        _srcfile = __file__[:-4] + '.py'
+    else:
+        _srcfile = __file__
+    _srcfile = os.path.normcase(_srcfile)
+
+#
+#_startTime is used as the base when calculating the relative time of events
+#
+_startTime = time.time()
+
+#
+# Some constants...
+#
+
+DEFAULT_TCP_LOGGING_PORT    = 9020
+DEFAULT_UDP_LOGGING_PORT    = 9021
+DEFAULT_HTTP_LOGGING_PORT   = 9022
+DEFAULT_SOAP_LOGGING_PORT   = 9023
+DEFAULT_LOGGING_CONFIG_PORT = 9030
+SYSLOG_UDP_PORT             = 514
+
+#---------------------------------------------------------------------------
+#   Level related stuff
+#---------------------------------------------------------------------------
+#
+# Default levels and level names, these can be replaced with any positive set
+# of values having corresponding names. There is a pseudo-level, ALL, which
+# is only really there as a lower limit for user-defined levels. Handlers and
+# loggers are initialized with ALL so that they will log all messages, even
+# at user-defined levels.
+#
+CRITICAL = 50
+FATAL = CRITICAL
+ERROR = 40
+WARN = 30
+INFO = 20
+DEBUG = 10
+ALL = 0
+
+_levelNames = {
+    CRITICAL : 'CRITICAL',
+    ERROR    : 'ERROR',
+    WARN     : 'WARN',
+    INFO     : 'INFO',
+    DEBUG    : 'DEBUG',
+    ALL      : 'ALL',
+    'CRITICAL'  : CRITICAL,
+    'ERROR'     : ERROR,
+    'WARN'      : WARN,
+    'INFO'      : INFO,
+    'DEBUG'     : DEBUG,
+    'ALL'       : ALL,
+}
+
+def getLevelName(lvl):
+    """
+    Return the textual representation of logging level 'lvl'. If the level is
+    one of the predefined levels (CRITICAL, ERROR, WARN, INFO, DEBUG) then you
+    get the corresponding string. If you have associated levels with names
+    using addLevelName then the name you have associated with 'lvl' is
+    returned. Otherwise, the string "Level %s" % lvl is returned.
+    """
+    return _levelNames.get(lvl, ("Level %s" % lvl))
+
+def addLevelName(lvl, levelName):
+    """
+    Associate 'levelName' with 'lvl'. This is used when converting levels
+    to text during message formatting.
+    """
+    _acquireLock()
+    try:    #unlikely to cause an exception, but you never know...
+        _levelNames[lvl] = levelName
+        _levelNames[levelName] = lvl
+    finally:
+        _releaseLock()
+
+#---------------------------------------------------------------------------
+#   Thread-related stuff
+#---------------------------------------------------------------------------
+
+#
+#_lock is used to serialize access to shared data structures in this module.
+#This needs to be an RLock because fileConfig() creates Handlers and so
+#might arbitrary user threads. Since Handler.__init__() updates the shared
+#dictionary _handlers, it needs to acquire the lock. But if configuring,
+#the lock would already have been acquired - so we need an RLock.
+#The same argument applies to Loggers and Manager.loggerDict.
+#
+_lock = None
+
+def _acquireLock():
+    """
+    Acquire the module-level lock for serializing access to shared data.
+    This should be released with _releaseLock().
+    """
+    global _lock
+    if (not _lock) and thread:
+        import threading    #this had better work
+        _lock = threading.RLock()
+    if _lock:
+        _lock.acquire()
+
+def _releaseLock():
+    """
+    Release the module-level lock acquired by calling _acquireLock().
+    """
+    if _lock:
+        _lock.release()
+
+#---------------------------------------------------------------------------
+#   The logging record
+#---------------------------------------------------------------------------
+
+class LogRecord:
+    """
+    LogRecord instances are created every time something is logged. They
+    contain all the information pertinent to the event being logged. The
+    main information passed in is in msg and args, which are combined
+    using msg % args to create the message field of the record. The record
+    also includes information such as when the record was created, the
+    source line where the logging call was made, and any exception
+    information to be logged.
+    """
+    def __init__(self, name, lvl, pathname, lineno, msg, args, exc_info):
+        """
+        Initialize a logging record with interesting information.
+        """
+        ct = time.time()
+        self.name = name
+        self.msg = msg
+        self.args = args
+        self.levelname = getLevelName(lvl)
+        self.levelno = lvl
+        self.pathname = pathname
+        try:
+            self.filename = os.path.basename(pathname)
+            self.module = os.path.splitext(self.filename)[0]
+        except:
+            self.filename = pathname
+            self.module = "Unknown module"
+        self.exc_info = exc_info
+        self.lineno = lineno
+        self.created = ct
+        self.msecs = (ct - long(ct)) * 1000
+        self.relativeCreated = (self.created - _startTime) * 1000
+        if thread:
+            self.thread = thread.get_ident()
+        else:
+            self.thread = None
+
+    def __str__(self):
+        return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
+            self.pathname, self.lineno, self.msg)
+
+    def getMessage(self):
+        """
+        Return the message for this LogRecord, merging any user-supplied
+        arguments with the message.
+        """
+        msg = str(self.msg)
+        if self.args:
+            msg = msg % self.args
+        return msg
+
+#---------------------------------------------------------------------------
+#   Formatter classes and functions
+#---------------------------------------------------------------------------
+
+class Formatter:
+    """
+    Formatters need to know how a LogRecord is constructed. They are
+    responsible for converting a LogRecord to (usually) a string which can
+    be interpreted by either a human or an external system. The base Formatter
+    allows a formatting string to be specified. If none is supplied, the
+    default value of "%s(message)\\n" is used.
+
+    The Formatter can be initialized with a format string which makes use of
+    knowledge of the LogRecord attributes - e.g. the default value mentioned
+    above makes use of the fact that the user's message and arguments are pre-
+    formatted into a LogRecord's message attribute. Currently, the useful
+    attributes in a LogRecord are described by:
+
+    %(name)s            Name of the logger (logging channel)
+    %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
+                        WARN, ERROR, CRITICAL)
+    %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
+                        "WARN", "ERROR", "CRITICAL")
+    %(pathname)s        Full pathname of the source file where the logging
+                        call was issued (if available)
+    %(filename)s        Filename portion of pathname
+    %(module)s          Module (name portion of filename)
+    %(lineno)d          Source line number where the logging call was issued
+                        (if available)
+    %(created)f         Time when the LogRecord was created (time.time()
+                        return value)
+    %(asctime)s         Textual time when the LogRecord was created
+    %(msecs)d           Millisecond portion of the creation time
+    %(relativeCreated)d Time in milliseconds when the LogRecord was created,
+                        relative to the time the logging module was loaded
+                        (typically at application startup time)
+    %(thread)d          Thread ID (if available)
+    %(message)s         The result of msg % args, computed just as the
+                        record is emitted
+    """
+    def __init__(self, fmt=None, datefmt=None):
+        """
+        Initialize the formatter either with the specified format string, or a
+        default as described above. Allow for specialized date formatting with
+        the optional datefmt argument (if omitted, you get the ISO8601 format).
+        """
+        if fmt:
+            self._fmt = fmt
+        else:
+            self._fmt = "%(message)s"
+        self.datefmt = datefmt
+
+    def formatTime(self, record, datefmt=None):
+        """
+        This method should be called from format() by a formatter which
+        wants to make use of a formatted time. This method can be overridden
+        in formatters to provide for any specific requirement, but the
+        basic behaviour is as follows: if datefmt (a string) is specified,
+        it is used with time.strftime() to format the creation time of the
+        record. Otherwise, the ISO8601 format is used. The resulting
+        string is returned.
+        """
+        ct = record.created
+        if datefmt:
+            s = time.strftime(datefmt, time.localtime(ct))
+        else:
+            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ct))
+            s = "%s,%03d" % (t, record.msecs)
+        return s
+
+    def formatException(self, ei):
+        """
+        Format the specified exception information as a string. This
+        default implementation just uses traceback.print_exception()
+        """
+        import traceback
+        sio = cStringIO.StringIO()
+        traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
+        s = sio.getvalue()
+        sio.close()
+        if s[-1] == "\n":
+            s = s[:-1]
+        return s
+
+    def format(self, record):
+        """
+        The record's attribute dictionary is used as the operand to a
+        string formatting operation which yields the returned string.
+        Before formatting the dictionary, a couple of preparatory steps
+        are carried out. The message attribute of the record is computed
+        using msg % args. If the formatting string contains "%(asctime)",
+        formatTime() is called to format the event time. If there is
+        exception information, it is formatted using formatException()
+        and appended to the message.
+        """
+        record.message = record.getMessage()
+        if string.find(self._fmt,"%(asctime)") >= 0:
+            record.asctime = self.formatTime(record, self.datefmt)
+        s = self._fmt % record.__dict__
+        if record.exc_info:
+            if s[-1] != "\n":
+                s = s + "\n"
+            s = s + self.formatException(record.exc_info)
+        return s
+
+#
+#   The default formatter to use when no other is specified
+#
+_defaultFormatter = Formatter()
+
+class BufferingFormatter:
+    """
+    A formatter suitable for formatting a number of records.
+    """
+    def __init__(self, linefmt=None):
+        """
+        Optionally specify a formatter which will be used to format each
+        individual record.
+        """
+        if linefmt:
+            self.linefmt = linefmt
+        else:
+            self.linefmt = _defaultFormatter
+
+    def formatHeader(self, records):
+        """
+        Return the header string for the specified records.
+        """
+        return ""
+
+    def formatFooter(self, records):
+        """
+        Return the footer string for the specified records.
+        """
+        return ""
+
+    def format(self, records):
+        """
+        Format the specified records and return the result as a string.
+        """
+        rv = ""
+        if len(records) > 0:
+            rv = rv + self.formatHeader(records)
+            for record in records:
+                rv = rv + self.linefmt.format(record)
+            rv = rv + self.formatFooter(records)
+        return rv
+
+#---------------------------------------------------------------------------
+#   Filter classes and functions
+#---------------------------------------------------------------------------
+
+class Filter:
+    """
+    The base filter class. Loggers and Handlers can optionally use Filter
+    instances to filter records as desired. The base filter class only allows
+    events which are below a certain point in the logger hierarchy. For
+    example, a filter initialized with "A.B" will allow events logged by
+    loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B"
+    etc. If initialized with the empty string, all events are passed.
+    """
+    def __init__(self, name=''):
+        """
+        Initialize with the name of the logger which, together with its
+        children, will have its events allowed through the filter. If no
+        name is specified, allow every event.
+        """
+        self.name = name
+        self.nlen = len(name)
+
+    def filter(self, record):
+        """
+        Is the specified record to be logged? Returns 0 for no, nonzero for
+        yes. If deemed appropriate, the record may be modified in-place.
+        """
+        if self.nlen == 0:
+            return 1
+        elif self.name == record.name:
+            return 1
+        elif string.find(record.name, self.name, 0, self.nlen) != 0:
+            return 0
+        return (record.name[self.nlen] == ".")
+
+class Filterer:
+    """
+    A base class for loggers and handlers which allows them to share
+    common code.
+    """
+    def __init__(self):
+        """
+        Initialize the list of filters to be an empty list.
+        """
+        self.filters = []
+
+    def addFilter(self, filter):
+        """
+        Add the specified filter to this handler.
+        """
+        if not (filter in self.filters):
+            self.filters.append(filter)
+
+    def removeFilter(self, filter):
+        """
+        Remove the specified filter from this handler.
+        """
+        if filter in self.filters:
+            self.filters.remove(filter)
+
+    def filter(self, record):
+        """
+        Determine if a record is loggable by consulting all the filters. The
+        default is to allow the record to be logged; any filter can veto this
+        and the record is then dropped. Returns a boolean value.
+        """
+        rv = 1
+        for f in self.filters:
+            if not f.filter(record):
+                rv = 0
+                break
+        return rv
+
+#---------------------------------------------------------------------------
+#   Handler classes and functions
+#---------------------------------------------------------------------------
+
+_handlers = {}  #repository of handlers (for flushing when shutdown called)
+
+class Handler(Filterer):
+    """
+    The base handler class. Acts as a placeholder which defines the Handler
+    interface. Handlers can optionally use Formatter instances to format
+    records as desired. By default, no formatter is specified; in this case,
+    the 'raw' message as determined by record.message is logged.
+    """
+    def __init__(self, level=ALL):
+        """
+        Initializes the instance - basically setting the formatter to None
+        and the filter list to empty.
+        """
+        Filterer.__init__(self)
+        self.level = level
+        self.formatter = None
+        #get the module data lock, as we're updating a shared structure.
+        _acquireLock()
+        try:    #unlikely to raise an exception, but you never know...
+            _handlers[self] = 1
+        finally:
+            _releaseLock()
+        self.createLock()
+
+    def createLock(self):
+        """
+        Acquire a thread lock for serializing access to the underlying I/O.
+        """
+        if thread:
+            self.lock = thread.allocate_lock()
+        else:
+            self.lock = None
+
+    def acquire(self):
+        """
+        Acquire the I/O thread lock.
+        """
+        if self.lock:
+            self.lock.acquire()
+
+    def release(self):
+        """
+        Release the I/O thread lock.
+        """
+        if self.lock:
+            self.lock.release()
+
+    def setLevel(self, lvl):
+        """
+        Set the logging level of this handler.
+        """
+        self.level = lvl
+
+    def format(self, record):
+        """
+        Do formatting for a record - if a formatter is set, use it.
+        Otherwise, use the default formatter for the module.
+        """
+        if self.formatter:
+            fmt = self.formatter
+        else:
+            fmt = _defaultFormatter
+        return fmt.format(record)
+
+    def emit(self, record):
+        """
+        Do whatever it takes to actually log the specified logging record.
+        This version is intended to be implemented by subclasses and so
+        raises a NotImplementedError.
+        """
+        raise NotImplementedError, 'emit must be implemented '\
+                                    'by Handler subclasses'
+
+    def handle(self, record):
+        """
+        Conditionally emit the specified logging record, depending on
+        filters which may have been added to the handler. Wrap the actual
+        emission of the record with acquisition/release of the I/O thread
+        lock.
+        """
+        if self.filter(record):
+            self.acquire()
+            try:
+                self.emit(record)
+            finally:
+                self.release()
+
+    def setFormatter(self, fmt):
+        """
+        Set the formatter for this handler.
+        """
+        self.formatter = fmt
+
+    def flush(self):
+        """
+        Ensure all logging output has been flushed. This version does
+        nothing and is intended to be implemented by subclasses.
+        """
+        pass
+
+    def close(self):
+        """
+        Tidy up any resources used by the handler. This version does
+        nothing and is intended to be implemented by subclasses.
+        """
+        pass
+
+    def handleError(self):
+        """
+        This method should be called from handlers when an exception is
+        encountered during an emit() call. By default it does nothing,
+        which means that exceptions get silently ignored. This is what is
+        mostly wanted for a logging system - most users will not care
+        about errors in the logging system, they are more interested in
+        application errors. You could, however, replace this with a custom
+        handler if you wish.
+        """
+        #import traceback
+        #ei = sys.exc_info()
+        #traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
+        #del ei
+        pass
+
+class StreamHandler(Handler):
+    """
+    A handler class which writes logging records, appropriately formatted,
+    to a stream. Note that this class does not close the stream, as
+    sys.stdout or sys.stderr may be used.
+    """
+    def __init__(self, strm=None):
+        """
+        If strm is not specified, sys.stderr is used.
+        """
+        Handler.__init__(self)
+        if not strm:
+            strm = sys.stderr
+        self.stream = strm
+        self.formatter = None
+
+    def flush(self):
+        """
+        Flushes the stream.
+        """
+        self.stream.flush()
+
+    def emit(self, record):
+        """
+        If a formatter is specified, it is used to format the record.
+        The record is then written to the stream with a trailing newline
+        [N.B. this may be removed depending on feedback]. If exception
+        information is present, it is formatted using
+        traceback.print_exception and appended to the stream.
+        """
+        try:
+            msg = self.format(record)
+            self.stream.write("%s\n" % msg)
+            self.flush()
+        except:
+            self.handleError()
+
+class FileHandler(StreamHandler):
+    """
+    A handler class which writes formatted logging records to disk files.
+    """
+    def __init__(self, filename, mode="a+"):
+        """
+        Open the specified file and use it as the stream for logging.
+        By default, the file grows indefinitely. You can call setRollover()
+        to allow the file to rollover at a predetermined size.
+        """
+        StreamHandler.__init__(self, open(filename, mode))
+        self.maxBytes = 0
+        self.backupCount = 0
+        self.baseFilename = filename
+        #self.backupIndex = 0
+        self.mode = mode
+
+    def setRollover(self, maxBytes, backupCount):
+        """
+        Set the rollover parameters so that rollover occurs whenever the
+        current log file is nearly maxBytes in length. If backupCount
+        is >= 1, the system will successively create new files with the
+        same pathname as the base file, but with extensions ".1", ".2"
+        etc. appended to it. For example, with a backupCount of 5 and a
+        base file name of "app.log", you would get "app.log", "app.log.1",
+        "app.log.2", ... through to "app.log.5". When the last file reaches
+        its size limit, the logging reverts to "app.log" which is truncated
+        to zero length. If maxBytes is zero, rollover never occurs.
+        """
+        self.maxBytes = maxBytes
+        self.backupCount = backupCount
+        if maxBytes > 0:
+            self.mode = "a+"
+
+    def doRollover(self):
+        """
+        Do a rollover, as described in setRollover().
+        """
+#       Old algorithm
+#        if self.backupIndex >= self.backupCount:
+#            self.backupIndex = 0
+#            fn = self.baseFilename
+#        else:
+#            self.backupIndex = self.backupIndex + 1
+#            fn = "%s.%d" % (self.baseFilename, self.backupIndex)
+#        self.stream.close()
+#        self.stream = open(fn, "w+")
+        self.stream.close()
+        if self.backupCount > 0:
+            for i in range(self.backupCount - 1, 0, -1):
+                sfn = "%s.%d" % (self.baseFilename, i)
+                dfn = "%s.%d" % (self.baseFilename, i + 1)
+                if os.path.exists(sfn):
+                    #print "%s -> %s" % (sfn, dfn)
+                    if os.path.exists(dfn):
+                        os.remove(dfn)
+                    os.rename(sfn, dfn)
+            dfn = self.baseFilename + ".1"
+            if os.path.exists(dfn):
+                os.remove(dfn)
+            os.rename(self.baseFilename, dfn)
+        self.stream = open(self.baseFilename, "w+")
+
+    def emit(self, record):
+        """
+        Output the record to the file, catering for rollover as described
+        in setRollover().
+        """
+        if self.maxBytes > 0:                   # are we rolling over?
+            msg = "%s\n" % self.format(record)
+            if self.stream.tell() + len(msg) >= self.maxBytes:
+                self.doRollover()
+        StreamHandler.emit(self, record)
+
+    def close(self):
+        """
+        Closes the stream.
+        """
+        self.stream.close()
+
+class SocketHandler(Handler):
+    """
+    A handler class which writes logging records, in pickle format, to
+    a streaming socket. The socket is kept open across logging calls.
+    If the peer resets it, an attempt is made to reconnect on the next call.
+    Note that the very simple wire protocol used means that packet sizes
+    are expected to be encodable within 16 bits (i.e. < 32767 bytes).
+    """
+
+    def __init__(self, host, port):
+        """
+        Initializes the handler with a specific host address and port.
+        """
+        Handler.__init__(self)
+        self.host = host
+        self.port = port
+        self.sock = None
+        self.closeOnError = 1
+
+    def makeSocket(self):
+        """
+        A factory method which allows subclasses to define the precise
+        type of socket they want.
+        """
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((self.host, self.port))
+        return s
+
+    def send(self, s):
+        """
+        Send a pickled string to the socket. This function allows for
+        partial sends which can happen when the network is busy.
+        """
+        sentsofar = 0
+        left = len(s)
+        while left > 0:
+            sent = self.sock.send(s[sentsofar:])
+            sentsofar = sentsofar + sent
+            left = left - sent
+
+    def makePickle(self, record):
+        """
+        Pickles the record in binary format with a length prefix, and
+        returns it ready for transmission across the socket.
+        """
+        s = cPickle.dumps(record.__dict__, 1)
+        n = len(s)
+        slen = "%c%c" % ((n >> 8) & 0xFF, n & 0xFF)
+        return slen + s
+
+    def handleError(self):
+        """
+        An error has occurred during logging. Most likely cause -
+        connection lost. Close the socket so that we can retry on the
+        next event.
+        """
+        if self.closeOnError and self.sock:
+            self.sock.close()
+            self.sock = None        #try to reconnect next time
+
+    def emit(self, record):
+        """
+        Pickles the record and writes it to the socket in binary format.
+        If there is an error with the socket, silently drop the packet.
+        If there was a problem with the socket, re-establishes the
+        socket.
+        """
+        try:
+            s = self.makePickle(record)
+            if not self.sock:
+                self.sock = self.makeSocket()
+            self.send(s)
+        except:
+            self.handleError()
+
+    def close(self):
+        """
+        Closes the socket.
+        """
+        if self.sock:
+            self.sock.close()
+            self.sock = None
+
+class DatagramHandler(SocketHandler):
+    """
+    A handler class which writes logging records, in pickle format, to
+    a datagram socket. Note that the very simple wire protocol used means
+    that packet sizes are expected to be encodable within 16 bits
+    (i.e. < 32767 bytes).
+
+    """
+    def __init__(self, host, port):
+        """
+        Initializes the handler with a specific host address and port.
+        """
+        SocketHandler.__init__(self, host, port)
+        self.closeOnError = 0
+
+    def makeSocket(self):
+        """
+        The factory method of SocketHandler is here overridden to create
+        a UDP socket (SOCK_DGRAM).
+        """
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        return s
+
+    def send(self, s):
+        """
+        Send a pickled string to a socket. This function allows for
+        partial sends which can happen when the network is busy.
+        """
+        sentsofar = 0
+        left = len(s)
+        addr = (self.host, self.port)
+        while left > 0:
+            sent = self.sock.sendto(s[sentsofar:], addr)
+            sentsofar = sentsofar + sent
+            left = left - sent
+
+class SysLogHandler(Handler):
+    """
+    A handler class which sends formatted logging records to a syslog
+    server. Based on Sam Rushing's syslog module:
+    http://www.nightmare.com/squirl/python-ext/misc/syslog.py
+    Contributed by Nicolas Untz (after which minor refactoring changes
+    have been made).
+    """
+
+    # from <linux/sys/syslog.h>:
+    # ======================================================================
+    # priorities/facilities are encoded into a single 32-bit quantity, where
+    # the bottom 3 bits are the priority (0-7) and the top 28 bits are the
+    # facility (0-big number). Both the priorities and the facilities map
+    # roughly one-to-one to strings in the syslogd(8) source code.  This
+    # mapping is included in this file.
+    #
+    # priorities (these are ordered)
+
+    LOG_EMERG     = 0       #  system is unusable
+    LOG_ALERT     = 1       #  action must be taken immediately
+    LOG_CRIT      = 2       #  critical conditions
+    LOG_ERR       = 3       #  error conditions
+    LOG_WARNING   = 4       #  warning conditions
+    LOG_NOTICE    = 5       #  normal but significant condition
+    LOG_INFO      = 6       #  informational
+    LOG_DEBUG     = 7       #  debug-level messages
+
+    #  facility codes
+    LOG_KERN      = 0       #  kernel messages
+    LOG_USER      = 1       #  random user-level messages
+    LOG_MAIL      = 2       #  mail system
+    LOG_DAEMON    = 3       #  system daemons
+    LOG_AUTH      = 4       #  security/authorization messages
+    LOG_SYSLOG    = 5       #  messages generated internally by syslogd
+    LOG_LPR       = 6       #  line printer subsystem
+    LOG_NEWS      = 7       #  network news subsystem
+    LOG_UUCP      = 8       #  UUCP subsystem
+    LOG_CRON      = 9       #  clock daemon
+    LOG_AUTHPRIV  = 10  #  security/authorization messages (private)
+
+    #  other codes through 15 reserved for system use
+    LOG_LOCAL0    = 16      #  reserved for local use
+    LOG_LOCAL1    = 17      #  reserved for local use
+    LOG_LOCAL2    = 18      #  reserved for local use
+    LOG_LOCAL3    = 19      #  reserved for local use
+    LOG_LOCAL4    = 20      #  reserved for local use
+    LOG_LOCAL5    = 21      #  reserved for local use
+    LOG_LOCAL6    = 22      #  reserved for local use
+    LOG_LOCAL7    = 23      #  reserved for local use
+
+    priority_names = {
+        "alert":    LOG_ALERT,
+        "crit":     LOG_CRIT,
+        "critical": LOG_CRIT,
+        "debug":    LOG_DEBUG,
+        "emerg":    LOG_EMERG,
+        "err":      LOG_ERR,
+        "error":    LOG_ERR,        #  DEPRECATED
+        "info":     LOG_INFO,
+        "notice":   LOG_NOTICE,
+        "panic":    LOG_EMERG,      #  DEPRECATED
+        "warn":     LOG_WARNING,    #  DEPRECATED
+        "warning":  LOG_WARNING,
+        }
+
+    facility_names = {
+        "auth":     LOG_AUTH,
+        "authpriv": LOG_AUTHPRIV,
+        "cron":     LOG_CRON,
+        "daemon":   LOG_DAEMON,
+        "kern":     LOG_KERN,
+        "lpr":      LOG_LPR,
+        "mail":     LOG_MAIL,
+        "news":     LOG_NEWS,
+        "security": LOG_AUTH,       #  DEPRECATED
+        "syslog":   LOG_SYSLOG,
+        "user":     LOG_USER,
+        "uucp":     LOG_UUCP,
+        "local0":   LOG_LOCAL0,
+        "local1":   LOG_LOCAL1,
+        "local2":   LOG_LOCAL2,
+        "local3":   LOG_LOCAL3,
+        "local4":   LOG_LOCAL4,
+        "local5":   LOG_LOCAL5,
+        "local6":   LOG_LOCAL6,
+        "local7":   LOG_LOCAL7,
+        }
+
+    def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER):
+        """
+        If address is specified as a string, UNIX socket is used.
+        If facility is not specified, LOG_USER is used.
+        """
+        Handler.__init__(self)
+
+        self.address = address
+        self.facility = facility
+        if type(address) == types.StringType:
+            self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            self.socket.connect(address)
+            self.unixsocket = 1
+        else:
+            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+            self.unixsocket = 0
+
+        self.formatter = None
+
+    # curious: when talking to the unix-domain '/dev/log' socket, a
+    #   zero-terminator seems to be required.  this string is placed
+    #   into a class variable so that it can be overridden if
+    #   necessary.
+    log_format_string = '<%d>%s\000'
+
+    def encodePriority (self, facility, priority):
+        """
+        Encode the facility and priority. You can pass in strings or
+        integers - if strings are passed, the facility_names and
+        priority_names mapping dictionaries are used to convert them to
+        integers.
+        """
+        if type(facility) == types.StringType:
+            facility = self.facility_names[facility]
+        if type(priority) == types.StringType:
+            priority = self.priority_names[priority]
+        return (facility << 3) | priority
+
+    def close (self):
+        """
+        Closes the socket.
+        """
+        if self.unixsocket:
+            self.socket.close()
+
+    def emit(self, record):
+        """
+        The record is formatted, and then sent to the syslog server. If
+        exception information is present, it is NOT sent to the server.
+        """
+        msg = self.format(record)
+        """
+        We need to convert record level to lowercase, maybe this will
+        change in the future.
+        """
+        msg = self.log_format_string % (
+            self.encodePriority(self.facility,
+                                string.lower(record.levelname)),
+            msg)
+        try:
+            if self.unixsocket:
+                self.socket.send(msg)
+            else:
+                self.socket.sendto(msg, self.address)
+        except:
+            self.handleError()
+
+class SMTPHandler(Handler):
+    """
+    A handler class which sends an SMTP email for each logging event.
+    """
+    def __init__(self, mailhost, fromaddr, toaddrs, subject):
+        """
+        Initialize the instance with the from and to addresses and subject
+        line of the email. To specify a non-standard SMTP port, use the
+        (host, port) tuple format for the mailhost argument.
+        """
+        Handler.__init__(self)
+        if type(mailhost) == types.TupleType:
+            host, port = mailhost
+            self.mailhost = host
+            self.mailport = port
+        else:
+            self.mailhost = mailhost
+            self.mailport = None
+        self.fromaddr = fromaddr
+        self.toaddrs = toaddrs
+        self.subject = subject
+
+    def getSubject(self, record):
+        """
+        If you want to specify a subject line which is record-dependent,
+        override this method.
+        """
+        return self.subject
+
+    def emit(self, record):
+        """
+        Format the record and send it to the specified addressees.
+        """
+        try:
+            import smtplib
+            port = self.mailport
+            if not port:
+                port = smtplib.SMTP_PORT
+            smtp = smtplib.SMTP(self.mailhost, port)
+            msg = self.format(record)
+            msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % (
+                            self.fromaddr,
+                            string.join(self.toaddrs, ","),
+                            self.getSubject(record), msg
+                            )
+            smtp.sendmail(self.fromaddr, self.toaddrs, msg)
+            smtp.quit()
+        except:
+            self.handleError()
+
+class BufferingHandler(Handler):
+    """
+  A handler class which buffers logging records in memory. Whenever each
+  record is added to the buffer, a check is made to see if the buffer should
+  be flushed. If it should, then flush() is expected to do the needful.
+    """
+    def __init__(self, capacity):
+        """
+        Initialize the handler with the buffer size.
+        """
+        Handler.__init__(self)
+        self.capacity = capacity
+        self.buffer = []
+
+    def shouldFlush(self, record):
+        """
+        Returns true if the buffer is up to capacity. This method can be
+        overridden to implement custom flushing strategies.
+        """
+        return (len(self.buffer) >= self.capacity)
+
+    def emit(self, record):
+        """
+        Append the record. If shouldFlush() tells us to, call flush() to process
+        the buffer.
+        """
+        self.buffer.append(record)
+        if self.shouldFlush(record):
+            self.flush()
+
+    def flush(self):
+        """
+        Override to implement custom flushing behaviour. This version just zaps
+        the buffer to empty.
+        """
+        self.buffer = []
+
+class MemoryHandler(BufferingHandler):
+    """
+    A handler class which buffers logging records in memory, periodically
+    flushing them to a target handler. Flushing occurs whenever the buffer
+    is full, or when an event of a certain severity or greater is seen.
+    """
+    def __init__(self, capacity, flushLevel=ERROR, target=None):
+        """
+        Initialize the handler with the buffer size, the level at which
+        flushing should occur and an optional target. Note that without a
+        target being set either here or via setTarget(), a MemoryHandler
+        is no use to anyone!
+        """
+        BufferingHandler.__init__(self, capacity)
+        self.flushLevel = flushLevel
+        self.target = target
+
+    def shouldFlush(self, record):
+        """
+        Check for buffer full or a record at the flushLevel or higher.
+        """
+        return (len(self.buffer) >= self.capacity) or \
+                (record.levelno >= self.flushLevel)
+
+    def setTarget(self, target):
+        """
+        Set the target handler for this handler.
+        """
+        self.target = target
+
+    def flush(self):
+        """
+        For a MemoryHandler, flushing means just sending the buffered
+        records to the target, if there is one. Override if you want
+        different behaviour.
+        """
+        if self.target:
+            for record in self.buffer:
+                self.target.handle(record)
+            self.buffer = []
+
+    def close(self):
+        """
+        Flush, set the target to None and lose the buffer.
+        """
+        self.flush()
+        self.target = None
+        self.buffer = []
+
+class NTEventLogHandler(Handler):
+    """
+    A handler class which sends events to the NT Event Log. Adds a
+    registry entry for the specified application name. If no dllname is
+    provided, win32service.pyd (which contains some basic message
+    placeholders) is used. Note that use of these placeholders will make
+    your event logs big, as the entire message source is held in the log.
+    If you want slimmer logs, you have to pass in the name of your own DLL
+    which contains the message definitions you want to use in the event log.
+    """
+    def __init__(self, appname, dllname=None, logtype="Application"):
+        Handler.__init__(self)
+        try:
+            import win32evtlogutil, win32evtlog
+            self.appname = appname
+            self._welu = win32evtlogutil
+            if not dllname:
+                dllname = os.path.split(self._welu.__file__)
+                dllname = os.path.split(dllname[0])
+                dllname = os.path.join(dllname[0], r'win32service.pyd')
+            self.dllname = dllname
+            self.logtype = logtype
+            self._welu.AddSourceToRegistry(appname, dllname, logtype)
+            self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE
+            self.typemap = {
+                DEBUG   : win32evtlog.EVENTLOG_INFORMATION_TYPE,
+                INFO    : win32evtlog.EVENTLOG_INFORMATION_TYPE,
+                WARN    : win32evtlog.EVENTLOG_WARNING_TYPE,
+                ERROR   : win32evtlog.EVENTLOG_ERROR_TYPE,
+                CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE,
+         }
+        except ImportError:
+            print "The Python Win32 extensions for NT (service, event "\
+                        "logging) appear not to be available."
+            self._welu = None
+
+    def getMessageID(self, record):
+        """
+        Return the message ID for the event record. If you are using your
+        own messages, you could do this by having the msg passed to the
+        logger being an ID rather than a formatting string. Then, in here,
+        you could use a dictionary lookup to get the message ID. This
+        version returns 1, which is the base message ID in win32service.pyd.
+        """
+        return 1
+
+    def getEventCategory(self, record):
+        """
+        Return the event category for the record. Override this if you
+        want to specify your own categories. This version returns 0.
+        """
+        return 0
+
+    def getEventType(self, record):
+        """
+        Return the event type for the record. Override this if you want
+        to specify your own types. This version does a mapping using the
+        handler's typemap attribute, which is set up in __init__() to a
+        dictionary which contains mappings for DEBUG, INFO, WARN, ERROR
+        and CRITICAL. If you are using your own levels you will either need
+        to override this method or place a suitable dictionary in the
+        handler's typemap attribute.
+        """
+        return self.typemap.get(record.levelno, self.deftype)
+
+    def emit(self, record):
+        """
+        Determine the message ID, event category and event type. Then
+        log the message in the NT event log.
+        """
+        if self._welu:
+            try:
+                id = self.getMessageID(record)
+                cat = self.getEventCategory(record)
+                type = self.getEventType(record)
+                msg = self.format(record)
+                self._welu.ReportEvent(self.appname, id, cat, type, [msg])
+            except:
+                self.handleError()
+
+    def close(self):
+        """
+        You can remove the application name from the registry as a
+        source of event log entries. However, if you do this, you will
+        not be able to see the events as you intended in the Event Log
+        Viewer - it needs to be able to access the registry to get the
+        DLL name.
+        """
+        #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype)
+        pass
+
+class HTTPHandler(Handler):
+    """
+    A class which sends records to a Web server, using either GET or
+    POST semantics.
+    """
+    def __init__(self, host, url, method="GET"):
+        """
+        Initialize the instance with the host, the request URL, and the method
+        ("GET" or "POST")
+        """
+        Handler.__init__(self)
+        method = string.upper(method)
+        if method not in ["GET", "POST"]:
+            raise ValueError, "method must be GET or POST"
+        self.host = host
+        self.url = url
+        self.method = method
+
+    def emit(self, record):
+        """
+        Send the record to the Web server as an URL-encoded dictionary
+        """
+        try:
+            import httplib, urllib
+            h = httplib.HTTP(self.host)
+            url = self.url
+            data = urllib.urlencode(record.__dict__)
+            if self.method == "GET":
+                if (string.find(url, '?') >= 0):
+                    sep = '&'
+                else:
+                    sep = '?'
+                url = url + "%c%s" % (sep, data)
+            h.putrequest(self.method, url)
+            if self.method == "POST":
+                h.putheader("Content-length", str(len(data)))
+            h.endheaders()
+            if self.method == "POST":
+                h.send(data)
+            h.getreply()    #can't do anything with the result
+        except:
+            self.handleError()
+
+#---------------------------------------------------------------------------
+#   Manager classes and functions
+#---------------------------------------------------------------------------
+
+class PlaceHolder:
+    """
+    PlaceHolder instances are used in the Manager logger hierarchy to take
+    the place of nodes for which no loggers have been defined [FIXME add
+    example].
+    """
+    def __init__(self, alogger):
+        """
+        Initialize with the specified logger being a child of this placeholder.
+        """
+        self.loggers = [alogger]
+
+    def append(self, alogger):
+        """
+        Add the specified logger as a child of this placeholder.
+        """
+        if alogger not in self.loggers:
+            self.loggers.append(alogger)
+
+#
+#   Determine which class to use when instantiating loggers.
+#
+_loggerClass = None
+
+def setLoggerClass(klass):
+    """
+    Set the class to be used when instantiating a logger. The class should
+    define __init__() such that only a name argument is required, and the
+    __init__() should call Logger.__init__()
+    """
+    if klass != Logger:
+        if type(klass) != types.ClassType:
+            raise TypeError, "setLoggerClass is expecting a class"
+        if not issubclass(klass, Logger):
+            raise TypeError, "logger not derived from logging.Logger: " + \
+                            klass.__name__
+    global _loggerClass
+    _loggerClass = klass
+
+class Manager:
+    """
+    There is [under normal circumstances] just one Manager instance, which
+    holds the hierarchy of loggers.
+    """
+    def __init__(self, root):
+        """
+        Initialize the manager with the root node of the logger hierarchy.
+        """
+        self.root = root
+        self.disable = 0
+        self.emittedNoHandlerWarning = 0
+        self.loggerDict = {}
+
+    def getLogger(self, name):
+        """
+        Get a logger with the specified name, creating it if it doesn't
+        yet exist. If a PlaceHolder existed for the specified name [i.e.
+        the logger didn't exist but a child of it did], replace it with
+        the created logger and fix up the parent/child references which
+        pointed to the placeholder to now point to the logger.
+        """
+        rv = None
+        _acquireLock()
+        try:
+            if self.loggerDict.has_key(name):
+                rv = self.loggerDict[name]
+                if isinstance(rv, PlaceHolder):
+                    ph = rv
+                    rv = _loggerClass(name)
+                    rv.manager = self
+                    self.loggerDict[name] = rv
+                    self._fixupChildren(ph, rv)
+                    self._fixupParents(rv)
+            else:
+                rv = _loggerClass(name)
+                rv.manager = self
+                self.loggerDict[name] = rv
+                self._fixupParents(rv)
+        finally:
+            _releaseLock()
+        return rv
+
+    def _fixupParents(self, alogger):
+        """
+        Ensure that there are either loggers or placeholders all the way
+        from the specified logger to the root of the logger hierarchy.
+        """
+        name = alogger.name
+        i = string.rfind(name, ".")
+        rv = None
+        while (i > 0) and not rv:
+            substr = name[:i]
+            if not self.loggerDict.has_key(substr):
+                self.loggerDict[substr] = PlaceHolder(alogger)
+            else:
+                obj = self.loggerDict[substr]
+                if isinstance(obj, Logger):
+                    rv = obj
+                else:
+                    assert isinstance(obj, PlaceHolder)
+                    obj.append(alogger)
+            i = string.rfind(name, ".", 0, i - 1)
+        if not rv:
+            rv = self.root
+        alogger.parent = rv
+
+    def _fixupChildren(self, ph, alogger):
+        """
+        Ensure that children of the placeholder ph are connected to the
+        specified logger.
+        """
+        for c in ph.loggers:
+            if string.find(c.parent.name, alogger.name) <> 0:
+                alogger.parent = c.parent
+                c.parent = alogger
+
+#---------------------------------------------------------------------------
+#   Logger classes and functions
+#---------------------------------------------------------------------------
+
+class Logger(Filterer):
+    """
+    Instances of the Logger class represent a single logging channel. A
+    "logging channel" indicates an area of an application. Exactly how an
+    "area" is defined is up to the application developer. Since an
+    application can have any number of areas, logging channels are identified
+    by a unique string. Application areas can be nested (e.g. an area
+    of "input processing" might include sub-areas "read CSV files", "read
+    XLS files" and "read Gnumeric files"). To cater for this natural nesting,
+    channel names are organized into a namespace hierarchy where levels are
+    separated by periods, much like the Java or Python package namespace. So
+    in the instance given above, channel names might be "input" for the upper
+    level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
+    There is no arbitrary limit to the depth of nesting.
+    """
+    def __init__(self, name, level=ALL):
+        """
+        Initialize the logger with a name and an optional level.
+        """
+        Filterer.__init__(self)
+        self.name = name
+        self.level = level
+        self.parent = None
+        self.propagate = 1
+        self.handlers = []
+        self.disabled = 0
+
+    def setLevel(self, lvl):
+        """
+        Set the logging level of this logger.
+        """
+        self.level = lvl
+
+#   def getRoot(self):
+#       """
+#       Get the root of the logger hierarchy.
+#       """
+#       return Logger.root
+
+    def debug(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'DEBUG'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
+        """
+        if self.manager.disable >= DEBUG:
+            return
+        if DEBUG >= self.getEffectiveLevel():
+            apply(self._log, (DEBUG, msg, args), kwargs)
+
+    def info(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'INFO'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
+        """
+        if self.manager.disable >= INFO:
+            return
+        if INFO >= self.getEffectiveLevel():
+            apply(self._log, (INFO, msg, args), kwargs)
+
+    def warn(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'WARN'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.warn("Houston, we have a %s", "bit of a problem", exc_info=1)
+        """
+        if self.manager.disable >= WARN:
+            return
+        if self.isEnabledFor(WARN):
+            apply(self._log, (WARN, msg, args), kwargs)
+
+    def error(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'ERROR'. To pass exception information,
+        use the keyword argument exc_info with a true value, e.g.
+
+        logger.error("Houston, we have a %s", "major problem", exc_info=1)
+        """
+        if self.manager.disable >= ERROR:
+            return
+        if self.isEnabledFor(ERROR):
+            apply(self._log, (ERROR, msg, args), kwargs)
+
+    def exception(self, msg, *args):
+        """
+        Convenience method for logging an ERROR with exception information
+        """
+        apply(self.error, (msg,) + args, {'exc_info': 1})
+
+    def critical(self, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with severity 'CRITICAL'. To pass exception
+        information, use the keyword argument exc_info with a true value, e.g.
+
+        logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
+        """
+        if self.manager.disable >= CRITICAL:
+            return
+        if CRITICAL >= self.getEffectiveLevel():
+            apply(self._log, (CRITICAL, msg, args), kwargs)
+
+    fatal = critical
+
+    def log(self, lvl, msg, *args, **kwargs):
+        """
+        Log 'msg % args' with the severity 'lvl'. To pass exception
+        information, use the keyword argument exc_info with a true value, e.g.
+        logger.log(lvl, "We have a %s", "mysterious problem", exc_info=1)
+        """
+        if self.manager.disable >= lvl:
+            return
+        if self.isEnabledFor(lvl):
+            apply(self._log, (lvl, msg, args), kwargs)
+
+    def findCaller(self):
+        """
+        Find the stack frame of the caller so that we can note the source
+        file name and line number.
+        """
+        rv = (None, None)
+        frame = inspect.currentframe().f_back
+        while frame:
+            sfn = inspect.getsourcefile(frame)
+            if sfn:
+                sfn = os.path.normcase(sfn)
+            if sfn != _srcfile:
+                #print frame.f_code.co_code
+                lineno = inspect.getlineno(frame)
+                rv = (sfn, lineno)
+                break
+            frame = frame.f_back
+        return rv
+
+    def makeRecord(self, name, lvl, fn, lno, msg, args, exc_info):
+        """
+        A factory method which can be overridden in subclasses to create
+        specialized LogRecords.
+        """
+        return LogRecord(name, lvl, fn, lno, msg, args, exc_info)
+
+    def _log(self, lvl, msg, args, exc_info=None):
+        """
+        Low-level logging routine which creates a LogRecord and then calls
+        all the handlers of this logger to handle the record.
+        """
+        if inspect and _srcfile:
+            _acquireLock()
+            try:
+                fn, lno = self.findCaller()
+            finally:
+                _releaseLock()
+        else:
+            fn, lno = "<unknown file>", 0
+        if exc_info:
+            exc_info = sys.exc_info()
+        record = self.makeRecord(self.name, lvl, fn, lno, msg, args, exc_info)
+        self.handle(record)
+
+    def handle(self, record):
+        """
+        Call the handlers for the specified record. This method is used for
+        unpickled records received from a socket, as well as those created
+        locally. Logger-level filtering is applied.
+        """
+        if (not self.disabled) and self.filter(record):
+            self.callHandlers(record)
+
+    def addHandler(self, hdlr):
+        """
+        Add the specified handler to this logger.
+        """
+        if not (hdlr in self.handlers):
+            self.handlers.append(hdlr)
+
+    def removeHandler(self, hdlr):
+        """
+        Remove the specified handler from this logger.
+        """
+        if hdlr in self.handlers:
+            hdlr.close()
+            self.handlers.remove(hdlr)
+
+    def callHandlers(self, record):
+        """
+        Loop through all handlers for this logger and its parents in the
+        logger hierarchy. If no handler was found, output a one-off error
+        message to sys.stderr. Stop searching up the hierarchy whenever a
+        logger with the "propagate" attribute set to zero is found - that
+        will be the last logger whose handlers are called.
+        """
+        c = self
+        found = 0
+        while c:
+            for hdlr in c.handlers:
+                found = found + 1
+                if record.levelno >= hdlr.level:
+                    hdlr.handle(record)
+            if not c.propagate:
+                c = None    #break out
+            else:
+                c = c.parent
+        if (found == 0) and not self.manager.emittedNoHandlerWarning:
+            sys.stderr.write("No handlers could be found for logger"
+                             " \"%s\"\n" % self.name)
+            self.manager.emittedNoHandlerWarning = 1
+
+    def getEffectiveLevel(self):
+        """
+        Loop through this logger and its parents in the logger hierarchy,
+        looking for a non-zero logging level. Return the first one found.
+        """
+        logger = self
+        while logger:
+            if logger.level:
+                return logger.level
+            logger = logger.parent
+        return ALL
+
+    def isEnabledFor(self, lvl):
+        """
+        Is this logger enabled for level lvl?
+        """
+        if self.manager.disable >= lvl:
+            return 0
+        return lvl >= self.getEffectiveLevel()
+
+class RootLogger(Logger):
+    """
+    A root logger is not that different to any other logger, except that
+    it must have a logging level and there is only one instance of it in
+    the hierarchy.
+    """
+    def __init__(self, lvl):
+        """
+        Initialize the logger with the name "root".
+        """
+        Logger.__init__(self, "root", lvl)
+
+_loggerClass = Logger
+
+root = RootLogger(DEBUG)
+Logger.root = root
+Logger.manager = Manager(Logger.root)
+
+#---------------------------------------------------------------------------
+# Configuration classes and functions
+#---------------------------------------------------------------------------
+
+BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
+
+def basicConfig():
+    """
+    Do basic configuration for the logging system by creating a
+    StreamHandler with a default Formatter and adding it to the
+    root logger.
+    """
+    if len(root.handlers) == 0:
+        hdlr = StreamHandler()
+        fmt = Formatter(BASIC_FORMAT)
+        hdlr.setFormatter(fmt)
+        root.addHandler(hdlr)
+
+def fileConfig(fname):
+    """
+    Read the logging configuration from a ConfigParser-format file. This can
+    be called several times from an application, allowing an end user the
+    ability to select from various pre-canned configurations (if the
+    developer provides a mechanism to present the choices and load the chosen
+    configuration).
+    """
+    import ConfigParser
+
+    cp = ConfigParser.ConfigParser()
+    cp.read(fname)
+    #first, do the formatters...
+    flist = cp.get("formatters", "keys")
+    if len(flist):
+        flist = string.split(flist, ",")
+        formatters = {}
+        for form in flist:
+            sectname = "formatter_%s" % form
+            opts = cp.options(sectname)
+            if "format" in opts:
+                fs = cp.get(sectname, "format", 1)
+            else:
+                fs = None
+            if "datefmt" in opts:
+                dfs = cp.get(sectname, "datefmt", 1)
+            else:
+                dfs = None
+            f = Formatter(fs, dfs)
+            formatters[form] = f
+    #next, do the handlers...
+    #critical section...
+    _acquireLock()
+    try:
+        try:
+            #first, lose the existing handlers...
+            _handlers.clear()
+            #now set up the new ones...
+            hlist = cp.get("handlers", "keys")
+            if len(hlist):
+                hlist = string.split(hlist, ",")
+                handlers = {}
+                fixups = [] #for inter-handler references
+                for hand in hlist:
+                    sectname = "handler_%s" % hand
+                    klass = cp.get(sectname, "class")
+                    opts = cp.options(sectname)
+                    if "formatter" in opts:
+                        fmt = cp.get(sectname, "formatter")
+                    else:
+                        fmt = ""
+                    klass = eval(klass)
+                    args = cp.get(sectname, "args")
+                    args = eval(args)
+                    h = apply(klass, args)
+                    if "level" in opts:
+                        lvl = cp.get(sectname, "level")
+                        h.setLevel(_levelNames[lvl])
+                    if len(fmt):
+                        h.setFormatter(formatters[fmt])
+                    #temporary hack for FileHandler and MemoryHandler.
+                    if klass == FileHandler:
+                        maxsize = 0
+                        if "maxsize" in opts:
+                            ms = cp.getint(sectname, "maxsize")
+                            if ms > 0:
+                                maxsize = ms
+                        if maxsize:
+                            backcount = 0
+                            if "backcount" in opts:
+                                bc = cp.getint(sectname, "backcount")
+                                if bc > 0:
+                                    backcount = bc
+                            h.setRollover(maxsize, backcount)
+                    elif klass == MemoryHandler:
+                        if "target" in opts:
+                            target = cp.get(sectname,"target")
+                        else:
+                            target = ""
+                        if len(target): #the target handler may not be loaded yet, so keep for later...
+                            fixups.append((h, target))
+                    handlers[hand] = h
+                #now all handlers are loaded, fixup inter-handler references...
+                for fixup in fixups:
+                    h = fixup[0]
+                    t = fixup[1]
+                    h.setTarget(handlers[t])
+            #at last, the loggers...first the root...
+            llist = cp.get("loggers", "keys")
+            llist = string.split(llist, ",")
+            llist.remove("root")
+            sectname = "logger_root"
+            log = root
+            opts = cp.options(sectname)
+            if "level" in opts:
+                lvl = cp.get(sectname, "level")
+                log.setLevel(_levelNames[lvl])
+            for h in root.handlers:
+                root.removeHandler(h)
+            hlist = cp.get(sectname, "handlers")
+            if len(hlist):
+                hlist = string.split(hlist, ",")
+                for hand in hlist:
+                    log.addHandler(handlers[hand])
+            #and now the others...
+            #we don't want to lose the existing loggers,
+            #since other threads may have pointers to them.
+            #existing is set to contain all existing loggers,
+            #and as we go through the new configuration we
+            #remove any which are configured. At the end,
+            #what's left in existing is the set of loggers
+            #which were in the previous configuration but
+            #which are not in the new configuration.
+            existing = root.manager.loggerDict.keys()
+            #now set up the new ones...
+            for log in llist:
+                sectname = "logger_%s" % log
+                qn = cp.get(sectname, "qualname")
+                opts = cp.options(sectname)
+                if "propagate" in opts:
+                    propagate = cp.getint(sectname, "propagate")
+                else:
+                    propagate = 1
+                logger = getLogger(qn)
+                if qn in existing:
+                    existing.remove(qn)
+                if "level" in opts:
+                    lvl = cp.get(sectname, "level")
+                    logger.setLevel(_levelNames[lvl])
+                for h in logger.handlers:
+                    logger.removeHandler(h)
+                logger.propagate = propagate
+                logger.disabled = 0
+                hlist = cp.get(sectname, "handlers")
+                if len(hlist):
+                    hlist = string.split(hlist, ",")
+                    for hand in hlist:
+                        logger.addHandler(handlers[hand])
+            #Disable any old loggers. There's no point deleting
+            #them as other threads may continue to hold references
+            #and by disabling them, you stop them doing any logging.
+            for log in existing:
+                root.manager.loggerDict[log].disabled = 1
+        except:
+            import traceback
+            ei = sys.exc_info()
+            traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
+            del ei
+    finally:
+        _releaseLock()
+
+#---------------------------------------------------------------------------
+# Utility functions at module level.
+# Basically delegate everything to the root logger.
+#---------------------------------------------------------------------------
+
+def getLogger(name=None):
+    """
+    Return a logger with the specified name, creating it if necessary.
+    If no name is specified, return the root logger.
+    """
+    if name:
+        return Logger.manager.getLogger(name)
+    else:
+        return root
+
+def getRootLogger():
+    """
+    Return the root logger. Note that getLogger('') now does the same thing,
+    so this function is deprecated and may disappear in the future.
+    """
+    return root
+
+def critical(msg, *args, **kwargs):
+    """
+    Log a message with severity 'CRITICAL' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.critical, (msg,)+args, kwargs)
+
+fatal = critical
+
+def error(msg, *args, **kwargs):
+    """
+    Log a message with severity 'ERROR' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.error, (msg,)+args, kwargs)
+
+def exception(msg, *args):
+    """
+    Log a message with severity 'ERROR' on the root logger,
+    with exception information.
+    """
+    apply(error, (msg,)+args, {'exc_info': 1})
+
+def warn(msg, *args, **kwargs):
+    """
+    Log a message with severity 'WARN' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.warn, (msg,)+args, kwargs)
+
+def info(msg, *args, **kwargs):
+    """
+    Log a message with severity 'INFO' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.info, (msg,)+args, kwargs)
+
+def debug(msg, *args, **kwargs):
+    """
+    Log a message with severity 'DEBUG' on the root logger.
+    """
+    if len(root.handlers) == 0:
+        basicConfig()
+    apply(root.debug, (msg,)+args, kwargs)
+
+def disable(level):
+    """
+    Disable all logging calls less severe than 'level'.
+    """
+    root.manager.disable = level
+
+def shutdown():
+    """
+    Perform any cleanup actions in the logging system (e.g. flushing
+    buffers). Should be called at application exit.
+    """
+    for h in _handlers.keys():
+        h.flush()
+        h.close()
+
+#
+#   The following code implements a socket listener for on-the-fly
+#   reconfiguration of logging.
+#
+#   _listener holds the server object doing the listening
+_listener = None
+
+def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
+    """
+    Start up a socket server on the specified port, and listen for new
+    configurations. These will be sent as a file suitable for processing
+    by fileConfig(). Returns a Thread object on which you can call start()
+    to start the server, and which you can join() when appropriate.
+    To stop the server, call stopListening().
+    """
+    if not thread:
+        raise NotImplementedError, "listen() needs threading to work"
+
+    import threading
+
+    class ConfigStreamHandler(StreamRequestHandler):
+        """
+        Handler for a logging configuration request. It expects a
+        completely new logging configuration and uses fileConfig to
+        install it.
+        """
+        def handle(self):
+            """
+            Each request is expected to be a 2-byte length,
+            followed by the config file. Uses fileConfig() to do the
+            needful.
+            """
+            import tempfile
+            try:
+                conn = self.connection
+                chunk = conn.recv(2)
+                if len(chunk) == 2:
+                    slen = (ord(chunk[0]) << 8) | ord(chunk[1])
+                    chunk = self.connection.recv(slen)
+                    while len(chunk) < slen:
+                        chunk = chunk + conn.recv(slen - len(chunk))
+                    #Apply new configuration. We'd like to be able to
+                    #create a StringIO and pass that in, but unfortunately
+                    #1.5.2 ConfigParser does not support reading file
+                    #objects, only actual files. So we create a temporary
+                    #file and remove it later.
+                    file = tempfile.mktemp(".ini")
+                    f = open(file, "w")
+                    f.write(chunk)
+                    f.close()
+                    fileConfig(file)
+                    os.remove(file)
+            except socket.error, e:
+                if type(e.args) != types.TupleType:
+                    raise
+                else:
+                    errcode = e.args[0]
+                    if errcode != RESET_ERROR:
+                        raise
+
+    class ConfigSocketReceiver(ThreadingTCPServer):
+        """
+        A simple TCP socket-based logging config receiver.
+        """
+
+        allow_reuse_address = 1
+
+        def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
+                handler=None):
+            ThreadingTCPServer.__init__(self, (host, port), handler)
+            _acquireLock()
+            self.abort = 0
+            _releaseLock()
+            self.timeout = 1
+
+        def serve_until_stopped(self):
+            import select
+            abort = 0
+            while not abort:
+                rd, wr, ex = select.select([self.socket.fileno()],
+                                           [], [],
+                                           self.timeout)
+                if rd:
+                    self.handle_request()
+                _acquireLock()
+                abort = self.abort
+                _releaseLock()
+
+    def serve(rcvr, hdlr):
+        server = rcvr(handler=hdlr)
+        global _listener
+        _acquireLock()
+        _listener = server
+        _releaseLock()
+        server.serve_until_stopped()
+
+    return threading.Thread(target=serve, args=(ConfigSocketReceiver, ConfigStreamHandler))
+
+def stopListening():
+    """
+    Stop the listening server which was created with a call to listen().
+    """
+    if _listener:
+        _acquireLock()
+        _listener.abort = 1
+        _listener = None
+        _releaseLock()
+
+
+# bicycle repair man stuff
+
+bike_logger_initialised = 0
+
+def init():
+    global bike_logger_initialised
+    if not bike_logger_initialised:
+        log = getLogger("bike")
+        h = StreamHandler()
+        h.setFormatter(Formatter(
+            fmt="%(pathname)s:%(lineno)s:%(levelname)s   %(message)s"))
+        log.addHandler(h)
+        bike_logger_initialised = 1
+
+if __name__ == "__main__":
+    print __doc__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/mock.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,143 @@
+#
+# (c) Dave Kirby 2001
+# dkirby@bigfoot.com
+#
+# Call interceptor code by Phil Dawes (pdawes@users.sourceforge.net)
+
+'''
+The Mock class emulates any other class for testing purposes.
+All method calls are stored for later examination.
+The class constructor takes a dictionary of method names and the values
+they return.  Methods that are not in the dictionary will return None.
+'''
+import inspect
+
+
+class Mock:
+    def __init__(self, returnValues=None ):
+        self.mockCalledMethods = {}
+        self.mockAllCalledMethods = []
+        self.mockReturnValues = returnValues or {}
+        self.setupMethodInterceptors()
+        
+    def setupMethodInterceptors(self):
+        if self.__class__ != Mock: # check we've been subclassed
+            methods =  inspect.getmembers(self.__class__,inspect.ismethod)
+            for m in methods:
+                name = m[0]
+                self.__dict__[name] = MethodCallInterceptor(name,self)        
+            
+    def __getattr__( self, name ):
+        return MockCaller( name, self )
+    
+    def getAllCalls(self):
+        '''return a list of MockCall objects,
+        representing all the methods in the order they were called'''
+        return self.mockAllCalledMethods
+
+    def getNamedCalls(self, methodName ):
+        '''return a list of MockCall objects,
+        representing all the calls to the named method in the order they were called'''
+        return self.mockCalledMethods.get(methodName, [] )
+    
+    def assertNamedCall(self,methodName,*args):
+        # assert call was made once
+        assert(len(self.getNamedCalls(methodName)) == 1)
+        # assert args are correct
+        argsdict = inspect.getargvalues(inspect.currentframe())[3]
+        i=0
+        for arg in argsdict['args']:
+            assert(self.getNamedCalls(methodName)[0].getParam(i) == arg)
+            i += 1
+
+    def assertCallInOrder(self,methodName,*args):
+        ''' Convenience method to allow client to check that calls were
+        made in the right order. Call once for each methodcall'''
+
+        # initialise callIndex. (n.b. __getattr__ method complicates
+        # this since attrs are MockCaller instances by default)
+        if type(self.callIndex) != type(1):
+            self.callIndex=0
+        
+        call = self.getAllCalls()[self.callIndex]
+        # assert method name is correct
+        assert(call.getName() == methodName)
+        # assert args are correct
+        argsdict = inspect.getargvalues(inspect.currentframe())[3]
+        i=0
+        for arg in argsdict['args']:
+            assert(call.getParam(i) == arg)
+            i += 1
+        # assert num args are correct
+        assert(call.getNumParams() == i)
+        self.callIndex += 1
+        
+    def assertNoMoreCalls(self):
+        assert(len(self.getAllCalls()) == self.callIndex)
+        
+class MockCall:
+    def __init__(self, name, params, kwparams ):
+        self.name = name
+        self.params = params
+        self.kwparams = kwparams
+    def getParam( self, n ):
+        if type(n) == type(1):
+            return self.params[n]
+        elif type(n) == type(''):
+            return self.kwparams[n]
+        else:
+            raise IndexError, 'illegal index type for getParam'
+
+    def getNumParams(self):
+        return len(self.params)
+
+
+    def getName(self):
+        return self.name
+    
+    #pretty-print the method call
+    def __str__(self):
+        s = self.name + "("
+        sep = ''
+        for p in self.params:
+            s = s + sep + repr(p)
+            sep = ', '
+        for k,v in self.kwparams.items():
+            s = s + sep + k+ '='+repr(v)
+            sep = ', '
+        s = s + ')'
+        return s
+    def __repr__(self):
+        return self.__str__()
+
+class MockCaller:
+    def __init__( self, name, mock):
+        self.name = name
+        self.mock = mock
+    def __call__(self,  *params, **kwparams ):
+        self.recordCall(params,kwparams)
+        return self.mock.mockReturnValues.get(self.name)
+
+    def recordCall(self,params,kwparams):
+        thisCall = MockCall( self.name, params, kwparams )
+        calls = self.mock.mockCalledMethods.get(self.name, [] )
+        if calls == []:
+            self.mock.mockCalledMethods[self.name] = calls 
+        calls.append(thisCall)
+        self.mock.mockAllCalledMethods.append(thisCall)
+
+
+# intercepts the call and records it, then delegates to the real call
+class MethodCallInterceptor(MockCaller):
+    
+    def __call__(self,  *params, **kwparams ):
+        self.recordCall(params,kwparams)
+        return self.makeCall(params)
+        
+    def makeCall(self,params):
+        argsstr="(self.mock"
+        for i in range(len(params)):
+            argsstr += ",params["+`i`+"]"
+        argsstr+=")"
+        return eval("self.mock.__class__."+self.name+argsstr)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,3 @@
+#from addtypeinfo import addtypeinfo
+#from load import load
+#from brmtransformer import parse
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/constants.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,3 @@
+messages={"PARSING":"Parsing","ADDTYPEINFO":"Deducing Type Information"}
+
+MAXCALLDEPTH = 10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/fastparser.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+from bike.parsing.fastparserast import *
+from bike.parsing.parserutils import *
+from parser import ParserError
+#import exceptions
+
+indentRE = re.compile("^\s*(\w+)")
+
+# returns a tree of objects representing nested classes and functions
+# in the source
+def fastparser(src,modulename="",filename=""):
+    try:
+        return fastparser_impl(src,modulename,filename)
+    except RuntimeError, ex:   # if recursive call exceeds maximum depth
+        if str(ex) == "maximum recursion limit exceeded":
+            raise ParserError,"maximum recursion depth exceeded when fast-parsing src "+filename
+        else:
+            raise
+
+def fastparser_impl(src,modulename,filename):
+    lines = src.splitlines(1)
+    maskedSrc = maskPythonKeywordsInStringsAndComments(src)
+    maskedLines = maskedSrc.splitlines(1)
+    root = Module(filename,modulename,lines,maskedSrc)
+    parentnode = root
+    lineno = 0
+    for line in maskedLines:
+        lineno+=1
+        #print "line",lineno,":",line
+        m = indentRE.match(line)
+        if m:
+            indent = m.start(1)
+            tokenstr = m.group(1)
+            if tokenstr == "import" or tokenstr == "from":
+                while indent <= parentnode.indent:   # root indent is -TABWIDTH
+                    parentnode = parentnode.getParent()
+                try:
+                    parentnode.importlines.append(lineno)
+                except AttributeError:
+                    parentnode.importlines = [lineno]
+            elif tokenstr == "class":
+                m2 = classNameRE.match(line)
+                if m2:
+                    n = Class(m2.group(1), filename, root, lineno, indent, lines, maskedSrc)
+                    root.flattenedNodes.append(n)
+
+                    while indent <= parentnode.indent:
+                        parentnode = parentnode.getParent()
+                    parentnode.addChild(n)
+                    parentnode = n
+
+            elif tokenstr == "def":
+                m2 = fnNameRE.match(line)
+                if m2:
+                    n = Function(m2.group(1), filename, root, lineno, indent, lines, maskedSrc)
+                    root.flattenedNodes.append(n)
+
+                    while indent <= parentnode.indent:
+                        parentnode = parentnode.getParent()
+                    parentnode.addChild(n)
+                    parentnode = n
+
+            elif indent <= parentnode.indent and \
+                     tokenstr in ['if','for','while','try']:
+                parentnode = parentnode.getParent()
+                while indent <= parentnode.indent:
+                    parentnode = parentnode.getParent()
+
+    return root
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/fastparserast.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,327 @@
+from __future__ import generators
+from parserutils import generateLogicalLines, maskStringsAndComments, maskStringsAndRemoveComments
+import re
+import os
+import compiler
+from bike.transformer.save import resetOutputQueue
+
+TABWIDTH = 4
+
+classNameRE = re.compile("^\s*class\s+(\w+)")
+fnNameRE = re.compile("^\s*def\s+(\w+)")
+
+_root = None
+
+def getRoot():
+    global _root
+    if _root is None:
+        resetRoot()
+    return _root 
+
+def resetRoot(root = None):
+    global _root
+    _root = root or Root()
+    _root.unittestmode = False
+    resetOutputQueue()
+
+
+def getModule(filename_path):
+    from bike.parsing.load import CantLocateSourceNodeException, getSourceNode
+    try:
+        sourcenode = getSourceNode(filename_path)
+        return sourcenode.fastparseroot
+    except CantLocateSourceNodeException:
+        return None
+
+def getPackage(directory_path):
+    from bike.parsing.pathutils import getRootDirectory
+    rootdir = getRootDirectory(directory_path)
+    if rootdir == directory_path:
+        return getRoot()
+    else:
+        return Package(directory_path,
+                       os.path.basename(directory_path))
+
+
+
+
+            
+class Root:
+    def __init__(self, pythonpath = None):
+        # singleton hack to allow functions in query package to appear
+        # 'stateless'
+        resetRoot(self)
+
+        # this is to get round a python optimisation which reuses an
+        # empty list as a default arg. unfortunately the client of
+        # this method may fill that list, so it's not empty
+        if not pythonpath:
+            pythonpath = []
+        self.pythonpath = pythonpath
+
+    def __repr__(self):
+        return "Root()"
+        #return "Root(%s)"%(self.getChildNodes())
+
+
+    # dummy method
+    def getChild(self,name):
+        return None
+
+class Package:
+    def __init__(self, path, name):
+        self.path = path
+        self.name = name
+
+    def getChild(self,name):
+        from bike.parsing.newstuff import getModule
+        return getModule(os.path.join(self.path,name+".py"))
+
+    def __repr__(self):
+        return "Package(%s,%s)"%(self.path, self.name)
+
+# used so that linenum can be an attribute
+class Line(str):
+    pass
+
+class StructuralNode:
+    def __init__(self, filename, srclines, modulesrc):
+        self.childNodes = []
+        self.filename = filename
+        self._parent = None
+        self._modulesrc = modulesrc
+        self._srclines = srclines
+        self._maskedLines = None
+
+    def addChild(self, node):
+        self.childNodes.append(node)
+        node.setParent(self)
+
+    def setParent(self, parent):
+        self._parent = parent
+
+    def getParent(self):
+        return self._parent
+
+    def getChildNodes(self):
+        return self.childNodes
+
+    def getChild(self,name):
+        matches = [c for c in self.getChildNodes() if c.name == name]
+        if matches != []:
+            return matches[0]
+
+    def getLogicalLine(self,physicalLineno):
+        return generateLogicalLines(self._srclines[physicalLineno-1:]).next()
+
+    # badly named: actually returns line numbers of import statements
+    def getImportLineNumbers(self):
+        try:
+            return self.importlines
+        except AttributeError:
+            return[]
+
+    def getLinesNotIncludingThoseBelongingToChildScopes(self):
+        srclines = self.getMaskedModuleLines()
+        lines = []
+        lineno = self.getStartLine()
+        for child in self.getChildNodes():
+            lines+=srclines[lineno-1: child.getStartLine()-1]
+            lineno = child.getEndLine()
+        lines+=srclines[lineno-1: self.getEndLine()-1]
+        return lines
+
+
+    def generateLinesNotIncludingThoseBelongingToChildScopes(self):
+        srclines = self.getMaskedModuleLines()
+        lines = []
+        lineno = self.getStartLine()
+        for child in self.getChildNodes():
+            for line in srclines[lineno-1: child.getStartLine()-1]:
+                yield self.attachLinenum(line,lineno)
+                lineno +=1
+            lineno = child.getEndLine()
+        for line in srclines[lineno-1: self.getEndLine()-1]:
+            yield self.attachLinenum(line,lineno)
+            lineno +=1
+
+    def generateLinesWithLineNumbers(self,startline=1):
+        srclines = self.getMaskedModuleLines()
+        for lineno in range(startline,len(srclines)+1):
+            yield self.attachLinenum(srclines[lineno-1],lineno)
+
+    def attachLinenum(self,line,lineno):
+        line = Line(line)
+        line.linenum = lineno
+        return line
+
+    def getMaskedModuleLines(self):
+        from bike.parsing.load import Cache
+        try:
+            maskedlines = Cache.instance.maskedlinescache[self.filename]
+        except:
+            # make sure src is actually masked
+            # (could just have keywords masked)
+            maskedsrc = maskStringsAndComments(self._modulesrc)
+            maskedlines = maskedsrc.splitlines(1)
+            Cache.instance.maskedlinescache[self.filename] = maskedlines
+        return maskedlines
+
+
+class Module(StructuralNode):
+    def __init__(self, filename, name, srclines, maskedsrc):
+        StructuralNode.__init__(self, filename, srclines, maskedsrc)
+        self.name = name
+        self.indent = -TABWIDTH
+        self.flattenedNodes = []
+        self.module = self
+
+    def getMaskedLines(self):
+        return self.getMaskedModuleLines()
+
+    def getFlattenedListOfChildNodes(self):
+        return self.flattenedNodes
+
+    def getStartLine(self):
+        return 1
+
+    def getEndLine(self):
+        return len(self.getMaskedModuleLines())+1
+
+    def getSourceNode(self):
+        return self.sourcenode
+
+    def setSourceNode(self, sourcenode):
+        self.sourcenode = sourcenode
+
+    def matchesCompilerNode(self,node):
+        return isinstance(node,compiler.ast.Module) and \
+               node.name == self.name
+
+    def getParent(self):
+        if self._parent is not None:
+            return self._parent
+        else:
+            from newstuff import getPackage
+            return getPackage(os.path.dirname(self.filename))
+
+
+    def __str__(self):
+        return "bike:Module:"+self.filename
+
+indentRE = re.compile("^(\s*)\S")
+class Node:
+    # module = the module node
+    # linenum = starting line number
+    def __init__(self, name, module, linenum, indent):
+        self.name = name
+        self.module = module
+        self.linenum = linenum
+        self.endline = None
+        self.indent = indent
+
+    def getMaskedLines(self):
+        return self.getMaskedModuleLines()[self.getStartLine()-1:self.getEndLine()-1]
+
+    def getStartLine(self):
+        return self.linenum
+
+    def getEndLine(self):
+        if self.endline is None:
+            physicallines = self.getMaskedModuleLines()
+            lineno = self.linenum
+            logicallines = generateLogicalLines(physicallines[lineno-1:])
+
+            # skip the first line, because it's the declaration
+            line = logicallines.next()
+            lineno+=line.count("\n")
+
+            # scan to the end of the fn
+            for line in logicallines:
+                #print lineno,":",line,
+                match = indentRE.match(line)
+                if match and match.end()-1 <= self.indent:
+                    break
+                lineno+=line.count("\n")
+            self.endline = lineno
+        return self.endline
+
+    # linenum starts at 0
+    def getLine(self, linenum):
+        return self._srclines[(self.getStartLine()-1) + linenum]
+
+
+baseClassesRE = re.compile("class\s+[^(]+\(([^)]+)\):")
+
+class Class(StructuralNode, Node):
+    def __init__(self, name, filename, module, linenum, indent, srclines, maskedmodulesrc):
+        StructuralNode.__init__(self, filename, srclines, maskedmodulesrc)
+        Node.__init__(self, name, module, linenum, indent)
+        self.type = "Class"
+
+    
+    def getBaseClassNames(self):
+        #line = self.getLine(0)
+        line = self.getLogicalLine(self.getStartLine())
+        match = baseClassesRE.search(line)
+        if match:
+            return [s.strip()for s in match.group(1).split(",")]
+        else:
+            return []
+
+    def getColumnOfName(self):
+        match = classNameRE.match(self.getLine(0))
+        return match.start(1)
+
+    def __repr__(self):
+        return "<bike:Class:%s>" % self.name
+
+    def __str__(self):
+        return "bike:Class:"+self.filename+":"+\
+               str(self.getStartLine())+":"+self.name
+
+    def matchesCompilerNode(self,node):
+        return isinstance(node,compiler.ast.Class) and \
+               node.name == self.name
+
+    def __eq__(self,other):
+        return isinstance(other,Class) and \
+               self.filename == other.filename and \
+               self.getStartLine() == other.getStartLine()
+
+# describes an instance of a class
+class Instance:
+    def __init__(self, type):
+        assert type is not None
+        self._type = type
+
+    def getType(self):
+        return self._type
+
+    def __str__(self):
+        return "Instance(%s)"%(self.getType())
+
+
+class Function(StructuralNode, Node):
+    def __init__(self, name, filename, module, linenum, indent,
+                 srclines, maskedsrc):
+        StructuralNode.__init__(self, filename, srclines, maskedsrc)
+        Node.__init__(self, name, module, linenum, indent)
+        self.type = "Function"
+
+    def getColumnOfName(self):
+        match = fnNameRE.match(self.getLine(0))
+        return match.start(1)
+
+    def __repr__(self):
+        return "<bike:Function:%s>" % self.name
+
+    def __str__(self):
+        return "bike:Function:"+self.filename+":"+\
+               str(self.getStartLine())+":"+self.name
+
+    def matchesCompilerNode(self,node):
+        return isinstance(node,compiler.ast.Function) and \
+               node.name == self.name
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/load.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,94 @@
+from bike.globals import *
+import os
+from bike.parsing.fastparser import fastparser
+
+class Cache:
+    def __init__(self):
+        self.reset()
+    def reset(self):
+        self.srcnodecache = {}
+        self.typecache = {}
+        self.maskedlinescache = {}
+
+    instance = None
+
+Cache.instance = Cache()
+
+class CantLocateSourceNodeException(Exception): pass
+
+def getSourceNode(filename_path):
+    #print "getSourceNode:",filename_path
+    sourcenode = None
+    
+    try:
+        sourcenode = Cache.instance.srcnodecache[filename_path]
+    except KeyError:
+        pass
+    
+    if sourcenode is None:
+        from bike.parsing.newstuff import translateFnameToModuleName
+        sourcenode = SourceFile.createFromFile(filename_path,
+                              translateFnameToModuleName(filename_path))
+    if sourcenode is None:
+        raise CantLocateSourceNodeException(filename_path)
+
+    Cache.instance.srcnodecache[filename_path]=sourcenode
+    return sourcenode
+
+class SourceFile:
+
+    def createFromString(filename, modulename, src):
+        return SourceFile(filename,modulename,src)
+    createFromString = staticmethod(createFromString)
+
+    def createFromFile(filename,modulename):
+        try:
+            f = file(filename)
+            src = f.read()
+            f.close()
+        except IOError:
+            return None
+        else:
+            return SourceFile(filename,modulename,src)
+                
+    createFromFile = staticmethod(createFromFile)
+    
+    def __init__(self, filename, modulename, src):
+
+        if os.path.isabs(filename):
+            self.filename = filename
+        else:
+            self.filename = os.path.abspath(filename)
+        self.modulename = modulename
+
+        self.resetWithSource(src)
+
+    def resetWithSource(self, source):
+        # fastparser ast
+        self.fastparseroot = fastparser(source,self.modulename,self.filename)
+        self.fastparseroot.setSourceNode(self)
+        self._lines = source.splitlines(1)
+        self.sourcenode = self
+
+    def __repr__(self):
+        return "Source(%s,%s)"%('source', self.filename)
+
+    def getChildNodes(self):
+        return self.fastparseroot.getChildNodes()        
+        
+    def getSource(self):
+        return  "".join(self.getLines())
+
+    def getLine(self,linenum):
+        return self.getLines()[linenum-1]
+
+    # TODO: rename me!
+    def getFlattenedListOfFastParserASTNodes(self):
+        return self.fastparseroot.getFlattenedListOfChildNodes()
+        
+    def getLines(self):
+        return self._lines
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/newstuff.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,114 @@
+from __future__ import generators 
+# Holding module for scaffolding needed to transition parsing package
+# into stateless design
+import os
+import re
+from bike.parsing.pathutils import getRootDirectory, getPackageBaseDirectory, \
+     filenameToModulePath, getPathOfModuleOrPackage, getFilesForName
+from bike.parsing.fastparserast import Module, Package, getRoot, getPackage, getModule 
+import sys
+from bike.parsing.load import getSourceNode, CantLocateSourceNodeException
+
+
+def translateFnameToModuleName(filename_path):
+    return filenameToModulePath(filename_path)
+
+
+
+# scope is the scope to search from
+def getModuleOrPackageUsingFQN(fqn, dirpath=None):
+    pythonpath = getPythonPath()
+    #print "getModuleOrPackageUsingFQN",pythonpath,fqn
+    if dirpath is not None:
+        assert os.path.isdir(dirpath)
+        pythonpath = [dirpath] + pythonpath
+    filename = getPathOfModuleOrPackage(fqn,pythonpath)
+    #print "getModuleOrPackageUsingFQN - filename",filename
+    if filename is not None:
+        if os.path.isdir(filename):
+            return getPackage(filename)
+        else:
+            return getModule(filename)
+    else:
+        return None
+
+def getPythonPath():
+    return getRoot().pythonpath
+
+
+def generateModuleFilenamesInPythonPath(contextFilename):
+    files = []
+    rootdir = getRootDirectory(contextFilename)
+    if rootdir in getPythonPath():
+        # just search the pythonpath
+        for path in getPythonPath():
+            for file in getFilesForName(path):
+                if file not in files:   # check for duplicates
+                    files.append(file)
+                    yield file
+    else:
+        # search the package hierarchy containing contextFilename
+        # in addition to pythonpath
+        basedir = getPackageBaseDirectory(contextFilename)
+        for path in [basedir] + getPythonPath():
+            for file in getFilesForName(path):
+                if file not in files:   # check for duplicates
+                    files.append(file)
+                    yield file
+
+        # and search the files immediately above the package hierarchy
+        for file in getFilesForName(os.path.join(rootdir,"*.py")):
+            if file not in files:   # check for duplicates
+                files.append(file)
+                yield file
+
+def generateModuleFilenamesInPackage(filenameInPackage):
+    basedir = getPackageBaseDirectory(filenameInPackage)
+    for file in getFilesForName(basedir):
+        yield file
+
+
+
+# search all sourcenodes globally from the perspective of file 'contextFilename'
+def getSourceNodesContainingRegex(regexstr,contextFilename):
+    regex = re.compile(regexstr)
+    for fname in generateModuleFilenamesInPythonPath(contextFilename):
+        try:
+            f = file(fname)
+            src = f.read()
+        finally:
+            f.close()
+        if regex.search(src) is not None:
+            yield getSourceNode(fname)
+
+
+
+
+fromRegex = re.compile("^\s*from\s+(\w+)\s+import")
+importregex = re.compile("^\s*import\s+(\w+)")
+
+# fileInPackage is the filename of a file in the package hierarchy
+# generates file and directory paths
+def generatePackageDependencies(fileInPackage):
+    rejectPackagePaths = [getPackageBaseDirectory(fileInPackage)]
+    for fname in generateModuleFilenamesInPackage(fileInPackage):
+
+        try:
+            f = file(fname)
+            src = f.read()
+        finally:
+            f.close()
+
+        packagepath = None
+
+        for line in src.splitlines():
+            match = fromRegex.search(line) or importregex.search(line)
+            if match is not None:
+                modulepath = match.group(1)
+                packagename = modulepath.split('.')[0]
+                packagepath = getPathOfModuleOrPackage(packagename,
+                                                       getPythonPath())
+            if packagepath is not None and \
+                   packagepath not in rejectPackagePaths:
+                rejectPackagePaths.append(packagepath) # avoid duplicates
+                yield packagepath
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/parserutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,194 @@
+from __future__ import generators
+import re
+
+escapedQuotesRE = re.compile(r"(\\\\|\\\"|\\\')")
+
+# changess \" \' and \\ into ** so that text searches
+# for " and ' won't hit escaped ones
+def maskEscapedQuotes(src):
+    return escapedQuotesRE.sub("**", src)
+
+stringsAndCommentsRE =  \
+      re.compile("(\"\"\".*?\"\"\"|'''.*?'''|\"[^\"]*\"|\'[^\']*\'|#.*?\n)", re.DOTALL)
+
+import string
+#transtable = string.maketrans('classdefifforwhiletry', "*********************")
+
+# performs a transformation on all of the comments and strings so that
+# text searches for python keywords won't accidently find a keyword in
+# a string or comment
+def maskPythonKeywordsInStringsAndComments(src):
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        allstrings[i] = allstrings[i].upper()
+        #allstrings[i] = allstrings[i].translate(transtable)
+    return "".join(allstrings)
+
+
+allchars = string.maketrans("", "")
+allcharsExceptNewline = allchars[: allchars.index('\n')]+allchars[allchars.index('\n')+1:]
+allcharsExceptNewlineTranstable = string.maketrans(allcharsExceptNewline, '*'*len(allcharsExceptNewline))
+
+
+# replaces all chars in a string or a comment with * (except newlines).
+# this ensures that text searches don't mistake comments for keywords, and that all
+# matches are in the same line/comment as the original
+def maskStringsAndComments(src):
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
+            allstrings[i] = allstrings[i][:3]+ \
+                           allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-3:]
+        else:
+            allstrings[i] = allstrings[i][0]+ \
+                           allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-1]
+
+    return "".join(allstrings)
+
+
+# replaces all chars in a string or a comment with * (except newlines).
+# this ensures that text searches don't mistake comments for keywords, and that all
+# matches are in the same line/comment as the original
+def maskStringsAndRemoveComments(src):
+    src = escapedQuotesRE.sub("**", src)
+    allstrings = stringsAndCommentsRE.split(src)
+    # every odd element is a string or comment
+    for i in xrange(1, len(allstrings), 2):
+        if allstrings[i].startswith("'''")or allstrings[i].startswith('"""'):
+            allstrings[i] = allstrings[i][:3]+ \
+                           allstrings[i][3:-3].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-3:]
+        elif allstrings[i].startswith("#"):
+            allstrings[i] = '\n'
+        else:
+            allstrings[i] = allstrings[i][0]+ \
+                           allstrings[i][1:-1].translate(allcharsExceptNewlineTranstable)+ \
+                           allstrings[i][-1]
+    return "".join(allstrings)
+        
+
+implicitContinuationChars = (('(', ')'), ('[', ']'), ('{', '}'))
+emptyHangingBraces = [0,0,0,0,0]
+linecontinueRE = re.compile(r"\\\s*(#.*)?$")
+multiLineStringsRE =  \
+      re.compile("(^.*?\"\"\".*?\"\"\".*?$|^.*?'''.*?'''.*?$)", re.DOTALL)
+
+#def splitLogicalLines(src):
+#    src = multiLineStringsRE.split(src)
+
+# splits the string into logical lines.  This requires the comments to
+# be removed, and strings masked (see other fns in this module)
+def splitLogicalLines(src):
+    physicallines = src.splitlines(1)
+    return [x for x in generateLogicalLines(physicallines)]
+
+
+class UnbalancedBracesException: pass
+
+# splits the string into logical lines.  This requires the strings
+# masked (see other fns in this module)
+# Physical Lines *Must* start on a non-continued non-in-a-comment line
+# (although detects unbalanced braces)
+def generateLogicalLines(physicallines):
+    tmp = []
+    hangingBraces = list(emptyHangingBraces)
+    hangingComments = 0
+    for line in physicallines:
+        # update hanging braces
+        for i in range(len(implicitContinuationChars)):
+            contchar = implicitContinuationChars[i]
+            numHanging = hangingBraces[i]
+            hangingBraces[i] = numHanging+line.count(contchar[0]) - \
+                               line.count(contchar[1])
+
+        hangingComments ^= line.count('"""') % 2
+        hangingComments ^= line.count("'''") % 2
+
+        if hangingBraces[0] < 0 or \
+           hangingBraces[1] < 0 or \
+           hangingBraces[2] < 0:
+            raise UnbalancedBracesException()
+        
+        if linecontinueRE.search(line):
+            tmp.append(line)
+        elif hangingBraces != emptyHangingBraces:
+            tmp.append(line)
+        elif hangingComments:
+            tmp.append(line)
+        else:
+            tmp.append(line)
+            yield "".join(tmp)
+            tmp = []
+    
+
+# see above but yields (line,linenum)
+#   needs physicallines to have linenum attribute
+#   TODO: refactor with previous function
+def generateLogicalLinesAndLineNumbers(physicallines):
+    tmp = []
+    hangingBraces = list(emptyHangingBraces)
+    hangingComments = 0
+    linenum = None
+    for line in physicallines:
+        if tmp == []:
+            linenum = line.linenum
+
+        # update hanging braces
+        for i in range(len(implicitContinuationChars)):
+            contchar = implicitContinuationChars[i]
+            numHanging = hangingBraces[i]
+            hangingBraces[i] = numHanging+line.count(contchar[0]) - \
+                               line.count(contchar[1])
+
+        hangingComments ^= line.count('"""') % 2
+        hangingComments ^= line.count("'''") % 2
+            
+        if linecontinueRE.search(line):
+            tmp.append(line)
+        elif hangingBraces != emptyHangingBraces:
+            tmp.append(line)
+        elif hangingComments:
+            tmp.append(line)
+        else:
+            tmp.append(line)
+            yield "".join(tmp),linenum
+            tmp = []
+        
+
+
+
+# takes a line of code, and decorates it with noops so that it can be
+# parsed by the python compiler.
+# e.g.  "if foo:"  -> "if foo: pass"
+# returns the line, and the adjustment made to the column pos of the first char
+# line must have strings and comments masked
+#
+# N.B. it only inserts keywords whitespace and 0's
+notSpaceRE = re.compile("\s*(\S)")
+commentRE = re.compile("#.*$")
+
+def makeLineParseable(line):
+    return makeLineParseableWhenCommentsRemoved(commentRE.sub("",line))
+
+def makeLineParseableWhenCommentsRemoved(line):
+    line = line.strip()
+    if ":" in line:
+        if line.endswith(":"):
+            line += " pass"
+        if line.startswith("try"):
+            line += "\nexcept: pass"
+        elif line.startswith("except") or line.startswith("finally"):
+            line = "try: pass\n" + line
+            return line
+        elif line.startswith("else") or line.startswith("elif"):
+            line = "if 0: pass\n" + line
+            return line
+    elif line.startswith("yield"):
+        return ("return"+line[5:])
+    return line
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/pathutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,165 @@
+
+# A some of this code is take from Pythius -
+# Copyright (GPL) 2001 Jurgen Hermann <jh@web.de>
+
+from bike.globals import *
+import os
+
+def containsAny(str, set):
+    """ Check whether 'str' contains ANY of the chars in 'set'
+    """
+    return 1 in [c in str for c in set]
+
+
+
+def getPathOfModuleOrPackage(dotted_name, pathlist = None):
+    """ Get the filesystem path for a module or a package.
+
+        Return the file system path to a file for a module,
+        and to a directory for a package. Return None if
+        the name is not found, or is a builtin or extension module.
+    """
+    from bike.parsing.newstuff import getPythonPath
+    if pathlist is None:
+        pathlist = getPythonPath()
+
+    import imp
+
+    # split off top-most name
+    parts = dotted_name.split('.', 1)
+
+    if len(parts) > 1:
+        # we have a dotted path, import top-level package
+        try:
+            file, pathname, description = imp.find_module(parts[0], pathlist)
+            if file: file.close()
+        except ImportError:
+            return None
+
+        # check if it's indeed a package
+        if description[2] == imp.PKG_DIRECTORY:
+            # recursively handle the remaining name parts
+            pathname = getPathOfModuleOrPackage(parts[1], [pathname])
+        else:
+            pathname = None
+    else:
+        # plain name
+        try:
+            file, pathname, description = imp.find_module(dotted_name, pathlist)
+            if file: file.close()
+            if description[2]not in[imp.PY_SOURCE, imp.PKG_DIRECTORY]:
+                pathname = None
+        except ImportError:
+            pathname = None
+
+    return pathname
+
+
+def getFilesForName(name):
+    """ Get a list of module files for a filename, a module or package name,
+        or a directory.
+    """
+    import imp
+
+    if not os.path.exists(name):
+        # check for glob chars
+        if containsAny(name, "*?[]"):
+            import glob
+            files = glob.glob(name)
+            list = []
+            for file in files:
+                list.extend(getFilesForName(file))
+            return list
+
+        # try to find module or package
+        name = getPathOfModuleOrPackage(name)
+        if not name:
+            return[]
+
+    if os.path.isdir(name):
+        # find all python files in directory
+        list = []
+        os.path.walk(name, _visit_pyfiles, list)
+        return list
+    elif os.path.exists(name) and not name.startswith("."):
+        # a single file
+        return [name]
+
+    return []
+
+def _visit_pyfiles(list, dirname, names):
+    """ Helper for getFilesForName().
+    """
+    # get extension for python source files
+    if not globals().has_key('_py_ext'):
+        import imp
+        global _py_ext
+        _py_ext = [triple[0]for triple in imp.get_suffixes()if triple[2] == imp.PY_SOURCE][0]
+
+    # don't recurse into CVS or Subversion directories
+    if 'CVS'in names:
+        names.remove('CVS')
+    if '.svn'in names:
+        names.remove('.svn')
+
+    names_copy = [] + names
+    for n in names_copy:
+        if os.path.isdir(os.path.join(dirname, n))and \
+           not os.path.exists(os.path.join(dirname, n, "__init__.py")):
+            names.remove(n)
+
+    # add all *.py files to list
+    list.extend(
+    [os.path.join(dirname, file)
+    for file in names
+    if os.path.splitext(file)[1] == _py_ext and not file.startswith(".")])
+
+
+# returns the directory which holds the first package of the package
+# hierarchy under which 'filename' belongs
+def getRootDirectory(filename):
+    if os.path.isdir(filename):
+        dir = filename
+    else:
+        dir = os.path.dirname(filename)
+    while dir != "" and \
+          os.path.exists(os.path.join(dir, "__init__.py")):
+        dir = os.path.dirname(dir)
+    return dir
+
+
+
+# Returns the root package directoryname of the package hierarchy
+# under which 'filename' belongs
+def getPackageBaseDirectory(filename):
+    if os.path.isdir(filename):
+        dir = filename
+    else:
+        dir = os.path.dirname(filename)
+
+    if not os.path.exists(os.path.join(dir, "__init__.py")):
+        # parent dir is not a package
+        return dir
+
+    while dir != "" and \
+          os.path.exists(os.path.join(os.path.dirname(dir), "__init__.py")):
+        dir = os.path.dirname(dir)
+    return dir
+
+
+
+def filenameToModulePath(fname):
+    directoriesPreceedingRoot = getRootDirectory(fname)
+    import os
+    # strip off directories preceeding root package directory
+    if directoriesPreceedingRoot != "":
+        mpath = fname.replace(directoriesPreceedingRoot, "")
+    else:
+        mpath = fname
+
+    if(mpath[0] == os.path.normpath("/")):
+        mpath = mpath[1:]
+    mpath, ext = os.path.splitext(mpath)
+    mpath = mpath.replace(os.path.normpath("/"), ".")
+    return mpath
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("../..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath("../.."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_fastparser.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+import unittest
+from fastparser import*
+from bike.parsing.load import*
+from bike.parsing.fastparserast import*
+from bike.testutils import *
+
+class TestFastParser(BRMTestCase):
+    def test_doesntGetClassDeclsInMLStrings(self):
+        src = trimLines('''
+        """
+        class foo bah
+        """
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() == []
+
+    def test_evaluatesMLStringWithQuoteInIt(self):
+        src = trimLines('''
+        """some ml comment inclosing a " """
+        def foo:
+            pass 
+        " hello "
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() != []
+
+    def test_handlesClassDefsWithTwoSpacesInDecl(self):
+        src = trimLines('''
+        class  foo: pass
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() != []
+        
+    def test_handlesFnDefsWithTwoSpacesInDecl(self):
+        src = trimLines('''
+        def  foo: pass
+        ''')
+        root = fastparser(src)
+        assert root.getChildNodes() != []
+
+
+MLStringWithQuoteInIt = """
+\"\"\"some ml comment inclosing a \" \"\"\"
+def foo:
+    pass
+\" hello \"
+"""
+
+def load(path):
+    files = getFilesForName(path)
+    for fname in files:
+        src = file(fname).read()
+        fastparser(src)
+        #print fname
+        #myroot = parseFile(fname)
+
+
+
+def fastparsetreeToString(root):
+    class stringholder: pass
+    s = stringholder()
+    s.mystr = ""
+    s.tabstr = ""
+    def t2s(node):
+        if isinstance(node, Class):
+            s.mystr+=s.tabstr+"class "+node.name+"\n"
+            s.tabstr+="\t"
+            for n in node.getChildNodes():
+                t2s(n)
+            s.tabstr = s.tabstr[:-1]
+
+        elif isinstance(node, Function):
+            s.mystr+=s.tabstr+"function "+node.name+"\n"
+            s.tabstr+="\t"
+            for n in node.getChildNodes():
+                t2s(n)
+            s.tabstr = s.tabstr[:-1]
+
+
+    for n in root.getChildNodes():
+        t2s(n)
+    return s.mystr
+
+
+def compilerParseTreeToString(root):
+    try:
+        class TreeVisitor:
+            def __init__(self):
+                self.mystr = ""
+                self.tabstr = ""
+
+            def visitClass(self, node):
+                self.mystr+=self.tabstr+"class "+node.name+"\n"
+                self.tabstr+="\t"
+                for child in node.getChildNodes():
+                    self.visit(child)
+                self.tabstr = self.tabstr[:-1]
+
+            def visitFunction(self, node):
+                self.mystr+=self.tabstr+"function "+node.name+"\n"
+                self.tabstr+="\t"
+                for child in node.getChildNodes():
+                    self.visit(child)
+                self.tabstr = self.tabstr[:-1]
+
+        return compiler.walk(root, TreeVisitor()).mystr
+
+    except:
+        log.exception("ex")
+        import sys
+        sys.exit(0)
+
+
+def compareCompilerWithFastparserOverPath(path):
+    from bike.parsing.load import getFilesForName
+    files = getFilesForName(path)
+    for fname in files:
+        if fname.endswith("bdist_wininst.py"): continue
+        log.info(fname)
+        src = file(fname).read()
+        try:
+            compiler_root = compiler.parse(src)
+        except SyntaxError:
+            continue
+        fastparse_root = fastparser(src)
+        str1 = fastparsetreeToString(fastparse_root)
+        str2 = compilerParseTreeToString(compiler_root)
+        assert str1 == str2, "\n"+"-"*70+"\n"+str1+"-"*70+"\n"+str2
+
+
+def timeParseOfPythonLibrary(path):
+    import time
+    t1 = time.time()
+    files = getFilesForName(path)
+    import sys
+    for fname in files:
+        if fname.endswith("bdist_wininst.py"): continue
+        src = file(fname).read()
+        fastparser(src)
+    print "\n", time.time()-t1
+
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.INFO)
+    # add soak tests to end of test
+    class Z_SoakTestFastparser(BRMTestCase):
+
+        def test_A_timeParseOfPythonLibrary(self):
+            timeParseOfPythonLibrary("/usr/local/lib/python2.2")
+
+        def test_parsesPythonLibraryCorrectly(self):
+            print ""
+            compareCompilerWithFastparserOverPath("/usr/local/lib/python2.2")
+
+    unittest.main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_fastparserast.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+import unittest
+from fastparserast import *
+from fastparser import fastparser
+from bike.query.getTypeOf import getTypeOf
+from bike.testutils import *
+
+class TestGetModule(BRMTestCase):
+
+    def test_getRootWorksAfterDefinedByCreateSourceNodeAt(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        assert root == getRoot()
+
+    def test_returnsNoneIfModuleDoesntExist(self):
+        assert getModule(tmpfile) == None
+
+
+class TestGetEndLine(BRMTestCase):
+    def test_returnsEndLineWithSimpleFunction(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.theMethod()
+        """)
+        root = fastparser(src)
+        fn = getTypeOf(root,"foo")
+        self.assertEqual(fn.getEndLine(),7)
+
+    def test_worksWithFunctionsThatHaveEmptyLinesInThem(self):
+        src = fnWithEmptyLineInIt
+        root = fastparser(src)
+        fn = getTypeOf(root,"TheClass.theFunction")
+        self.assertEqual(fn.getEndLine(),8)
+
+class TestGetBaseClassNames(BRMTestCase):
+    def test_worksForClassHierarchy(self):
+        src = trimLines("""
+        class root:
+            def theMethod():
+                pass
+
+        class a(root):
+            def theMethod():
+                pass    
+
+        class b(root):
+            pass
+
+        class TheClass(a,b):
+            def theMethod():
+                pass
+
+        rootinstance = root()
+        rootinstance.theMethod()
+        """)
+        #classes = getASTNodeFromSrc(src,"Source").fastparseroot.getChildNodes()
+        classes = createAST(src).fastparseroot.getChildNodes()
+        self.assertEqual(classes[3].getBaseClassNames(),['a','b'])
+
+    def test_returnsEmptyListForClassWithNoBases(self):
+        src = trimLines("""
+        class root:
+            pass
+        """)
+        #classes = getASTNodeFromSrc(src,"Source").fastparseroot.getChildNodes()
+        classes = createAST(src).fastparseroot.getChildNodes()        
+        self.assertEqual(classes[0].getBaseClassNames(),[])
+
+
+class TestGetMaskedLines(BRMTestCase):
+    def test_doit(self):
+        src =trimLines("""
+        class foo: #bah
+            pass
+        """)
+        mod = createAST(src).fastparseroot
+        lines = mod.getMaskedModuleLines()
+        assert lines[0] == "class foo: #***\n"
+
+
+class TestGetLinesNotIncludingThoseBelongingToChildScopes(BRMTestCase):
+    def test_worksForModule(self):
+        src =trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.theMethod()
+        """)
+        mod = createAST(src).fastparseroot
+        self.assertEqual(''.join(mod.getLinesNotIncludingThoseBelongingToChildScopes()),
+                         trimLines("""
+                         a = foo()
+                         a.theMethod()
+                         """))
+
+    def test_worksForModuleWithSingleLineFunctions(self):
+        src=trimLines("""
+        a = blah()
+        def foo(): pass
+        b = 1
+        """)
+        mod = createAST(src).fastparseroot
+        lines = mod.getLinesNotIncludingThoseBelongingToChildScopes()
+        self.assertEqual(''.join(lines),
+                         trimLines("""
+                         a = blah()
+                         b = 1
+                         """))
+
+
+    def test_worksForSingleLineFunction(self):
+        src=trimLines("""
+        a = blah()
+        def foo(): pass
+        b = 1
+        """)
+        fn = createAST(src).fastparseroot.getChildNodes()[0]
+        lines = fn.getLinesNotIncludingThoseBelongingToChildScopes()
+        self.assertEqual(''.join(lines),
+                         trimLines("""
+                         def foo(): pass
+                         """))
+
+
+fnWithEmptyLineInIt = """
+class TheClass:
+    def theFunction():
+        a = foo()
+
+        print 'a'
+
+    # end of function
+"""
+
+if __name__ == "__main__":
+    unittest.main()
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_load.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import compiler
+import os
+
+from bike import testdata
+from bike.testutils import *
+from bike.mock import Mock
+
+from pathutils import getPathOfModuleOrPackage
+from load import *
+import load as loadmodule
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_newstuff.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,284 @@
+#!/usr/bin/env python
+import setpath
+import os
+import unittest
+from bike.testutils import *
+from bike.parsing.fastparserast import getRoot
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN,\
+     generateModuleFilenamesInPythonPath, getSourceNodesContainingRegex,\
+     generatePackageDependencies
+     
+
+class TestGetModuleOrPackageUsingFQN(BRMTestCase):
+    def test_worksForFullPath(self):
+        try:
+            createPackageStructure("pass","pass")
+            self.assertEqual(getModuleOrPackageUsingFQN("a.b.bah").filename,
+                             pkgstructureFile2)
+        finally:
+            removePackageStructure()
+        
+    def test_worksForPackage(self):
+        try:
+            createPackageStructure("pass","pass")
+            self.assertEqual(getModuleOrPackageUsingFQN("a.b").path,
+                             pkgstructureChilddir)
+        finally:
+            removePackageStructure()
+
+
+class TestGenerateModuleFilenamesInPythonPath(BRMTestCase):
+    def test_works(self):
+        try:
+            createPackageStructure("pass","pass")
+            fnames = [f for f in \
+                 generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+
+
+            assert os.path.join(pkgstructureBasedir,"__init__.py") in fnames
+            assert pkgstructureFile1 in fnames
+            assert os.path.join(pkgstructureChilddir,"__init__.py") in fnames
+            assert pkgstructureFile2 in fnames
+            assert len(fnames) == 5
+        finally:
+            removePackageStructure()
+
+        
+
+    def test_doesntTraverseIntoNonPackages(self):
+        try:
+            createPackageStructure("pass","pass")
+            nonPkgDir = os.path.join(pkgstructureChilddir,"c")
+            newfile = os.path.join(nonPkgDir,"baz.py")
+            # N.B. don't put an __init__.py in it, so isnt a package
+            os.makedirs(nonPkgDir)
+            writeFile(newfile,"pass")
+            fnames = [f for f in \
+                 generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            assert newfile not in fnames
+        finally:
+            #os.remove(initfile)
+            os.remove(newfile)
+            os.removedirs(nonPkgDir)
+            removePackageStructure()
+
+
+    def test_doesScanFilesInTheRootDirectory(self):
+        try:
+            createPackageStructure("pass","pass","pass")
+            fnames = [f for f in \
+                 generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            assert pkgstructureFile0 in fnames
+        finally:
+            #os.remove(initfile)
+            removePackageStructure()
+
+    def test_returnsOtherFilesInSameNonPackageDirectory(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            writeTmpTestFile("")
+            newtmpfile = os.path.join(tmproot,"baz.py")
+            writeFile(newtmpfile, "")
+            fnames = [f for f in \
+                      generateModuleFilenamesInPythonPath(tmpfile)]
+            assert newtmpfile in fnames
+        finally:
+            os.remove(newtmpfile)
+            deleteTmpTestFile()
+            getRoot().pythonpath = oldpath
+            
+
+
+    def test_doesntTraverseIntoNonPackagesUnderRoot(self):
+        try:
+            os.makedirs(pkgstructureBasedir)
+            writeFile(pkgstructureFile1,"pass")
+            fnames = [f for f in \
+                      generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            assert pkgstructureFile1 not in fnames
+        finally:
+            os.remove(pkgstructureFile1)
+            os.removedirs(pkgstructureBasedir)
+
+
+    def test_doesntGenerateFilenamesMoreThanOnce(self):
+        try:
+            createPackageStructure("pass","pass")
+            newfile = os.path.join(pkgstructureChilddir,"baz.py")
+            writeFile(newfile,"pass")
+            fnames = [f for f in \
+                generateModuleFilenamesInPythonPath(pkgstructureFile2)]
+            matched = [f for f in fnames if f == newfile]
+            self.assertEqual(1, len(matched))
+        finally:
+            os.remove(newfile)
+            removePackageStructure()
+
+class TestGetSourceNodesContainingRegex(BRMTestCase):
+    def test_works(self):
+        try:
+            createPackageStructure("# testregexfoobah","pass")
+            srcfiles = [s for s in 
+                        getSourceNodesContainingRegex("testregexfoobah",
+                                                      pkgstructureFile2)]
+            self.assertEqual(pkgstructureFile1,srcfiles[0].filename)
+        finally:
+            removePackageStructure()
+
+class TestGenerateModuleFilenamesInPythonPath2(BRMTestCase):
+    def test_getsAllFilenamesInSameHierarchyAsContextFile(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            createPackageStructure("","")
+            fnames = [f for f in
+                      generateModuleFilenamesInPythonPath(pkgstructureFile1)]
+            self.assert_(pkgstructureFile0 in fnames)
+            self.assert_(pkgstructureFile1 in fnames)
+            self.assert_(pkgstructureFile2 in fnames)
+        finally:
+            getRoot().pythonpath = oldpath 
+            removePackageStructure()
+
+    def test_getsFilenamesInSubPackagesIfCtxFilenameIsInTheRoot(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            createPackageStructure("","")
+            fnames = [f for f in
+                      generateModuleFilenamesInPythonPath(pkgstructureFile0)]
+            self.assert_(pkgstructureFile1 in fnames)
+            self.assert_(pkgstructureFile2 in fnames)
+        finally:
+            getRoot().pythonpath = oldpath 
+            removePackageStructure()
+
+    def test_doesntTraverseOtherPackagesOffOfTheRoot(self):
+        try:
+            oldpath = getRoot().pythonpath
+            getRoot().pythonpath = []   # clear the python path
+            createPackageStructure("","")
+            os.makedirs(os.path.join(pkgstructureRootDir, "c"))
+            writeFile(os.path.join(pkgstructureRootDir, "c", "__init__.py"), "# ")
+            bazfile = os.path.join(pkgstructureRootDir, "c", "baz.py")
+            writeFile(bazfile, "pass")
+            fnames = [f for f in
+                      generateModuleFilenamesInPythonPath(pkgstructureFile1)]
+            self.assert_(pkgstructureFile0 in fnames)
+            self.assert_(pkgstructureFile1 in fnames)
+            self.assert_(pkgstructureFile2 in fnames)
+            self.assert_(bazfile not in fnames)
+        finally:
+            getRoot().pythonpath = oldpath 
+            os.remove(os.path.join(pkgstructureRootDir, "c", "baz.py"))
+            os.remove(os.path.join(pkgstructureRootDir, "c", "__init__.py"))
+            os.removedirs(os.path.join(pkgstructureRootDir, "c"))
+            removePackageStructure()
+
+
+class TestGetPackageDependencies(BRMTestCase):
+
+    def test_followsImportModule(self):
+        try:
+            createPackageStructure("","import c.bing")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_followsFromImportPackage(self):
+        try:
+            createPackageStructure("","import c")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+
+    def test_followsFromImportStar(self):
+        try:
+            createPackageStructure("","from c import *")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+    def test_followsFromImportModule(self):
+        try:
+            createPackageStructure("","from c import bing")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([pkgstructureBasedir2],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_doesntBreakIfImportIsInAMultilineString(self):
+        try:
+            createPackageStructure("",trimLines("""
+            '''
+            from aoeuaoeu import aocxaoieicxoe
+            '''
+            """))
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+    def test_doesntBreakIfImportIsCommented(self):
+        try:
+            createPackageStructure("","#from aoeuaoeu import aocxaoieicxoe")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_doesntBreakIfCantFindImport(self):
+        try:
+            createPackageStructure("","from aoeuaoeu import aocxaoieicxoe")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+    def test_doesntIncludeCurrentPackage(self):
+        try:
+            createPackageStructure("","import a.foo")
+            createSecondPackageStructure("")
+            dependencies = [d for d in
+                            generatePackageDependencies(pkgstructureFile2)]
+            self.assertEqual([],dependencies)
+        finally:
+            removeSecondPackageStructure()
+            removePackageStructure()
+
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_parserutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+import unittest
+from parserutils import *
+from bike.testutils import *
+
+class TestRemoveEscapedQuotes(BRMTestCase):
+
+    def testMaskEscapedQuotes_MasksEscapedQuotes(self):
+        src = '\" \\\\\\\" \' \\\\\\\\\"  \'  \''
+        self.assertEqual(maskEscapedQuotes(src),'" **** \' ****"  \'  \'')
+
+class TestMungePythonKeywordsInStrings(BRMTestCase):
+    def test_mungesKeywords(self):
+        src = '\"\"\"class try while\"\"\" class2 try2 while2 \'\'\' def if for \'\'\' def2 if2 for2'
+        self.assertEqual(maskPythonKeywordsInStringsAndComments(src),
+                      '"""CLASS TRY WHILE""" class2 try2 while2 \'\'\' DEF IF FOR \'\'\' def2 if2 for2')
+
+
+class TestSplitLines(BRMTestCase):
+    def test_handlesExplicitlyContinuedLineWithComment(self):
+        self.assertEqual(splitLogicalLines(explicitlyContinuedLineWithComment),
+              ['\n', 'z = a + b + \\  # comment\n  c + d\n', 'pass\n'])
+
+    def test_handlesImplicitlyContinuedLine(self):
+        self.assertEqual(splitLogicalLines(implicitlyContinuedLine), 
+                         ['\n', 'z = a + b + (\n  c + d)\n', 'pass\n'])
+
+    def test_handlesNestedImplicitlyContinuedLine(self):
+        self.assertEqual(splitLogicalLines(implicitlyContinuedLine2), 
+                         ['\n', 'z = a + b + ( c + [d\n  + e]\n  + f)   # comment\n', 'pass\n'])
+
+
+    def test_handlesMultiLineStrings(self):
+        self.assertEqual(splitLogicalLines(multilineComment),
+                         ['\n', "''' this is an mlc\nso is this\n'''\n", 'pass\n'])
+                         
+
+class TestMakeLineParseable(BRMTestCase):
+    def test_worksWithIfStatement(self):
+        src = "if foo:"
+        self.assertEqual(makeLineParseable(src),("if foo: pass"))
+
+    def test_worksWithTryStatement(self):
+        src = "try :"
+        self.assertEqual(makeLineParseable(src),("try : pass\nexcept: pass"))
+
+    def test_worksOnTryStatementWithCodeInlined(self):
+        src = "try : a = 1"
+        self.assertEqual(makeLineParseable(src),("try : a = 1\nexcept: pass"))
+
+    def test_worksWithExceptStatement(self):
+        src = "except :"
+        self.assertEqual(makeLineParseable(src),("try: pass\nexcept : pass"))
+
+    def test_worksWithFinallyStatement(self):
+        src = "finally:"
+        self.assertEqual(makeLineParseable(src),("try: pass\nfinally: pass"))
+
+    def test_worksWithIfStatement(self):
+        src = "if foo:"
+        self.assertEqual(makeLineParseable(src),("if foo: pass"))
+
+    def test_worksWithElseStatement(self):
+        src = "else :"
+        self.assertEqual(makeLineParseable(src),("if 0: pass\nelse : pass"))
+
+    def test_worksWithElifStatement(self):
+        src = "elif foo:"
+        self.assertEqual(makeLineParseable(src),("if 0: pass\nelif foo: pass"))
+
+
+def runOverPath(path):
+    import compiler
+    from parser import ParserError
+    from bike.parsing.load import getFilesForName
+    files = getFilesForName(path)
+    for fname in files:
+        print fname
+        src = file(fname).read()
+        #print src
+        src = maskStringsAndRemoveComments(src)
+
+        for logicalline in splitLogicalLines(src):
+            #print "logicalline=",logicalline    
+            logicalline = logicalline.strip()
+            logicalline = makeLineParseable(logicalline)
+            try:
+                compiler.parse(logicalline)
+            except ParserError:
+                print "ParserError on logicalline:",logicalline
+            except:
+                log.exception("caught exception")
+                
+
+explicitlyContinuedLineWithComment = """
+z = a + b + \  # comment
+  c + d
+pass
+"""
+
+implicitlyContinuedLine = """
+z = a + b + (
+  c + d)
+pass
+"""
+
+
+implicitlyContinuedLine2 = """
+z = a + b + ( c + [d
+  + e]
+  + f)   # comment
+pass
+"""
+
+multilineComment = """
+''' this is an mlc
+so is this
+'''
+pass
+"""
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.INFO)
+    
+    # add soak tests to end of test
+    class Z_SoakTest(BRMTestCase):
+        def test_linesRunThroughPythonParser(self):
+            print ""
+            #print splitLogicalLines(file('/usr/local/lib/python2.2/aifc.py').read())
+            #runOverPath('/usr/local/lib/python2.2/test/badsyntax_nocaret.py')
+            runOverPath('/usr/local/lib/python2.2/')
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_pathutils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import compiler
+import os
+
+from bike import testdata
+from bike.testutils import *
+from bike.mock import Mock
+
+from pathutils import getPathOfModuleOrPackage
+from pathutils import *
+import pathutils as loadmodule
+
+class TestGetFilesForName(BRMTestCase):
+    def testGetFilesForName_recursivelyReturnsFilesInBreadthFirstOrder(self):
+        createPackageStructure("pass", "pass")
+
+        files = getFilesForName(pkgstructureBasedir)
+        for f in files:
+            assert f in \
+                  [os.path.join(pkgstructureBasedir, '__init__.py'), 
+                    os.path.join(pkgstructureBasedir, 'foo.py'), 
+                    os.path.join(pkgstructureChilddir, '__init__.py'), 
+                    os.path.join(pkgstructureChilddir, 'bah.py')]
+
+    def testGetFilesForName_globsStars(self):
+        createPackageStructure("pass", "pass")
+        assert getFilesForName(os.path.join(pkgstructureBasedir, "fo*")) == [os.path.join(pkgstructureBasedir, 'foo.py')]
+        removePackageStructure()
+
+    def testGetFilesForName_doesntListFilesWithDotAtFront(self):
+        writeFile(os.path.join(".foobah.py"),"")
+        files = getFilesForName("a")
+        self.assertEqual([],files)
+        
+
+
+
+class TestGetRootDirectory(BRMTestCase):
+    def test_returnsParentDirectoryIfFileNotInPackage(self):
+        try:
+            # this doesnt have __init__.py file, so
+            # isnt package
+            os.makedirs("a")
+            writeFile(os.path.join("a", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory(os.path.join("a", "foo.py"))
+            assert dir == "a"
+        finally:
+            os.remove(os.path.join("a", "foo.py"))
+            os.removedirs(os.path.join("a"))
+
+    def test_returnsFirstNonPackageParentDirectoryIfFileInPackage(self):
+        try:
+            os.makedirs(os.path.join("root", "a", "b"))
+            writeFile(os.path.join("root", "a", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory(os.path.join("root", "a", "b", "foo.py"))
+            assert dir == "root"
+        finally:
+            os.remove(os.path.join("root", "a", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "foo.py"))
+            os.removedirs(os.path.join("root", "a", "b"))
+
+    def test_returnsFirstNonPackageParentDirectoryIfPathIsAPackage(self):
+        try:
+            os.makedirs(os.path.join("root", "a", "b"))
+            writeFile(os.path.join("root", "a", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory(os.path.join("root", "a", "b"))
+            assert dir == "root"
+        finally:
+            os.remove(os.path.join("root", "a", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "foo.py"))
+            os.removedirs(os.path.join("root", "a", "b"))
+
+    def test_returnsDirIfDirIsTheRootDirectory(self):
+        try:
+            os.makedirs(os.path.join("root", "a", "b"))
+            writeFile(os.path.join("root", "a", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "__init__.py"), "# ")
+            writeFile(os.path.join("root", "a", "b", "foo.py"), "pass")
+            dir = loadmodule.getRootDirectory("root")
+            assert dir == "root"
+        finally:
+            os.remove(os.path.join("root", "a", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "__init__.py"))
+            os.remove(os.path.join("root", "a", "b", "foo.py"))
+            os.removedirs(os.path.join("root", "a", "b"))
+
+
+class getPackageBaseDirectory(BRMTestCase):
+    def test_returnsBasePackageIfFileInPackageHierarchy(self):
+        try:
+            createPackageStructure("","")
+            dir = loadmodule.getPackageBaseDirectory(pkgstructureFile2)
+            self.assertEqual(pkgstructureBasedir, dir)
+        finally:
+            removePackageStructure()
+
+    def test_returnsFileDirectoryIfFileNotInPackage(self):
+        try:
+            createPackageStructure("","")
+            dir = loadmodule.getPackageBaseDirectory(pkgstructureFile0)
+            self.assertEqual(pkgstructureRootDir, dir)
+        finally:
+            removePackageStructure()
+
+
+class TestGetPathOfModuleOrPackage(BRMTestCase):
+    def test_worksForFullPath(self):
+        try:
+            createPackageStructure("pass","pass")
+            import sys
+            self.assertEqual(getPathOfModuleOrPackage("a.b.bah",
+                                                      [pkgstructureRootDir]),
+                             pkgstructureFile2)
+        finally:
+            removePackageStructure()
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_utils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from utils import *
+
+class Test_CarCdrEtc(unittest.TestCase):
+    def test_carReturnsTheFirstElementOfTheFqn(self):
+        fqn = "apple.pear.foo"
+        assert fqn_car(fqn) == "apple"
+        
+    def test_carReturnsElementInOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_car(fqn) == "apple"
+
+    def test_cdrReturnsTheAllElementsOfTheFqnExceptFirst(self):
+        fqn = "apple.pear.foo"
+        assert fqn_cdr(fqn) == "pear.foo"
+        
+    def test_cdrReturnsEmptyStringForOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_cdr(fqn) == ""
+
+    def test_rcarReturnsTheLastElementOfTheFqn(self):
+        fqn = "apple.pear.foo"
+        assert fqn_rcar(fqn) == "foo"
+        
+    def test_rcarReturnsElementInOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_rcar(fqn) == "apple"
+
+    def test_rdrReturnsTheAllElementsOfTheFqnExceptLast(self):
+        fqn = "apple.pear.foo"
+        assert fqn_rcdr(fqn) == "apple.pear"
+        
+    def test_rdrReturnsEmptyStringForOneElementFqn(self):
+        fqn = "apple"
+        assert fqn_rcdr(fqn) == ""
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/test_visitor.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+from __future__ import generators
+import setpath
+import unittest
+import visitor
+from bike.testutils import *
+
+class TestVisitor(BRMTestCase):
+    def test_callsVistorFunctions(self):
+        tree = createTree()
+
+        class TreeVisitor:
+            def __init__(self):
+                self.txt = []
+
+            def visitAClass(self,node):
+                self.txt.append("visitAClass")
+                self.txt.append(node.txt)
+                return self.visitChildren(node)
+                
+            def visitCClass(self,node):
+                self.txt.append("visitCClass")
+                self.txt.append(node.txt)
+
+            def getTxt(self):
+                return ",".join(self.txt)
+        
+        self.assertEqual(visitor.walk(tree,TreeVisitor()).getTxt(),
+                         "visitAClass,aclass,visitCClass,cclass0,visitCClass,cclass1,visitCClass,cclass2")
+
+
+    def test_callsVisitorFunctionsWithYield(self):
+        tree = createTree()
+        
+        class TreeVisitor:
+            def __init__(self):
+                self.txt = []
+
+            def visitAClass(self,node):
+                self.txt.append("visitAClass")
+                self.txt.append(node.txt)
+                yield node
+                for i in self.visitChildren(node):
+                    yield i
+                
+            def visitCClass(self,node):
+                self.txt.append("visitCClass")
+                self.txt.append(node.txt)
+                if 0: yield 1
+
+            def getTxt(self):
+                return ",".join(self.txt)
+
+        for node in visitor.walkAndGenerate(tree,TreeVisitor()):
+            assert node.txt == "aclass"
+        
+
+def createTree():
+    n = AClass("aclass")
+    for i in xrange(3):
+        b = n.addChildNode(BClass("bclass%d" % i))
+        for j in xrange(20):
+            b = b.addChildNode(BClass("bclass%d" % i))
+        b.addChildNode(CClass("cclass%d" % i))
+    return n
+
+class node(object):
+    def __init__(self,txt):
+        self._childNodes=[]
+        self.txt = txt
+    
+    def addChildNode(self,node):
+        self._childNodes.append(node)
+        return node
+    
+    def getChildNodes(self):
+        return [x for x in self._childNodes]
+
+
+class AClass(node):
+    pass
+
+class BClass(node):
+    pass
+
+class CClass(node):
+    pass
+
+if __name__ == "__main__":
+
+    # add perf test at end of tests
+    class Z_SoakTestFastparser(BRMTestCase):
+        def test_parsesPythonLibraryCorrectly(self):
+
+            class TreeVisitor:
+                pass
+            
+            import time
+
+            tree = createTree()
+
+            t1 = time.time()
+            for i in xrange(1000):
+                visitor.walk(tree,TreeVisitor())
+            print "tree without yield",time.time()-t1
+
+            t1 = time.time()
+            for i in xrange(1000):
+                for node in visitor.walkAndGenerate(tree,TreeVisitor()):
+                    pass
+            print "tree with yield",time.time()-t1
+
+
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+import setpath
+
+import unittest
+
+#import all the tests
+from test_load import *
+from test_newstuff import *
+from test_parserutils import *
+from test_fastparser import *
+from test_fastparserast import *
+
+if __name__ == "__main__":
+    from bike import logging
+    logging.init()
+    log = logging.getLogger("bike")
+    log.setLevel(logging.WARN)
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/utils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,30 @@
+# get the first element of a fully qualified python path
+#(e.g. _car('a.b.c.d') = 'a')
+def fqn_car(fqn):
+    try:
+        return fqn[:fqn.index(".")]
+    except ValueError:   # i.e. no dots in fqn
+        return fqn
+
+# get the other elements of a fully qualified python path
+#(e.g. _cdr('a.b.c.d') = 'b.c.d')
+def fqn_cdr(fqn):
+    try:
+        return fqn[fqn.index(".")+1:]
+    except ValueError:   # i.e. no dots in fqn
+        return ""
+
+# reverse of above _rcar("a.b.c.d") = "d"
+def fqn_rcar(fqn):
+    try:
+        return fqn[fqn.rindex(".")+1:]
+    except ValueError:   # i.e. no dots in fqn
+        return fqn
+
+
+# reverse of above _rcdr("a.b.c.d") = "a.b.c"
+def fqn_rcdr(fqn):
+    try:
+        return fqn[:fqn.rindex(".")]
+    except ValueError:   # i.e. no dots in fqn
+        return ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/parsing/visitor.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,49 @@
+from __future__ import generators
+
+class TreeWalker(object):
+    VERBOSE = 0
+
+    def __init__(self):
+        self.node = None
+        self._cache = {}
+
+    def default(self, node, *args):
+        for child in node.getChildNodes():
+            self.dispatch(child, *args)
+
+    def dispatch(self, node, *args):
+        self.node = node
+        klass = node.__class__
+        meth = self._cache.get(klass, None)
+        if meth is None:
+            className = klass.__name__
+            meth = getattr(self.visitor, 'visit' + className, self.default)
+            self._cache[klass] = meth
+        return meth(node, *args)
+
+    def preorder(self, tree, visitor, *args):
+        """Do preorder walk of tree using visitor"""
+        self.visitor = visitor
+        visitor.visit = self.dispatch
+        visitor.visitChildren = self.default
+        return self.dispatch(tree, *args)
+
+class GeneratingTreeWalker(TreeWalker):
+
+    def default(self, node, *args):
+        for child in node.getChildNodes():
+            for i in self.dispatch(child, *args):
+                yield i
+
+
+def walk(tree, visitor):
+    walker = TreeWalker()
+    walker.preorder(tree, visitor)
+    return walker.visitor
+    
+
+def walkAndGenerate(tree,visitor):
+    walker = GeneratingTreeWalker()
+    return walker.preorder(tree, visitor)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1 @@
+#
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/common.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,333 @@
+from __future__ import generators
+from bike.globals import *
+from bike.parsing.fastparserast import getRoot, Function, Class, Module, getModule
+from bike.parsing.parserutils import generateLogicalLines, makeLineParseable, UnbalancedBracesException, generateLogicalLinesAndLineNumbers
+from bike.parsing.newstuff import getSourceNodesContainingRegex
+from bike.parsing import visitor
+from bike import log
+import compiler
+from compiler.ast import Getattr, Name
+import re
+
+class Match:
+    def __repr__(self):
+        return ",".join([self.filename, str(self.lineno), str(self.colno),
+                         str(self.confidence)])
+    def __eq__(self,other):
+        if self is None or other is None:
+            return False
+        return self.filename == other.filename and \
+               self.lineno == other.lineno and \
+               self.colno == other.colno
+
+def getScopeForLine(sourceNode, lineno):
+    scope = None
+    childnodes = sourceNode.getFlattenedListOfFastParserASTNodes()
+    if childnodes == []:
+        return sourceNode.fastparseroot #module node
+
+    scope = sourceNode.fastparseroot
+
+    for node in childnodes:
+        if node.linenum > lineno: break
+        scope = node
+
+    if scope.getStartLine() != scope.getEndLine(): # is inline
+        while scope.getEndLine() <= lineno:
+            scope = scope.getParent()
+    return scope
+
+
+
+# global from the perspective of 'contextFilename'
+def globalScanForMatches(contextFilename, matchFinder, targetname):
+    for sourcenode in getSourceNodesContainingRegex(targetname, contextFilename):
+        print >> log.progress, "Scanning", sourcenode.filename
+        searchscope = sourcenode.fastparseroot
+        for match in scanScopeForMatches(sourcenode,searchscope,
+                                         matchFinder,targetname):
+            yield match
+
+
+def scanScopeForMatches(sourcenode,scope,matchFinder,targetname):
+    lineno = scope.getStartLine()
+    for line in generateLogicalLines(scope.getMaskedLines()):
+        if line.find(targetname) != -1:
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            scope = getScopeForLine(sourcenode, lineno)
+            matchFinder.reset(line)
+            matchFinder.setScope(scope)
+            matches = visitor.walk(ast, matchFinder).getMatches()
+            for index, confidence in matches:
+                match = Match()
+                match.filename = sourcenode.filename
+                match.sourcenode = sourcenode
+                x, y = indexToCoordinates(line, index)
+                match.lineno = lineno+y
+                match.colno = x
+                match.colend = match.colno+len(targetname)
+                match.confidence = confidence
+                yield match
+        lineno+=line.count("\n")
+    
+
+def walkLinesContainingStrings(scope,astWalker,targetnames):
+    lineno = scope.getStartLine()
+    for line in generateLogicalLines(scope.getMaskedLines()):
+        if lineContainsOneOf(line,targetnames):
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            astWalker.lineno = lineno
+            matches = visitor.walk(ast, astWalker)
+        lineno+=line.count("\n")
+
+
+def lineContainsOneOf(line,targetnames):
+    for name in targetnames:
+        if line.find(name) != -1:
+            return True
+    return False
+
+
+# translates an idx in a logical line into physical line coordinates
+# returns x and y coords
+def indexToCoordinates(src, index):
+    y = src[: index].count("\n")
+    startOfLineIdx = src.rfind("\n", 0, index)+1
+    x = index-startOfLineIdx
+    return x, y
+
+
+
+# interface for MatchFinder classes
+# implement the visit methods
+class MatchFinder:
+    def setScope(self, scope):
+        self.scope = scope
+
+    def reset(self, line):
+        self.matches = []
+        self.words = re.split("(\w+)", line) # every other one is a non word
+        self.positions = []
+        i = 0
+        for word in self.words:
+            self.positions.append(i)
+            #if '\n' in word:  # handle newlines
+            #    i = len(word[word.index('\n')+1:])
+            #else:
+            i+=len(word)
+        self.index = 0
+
+    def getMatches(self):
+        return self.matches
+
+    # need to visit childnodes in same order as they appear
+    def visitPrintnl(self,node):
+        if node.dest:
+            self.visit(node.dest)
+        for n in node.nodes:
+            self.visit(n)
+    
+    def visitName(self, node):
+        self.popWordsUpTo(node.name)
+
+    def visitClass(self, node):
+        self.popWordsUpTo(node.name)
+        for base in node.bases:
+            self.visit(base)
+
+    def zipArgs(self, argnames, defaults):
+        """Takes a list of argument names and (possibly a shorter) list of
+        default values and zips them into a list of pairs (argname, default).
+        Defaults are aligned so that the last len(defaults) arguments have
+        them, and the first len(argnames) - len(defaults) pairs have None as a
+        default.
+        """
+        fixed_args = len(argnames) - len(defaults)
+        defaults = [None] * fixed_args + list(defaults)
+        return zip(argnames, defaults)
+
+    def visitFunction(self, node):
+        self.popWordsUpTo(node.name)
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+    def visitGetattr(self,node):
+        self.visit(node.expr)
+        self.popWordsUpTo(node.attrname)
+
+    def visitAssName(self, node):
+        self.popWordsUpTo(node.name)
+
+    def visitAssAttr(self, node):
+        self.visit(node.expr)
+        self.popWordsUpTo(node.attrname)
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            for nameelem in name.split("."):
+                self.popWordsUpTo(nameelem)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            self.popWordsUpTo(elem)
+        for name, alias in node.names:
+            self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    def visitLambda(self, node):
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+    def visitGlobal(self, node):
+        for name in node.names:
+            self.popWordsUpTo(name)
+
+    def popWordsUpTo(self, word):
+        if word == "*":
+            return        # won't be able to find this
+        posInWords = self.words.index(word)
+        idx = self.positions[posInWords]
+        self.words = self.words[posInWords+1:]
+        self.positions = self.positions[posInWords+1:]
+
+    def appendMatch(self,name,confidence=100):
+        idx = self.getNextIndexOfWord(name)
+        self.matches.append((idx, confidence))
+
+    def getNextIndexOfWord(self,name):
+        return self.positions[self.words.index(name)]
+
+class CouldNotLocateNodeException(Exception): pass
+
+def translateSourceCoordsIntoASTNode(filename,lineno,col):
+    module = getModule(filename)
+    maskedlines = module.getMaskedModuleLines()
+    lline,backtrackchars = getLogicalLine(module, lineno)
+    doctoredline = makeLineParseable(lline)
+    ast = compiler.parse(doctoredline)
+    idx = backtrackchars+col
+    nodefinder = ASTNodeFinder(lline,idx)
+    node = compiler.walk(ast, nodefinder).node
+    if node is None:
+        raise CouldNotLocateNodeException("Could not translate editor coordinates into source node")
+    return node
+
+def getLogicalLine(module, lineno):
+    # we know that the scope is the start of a logical line, so
+    # we search from there
+    scope = getScopeForLine(module.getSourceNode(), lineno)
+    linegenerator = \
+            module.generateLinesWithLineNumbers(scope.getStartLine())
+    for lline,llinenum in \
+            generateLogicalLinesAndLineNumbers(linegenerator):
+        if llinenum > lineno:
+            break
+        prevline = lline
+        prevlinenum = llinenum
+
+    backtrackchars = 0
+    for i in range(prevlinenum,lineno):
+        backtrackchars += len(module.getSourceNode().getLines()[i-1])
+    return prevline, backtrackchars
+
+
+
+class ASTNodeFinder(MatchFinder):
+    # line is a masked line of text
+    # lineno and col are coords
+    def __init__(self,line,col):
+        self.line = line
+        self.col = col
+        self.reset(line)
+        self.node = None
+
+    def visitName(self,node):
+        if self.checkIfNameMatchesColumn(node.name):
+            self.node = node
+        self.popWordsUpTo(node.name)
+
+    def visitGetattr(self,node):
+        self.visit(node.expr)
+        if self.checkIfNameMatchesColumn(node.attrname):
+            self.node = node
+        self.popWordsUpTo(node.attrname)
+
+    def visitFunction(self, node):
+        if self.checkIfNameMatchesColumn(node.name):
+            self.node = node
+        self.popWordsUpTo(node.name)
+
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            if self.checkIfNameMatchesColumn(arg):
+                self.node = Name(arg)
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+
+    visitAssName = visitName
+    visitAssAttr = visitGetattr
+
+    def visitClass(self, node):
+        if self.checkIfNameMatchesColumn(node.name):
+            self.node = node
+        self.popWordsUpTo(node.name)
+        for base in node.bases:
+            self.visit(base)
+
+
+    def checkIfNameMatchesColumn(self,name):
+        idx = self.getNextIndexOfWord(name)
+        #print "name",name,"idx",idx,"self.col",self.col
+        if idx <= self.col and idx+len(name) > self.col:
+            return 1
+        return 0
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            self.popWordsUpTo(elem)
+        for name, alias in node.names:
+            if self.checkIfNameMatchesColumn(name):
+                self.node = self._manufactureASTNodeFromFQN(name)
+                return
+            self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    # gets round the fact that imports etc dont contain nested getattr
+    # nodes for fqns (e.g. import a.b.bah) by converting the fqn
+    # string into a getattr instance
+    def _manufactureASTNodeFromFQN(self,fqn):
+        if "." in fqn:
+            assert 0, "getattr not supported yet"
+        else:
+            return Name(fqn)
+
+def isAMethod(scope,node):
+    return isinstance(node,compiler.ast.Function) and \
+           isinstance(scope,Class)
+
+def convertNodeToMatchObject(node,confidence=100):
+    m = Match()
+    m.sourcenode = node.module.getSourceNode()
+    m.filename = node.filename
+    if isinstance(node,Module):
+        m.lineno = 1
+        m.colno = 0
+    elif isinstance(node,Class) or isinstance(node,Function):
+        m.lineno = node.getStartLine()
+        m.colno = node.getColumnOfName()
+    m.confidence = confidence
+    return m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/findDefinition.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,277 @@
+from __future__ import generators
+from bike.query.common import Match, MatchFinder, \
+     getScopeForLine, indexToCoordinates, \
+     translateSourceCoordsIntoASTNode, scanScopeForMatches, \
+     isAMethod, convertNodeToMatchObject, walkLinesContainingStrings
+from bike.parsing.parserutils import generateLogicalLines,\
+     generateLogicalLinesAndLineNumbers, \
+     splitLogicalLines, makeLineParseable
+import compiler
+from compiler.ast import Getattr, Name, AssName, AssAttr
+from bike.parsing.fastparserast import getRoot, Package, Class, \
+                                       Module, Function, Instance
+import re
+from bike.query.getTypeOf import getTypeOfExpr, UnfoundType, \
+     isWordInLine, resolveImportedModuleOrPackage
+from bike.parsing import visitor
+from bike.parsing.visitor import walkAndGenerate
+
+from bike.parsing.parserutils import makeLineParseable,splitLogicalLines
+from bike.parsing.newstuff import getSourceNodesContainingRegex
+from bike.parsing.load import getSourceNode
+from bike import log
+
+
+class CantFindDefinitionException:
+    pass
+
+
+def findAllPossibleDefinitionsByCoords(filepath,lineno,col):
+    
+    #try:
+    node = translateSourceCoordsIntoASTNode(filepath,lineno,col)
+    #except:
+    #    import traceback
+    #    traceback.print_exc()
+
+    if node is None:
+        raise "selected node type not supported"
+    scope = getScopeForLine(getSourceNode(filepath),lineno)
+    match = findDefinitionFromASTNode(scope,node)
+    if match is not None:
+        yield match
+    if isinstance(node,Getattr) and (match is None or match.confidence != 100):
+        root = getRoot()
+        name = node.attrname
+        for match in scanPythonPathForMatchingMethodNames(name,filepath):
+            yield match
+    print >>log.progress,"done"
+
+
+def findDefinitionFromASTNode(scope,node):
+    assert node is not None
+    if isinstance(node,Name) or isinstance(node,AssName):
+        while 1:
+            # try scope children
+            childscope = scope.getChild(node.name)
+            if childscope is not None:
+                return convertNodeToMatchObject(childscope,100)
+
+            if isinstance(scope,Package):
+                scope = scope.getChild("__init__")
+
+            # try arguments and assignments
+            match = scanScopeAST(scope,node.name,
+                                 AssignmentAndFnArgsSearcher(node.name))
+            if match is not None:
+                return match
+            
+            # try imports
+            match = searchImportedModulesForDefinition(scope,node)
+            if match is not None:
+                return match
+
+
+            if not isinstance(scope,Module):
+                # try parent scope
+                scope = scope.getParent()
+            else:
+                break
+        assert isinstance(scope,Module)
+
+    elif isinstance(node,Getattr) or isinstance(node,AssAttr):
+        exprtype = getTypeOfExpr(scope,node.expr)
+        if not (exprtype is None or isinstance(exprtype,UnfoundType)):
+            if isinstance(exprtype,Instance):
+                exprtype = exprtype.getType()
+                match = findDefinitionOfAttributeFromASTNode(exprtype,
+                                                         node.attrname)
+            else:
+                match = findDefinitionFromASTNode(exprtype,
+                                                  Name(node.attrname))
+            if match is not None:
+                return match
+
+    elif isinstance(node,compiler.ast.Function) or \
+             isinstance(node,compiler.ast.Class):
+        if isAMethod(scope,node): 
+            match = findDefinitionOfAttributeFromASTNode(scope,
+                                                        node.name)
+        else:
+            match = findDefinitionFromASTNode(scope,Name(node.name))
+        if match is not None:
+            return match
+
+
+    type = getTypeOfExpr(scope,node)
+    if type is not None and (not isinstance(type,UnfoundType)) and \
+                             (not isinstance(type,Instance)):
+        return  convertNodeToMatchObject(type,100)
+    else:
+        return None
+
+
+def findDefinitionOfAttributeFromASTNode(type,name):
+    assert isinstance(type,Class)
+    attrfinder = AttrbuteDefnFinder([type],name)
+
+    # first scan the method names:
+    for child in type.getChildNodes():
+        if child.name == name:
+            return convertNodeToMatchObject(child,100)
+    # then scan the method source for attribues
+    for child in type.getChildNodes():
+        if isinstance(child,Function):
+            try:
+                return scanScopeForMatches(child.module.getSourceNode(),
+                                        child, attrfinder,
+                                        name).next()
+            except StopIteration:
+                continue
+
+
+class AttrbuteDefnFinder(MatchFinder):
+    def __init__(self,targetClasses,targetAttribute):
+        self.targetClasses = targetClasses
+        self.targetAttributeName = targetAttribute
+
+    def visitAssAttr(self, node):
+        for c in node.getChildNodes():
+            self.visit(c)
+
+        if node.attrname == self.targetAttributeName:
+            exprtype = getTypeOfExpr(self.scope,node.expr)
+            if isinstance(exprtype,Instance) and \
+               exprtype.getType() in self.targetClasses:
+                self.appendMatch(self.targetAttributeName)
+            #else:
+            #    self.appendMatch(self.targetAttributeName,50)
+        self.popWordsUpTo(node.attrname)
+
+
+    
+
+def searchImportedModulesForDefinition(scope,node):
+    lines = scope.module.getSourceNode().getLines()
+    for lineno in scope.getImportLineNumbers():
+        logicalline = getLogicalLine(lines,lineno)
+        logicalline = makeLineParseable(logicalline)
+        ast = compiler.parse(logicalline)
+        class ImportVisitor:
+            def __init__(self,node):
+                self.target = node
+                self.match = None
+                assert isinstance(self.target,Name), \
+                       "Getattr not supported"
+                
+            def visitFrom(self, node):
+                module = resolveImportedModuleOrPackage(scope,node.modname)
+                if module is None: # couldn't find module
+                    return 
+                
+                if node.names[0][0] == '*': # e.g. from foo import *
+                    match = findDefinitionFromASTNode(module,self.target)
+                    if match is not None:
+                        self.match = match
+                    return
+                    
+                for name, alias in node.names:
+                    if alias is None and name == self.target.name:
+                        match = findDefinitionFromASTNode(module,self.target)
+                        if match is not None:
+                            self.match = match
+                        return
+
+
+        match = visitor.walk(ast, ImportVisitor(node)).match
+        if match:
+            return match
+    # loop
+
+
+def getLogicalLine(lines,lineno):
+    return generateLogicalLines(lines[lineno-1:]).next()
+
+class AssignmentAndFnArgsSearcher(MatchFinder):
+    def __init__(self,name):
+        self.targetname = name
+        self.match = None
+
+    def visitAssName(self, node):
+        if node.name == self.targetname:
+            idx = self.getNextIndexOfWord(self.targetname)
+            self.match = idx
+            return 
+
+    def visitFunction(self, node):
+        self.popWordsUpTo(node.name)
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            if arg == self.targetname:
+                idx = self.getNextIndexOfWord(self.targetname)
+                self.match = idx
+                return
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+    def getMatch(self):
+        return self.match
+
+
+
+# scans for lines containing keyword, and then runs the visitor over
+# the parsed AST for that line
+def scanScopeAST(scope,keyword,matchfinder):
+    lines = scope.generateLinesNotIncludingThoseBelongingToChildScopes()
+    match = None
+    for line,linenum in generateLogicalLinesAndLineNumbers(lines):
+        if isWordInLine(keyword, line):
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            matchfinder.reset(line)
+            match = visitor.walk(ast,matchfinder).getMatch()
+            if match is not None:
+                column,yoffset = indexToCoordinates(line,match)
+                m = createMatch(scope,linenum + yoffset,column)
+                return m
+    return None
+
+def createMatch(scope,lineno,x):
+    m = Match()
+    m.sourcenode = scope.module.getSourceNode()
+    m.filename = m.sourcenode.filename
+    m.lineno = lineno
+    m.colno = x
+    m.confidence = 100
+    return m
+
+# scan for methods globally (from perspective of 'perspectiveFilename')
+def scanPythonPathForMatchingMethodNames(name, contextFilename):
+    class MethodFinder:
+        def __init__(self,srcnode):
+            self.matches = []
+            self.srcnode = srcnode
+        def visitFunction(self,node):
+            node = getScopeForLine(self.srcnode, self.lineno)
+            if isinstance(node.getParent(),Class):
+                if node.name == name:
+                    self.matches.append(convertNodeToMatchObject(node,50))
+
+    for srcnode in getSourceNodesContainingRegex(name,contextFilename):
+        m = MethodFinder(srcnode)
+        walkLinesContainingStrings(srcnode.fastparseroot,m,[name])
+        for match in m.matches:
+            yield match
+
+
+def getIndexOfWord(line,targetword):
+    words = re.split("(\w+)", line)
+    idx = 0
+    for word in words:
+        if word == targetword:
+            break
+        idx += len(word)
+    return idx
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/findReferences.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,224 @@
+from __future__ import generators
+from bike.globals import *
+from bike.parsing.fastparserast import Module, Class, Function, getRoot, Instance
+from bike.query.common import Match, MatchFinder,\
+     getScopeForLine, indexToCoordinates, \
+     translateSourceCoordsIntoASTNode, scanScopeForMatches,\
+     globalScanForMatches, isAMethod, convertNodeToMatchObject
+from compiler.ast import AssName,Name,Getattr,AssAttr
+import compiler
+from findDefinition import findDefinitionFromASTNode
+from bike.query.getTypeOf import getTypeOfExpr, UnfoundType
+from bike.query.relationships import getRootClassesOfHierarchy
+from bike import log
+from bike.parsing.load import getSourceNode
+
+
+class CouldntFindDefinitionException(Exception):
+    pass
+
+def findReferencesIncludingDefn(filename,lineno,col):
+    return findReferences(filename,lineno,col,1)
+
+
+def findReferences(filename,lineno,col,includeDefn=0):
+    sourcenode = getSourceNode(filename)
+    node = translateSourceCoordsIntoASTNode(filename,lineno,col)
+    assert node is not None
+    scope,defnmatch = getDefinitionAndScope(sourcenode,lineno,node)
+
+    try:
+        for match in findReferencesIncludingDefn_impl(sourcenode,node,
+                                                      scope,defnmatch):
+            if not includeDefn and match == defnmatch: 
+                continue        # don't return definition
+            else:
+                yield match
+    except CouldntFindDefinitionException:
+        raise CouldntFindDefinitionException("Could not find definition. Please locate manually (maybe using find definition) and find references from that")
+
+def findReferencesIncludingDefn_impl(sourcenode,node,scope,defnmatch):
+    if isinstance(node,Name) or isinstance(node,AssName):
+        return generateRefsToName(node.name,scope,sourcenode,defnmatch)
+    elif isinstance(node,Getattr) or isinstance(node,AssAttr):
+        exprtype = getTypeOfExpr(scope,node.expr)
+        if exprtype is None or isinstance(exprtype,UnfoundType):
+            raise CouldntFindDefinitionException()
+
+        if isinstance(exprtype,Instance):
+            exprtype = exprtype.getType()
+            return generateRefsToAttribute(exprtype,node.attrname)
+        
+        else:
+            targetname = node.attrname
+            return globalScanForMatches(sourcenode.filename,
+                                        NameRefFinder(targetname, defnmatch),
+                                        targetname, )
+        if match is not None:
+            return match
+    elif isinstance(node,compiler.ast.Function) or \
+                             isinstance(node,compiler.ast.Class):
+        return handleClassOrFunctionRefs(scope, node, defnmatch)
+    else:
+        assert 0,"Seed to references must be Name,Getattr,Function or Class"
+
+def handleClassOrFunctionRefs(scope, node, defnmatch):
+    if isAMethod(scope,node):        
+        for ref in generateRefsToAttribute(scope,node.name):
+            yield ref
+    else:
+        #yield convertNodeToMatchObject(node,100)
+        yield defnmatch
+        for ref in generateRefsToName(node.name,scope,
+                                    scope.module.getSourceNode(),
+                                    defnmatch):
+            yield ref
+
+def getDefinitionAndScope(sourcenode,lineno,node):
+    scope = getScopeForLine(sourcenode,lineno)
+    if scope.getStartLine() == lineno and \
+           scope.matchesCompilerNode(node):  # scope is the node
+        return scope.getParent(), convertNodeToMatchObject(scope,100)
+    defnmatch = findDefinitionFromASTNode(scope,node)
+    if defnmatch is None:
+        raise CouldntFindDefinitionException()
+    scope = getScopeForLine(sourcenode,defnmatch.lineno)
+    return scope,defnmatch
+
+def generateRefsToName(name,scope,sourcenode,defnmatch):
+    assert scope is not None
+    if isinstance(scope,Function):
+        # search can be limited to scope
+        return scanScopeForMatches(sourcenode,scope,
+                                   NameRefFinder(name,defnmatch),
+                                   name)
+    else:        
+        return globalScanForMatches(sourcenode.filename,
+                                    NameRefFinder(name,defnmatch),
+                                    name)
+
+
+class NameRefFinder(MatchFinder):
+    def __init__(self, targetstr,targetMatch):
+        self.targetstr = targetstr
+        self.targetMatch = targetMatch
+        
+    def visitName(self, node):
+        if node.name == self.targetstr:
+            potentualMatch = findDefinitionFromASTNode(self.scope, node)
+            if  potentualMatch is not None and \
+                   potentualMatch == self.targetMatch:
+                self.appendMatch(node.name)
+        self.popWordsUpTo(node.name)
+
+    visitAssName = visitName
+
+    def visitFunction(self, node):
+        self.popWordsUpTo(node.name)
+        for arg, default in self.zipArgs(node.argnames, node.defaults):
+            if arg == self.targetstr:
+                self.appendMatch(arg)
+            self.popWordsUpTo(arg)
+            if default is not None:
+                self.visit(default)
+        self.visit(node.code)
+
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            self.popWordsUpTo(elem)
+            
+        for name, alias in node.names:
+            if name == self.targetstr:
+                if alias is not None:
+                    pretendNode = Name(alias)
+                else:
+                    pretendNode = Name(name)
+                if findDefinitionFromASTNode(self.scope, pretendNode) \
+                                                    == self.targetMatch:
+                    self.appendMatch(name)
+            self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+
+    def visitGetattr(self, node):        
+        for c in node.getChildNodes():
+            self.visit(c)
+        if node.attrname == self.targetstr:
+            defn = findDefinitionFromASTNode(self.scope, node)
+            if defn is not None and defn == self.targetMatch:
+                self.appendMatch(node.attrname)
+        self.popWordsUpTo(node.attrname)
+
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            if name.split(".")[-1] == self.targetstr:
+                getattr = self.createGetattr(name)
+                if findDefinitionFromASTNode(self.scope, getattr) == self.targetMatch:
+                    self.appendMatch(self.targetstr)
+            for nameelem in name.split("."):
+                self.popWordsUpTo(nameelem)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    
+    def createGetattr(self,fqn):
+        node = Name(fqn[0])
+        for name in fqn.split(".")[1:]:
+            node = Getattr(node,name)
+        return node
+                           
+def generateRefsToAttribute(classobj,attrname):
+    rootClasses = getRootClassesOfHierarchy(classobj)
+    attrRefFinder = AttrbuteRefFinder(rootClasses,attrname)
+    for ref in globalScanForMatches(classobj.filename, attrRefFinder, attrname):
+        yield ref
+    print >>log.progress,"Done"
+    
+
+class AttrbuteRefFinder(MatchFinder):
+    def __init__(self,rootClasses,targetAttribute):
+        self.rootClasses = rootClasses
+        self.targetAttributeName = targetAttribute
+
+    
+    def visitGetattr(self, node):
+        for c in node.getChildNodes():
+            self.visit(c)
+
+        if node.attrname == self.targetAttributeName:
+            exprtype = getTypeOfExpr(self.scope,node.expr)            
+
+            if isinstance(exprtype,Instance) and \
+                 self._isAClassInTheSameHierarchy(exprtype.getType()):
+                self.appendMatch(self.targetAttributeName)
+            elif isinstance(exprtype,UnfoundType) or \
+                 exprtype is None:   # couldn't find type, so not sure
+                self.appendMatch(self.targetAttributeName,50)
+            else:
+                pass # definately not a match
+        self.popWordsUpTo(node.attrname)
+
+    visitAssAttr = visitGetattr
+
+    def visitFunction(self,node):  # visit methods
+        if node.name == self.targetAttributeName:
+            parentScope = self.scope.getParent()
+            #print parentScope
+            #print self.targetClasses
+            if isinstance(parentScope,Class) and \
+                   self._isAClassInTheSameHierarchy(parentScope):
+                self.appendMatch(node.name)
+
+        for c in node.getChildNodes():
+            self.visit(c)
+        
+    def _isAClassInTheSameHierarchy(self,classobj):
+        #return classobj in self.targetClasses
+        targetRootClasses = getRootClassesOfHierarchy(classobj)
+        for rootclass in self.rootClasses:
+            if rootclass in targetRootClasses:
+                return True
+        return False
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getAllRelatedClasses.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,47 @@
+
+
+"""
+
+def getAllRelatedClasses(root,classfqn):
+    classobj = getTypeOf(root,classfqn)
+    rootClasses = _getRootClasses(classobj)
+    #print rootClasses
+    relatedClasses = [] + rootClasses
+    for rootClass in rootClasses:
+        relatedClasses += _getAllSubClasses(rootClass,root)
+    return relatedClasses
+
+def _getRootClasses(klass):
+    if klass is None:  # i.e. dont have base class in our ast
+        return None
+    if klass.getBaseClassNames() == []:  # i.e. is a root class
+        return[klass]
+    else:
+        rootclasses = []
+        for base in klass.getBaseClassNames():
+            baseclass = getTypeOf(klass,base)
+            rootclass = _getRootClasses(baseclass)
+            if rootclass is None:  # base class not in our ast
+                rootclass = [klass]
+            rootclasses+=rootclass
+        return rootclasses
+
+
+def _getAllSubClasses(baseclass, root, subclasses = []):
+    class ClassVisitor:
+        def visitSource(self,node):
+            self.visit(node.fastparseroot)
+            
+        def visitClass(self, node):
+            for basename in node.getBaseClassNames():
+                if basename.find(baseclass.name) != -1 and \
+                       getTypeOf(node,basename) == baseclass:
+                    subclasses.append(node)
+                    _getAllSubClasses(node,root,subclasses)
+            for child in node.getChildNodes():
+                self.visit(child)
+                
+    walk(root, ClassVisitor())
+    return subclasses
+
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getPackageDependencies.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+# fileInPackage is the filename of a file in the package hierarchy
+def getPackageDependencies(fileInPackage):
+    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getReferencesToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,62 @@
+from __future__ import generators
+from bike.query.common import Match, globalScanForMatches, getScopeForLine, MatchFinder
+from getTypeOf import getTypeOf, getTypeOfExpr
+import compiler
+import re
+
+def getReferencesToModule(root, fqn):
+    
+    modulename = fqn.split(".")[-1]
+    moduleobj = getTypeOf(root, fqn)
+    moduleRefFinder = ModuleRefFinder(moduleobj)
+    
+    for ref in globalScanForMatches(moduleRefFinder, modulename):
+        yield ref
+
+        
+class ModuleRefFinder(MatchFinder):
+    def __init__(self, targetmodule):
+        self.targetmodule = targetmodule
+
+    def visitName(self, node):
+        if node.name == self.targetmodule.name:
+            if getTypeOfExpr(self.scope, node) == self.targetmodule:
+                self.appendMatch(node.name)
+        self.popWordsUpTo(node.name)
+
+    def visitImport(self, node):
+        for name, alias in node.names:
+            if name.split(".")[-1] == self.targetmodule.name:
+                if getTypeOf(self.scope, name) == self.targetmodule:
+                    self.appendMatch(self.targetmodule.name)
+            for nameelem in name.split("."):
+                self.popWordsUpTo(nameelem)
+            if alias is not None:
+                self.popWordsUpTo(alias)
+
+    def visitGetattr(self, node):
+        for c in node.getChildNodes():
+            self.visit(c)
+        if node.attrname == self.targetmodule.name:
+            if getTypeOfExpr(self.scope, node) == self.targetmodule:
+                self.appendMatch(self.targetmodule.name)
+        self.popWordsUpTo(node.attrname)
+
+    def visitFrom(self, node):
+        for elem in node.modname.split("."):
+            if elem == self.targetmodule.name:
+                getTypeOf(self.scope, elem) == self.targetmodule
+                self.appendMatch(self.targetmodule.name)
+            self.popWordsUpTo(elem)
+            
+        for name, alias in node.names:
+            if name == self.targetmodule.name:
+                if alias and \
+                   getTypeOf(self.scope, alias) == self.targetmodule:
+                    self.appendMatch(self.targetmodule.name)
+                elif getTypeOf(self.scope, name) == self.targetmodule:
+                    self.appendMatch(self.targetmodule.name)
+            if name != "*":
+                self.popWordsUpTo(name)
+            if alias is not None:
+                self.popWordsUpTo(alias)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/getTypeOf.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,377 @@
+# getTypeOf(scope,fqn) and getTypeOfExpr(scope,ast)
+
+from bike.parsing.fastparserast import Class, Function, Module, Root, getRoot, Package, Instance, getModule
+from bike.parsing.parserutils import generateLogicalLines, makeLineParseable,splitLogicalLines, makeLineParseable
+from bike.parsing import visitor
+from bike import log
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN
+from bike.parsing.pathutils import getPackageBaseDirectory
+from bike.parsing.load import Cache
+import os
+import re
+import compiler
+
+# used if an assignment exists, but cant find type
+# e.g. a = SomeFunctionNotLoaded()
+# (as opposed to 'None' if cant find an assignment)
+class UnfoundType: pass
+
+
+getTypeOfStack = []
+
+# name is the fqn of the reference, scope is the scope ast object from
+# which the question is being asked.
+# returns an fastparser-ast object representing the type
+# or None if type not found
+def getTypeOf(scope, fqn):
+    if isinstance(scope, Root):
+        assert False, "Can't use getTypeOf to resolve from Root. Use getModuleOrPackageUsingFQN instead"
+
+
+    #print "getTypeOf:"+fqn+" -- "+str(scope)
+    #print 
+    #print str(getTypeOfStack)
+    #print 
+    if (fqn,scope) in getTypeOfStack:   # loop protection
+        return None
+
+    # this is crap!
+    hashcode = str(scope)+fqn
+
+    try:
+        getTypeOfStack.append((fqn,scope))
+
+        try:
+            type = Cache.instance.typecache[hashcode]
+        except KeyError:
+            type = getTypeOf_impl(scope, fqn)
+            Cache.instance.typecache[hashcode] = type
+        return type
+    finally:
+        del getTypeOfStack[-1]
+        
+
+
+def getTypeOf_impl(scope, fqn):
+    #print "getTypeOf_impl",scope,fqn
+    if fqn == "None":
+        return None
+
+    if "."in fqn:
+        rcdr = ".".join(fqn.split(".")[:-1])
+        rcar = fqn.split(".")[-1]
+        newscope = getTypeOf(scope,rcdr)
+        if newscope is not None:
+            return getTypeOf(newscope, rcar)
+        else: 
+            #print "couldnt find "+rcdr+" in "+str(scope)
+            pass
+
+    assert scope is not None
+    #assert not ("." in fqn) 
+    
+    if isinstance(scope,UnfoundType):
+        return UnfoundType()
+    
+    if isinstance(scope, Package):
+        #assert 0,scope
+        return handlePackageScope(scope, fqn)
+    elif isinstance(scope,Instance):
+        return handleClassInstanceAttribute(scope, fqn)
+    else:
+        return handleModuleClassOrFunctionScope(scope,fqn)
+
+
+
+def handleModuleClassOrFunctionScope(scope,name):
+    if name == "self" and isinstance(scope,Function) and \
+           isinstance(scope.getParent(),Class):
+        return Instance(scope.getParent())
+    
+    matches = [c for c in scope.getChildNodes()if c.name == name]
+    if matches != []:
+        return matches[0]
+    
+    type = scanScopeSourceForType(scope, name)
+    if type != None:
+        return type
+    
+    #print "name = ",name,"scope = ",scope
+    type = getImportedType(scope, name)   # try imported types
+    #print "type=",type
+    if type != None:
+        return type
+    parentScope = scope.getParent()
+    while isinstance(parentScope,Class):
+        # don't search class scope, since this is not accessible except
+        # through self   (is this true?)
+        parentScope = parentScope.getParent()
+
+    if not (isinstance(parentScope,Package) or isinstance(parentScope,Root)):
+        return getTypeOf(parentScope, name)
+
+
+def handleClassInstanceAttribute(instance, attrname):
+    theClass = instance.getType()
+
+    # search methods and inner classes
+    match = theClass.getChild(attrname)
+    if match:
+        return match
+
+    #search methods for assignments with self.foo getattrs
+    for child in theClass.getChildNodes():
+        if not isinstance(child,Function):
+            continue
+        res = scanScopeAST(child,attrname,
+                          SelfAttributeAssignmentVisitor(child,attrname))
+        if res is not None:
+            return res
+
+def handlePackageScope(package, fqn):
+    #print "handlePackageScope",package,fqn
+    child = package.getChild(fqn)
+    if child:
+        return child
+
+    if isinstance(package,Root):
+        return getModuleOrPackageUsingFQN(fqn)
+
+    # try searching the fs
+    node = getModuleOrPackageUsingFQN(fqn,package.path)
+    if node:
+        return node
+    
+    
+
+
+    # try the package init module
+    initmod = package.getChild("__init__")
+    if initmod is not None:
+        type = getImportedType(initmod, fqn)
+        if type:
+            return type
+    # maybe fqn is absolute
+    return getTypeOf(getRoot(), fqn)
+
+
+wordRE = re.compile("\w+")
+def isWordInLine(word, line):
+    if line.find(word) != -1:
+        words = wordRE.findall(line)
+        if word in words:
+            return 1
+    return 0
+
+def getImportedType(scope, fqn):
+    lines = scope.module.getSourceNode().getLines()
+    for lineno in scope.getImportLineNumbers():
+        logicalline = generateLogicalLines(lines[lineno-1:]).next()
+        logicalline = makeLineParseable(logicalline)
+        ast = compiler.parse(logicalline)
+        match = visitor.walk(ast, ImportVisitor(scope,fqn)).match
+        if match:
+            return match
+        #else loop
+
+class ImportVisitor:
+    def __init__(self,scope,fqn):
+        self.match = None
+        self.targetfqn = fqn
+        self.scope = scope
+
+    def visitImport(self, node):
+        # if target fqn is an import, then it must be a module or package
+        for name, alias in node.names:
+            if name == self.targetfqn:
+                self.match = resolveImportedModuleOrPackage(self.scope,name)
+            elif alias is not None and alias == self.targetfqn:
+                self.match = resolveImportedModuleOrPackage(self.scope,name)
+
+    def visitFrom(self, node):
+        if node.names[0][0] == '*': # e.g. from foo import *
+            if not "."in self.targetfqn:
+                module = resolveImportedModuleOrPackage(self.scope,
+                                                        node.modname)
+                if module:
+                    self.match = getTypeOf(module, self.targetfqn)
+        else:
+            for name, alias in node.names:
+                if alias == self.targetfqn or \
+                   (alias is None and name == self.targetfqn):
+                    scope = resolveImportedModuleOrPackage(self.scope,
+                                                            node.modname)
+                    if scope is not None:
+                        if isinstance(scope,Package):
+                            self.match = getModuleOrPackageUsingFQN(name,scope.path)
+                        else:  
+                            assert isinstance(scope,Module)
+                            self.match = getTypeOf(scope, name)
+
+
+
+
+class TypeNotSupportedException:
+    def __init__(self,msg):
+        self.msg = msg
+
+    def __str__(self):
+        return self.msg
+
+# attempts to evaluate the type of the expression
+def getTypeOfExpr(scope, ast):
+    if isinstance(ast, compiler.ast.Name):
+        return getTypeOf(scope, ast.name)
+
+    elif isinstance(ast, compiler.ast.Getattr) or \
+             isinstance(ast, compiler.ast.AssAttr):
+
+        # need to do this in order to match foo.bah.baz as
+        # a string in import statements
+        fqn = attemptToConvertGetattrToFqn(ast)
+        if fqn is not None:
+            return getTypeOf(scope,fqn)
+
+        expr = getTypeOfExpr(scope, ast.expr)
+        if expr is not None:
+            attrnametype = getTypeOf(expr, ast.attrname)
+            return attrnametype
+        return None
+
+    elif isinstance(ast, compiler.ast.CallFunc):
+        node = getTypeOfExpr(scope,ast.node)
+        if isinstance(node,Class):
+            return Instance(node)
+        elif isinstance(node,Function):
+            return getReturnTypeOfFunction(node)
+    else:
+        #raise TypeNotSupportedException, \
+        #      "Evaluation of "+str(ast)+" not supported. scope="+str(scope)
+        print >> log.warning, "Evaluation of "+str(ast)+" not supported. scope="+str(scope)
+        return None
+
+
+def attemptToConvertGetattrToFqn(ast):
+    fqn = ast.attrname
+    ast = ast.expr
+    while isinstance(ast,compiler.ast.Getattr):
+        fqn = ast.attrname + "." + fqn
+        ast = ast.expr
+    if isinstance(ast,compiler.ast.Name):
+        return ast.name + "." + fqn
+    else:
+        return None
+
+
+getReturnTypeOfFunction_stack = []
+def getReturnTypeOfFunction(function):
+    if function in getReturnTypeOfFunction_stack:   # loop protection
+        return None
+    try:
+        getReturnTypeOfFunction_stack.append(function)
+        return getReturnTypeOfFunction_impl(function)
+    finally:
+        del getReturnTypeOfFunction_stack[-1]
+
+def getReturnTypeOfFunction_impl(function):
+    return scanScopeAST(function,"return",ReturnTypeVisitor(function))
+    
+
+# does parse of scope sourcecode to deduce type
+def scanScopeSourceForType(scope, name):
+    return scanScopeAST(scope,name,AssignmentVisitor(scope,name))
+
+
+# scans for lines containing keyword, and then runs the visitor over
+# the parsed AST for that line
+def scanScopeAST(scope,keyword,astvisitor):
+    lines = scope.getLinesNotIncludingThoseBelongingToChildScopes()
+    src = ''.join(lines)
+    match = None
+    #print "scanScopeAST:"+str(scope)
+    for line in splitLogicalLines(src):
+        if isWordInLine(keyword, line):
+            #print "scanning for "+keyword+" in line:"+line[:-1]
+            doctoredline = makeLineParseable(line)
+            ast = compiler.parse(doctoredline)
+            match = visitor.walk(ast,astvisitor).getMatch()
+            if match:
+                return match
+    return match
+    
+
+class AssignmentVisitor:
+    def __init__(self,scope,targetName):
+        self.match=None
+        self.scope = scope
+        self.targetName = targetName
+
+    def getMatch(self):
+        return self.match
+
+    def visitAssign(self,node):
+        if isinstance(node.expr,compiler.ast.CallFunc):
+            for assnode in node.nodes:
+                if isinstance(assnode,compiler.ast.AssName) and \
+                   assnode.name == self.targetName:
+                    self.match = getTypeOfExpr(self.scope,node.expr)
+                    if self.match is None:
+                        self.match = UnfoundType()
+                    
+                    
+
+class SelfAttributeAssignmentVisitor:
+    def __init__(self,scope,targetName):
+        self.match=None
+        self.scope = scope
+        self.targetName = targetName
+
+    def getMatch(self):
+        return self.match
+
+    def visitAssign(self,node):
+        if isinstance(node.expr,compiler.ast.CallFunc):
+            for assnode in node.nodes:
+                if isinstance(assnode,compiler.ast.AssAttr) and \
+                   isinstance(assnode.expr,compiler.ast.Name) and \
+                   assnode.expr.name == "self" and \
+                   assnode.attrname == self.targetName:
+                    self.match = getTypeOfExpr(self.scope,node.expr)
+                    #print "here!",self.match.getType().fqn
+
+
+class ReturnTypeVisitor:
+    def __init__(self,fn):
+        self.match=None
+        self.fn = fn
+
+    def getMatch(self):
+        return self.match
+    
+    def visitReturn(self,node):
+        try:
+            self.match = getTypeOfExpr(self.fn,node.value)
+        except TypeNotSupportedException, ex:
+            pass
+
+
+def resolveImportedModuleOrPackage(scope,fqn):
+    # try searching from directory containing scope module
+    path = os.path.dirname(scope.module.filename)
+    node = getModuleOrPackageUsingFQN(fqn,path)
+    if node is not None:
+        return node
+
+    # try searching in same package hierarchy
+    basedir = getPackageBaseDirectory(scope.module.filename)
+    if fqn.split('.')[0] == os.path.split(basedir)[-1]:
+        # base package in fqn matches base directory
+        restOfFqn = ".".join(fqn.split('.')[1:])
+        node = getModuleOrPackageUsingFQN(restOfFqn,basedir)
+    if node is not None:
+        return node
+
+    # try searching the python path
+    node = getModuleOrPackageUsingFQN(fqn)
+    if node is not None:
+        return node
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/relationships.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,26 @@
+# queries to do with module/class/function relationships
+from __future__ import generators
+from bike.globals import *
+from getTypeOf import getTypeOf, getTypeOfExpr
+from bike.parsing.newstuff import generateModuleFilenamesInPythonPath, generateModuleFilenamesInPackage, getPythonPath
+from bike.parsing.pathutils import getPackageBaseDirectory
+from bike.query.common import MatchFinder, walkLinesContainingStrings, getScopeForLine
+from bike import log
+from bike.parsing.fastparserast import Module
+import re
+
+def getRootClassesOfHierarchy(klass):
+    if klass is None:  # i.e. dont have base class in our ast
+        return None
+    if klass.getBaseClassNames() == []:  # i.e. is a root class
+        return [klass]
+    else:
+        rootclasses = []
+        for base in klass.getBaseClassNames():
+            baseclass = getTypeOf(klass,base)
+            rootclass = getRootClassesOfHierarchy(baseclass)
+            if rootclass is None:  # base class not in our ast
+                rootclass = [klass]
+            rootclasses+=rootclass
+        return rootclasses
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath(".."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_common.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+import compiler
+from bike.testutils import *
+from bike.parsing.load import getSourceNode
+from bike.parsing.fastparser import fastparser
+from bike.parsing.fastparserast import Module, Class
+from common import indexToCoordinates, getScopeForLine, walkLinesContainingStrings, translateSourceCoordsIntoASTNode
+
+
+class TestGetScopeForLine(BRMTestCase):
+
+    def test_worksWithFunctionScope(self):
+        src = trimLines("""
+        class a:
+            def foo():
+                pass
+        """)
+        node = createAST(src)
+        self.assertEqual(getScopeForLine(node,3).name,"foo")
+
+    def test_worksWithModuleScope(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        node = createAST(src)
+        assert isinstance(getScopeForLine(node,3),Module)
+
+    def test_worksWithInlineClass(self):
+        src = trimLines("""
+        class TheClass: pass""")
+        node = createAST(src)
+        assert isinstance(getScopeForLine(node,1),Class)
+
+
+class TestIndexToCoordinates(BRMTestCase):
+
+    def test_worksOnSingleLineString(self):
+        src = trimLines('''
+        foo bah
+        ''')
+        x,y = indexToCoordinates(src,src.index("bah"))
+        self.assertEqual(x,4)
+        self.assertEqual(y,0)
+        x,y = indexToCoordinates(src,src.index("foo"))
+        self.assertEqual(x,0)
+        self.assertEqual(y,0)
+
+    def test_worksOnMultilLineString(self):
+        src = trimLines('''
+        foo bah
+        baz boh
+        ''')
+        x,y = indexToCoordinates(src,src.index("boh"))
+        self.assertEqual(x,4)
+        self.assertEqual(y,1)
+
+
+class TestTranslateSourceCoordsIntoASTNode(BRMTestCase):
+
+    def test_worksOnImport(self):
+        src = trimLines('''
+        from foo import bar, baz
+        ''')
+        createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        node = translateSourceCoordsIntoASTNode(filename, 1, 17)
+        assert node.name == 'bar'
+
+    def test_worksOnMultiline(self):
+        src = trimLines("""
+        def foo(x,
+                y,
+                z):
+            return x*y*z
+        """)
+        createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        node = translateSourceCoordsIntoASTNode(filename, 3, 8)
+        assert node.name == 'z'
+
+        
+
+
+class TestMatchFinder(BRMTestCase):
+
+    def test_visitLambda(self):
+        from common import MatchFinder
+        finder = MatchFinder()
+        src = '''x = lambda a, b, c=None, d=None: (a + b) and c or d'''
+        ast = compiler.parse(src)
+        finder.reset(src)
+        compiler.walk(ast, finder)
+
+
+class TestWalkLinesContainingStrings(BRMTestCase):
+    def test_walksClasses(self):
+        src=trimLines("""
+        class TestClass(a,
+                        baseclass):
+            pass
+        """)
+        class MyWalker:            
+            def visitClass(self, node):
+                self.basenames = []
+                for name in node.bases:
+                    self.basenames.append(name.name)
+        
+        writeTmpTestFile(src)
+        srcnode = getSourceNode(tmpfile)
+        walker = MyWalker()
+        walkLinesContainingStrings(srcnode.fastparseroot,walker,
+                                   "baseclass")
+        self.assertEqual(["a","baseclass"],walker.basenames)
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_findDefinition.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,632 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+
+from bike import testdata
+from bike.query.findDefinition import findAllPossibleDefinitionsByCoords
+from bike.query.getTypeOf import getTypeOf,resolveImportedModuleOrPackage
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN
+from bike.parsing.fastparserast import getRoot
+from bike.testutils import *
+        
+class TestFindDefinitionByCoords(BRMTestCase):
+
+    def test_findsClassRef(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),3,6)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def tests_findsMethodRef(self):
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),5,3)]
+
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 100
+        
+
+    def test_returnsOtherMethodsWithSameName(self):
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = SomeOtherClass()
+        a.theMethod()
+        """)
+
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),5,3)]
+
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 50
+
+
+
+
+    def test_findsTemporaryDefinition(self):
+        src=trimLines("""
+        a = 3
+        b = a + 1
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),2,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsArgumentDefinition(self):
+        src=trimLines("""
+        def someFunction(a):
+            b = a + 1
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),2,8)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 17
+        assert defn[0].confidence == 100
+
+    def test_findsClassInstanceDefinition(self):
+        src=trimLines("""
+        class TheClass():
+            pass
+        a = TheClass()
+        print a
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),4,6)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 3
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitionInParentScope(self):
+        src=trimLines("""
+        a = 3
+        def foo(self):
+            b = a + 1
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),3,8)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitionWithinFunction(self):
+        src=trimLines("""
+        def foo(yadda):
+            a = someFunction()
+            print a
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),3,10)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 4
+        assert defn[0].confidence == 100
+        
+
+    def test_findsDefinitionFromSubsequentAssignment(self):
+        src=trimLines("""
+        def foo(yadda):
+            a = 3
+            print a
+            a = 5
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),4,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 4
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitionFromDefinition(self):
+        src=trimLines("""
+        def foo(yadda):
+            a = 3
+            print a
+            a = 5
+        """)
+        createSourceNodeAt(src,"mymodule")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(os.path.abspath("mymodule.py"),4,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 4
+        assert defn[0].confidence == 100
+
+
+    def test_findsClassRefUsingFromImportStatement(self):
+        src=trimLines("""
+        from a.b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(classsrc, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,1,21)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingFromImportStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import mytext
+        print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,6)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingImportStatement(self):
+        importsrc=trimLines("""
+        import a.b.bah
+        print a.b.bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,14)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingFromImportStarStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import *
+        print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        createSourceNodeAt(importsrc,"a.foo")
+        createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,6)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsVariableRefUsingFromPackageImportModuleStatement(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        print bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.b.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","b","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,10)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsImportedVariableRefInAFunctionArg(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        someFunction(bah.mytext)
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.b.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","b","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,17)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefUsingFromImportStatementInFunction(self):
+        importsrc=trimLines("""
+        def foo:
+            from a.b.bah import mytext
+            print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,3,10)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a","b","bah.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+    def test_findsVariableRefByImportingModule(self):
+        importsrc=trimLines("""
+        import a.b.bah
+        print a.b.bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        defn = self.helper(importsrc, src, 2, 14)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def test_findsVariableRefByImportingModuleWithFrom(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        someFunction(bah.mytext)
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+
+        defn = self.helper(importsrc, src, 2, 17)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 0
+        assert defn[0].confidence == 100
+
+
+    def helper(self, src, classsrc, line, col):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile1
+            #Root(None,None,[pkgstructureRootDir])
+            defn = [x for x in findAllPossibleDefinitionsByCoords(filename,line,col)]
+        finally:
+            removePackageStructure()
+        return defn
+
+    def test_doesntfindVariableRefOfUnimportedModule(self):
+        importsrc=trimLines("""
+        # a.b.bah not imported
+        print a.b.bah.mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        root = createSourceNodeAt(importsrc,"a.b.foo")
+        root = createSourceNodeAt(src, "a.b.bah")
+        filename = os.path.abspath(os.path.join("a","b","foo.py"))        
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,14)]
+        self.assertEqual(defn,[])
+
+
+
+    def test_findsSelfAttributeDefinition(self):
+        src=trimLines("""
+        class MyClass:
+           def __init__(self):
+               self.a = 'hello'
+           def myMethod(self):
+               print self.a
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,5,18)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 3
+        assert defn[0].colno == 12
+        assert defn[0].confidence == 100
+
+    def test_findsSelfAttributeDefinitionFromSamePlace(self):
+        src=trimLines("""
+        class MyClass:
+           def __init__(self):
+               self.a = 'hello'
+           def myMethod(self):
+               print self.a
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,3,12)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 3
+        assert defn[0].colno == 12
+        assert defn[0].confidence == 100
+
+
+    def test_findsSelfAttributeDefinition(self):
+        src=trimLines("""
+        class MyClass:
+            def someOtherFn(self):
+                pass
+            def load(self, source):
+                # fastparser ast
+                self.fastparseroot = fastparser(source,self.modulename)
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,6,14)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 6
+        assert defn[0].colno == 13
+        assert defn[0].confidence == 100
+
+
+    def test_findsDefnOfInnerClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,4,14)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 10
+        assert defn[0].confidence == 100
+
+    def test_findsDefnOfOuterClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,4,4)]
+        assert defn[0].filename == os.path.abspath("mymodule.py")
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+    def test_findsClassDeclaredIn__init__Module(self):
+        importsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        src=trimLines("""
+        from a import TheClass
+        c = TheClass()
+        """)
+
+
+
+        root = createSourceNodeAt(importsrc,"a.__init__")
+        root = createSourceNodeAt(src, "mymodule")
+        filename = os.path.abspath("mymodule.py")
+        defn = [x for x in findAllPossibleDefinitionsByCoords(filename,2,6)]
+        assert defn[0].filename == os.path.abspath(os.path.join("a",
+                                                                "__init__.py"))
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+class TestFindDefinitionUsingFiles(BRMTestCase):
+    def test_findsASimpleDefinitionUsingFiles(self):
+        src=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        writeTmpTestFile(src)
+        defn = [x for x in findAllPossibleDefinitionsByCoords(tmpfile,3,6)]
+        assert defn[0].filename == tmpfile
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+    def test_findsDefinitionInAnotherModuleUsingFiles(self):
+        src=trimLines("""
+        from a.b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        defn = self.helper(src, classsrc, 1, 21)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+
+
+    def test_findsDefinitionInAnotherRelativeModuleUsingFiles(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            pass
+        """)
+        defn = self.helper(src, classsrc,1,21)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def test_findsMethodDefinitionInAnotherModuleUsingFiles(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        defn = self.helper(src, classsrc, 3, 2)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 100
+
+    def test_findsDefinitonOfMethodWhenUseIsOnAMultiLine(self):
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        src=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        i,j = (32,
+               a.theMethod())  # <--- find me!
+        something=somethingelse
+        """)
+        defn = self.helper(src, classsrc, 4, 9)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 2
+        assert defn[0].colno == 8
+        assert defn[0].confidence == 100
+
+
+    def test_findsDefinitionWhenUseIsOnAMultilineAndNextLineBalancesBrace(self):
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        src=trimLines("""
+        from b.bah import TheClass
+        c = TheClass()
+        f1, f2 = (c.func1, 
+                c.theMethod)
+        f1, f2 = (c.func1, 
+                c.theMethod)
+        """)
+        defn = self.helper(src, classsrc, 4, 10)
+        self.assertEqual(pkgstructureFile2,defn[0].filename)
+        self.assertEqual(2,defn[0].lineno)
+        self.assertEqual(8,defn[0].colno)
+        self.assertEqual(100,defn[0].confidence)
+
+    def test_worksIfFindingDefnOfRefInSlashMultiline(self):
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        src=trimLines("""
+        from b.bah import TheClass
+        c = TheClass()
+        f1, f2 = c.func1 \\
+               ,c.theMethod
+        """)
+        defn = self.helper(src, classsrc, 4, 10)
+        self.assertEqual(pkgstructureFile2,defn[0].filename)
+        self.assertEqual(2,defn[0].lineno)
+        self.assertEqual(8,defn[0].colno)
+        self.assertEqual(100,defn[0].confidence)
+
+    def test_findsDefnInSameNonPackageDirectory(self):
+        try:
+            getRoot().pythonpath = []   # clear the python path
+            classsrc = trimLines("""
+            def testFunction():
+                print 'hello'
+            """)
+            src = trimLines("""
+            from baz import testFunction
+            """)
+            writeTmpTestFile(src)
+            newtmpfile = os.path.join(tmproot,"baz.py")
+            writeFile(newtmpfile, classsrc)
+            refs = [x for x in findAllPossibleDefinitionsByCoords(tmpfile,1,16)]
+            assert refs[0].filename == newtmpfile
+            assert refs[0].lineno == 1
+        finally:
+            os.remove(newtmpfile)
+            deleteTmpTestFile()
+
+
+    def test_findsDefnInPackageSubDirectoryAndRootNotInPath(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        getRoot().pythonpath = []   # clear the python path
+        defn = self.helper(src, classsrc, 1, 18)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def test_findsDefnInSamePackageHierarchyAndRootNotInPath(self):
+        src=trimLines("""
+        from a.b.bah import TheClass
+        """)
+        classsrc=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        getRoot().pythonpath = []   # clear the python path
+        defn = self.helper(src, classsrc, 1, 20)
+        assert defn[0].filename == pkgstructureFile2
+        assert defn[0].lineno == 1
+        assert defn[0].colno == 6
+        assert defn[0].confidence == 100
+
+    def helper(self, src, classsrc, line, col):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile1
+            #Root(None,None,[pkgstructureRootDir])
+            defn = [x for x in findAllPossibleDefinitionsByCoords(filename,line,col)]
+        finally:
+            removePackageStructure()
+        return defn
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_findReferences.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,516 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+#from bike.testutils import trimLines, createSourceNodeAt, \
+#     createSourceNodeAt_old, BRMTestCase
+from bike import testdata
+from findReferences import findReferences, findReferencesIncludingDefn
+from bike.query.getTypeOf import getTypeOf
+
+class helpers:
+    def helper(self,src,lineno,colno):
+        writeTmpTestFile(src)
+        refs =  [x for x in findReferences(tmpfile,lineno,colno)]
+        return refs
+
+    def helper2(self,src,lineno,colno):
+        writeTmpTestFile(src)
+        refs =  [x for x in findReferencesIncludingDefn(tmpfile,lineno,
+                                                           colno)]
+        return refs
+        
+    def helper3(self, src, importedsrc, line, col):
+        createPackageStructure(src,importedsrc)
+        filename = pkgstructureFile2
+        refs =  [x for x in findReferences(filename,line,col)
+                 if x.confidence == 100]
+        return refs
+
+    def helper4(self, src, importedsrc, line, col):
+        createPackageStructure(src,importedsrc)
+        filename = pkgstructureFile1
+        refs =  [x for x in findReferences(filename,line,col)
+                 if x.confidence == 100]
+        return refs
+
+    
+
+class TestFindReferences(BRMTestCase,helpers):
+    def test_findsSimpleReferencesGivenAssignment(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+        refs = self.helper(src,3,10)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 3
+        assert refs[0].colno == 10
+        assert refs[0].confidence == 100
+
+
+
+    def test_findsSimpleReferencesGivenReference(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+
+        refs = self.helper2(src,3,10)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 2
+        assert refs[0].colno == 4
+        assert refs[0].confidence == 100
+
+
+    def test_findsReferencesToOtherAssignments(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            a = 4
+        """)
+        refs = self.helper(src,2,4)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 3
+        assert refs[0].colno == 4
+        assert refs[0].confidence == 100
+
+    def test_findsFunctionArg(self):
+        src=trimLines("""
+        def foo(a):
+            print a
+        """)
+        refs = self.helper2(src,2,10)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 1
+        assert refs[0].colno == 8
+        assert refs[0].confidence == 100
+
+    def test_findsFunctionArgWithDefault(self):
+        src=trimLines("""
+        def foo(a=None, b=None):
+            print a, b
+        """)
+        refs = self.helper(src,1,4)
+        self.assertEquals(refs, [])
+
+    def test_findsFunctionArgWithDefault2(self):
+        src=trimLines("""
+        def foo(a=None, b=None):
+            print a, b
+        """)
+        refs = self.helper2(src,2,13)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 1
+        assert refs[0].colno == 16
+        assert refs[0].confidence == 100
+
+
+    def test_findsReferencesGivenFunctionArg(self):
+        src=trimLines("""
+        def foo(a):
+            print a
+        """)
+        refs = self.helper(src,1,8)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 2
+        assert refs[0].colno == 10
+        assert refs[0].confidence == 100
+
+
+    def test_findsVariableRefInImportStatementUsingFromImportStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        refs = self.helper3(importsrc,src,1,1)
+        assert refs[0].filename == pkgstructureFile1        
+        assert refs[0].lineno == 1
+        assert refs[0].colno == 20
+        assert refs[0].confidence == 100
+
+
+
+    def test_findsVariableRefUsingFromImportStatement(self):
+        importsrc=trimLines("""
+        from a.b.bah import mytext
+        print mytext
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        refs = self.helper3(importsrc,src,1,1)
+        assert refs[0].filename == pkgstructureFile1        
+        assert refs[1].lineno == 2
+        assert refs[1].colno == 6
+        assert refs[1].confidence == 100
+
+    def test_findsImportedVariableRefInAFunctionArg(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        someFunction(bah.mytext)
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)
+        refs = self.helper3(importsrc,src,1,1)
+        assert refs[0].filename == pkgstructureFile1        
+        assert refs[0].lineno == 2
+        assert refs[0].colno == 17
+        assert refs[0].confidence == 100
+
+    def test_getsReferenceOfSimpleMethodCall(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        refs = self.helper4(src,testdata.TheClass,3,2)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,2)
+
+
+    def test_findsRefToSelfAttribute(self):
+        src=trimLines("""
+        class MyClass:
+           def __init__(self):
+               self.a = 'hello'
+           def myMethod(self):
+               print self.a
+        """)
+        refs = self.helper(src,3,12)
+        assert refs[0].filename == tmpfile
+        assert refs[0].lineno == 5
+        assert refs[0].colno == 18
+        assert refs[0].confidence == 100
+
+
+class FindReferencesToMethod(BRMTestCase,helpers):
+    def test_findsReferenceOfSimpleMethodCall(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,2)
+        self.assertEqual(refs[0].colno,2)
+
+    def test_getsReferenceOfMethodCallFromClassImportedWithAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceOfMethodCallWhenInstanceReturnedByFunction(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            return TheClass()
+        a = foo()
+        a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,6)
+        self.assertEqual(refs[0].colno,2)
+
+    def test_getsReferenceOfMethodCallInSameClass(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+            def anotherMethod(self):
+                self.theMethod()
+        """)
+        refs = self.helper4(src,testClass,2,8)
+        assert refs[0].filename == pkgstructureFile1
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,13)
+
+    def test_getsReferenceOfMethodOnBaseClassInstance(self):
+        src = trimLines("""
+        class root:
+            def theMethod(self):
+                pass
+                
+        class a(root):
+            def theMethod(self):
+                pass
+                
+        class b(root):
+            pass
+            
+        class TheClass(b):
+            def theMethod(self):
+                pass
+                
+        rootinstance = root()
+        rootinstance.theMethod()
+        """)
+        refs = self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[2].filename,pkgstructureFile1)
+        self.assertEqual(refs[2].lineno,17)
+        self.assertEqual(refs[2].colno,13)
+        
+    def test_doesntGetReferenceToMethodWhenObjectCreatedInChildScopeToMethodReference(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        refs = self.helper3(src,testClass,2,8)
+        assert refs == []
+        
+    def test_renamesMethodReferenceOfInstanceCreatedInSubsequentFunction(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.theMethod()
+            
+        def bah():
+            return TheClass()
+        """)
+        refs = self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,10)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceInMiddleOfBiggerCompoundCall(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self): return AnotherClass()
+        TheClass().theMethod().anotherMethod()
+        """)
+
+        refs = self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,11)
+        self.assertEqual(refs[0].colend,20)
+
+    def test_doesntBarfWhenObjectIsArrayMember(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a[0] = TheClass()
+        a[0].theMethod()
+        """)
+        refs = self.helper4(src,"pass",2,8)
+        # should get to here without exception
+
+class FindReferencesToClass(BRMTestCase, helpers):
+    def test_returnsEmptyListIfNoReferences(self):
+        src = trimLines("""
+        class MyClass:
+            pass
+        a = TheClass()
+        """)
+        refs = self.helper4(src,"pass",1,6)
+        assert refs == []
+
+
+    def test_findsSimpleReferenceInSameModule(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        refs = self.helper4(src,"pass",1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_doesntBarfOnSingleLineSourceWithInlineClass(self):
+        src=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        """)
+        refs = self.helper3(src,"class TheClass: pass",1,6)
+        assert refs != []
+
+    def test_findsReferenceToClassImportedInSameClassScope(self):
+        src=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+        refs = self.helper3(src,"class TheClass: pass",1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,22)
+
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,4)
+
+    def testFindsClassReferenceWhenScopeIsSameNameAsClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        refs = self.helper4(src,"pass",2,10)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,4)
+        self.assertEqual(refs[0].colno,13)
+        self.assertEqual(refs[0].confidence,100)
+
+    def testFindsClassReferenceWhenChildIsSameNameAsClass(self):
+        src = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        refs = self.helper4(src,"pass",1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,4)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+
+class TestFindReferencesIncludingDefn(BRMTestCase,helpers):
+    def test_findsMethodDecl(self):
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        refs = self.helper2(src,2,8)
+        self.assertEqual(refs[0].filename,tmpfile)
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,8)
+        self.assertEqual(refs[0].confidence,100)
+
+
+
+class TestFindReferencesUsingFiles(BRMTestCase):
+    def test_findsSimpleReferencesUsingFiles(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+        refs = self.helper("pass",src,2,4)
+        assert refs[0].filename == pkgstructureFile2
+        assert refs[0].lineno == 3
+        assert refs[0].colno == 10
+        assert refs[0].confidence == 100
+        
+    def test_findsReferenceInModuleWhichImportsClassWithFromAndAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        def foo():
+            a = MyTheClass()
+        """)
+        refs = self.helper(src,testClass,1,6)
+        self.assertEqual(refs[0].filename,pkgstructureFile1)
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_doesntBarfWhenCantLocatePackageWhenTryingToFindBaseClass(self):
+        src = trimLines("""
+        from doesntexist import baseclass
+        class foo(baseclass):
+            def myMethod(self):
+                pass
+        """)
+        refs = self.helper("",src,3,8)
+
+    def test_doesntBarfWhenComesAcrossAPrintNl(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+
+        print >>foo, TheClass
+        """)
+        refs = self.helper("",src,1,6)
+
+
+    def test_returnsOtherFilesInSameNonPackageDirectory(self):
+        try:
+            getRoot().pythonpath = []   # clear the python path
+            classsrc = trimLines("""
+            def testFunction():
+                print 'hello'
+            """)
+            src = trimLines("""
+            from baz import testFunction
+            """)
+            writeTmpTestFile(src)
+            newtmpfile = os.path.join(tmproot,"baz.py")
+            writeFile(newtmpfile, classsrc)
+            refs = [x for x in findReferences(newtmpfile,1,4)]
+
+            assert refs[0].filename == tmpfile
+            assert refs[0].lineno == 1
+        finally:
+            os.remove(newtmpfile)
+            deleteTmpTestFile()
+
+
+
+
+    def helper(self, src, classsrc, line, col):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile2
+            refs = [x for x in findReferences(filename,line,col)]
+        finally:
+            removePackageStructure()
+        return refs
+
+
+
+
+testClass = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getPackageDependencies.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+
+class TestGetPackageDependencies(BRMTestCase):
+    def test_foo(self):
+        assert 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getReferencesToClass.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,280 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.findReferences import findReferences
+from bike.parsing.fastparserast import Module
+
+class TestGetReferencesToClass(BRMTestCase):
+    def test_returnsEmptyListIfNoReferences(self):
+        src = trimLines("""
+        class MyClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        refs = [x for x in findReferences(os.path.abspath("mymodule.py"),1,6)]
+        self.assertEqual(refs,[])
+
+    def test_findsSimpleReferenceInSameModule(self):
+        src = trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        refs = [x for x in findReferences(os.path.abspath("mymodule.py"),1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath("mymodule.py"))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferencesInModuleWhichImportsClass(self):
+        src = trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        refs = [x for x in findReferences(os.path.abspath("a/b/bah.py"),1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_findsReferenceInModuleWhichImportsClassWithFrom(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        def foo():
+            a = TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a/foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,8)
+        self.assertEqual(refs[1].confidence,100)
+
+    def test_findsReferenceToClassImportedInSameClassScope(self):
+        src=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        assert refs != []
+
+    def test_findsReferenceInModuleWhichImportsClassWithFromAndAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_findsReferenceInModuleWhichImportsClassWithImportAs(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceInModuleWhichImportsClassWithFromImportStar(self):
+        src = trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceInModuleWhichImportsClassWithFromImportStar2(self):
+        src = trimLines("""
+        from a.b.bah import *
+        a = TheClass()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_findsClassReferenceInInstanceCreation(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self): pass
+        TheClass().theMethod()
+        """)
+        root = createSourceNodeAt(src, "a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,0)
+        self.assertEqual(refs[0].confidence,100)
+
+    
+    def test_findsClassReferenceInInstanceCreationWithFQN(self):
+        src = trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_doesntfindReferenceInModuleWhichDoesntImportClass(self):
+        src = trimLines("""
+        a = TheClass()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        assert refs == []
+
+    def test_findsReferenceInClassBases(self):
+        src =trimLines("""
+        from b.bah import TheClass
+        class DerivedClass(TheClass):
+            pass
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,2)
+        self.assertEqual(refs[1].colno,19)
+        self.assertEqual(refs[1].confidence,100)
+        
+
+    
+    def test_findsReferenceInMultiLineImportStatement(self):
+        src =trimLines("""
+        from b.bah import foo, \\
+                  TheFooBah, TheClass, Foobah, SomethingElse
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,21)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceWhenModulenameSameAsClassMethodName(self):
+        # asserts that brm doesnt search class scope after not finding name
+        # in method scope (since class scope is invisible unless called on 'self'
+        src =trimLines("""
+        from a.b import bah
+        class baz:
+            def bah(self):
+                print bah.TheClass
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,4)
+        self.assertEqual(refs[0].colno,18)
+        self.assertEqual(refs[0].confidence,100)
+
+
+    def test_doesntBarfOnFromImportStarWhenNameIsInFromClause(self):
+        src = trimLines("""
+        from a.b.bah import TheClass
+        a = TheClass()
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(ClassTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,1,6)]
+
+
+ClassTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getReferencesToMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.findReferences import findReferences
+from bike.parsing.fastparserast import Module
+
+class TestGetReferencesToMethod(BRMTestCase):
+
+    def test_getsReferenceOfSimpleMethodCall(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,2)
+        self.assertEqual(refs[0].colno,2)
+
+    def test_getsReferenceOfMethodCallFromClassImportedWithAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceOfMethodCallWhenInstanceReturnedByFunction(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            return TheClass()
+        a = foo()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,6)
+        self.assertEqual(refs[0].colno,2)
+        
+    def test_getsReferenceOfMethodCallInSameClass(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+            def anotherMethod(self):
+                self.theMethod()
+        """)
+
+        root = createSourceNodeAt(src,"a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,5)
+        self.assertEqual(refs[0].colno,13)
+
+    def test_getsReferenceOfMethodOnBaseClassInstance(self):
+        src = trimLines("""
+        class root:
+            def theMethod():
+                pass
+                
+        class a(root):
+            def theMethod():
+                pass
+                
+        class b(root):
+            pass
+            
+        class TheClass(b):
+            def theMethod(self):
+                pass
+                
+        rootinstance = root()
+        rootinstance.theMethod()
+        """)
+
+        refs =self.helper4(src,"pass",2,8)
+        self.assertEqual(refs[2].filename,pkgstructureFile1)
+        self.assertEqual(refs[2].lineno,17)
+        self.assertEqual(refs[2].colno,13)
+
+    def helper4(self, src, importedsrc, line, col):
+        try:
+            createPackageStructure(src,importedsrc)
+            filename = pkgstructureFile1
+            refs =  [x for x in findReferences(filename,line,col)
+                     if x.confidence == 100]
+        finally:
+            removePackageStructure()
+        return refs
+        
+    def test_doesntGetReferenceToMethodWhenObjectCreatedInChildScopeToMethodReference(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(MethodTestdata, "a.b.bah")
+        filename = os.path.abspath("a/b/bah.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        assert len(refs) == 0
+        
+    def test_renamesMethodReferenceOfInstanceCreatedInSubsequentFunction(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.theMethod()
+            
+        def bah():
+            return TheClass()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,10)
+        self.assertEqual(refs[0].colno,6)
+
+
+    def test_getsReferenceInMiddleOfBiggerCompoundCall(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self): return AnotherClass()
+        TheClass().theMethod().anotherMethod()
+        """)
+
+        root = createSourceNodeAt(src,"a.foo")
+        filename = os.path.abspath("a/foo.py")
+        refs = [x for x in findReferences(filename,2,8)
+                if x.confidence == 100]
+        self.assertEqual(refs[0].filename,
+                         os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,3)
+        self.assertEqual(refs[0].colno,11)
+        self.assertEqual(refs[0].colend,20)
+
+
+MethodTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getReferencesToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.getReferencesToModule import *
+from bike.parsing.fastparserast import Module
+
+class TestGetReferencesToModule(BRMTestCase):
+    
+    def test_returnsEmptyListIfNoReferences(self):
+        src = trimLines("""
+        class MyClass:
+            pass
+        a = TheClass()
+        """)
+        root = createSourceNodeAt(src,"mymodule")
+        self.assertEqual([x for x in getReferencesToModule(root,"myothermodule")],[])
+
+    def test_findsReferencesInModuleWhichImportsModule(self):
+        src = trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,9)
+        self.assertEqual(refs[0].confidence,100)
+
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,10)
+        self.assertEqual(refs[0].confidence,100)
+        
+    def test_findsReferenceInModuleWhichImportsModuleWithFrom(self):
+        src = trimLines("""
+        from b import bah
+        def foo():
+            a = bah.TheClass()
+            a.theMethod()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a/foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,8)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceInModuleWhichImportsModuleWithFromAndAlias(self):
+        src = trimLines("""
+        from b import bah as mymodule
+        def foo():
+            a = mymodule.MyTheClass()
+            a.theMethod()
+        """)
+
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,14)
+        self.assertEqual(refs[0].confidence,100)
+
+        """ # mymodule.MyTheClass
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,3)
+        self.assertEqual(refs[1].colno,10)
+        self.assertEqual(refs[1].confidence,100)
+        """
+
+    def test_findsReferenceInModuleWhichImportsModuleWithFromImportStar(self):
+        src = trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.theMethod()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,7)
+        self.assertEqual(refs[0].confidence,100)
+
+    ''' Dont think this is a valid test, since cant import a module with
+        from package import *
+    def test_findsReferenceInModuleWhichImportsClassWithFromImportStar2(self):
+        src = trimLines("""
+        from a.b import * 
+        a = bah.TheClass()
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,4)
+        self.assertEqual(refs[0].confidence,100)
+    '''
+    
+    def test_findsReferenceInClassBases(self):
+        src =trimLines("""
+        from b import bah
+        class DerivedClass(bah.TheClass):
+            pass
+        """)
+
+        root = createSourceNodeAt(src, "a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+        
+        self.assertEqual(refs[1].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[1].lineno,2)
+        self.assertEqual(refs[1].colno,19)
+        self.assertEqual(refs[1].confidence,100)
+            
+    def test_findsReferenceInMultiLineImportStatement(self):
+        src =trimLines("""
+        from b import foo, \\
+                  TheFooBah, TheClass, TheBastard, SomethingElse, bah
+        """)
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,2)
+        self.assertEqual(refs[0].colno,58)
+        self.assertEqual(refs[0].confidence,100)
+
+    def test_findsReferenceWhenModulenameSameAsClassMethodName(self):
+        # asserts that brm doesnt search class scope after not finding name
+        # in method scope (since class scope is invisible unless called on 'self'
+        src =trimLines("""
+        from a.b import bah
+        class baz:
+            def bah(self):
+                print bah.TheClass
+        """)        
+
+        root = createSourceNodeAt( src, "a.foo")
+        root = createSourceNodeAt( testdata.TheClass, "a.b.bah")
+        refs = [x for x in getReferencesToModule(root,"a.b.bah")]
+        
+        self.assertEqual(refs[0].filename,os.path.abspath(os.path.join("a","foo.py")))
+        self.assertEqual(refs[0].lineno,1)
+        self.assertEqual(refs[0].colno,16)
+        self.assertEqual(refs[0].confidence,100)
+        
+        assert (len(refs))==2
+
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_getTypeOf.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.getTypeOf import getTypeOf, UnfoundType,\
+     attemptToConvertGetattrToFqn
+from bike.parsing.fastparserast import Class, Function, Instance
+from bike.parsing.newstuff import getModuleOrPackageUsingFQN
+from compiler.ast import Getattr,CallFunc,Name
+
+class TestGetTypeOf(BRMTestCase):
+    def test_getsTypeOfSimpleClassInstanceReference(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        res =  getTypeOf(module,"a")
+        assert isinstance(res,Instance)
+        assert isinstance(res.getType(),Class)
+        assert res.getType().name == "TheClass"
+
+    def test_getsTypeOfImportedClassReference(self):
+        src = trimLines("""
+        import b.bah
+        a = b.bah.TheClass()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        res =  getTypeOf(module,"a")
+        assert isinstance(res,Instance)
+        assert isinstance(res.getType(),Class)
+        assert res.getType().name == "TheClass"
+
+    def test_getsTypeOfClassReferenceFromImportedPackage(self):
+        src = trimLines("""
+        import b
+        a = b.bah.TheClass()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        module = getModuleOrPackageUsingFQN("a.foo")
+        res =  getTypeOf(module,"a")
+        assert isinstance(res,Instance)
+        assert isinstance(res.getType(),Class)
+        assert res.getType().name == "TheClass"
+
+    def test_getsTypeOfInstanceThatIsAnAttributeOfSelf(self):
+        src = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        
+        class AnotherClass:
+            def __init__(self):
+                self.a = TheClass()
+            def anotherFn(self):
+                self.a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        module = getModuleOrPackageUsingFQN('a.foo')
+        theclass = getTypeOf(module,"TheClass")
+        fn = getTypeOf(module,"AnotherClass.anotherFn")
+        self.assertEqual(getTypeOf(fn,"self.a").getType().name, "TheClass")
+        #self.assertEqual(getTypeOf(fn,"self.a").getType(), theclass)
+        
+        
+
+    def test_doesntGetTypeDefinedInChildFunction(self):
+        src = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        
+        themodule = getModuleOrPackageUsingFQN("a.foo")
+        assert isinstance(getTypeOf(themodule,"a"),UnfoundType)
+    
+
+    def test_getsTypeOfClassReferencedViaAlias(self):
+        src = trimLines("""
+        from b.bah import TheClass as FooBah
+        FooBah()
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        root = createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        themodule = getModuleOrPackageUsingFQN("a.foo")
+        self.assertEqual(getTypeOf(themodule,"FooBah").name,"TheClass")
+        self.assertEqual(getTypeOf(themodule,"FooBah").filename,
+                         os.path.abspath(os.path.join("a","b","bah.py")))
+        
+
+    def test_getsTypeOfClassImportedFromPackageScope(self):
+        initfile = trimLines("""
+        from bah import TheClass
+        """)
+        src = trimLines("""
+        from a import b
+        b.TheClass()
+        """)
+        createSourceNodeAt(src,"a.foo")
+        createSourceNodeAt(testdata.TheClass, "a.b.bah")
+        createSourceNodeAt(initfile,"a.b.__init__")
+        themodule = getModuleOrPackageUsingFQN("a.foo")
+        self.assertEqual(getTypeOf(themodule,"b.TheClass").name,"TheClass")
+        self.assertEqual(getTypeOf(themodule,"b.TheClass").filename,
+                         os.path.abspath(os.path.join("a","b","bah.py")))
+
+
+    def test_attemptToConvertGetattrToFqn_returnsNoneIfFails(self):
+        ast = Getattr(CallFunc(Name("foo"),[],[],[]),"hello")
+        assert attemptToConvertGetattrToFqn(ast) is None
+
+    def test_attemptToConvertGetattrToFqn_works(self):
+        ast = Getattr(Getattr(Name("foo"),"bah"),"hello")
+        assert attemptToConvertGetattrToFqn(ast) == "foo.bah.hello"
+
+    
+    def test_handlesRecursionProblem(self):
+        src = trimLines("""
+        def fn(root):
+            node = root
+            node = node.getPackage('something')
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        m = getModuleOrPackageUsingFQN("a.foo")
+        fn = getTypeOf(m,"fn")
+        getTypeOf(fn,"node")   # stack overflow!
+
+
+    def test_doesntGotIntoRecursiveLoopWhenEvaluatingARecursiveFunction(self):
+        src = trimLines("""
+        def fn(v):
+            if v < 45:
+                return fn(root+1)
+        val = fn(3)
+        """)
+        root = createSourceNodeAt(src,"a.foo")
+        mod = getModuleOrPackageUsingFQN("a.foo")
+        getTypeOf(mod,"val")   # stack overflow!
+
+    def test_getsModuleImportedWithFrom(self):
+        importsrc=trimLines("""
+        from a.b import bah
+        """)
+        src=trimLines("""
+        mytext = 'hello'
+        """)        
+        type = self.helper(importsrc,src,'bah')
+        self.assertEqual(pkgstructureFile2,type.filename)
+
+    def helper(self,importsrc,src,name):
+        try:
+            createPackageStructure(importsrc,src)
+            from bike.parsing.newstuff import getModule
+            scope = getModule(pkgstructureFile1)
+            return getTypeOf(scope,name)
+        finally:
+            removePackageStructure()
+    
+
+    def test_getsTypeOfClassImportedAsAlias(self):
+        importsrc = trimLines("""
+        from b.bah import TheClass as MyTheClass
+        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        src=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        type = self.helper(importsrc,src,'MyTheClass')
+        self.assertEqual("TheClass",type.name)
+
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/test_relationships.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+import os
+from bike import testdata
+from bike.testutils import *
+from bike.query.getTypeOf import getTypeOf
+from bike.parsing.fastparserast import Module
+from bike.query.relationships import getRootClassesOfHierarchy
+from bike.parsing.newstuff import getModule
+
+
+class TestGetRootClassesOfHierarchy(BRMTestCase):
+    def test_getsRootClassFromDerivedClass(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+
+        """)
+        rootclasses = self.helper(src,"DerivedClass")
+        self.assertEqual("TheClass",rootclasses[0].name)
+        self.assertEqual(len(rootclasses),1)        
+        
+    def test_getsRootClassFromDerivedDerivedClass(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+        class DerivedDerivedClass(DerivedClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("TheClass",rootclasses[0].name)
+        self.assertEqual(len(rootclasses),1)
+
+
+    def test_getsRootClassFromDiamondOfClasses(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+        class DerivedDerivedClass(DerivedClass,BaseClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("TheClass",rootclasses[0].name)
+        self.assertEqual("TheClass",rootclasses[1].name)
+        self.assertEqual(len(rootclasses),2)
+
+
+    def test_getsRootClassesFromMultipleInheritance(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass:
+            pass
+        class DerivedDerivedClass(DerivedClass,BaseClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("DerivedClass",rootclasses[0].name)
+        self.assertEqual("TheClass",rootclasses[1].name)
+        self.assertEqual(len(rootclasses),2)
+
+    def test_getsRootClassesFromMultipleInheritanceWithNewStyleClass(self):
+        src = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(Object):
+            pass
+        class DerivedDerivedClass(DerivedClass,BaseClass):
+            pass
+        """)
+        rootclasses = self.helper(src,"DerivedDerivedClass")
+        self.assertEqual("DerivedClass",rootclasses[0].name)
+        self.assertEqual("TheClass",rootclasses[1].name)
+        self.assertEqual(len(rootclasses),2)
+
+
+    def helper(self,src,classname):
+        try:
+            createPackageStructure(src,testdata.TheClass)
+            classobj = getTypeOf(getModule(pkgstructureFile1),classname)
+            return getRootClassesOfHierarchy(classobj)
+        finally:
+            removePackageStructure()
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/query/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import setpath
+
+from test_common import *
+from test_getReferencesToClass import *
+from test_getReferencesToMethod import *
+#from test_getReferencesToModule import *
+from test_findDefinition import *
+from test_findReferences import *
+from test_relationships import *
+from test_getTypeOf import *
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/__init__.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,1 @@
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/extractMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,363 @@
+import re
+import compiler
+from bike.parsing import visitor
+from bike.query.common import getScopeForLine
+from bike.parsing.parserutils import generateLogicalLines, \
+                makeLineParseable, maskStringsAndRemoveComments
+from parser import ParserError
+from bike.parsing.fastparserast import Class
+from bike.transformer.undo import getUndoStack
+from bike.refactor.utils import getTabWidthOfLine, getLineSeperator, \
+                reverseCoordsIfWrongWayRound
+from bike.transformer.save import queueFileToSave
+from bike.parsing.load import getSourceNode
+TABSIZE = 4
+
+class coords:
+    def __init__(self, line, column):
+        self.column = column
+        self.line = line
+    def __str__(self):
+        return "("+str(self.column)+","+str(self.line)+")"
+
+commentRE = re.compile(r"#.*?$")
+
+class ParserException(Exception): pass
+
+def extractMethod(filename, startcoords, endcoords, newname):
+    ExtractMethod(getSourceNode(filename),
+                  startcoords, endcoords, newname).execute()
+
+class ExtractMethod(object):
+    def __init__(self,sourcenode, startcoords, endcoords, newname):
+        self.sourcenode = sourcenode
+
+        startcoords, endcoords = \
+               reverseCoordsIfWrongWayRound(startcoords,endcoords)
+
+        self.startline = startcoords.line
+        self.endline = endcoords.line
+        self.startcol = startcoords.column
+        self.endcol= endcoords.column
+
+        self.newfn = NewFunction(newname)
+
+        self.getLineSeperator()
+        self.adjustStartColumnIfLessThanTabwidth()
+        self.adjustEndColumnIfStartsANewLine()
+        self.fn = self.getFunctionObject()
+        self.getRegionToBuffer()
+        #print "-"*80
+        #print self.extractedLines
+        #print "-"*80
+        self.deduceIfIsMethodOrFunction()
+
+    def execute(self):
+        self.deduceArguments()
+        getUndoStack().addSource(self.sourcenode.filename,
+                                 self.sourcenode.getSource())
+        srclines = self.sourcenode.getLines()
+        newFnInsertPosition = self.fn.getEndLine()-1
+        self.insertNewFunctionIntoSrcLines(srclines, self.newfn,
+                                           newFnInsertPosition)
+        self.writeCallToNewFunction(srclines)
+
+        src = "".join(srclines)
+        queueFileToSave(self.sourcenode.filename,src)        
+
+    def getLineSeperator(self):
+        line = self.sourcenode.getLines()[self.startline-1]
+        linesep = getLineSeperator(line)
+        self.linesep = linesep        
+
+    def adjustStartColumnIfLessThanTabwidth(self):
+        tabwidth = getTabWidthOfLine(self.sourcenode.getLines()[self.startline-1])
+        if self.startcol < tabwidth: self.startcol = tabwidth
+
+    def adjustEndColumnIfStartsANewLine(self):
+        if self.endcol == 0:
+            self.endline -=1
+            nlSize = len(self.linesep)
+            self.endcol = len(self.sourcenode.getLines()[self.endline-1])-nlSize
+
+
+    def getFunctionObject(self):
+        return getScopeForLine(self.sourcenode,self.startline)
+
+
+    def getTabwidthOfParentFunction(self):
+        line = self.sourcenode.getLines()[self.fn.getStartLine()-1]
+        match = re.match("\s+",line)
+        if match is None:
+            return 0
+        else:
+            return match.end(0)
+
+    # should be in the transformer module
+    def insertNewFunctionIntoSrcLines(self,srclines,newfn,insertpos):
+        tabwidth = self.getTabwidthOfParentFunction()
+
+        while re.match("\s*"+self.linesep,srclines[insertpos-1]):
+            insertpos -= 1
+
+        srclines.insert(insertpos, self.linesep)
+        insertpos +=1
+
+        fndefn = "def "+newfn.name+"("
+
+        if self.isAMethod:
+            fndefn += "self"
+            if newfn.args != []:
+                fndefn += ", "+", ".join(newfn.args)
+        else:
+            fndefn += ", ".join(newfn.args)
+
+        fndefn += "):"+self.linesep
+
+
+        srclines.insert(insertpos,tabwidth*" "+fndefn)
+        insertpos +=1
+
+        tabwidth += TABSIZE
+
+
+        if self.extractedCodeIsAnExpression(srclines):
+            assert len(self.extractedLines) == 1
+
+            fnbody = [tabwidth*" "+ "return "+self.extractedLines[0]]
+
+
+        else:
+            fnbody = [tabwidth*" "+line for line in self.extractedLines]
+            if newfn.retvals != []:
+                fnbody.append(tabwidth*" "+"return "+
+                             ", ".join(newfn.retvals) + self.linesep)
+
+        for line in fnbody:
+            srclines.insert(insertpos,line)
+            insertpos +=1
+
+
+    def writeCallToNewFunction(self, srclines):
+        startline = self.startline
+        endline = self.endline
+        startcol = self.startcol
+        endcol= self.endcol
+
+        fncall = self.constructFunctionCallString(self.newfn.name, self.newfn.args,
+                                                  self.newfn.retvals)
+
+        self.replaceCodeWithFunctionCall(srclines, fncall,
+                                         startline, endline, startcol, endcol)
+
+
+    def replaceCodeWithFunctionCall(self, srclines, fncall,
+                                    startline, endline, startcol, endcol):
+        if startline == endline:  # i.e. extracted code part of existing line
+            line = srclines[startline-1]
+            srclines[startline-1] = self.replaceSectionOfLineWithFunctionCall(line,
+                                                         startcol, endcol, fncall)
+        else:
+            self.replaceLinesWithFunctionCall(srclines, startline, endline, fncall)
+
+
+    def replaceLinesWithFunctionCall(self, srclines, startline, endline, fncall):
+        tabwidth = getTabWidthOfLine(srclines[startline-1])
+        line = tabwidth*" " + fncall + self.linesep
+        srclines[startline-1:endline] = [line]
+
+
+
+    def replaceSectionOfLineWithFunctionCall(self, line, startcol, endcol, fncall):
+        line = line[:startcol] + fncall + line[endcol:]
+        if not line.endswith(self.linesep):
+            line+=self.linesep
+        return line
+
+
+
+    def constructFunctionCallString(self, fnname, fnargs, retvals):
+        fncall = fnname + "("+", ".join(fnargs)+")"
+        if self.isAMethod:
+            fncall = "self." + fncall
+
+        if retvals != []:
+            fncall = ", ".join(retvals) + " = "+fncall
+        return fncall
+
+
+    def deduceArguments(self):
+        lines = self.fn.getLinesNotIncludingThoseBelongingToChildScopes()
+
+        # strip off comments
+        lines = [commentRE.sub(self.linesep,line) for line in lines]
+        extractedLines = maskStringsAndRemoveComments("".join(self.extractedLines)).splitlines(1)
+
+        linesbefore = lines[:(self.startline - self.fn.getStartLine())]
+        linesafter = lines[(self.endline - self.fn.getStartLine()) + 1:]
+
+        # split into logical lines
+        linesbefore = [line for line in generateLogicalLines(linesbefore)]        
+        extractedLines = [line for line in generateLogicalLines(extractedLines)]
+        linesafter = [line for line in generateLogicalLines(linesafter)]
+
+        if self.startline == self.endline:
+            # need to include the line code is extracted from
+            line = generateLogicalLines(lines[self.startline - self.fn.getStartLine():]).next()
+            linesbefore.append(line[:self.startcol] + "dummyFn()" + line[self.endcol:])
+        assigns = getAssignments(linesbefore)
+        fnargs = getFunctionArgs(linesbefore)
+        candidateArgs = assigns + fnargs            
+        refs = getVariableReferencesInLines(extractedLines)
+        self.newfn.args = [ref for ref in refs if ref in candidateArgs]
+
+        assignsInExtractedBlock = getAssignments(extractedLines)
+        usesAfterNewFunctionCall = getVariableReferencesInLines(linesafter)
+        usesInPreceedingLoop = getVariableReferencesInLines(
+            self.getPreceedingLinesInLoop(linesbefore,line))
+        self.newfn.retvals = [ref for ref in usesInPreceedingLoop+usesAfterNewFunctionCall
+                                   if ref in assignsInExtractedBlock]
+
+    def getPreceedingLinesInLoop(self,linesbefore,firstLineToExtract):
+        if linesbefore == []: return []
+        tabwidth = getTabWidthOfLine(firstLineToExtract)
+        rootTabwidth = getTabWidthOfLine(linesbefore[0])
+        llines = [line for line in generateLogicalLines(linesbefore)]
+        startpos = len(llines)-1
+        loopTabwidth = tabwidth
+        for idx in range(startpos,0,-1):
+            line = llines[idx]
+            if re.match("(\s+)for",line) is not None or \
+               re.match("(\s+)while",line) is not None:
+                candidateLoopTabwidth = getTabWidthOfLine(line)
+                if candidateLoopTabwidth < loopTabwidth:
+                    startpos = idx
+        return llines[startpos:]
+
+    
+
+
+
+
+    def getRegionToBuffer(self):
+        startline = self.startline
+        endline = self.endline
+        startcol = self.startcol
+        endcol= self.endcol
+
+
+        self.extractedLines = self.sourcenode.getLines()[startline-1:endline]
+
+        match = re.match("\s*",self.extractedLines[0])
+        tabwidth = match.end(0)
+
+        self.extractedLines = [line[startcol:] for line in self.extractedLines]
+
+        # above cropping can take a blank line's newline off.
+        # this puts it back
+        for idx in range(len(self.extractedLines)):
+            if self.extractedLines[idx] == '':
+                self.extractedLines[idx] = self.linesep
+
+        if startline == endline:
+            # need to crop the end
+            # (n.b. if region is multiple lines, then whole lines are taken)
+            self.extractedLines[-1] = self.extractedLines[-1][:endcol-startcol]
+
+        if self.extractedLines[-1][-1] != '\n':
+            self.extractedLines[-1] += self.linesep
+
+    def extractedCodeIsAnExpression(self,lines):
+        if len(self.extractedLines) == 1:
+            charsBeforeSelection = lines[self.startline-1][:self.startcol]
+            if re.match("^\s*$",charsBeforeSelection) is not None:
+                return 0
+            if re.search(":\s*$",charsBeforeSelection) is not None:
+                return 0
+            return 1
+        return 0
+
+    def deduceIfIsMethodOrFunction(self):
+        if isinstance(self.fn.getParent(),Class):
+            self.isAMethod = 1
+        else:
+            self.isAMethod = 0
+
+
+# holds information about the new function
+class NewFunction:
+    def __init__(self,name):
+        self.name = name
+
+
+# lines = list of lines.
+# Have to have strings masked and comments removed
+def getAssignments(lines):
+    class AssignVisitor:
+        def __init__(self):
+            self.assigns = []
+
+        def visitAssTuple(self, node):
+            for a in node.nodes:
+                if a.name not in self.assigns:
+                    self.assigns.append(a.name)
+
+        def visitAssName(self, node):
+            if node.name not in self.assigns:
+                self.assigns.append(node.name)
+
+        def visitAugAssign(self, node):
+            if isinstance(node.node, compiler.ast.Name):
+                if node.node.name not in self.assigns:
+                    self.assigns.append(node.node.name)
+
+    assignfinder = AssignVisitor()
+    for line in lines:
+        doctoredline = makeLineParseable(line)
+        try:
+            ast = compiler.parse(doctoredline)
+        except ParserError:
+            raise ParserException("couldnt parse:"+doctoredline)
+        visitor.walk(ast, assignfinder)
+    return assignfinder.assigns
+
+
+# lines = list of lines.
+# Have to have strings masked and comments removed
+def getFunctionArgs(lines):
+    if lines == []: return []
+
+    class FunctionVisitor:
+        def __init__(self):
+            self.result = []
+        def visitFunction(self, node):
+            for n in node.argnames:
+                if n != "self":
+                    self.result.append(n)
+    fndef = generateLogicalLines(lines).next()
+    doctoredline = makeLineParseable(fndef)
+    try:
+        ast = compiler.parse(doctoredline)
+    except ParserError:
+        raise ParserException("couldnt parse:"+doctoredline)
+    return visitor.walk(ast, FunctionVisitor()).result
+
+
+
+# lines = list of lines. Have to have strings masked and comments removed
+def getVariableReferencesInLines(lines):
+    class NameVisitor:
+        def __init__(self):
+            self.result = []
+        def visitName(self, node):
+            if node.name not in self.result:
+                self.result.append(node.name)
+    reffinder = NameVisitor()
+    for line in lines:
+        doctoredline = makeLineParseable(line)
+        try:
+            ast = compiler.parse(doctoredline)
+        except ParserError:
+            raise ParserException("couldnt parse:"+doctoredline)
+        visitor.walk(ast, reffinder)
+    return reffinder.result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/extractVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,32 @@
+from bike.parsing.parserutils import maskStringsAndRemoveComments
+from bike.transformer.undo import getUndoStack
+from parser import ParserError
+import compiler
+from bike.refactor.extractMethod import coords
+from bike.refactor.utils import getTabWidthOfLine, getLineSeperator,\
+     reverseCoordsIfWrongWayRound
+from bike.transformer.save import queueFileToSave
+from bike.parsing.load import getSourceNode
+
+
+def extractLocalVariable(filename, startcoords, endcoords, varname):
+    sourceobj = getSourceNode(filename)
+    if startcoords.line != endcoords.line:
+        raise "Can't do multi-line extracts yet"
+    startcoords, endcoords = \
+                 reverseCoordsIfWrongWayRound(startcoords,endcoords)
+    line = sourceobj.getLine(startcoords.line)
+    tabwidth = getTabWidthOfLine(line)
+    linesep = getLineSeperator(line)
+    region = line[startcoords.column:endcoords.column]
+    
+    getUndoStack().addSource(sourceobj.filename,sourceobj.getSource())
+    sourceobj.getLines()[startcoords.line-1] = \
+          line[:startcoords.column] + varname + line[endcoords.column:]
+
+    defnline = tabwidth*" " + varname + " = " + region + linesep
+    
+    sourceobj.getLines().insert(startcoords.line-1,defnline)
+
+    queueFileToSave(sourceobj.filename,"".join(sourceobj.getLines()))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/inlineVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,94 @@
+from bike.query.findDefinition import findAllPossibleDefinitionsByCoords
+from bike.query.findReferences import findReferences
+from bike.parsing.parserutils import maskStringsAndRemoveComments, linecontinueRE
+from bike.transformer.undo import getUndoStack
+from bike.transformer.save import queueFileToSave
+from parser import ParserError
+from bike.parsing.load import getSourceNode
+import compiler
+import re
+
+
+def inlineLocalVariable(filename, lineno,col):
+    sourceobj = getSourceNode(filename)
+    return inlineLocalVariable_old(sourceobj, lineno,col)
+
+def inlineLocalVariable_old(sourcenode,lineno,col):
+    definition, region, regionlinecount = getLocalVariableInfo(sourcenode, lineno, col)
+    addUndo(sourcenode)
+    replaceReferences(sourcenode, findReferences(sourcenode.filename, definition.lineno, definition.colno), region)
+    delLines(sourcenode, definition.lineno-1, regionlinecount)
+    updateSource(sourcenode)
+
+def getLocalVariableInfo(sourcenode, lineno, col):
+    definition = findDefinition(sourcenode, lineno, col)
+    region, linecount = getRegionToInline(sourcenode, definition)
+    return definition, region, linecount
+
+def findDefinition(sourcenode, lineno, col):
+    definition = findAllPossibleDefinitionsByCoords(sourcenode.filename,
+                                                    lineno,col).next()
+    assert definition.confidence == 100    
+    return definition
+
+def getRegionToInline(sourcenode, defn):
+    line, linecount = getLineAndContinues(sourcenode, defn.lineno)
+    start, end = findRegionToInline(maskStringsAndRemoveComments(line))
+    return line[start:end], linecount
+
+def findRegionToInline(maskedline):
+    match = re.compile("[^=]+=\s*(.+)$\n", re.DOTALL).match(maskedline)
+    assert match
+    return match.start(1), match.end(1)
+
+# Possible refactoring: move to class of sourcenode
+def getLineAndContinues(sourcenode, lineno):
+    line = sourcenode.getLine(lineno)
+    
+    linecount = 1
+    while linecontinueRE.search(line):
+        line += sourcenode.getLine(lineno + linecount)
+        linecount += 1
+
+    return line, linecount
+
+def addUndo(sourcenode):
+    getUndoStack().addSource(sourcenode.filename,sourcenode.getSource())
+
+def replaceReferences(sourcenode, references, replacement):
+    for reference in safeReplaceOrder( references ):
+        replaceReference(sourcenode, reference, replacement)
+
+def safeReplaceOrder( references ):
+    """ 
+    When inlining a variable, if multiple instances occur on the line, then the
+    last reference must be replaced first. Otherwise the remaining intra-line
+    references will be incorrect.
+    """
+    def safeReplaceOrderCmp(self, other):
+        return -cmp(self.colno, other.colno)
+
+    result = list(references)
+    result.sort(safeReplaceOrderCmp)
+    return result
+
+
+def replaceReference(sourcenode, ref, replacement):
+    """ sourcenode.getLines()[ref.lineno-1][ref.colno:ref.colend] = replacement
+    But strings don't support slice assignment as they are immutable. :(
+    """
+    sourcenode.getLines()[ref.lineno-1] = \
+        replaceSubStr(sourcenode.getLines()[ref.lineno-1],
+            ref.colno, ref.colend, replacement)
+
+def replaceSubStr(str, start, end, replacement):
+    return str[:start] + replacement + str[end:]
+
+# Possible refactoring: move to class of sourcenode
+def delLines(sourcenode, lineno, linecount=1):
+    del sourcenode.getLines()[lineno:lineno+linecount]
+    
+def updateSource(sourcenode):
+    queueFileToSave(sourcenode.filename,"".join(sourcenode.getLines()))
+    
+                    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/moveToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,148 @@
+import bike.globals
+from bike.parsing.load import getSourceNode
+from bike.parsing.fastparserast import Module
+from bike.query.common import getScopeForLine, convertNodeToMatchObject
+from bike.transformer.save import queueFileToSave, save
+from bike.transformer.undo import getUndoStack
+from bike.refactor.extractMethod import getVariableReferencesInLines
+from bike.refactor.utils import getLineSeperator
+from bike.query.findDefinition import findDefinitionFromASTNode
+from bike.query.findReferences import findReferences
+from bike.parsing.pathutils import filenameToModulePath
+from compiler.ast import Name
+import re
+
+def moveClassToNewModule(origfile,line,newfile):
+    srcnode = getSourceNode(origfile)
+    targetsrcnode = getSourceNode(newfile)
+    classnode = getScopeForLine(srcnode,line)
+    classlines = srcnode.getLines()[classnode.getStartLine()-1:
+                                    classnode.getEndLine()-1]
+    getUndoStack().addSource(srcnode.filename,
+                             srcnode.getSource())
+    getUndoStack().addSource(targetsrcnode.filename,
+                             targetsrcnode.getSource())
+
+    srcnode.getLines()[classnode.getStartLine()-1:
+                       classnode.getEndLine()-1] = []
+    
+    targetsrcnode.getLines().extend(classlines)
+
+    queueFileToSave(srcnode.filename,srcnode.getSource())
+    queueFileToSave(targetsrcnode.filename,targetsrcnode.getSource())
+
+
+exactFromRE = "(from\s+\S+\s+import\s+%s)(.*)"    
+fromRE = "from\s+\S+\s+import\s+(.*)"
+
+def moveFunctionToNewModule(origfile,line,newfile):
+    
+    srcnode = getSourceNode(origfile)
+    targetsrcnode = getSourceNode(newfile)
+    scope = getScopeForLine(srcnode,line)
+
+    linesep = getLineSeperator(srcnode.getLines()[0])
+
+    matches =[m for m in findReferences(origfile, line, scope.getColumnOfName())]
+
+    origFileImport = []
+    fromline = 'from %s import %s'%(filenameToModulePath(newfile),scope.name)
+    
+    for match in matches:
+        if match.filename == origfile:
+            origFileImport = fromline + linesep
+        else:
+            s = getSourceNode(match.filename)
+            m = s.fastparseroot
+            if match.lineno in m.getImportLineNumbers():                
+                getUndoStack().addSource(s.filename,
+                                         s.getSource())
+
+                maskedline = m.getLogicalLine(match.lineno)
+                origline = s.getLines()[match.lineno-1]
+                reMatch =  re.match(exactFromRE%(scope.name),maskedline)
+                if reMatch and not (',' in reMatch.group(2) or \
+                                    '\\' in reMatch.group(2)):
+                    # i.e. line is 'from module import foo'
+
+                    if match.filename == newfile:
+                        #remove the import
+                        s.getLines()[match.lineno-1:match.lineno] = []
+                        pass
+                    else:
+                        restOfOrigLine = origline[len(reMatch.group(1)):]
+                        s.getLines()[match.lineno-1] = fromline + restOfOrigLine
+
+                elif re.match(fromRE,maskedline):
+                    # i.e. line is 'from module import foo,bah,baz'
+                    #remove the element from the import stmt
+                    line = removeNameFromMultipleImportLine(scope.name, origline)
+                    s.getLines()[match.lineno-1] = line
+                    #and add a new line
+                    nextline = match.lineno + maskedline.count('\\') + 1
+                    s.getLines()[nextline-1:nextline-1] = [fromline+linesep]
+                    
+                queueFileToSave(s.filename,s.getSource())
+                    
+    
+    refs = getVariableReferencesInLines(scope.getMaskedLines())
+
+    scopeLines = srcnode.getLines()[scope.getStartLine()-1:
+                                    scope.getEndLine()-1]
+    importModules = deduceImportsForNewFile(refs, scope)
+    importlines = composeNewFileImportLines(importModules, linesep)
+
+
+
+    getUndoStack().addSource(srcnode.filename,
+                             srcnode.getSource())
+    getUndoStack().addSource(targetsrcnode.filename,
+                             targetsrcnode.getSource())
+
+    srcnode.getLines()[scope.getStartLine()-1:
+                       scope.getEndLine()-1] = origFileImport
+
+    targetsrcnode.getLines().extend(importlines+scopeLines)
+
+    queueFileToSave(srcnode.filename,srcnode.getSource())
+    queueFileToSave(targetsrcnode.filename,targetsrcnode.getSource())
+
+def removeNameFromMultipleImportLine(name, origline):
+    def replacefn(match):
+        return match.group(1)
+    line = re.sub('(\W)%s\s*?,'%(name),replacefn,origline)
+    return line
+
+
+
+
+def composeNewFileImportLines(importModules, linesep):
+    importlines = []
+    for mpath in importModules:
+        importlines += "from %s import %s"%(mpath,
+                                  ', '.join(importModules[mpath]))
+        importlines += linesep
+    return importlines
+
+def deduceImportsForNewFile(refs, scope):
+    importModules = {}
+    for ref in refs:
+        match = findDefinitionFromASTNode(scope,Name(ref))
+
+        if match.filename == scope.module.filename:
+            tgtscope = getScopeForLine(getSourceNode(match.filename),
+                                       match.lineno)
+            while tgtscope != scope and not isinstance(tgtscope,Module):
+                tgtscope = tgtscope.getParent()
+            
+            if not isinstance(tgtscope,Module):
+                continue   # was defined in this function
+        
+        mpath = filenameToModulePath(match.filename)            
+        if mpath in importModules:            
+            importModules[mpath].append(ref)
+        else:
+            importModules[mpath] = [ref]
+    return importModules
+    
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/rename.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,19 @@
+from bike.transformer.WordRewriter import WordRewriter
+from bike.query.findReferences import findReferencesIncludingDefn
+from bike.transformer.save import save
+
+def rename(filename,lineno,col,newname,promptcallback=None):
+    strrewrite = WordRewriter()
+    for match in findReferencesIncludingDefn(filename,lineno,col):
+        #print "rename match ",match
+        if match.confidence == 100 or promptUser(promptcallback,match):
+            strrewrite.rewriteString(match.sourcenode,
+                                     match.lineno,match.colno,newname)
+    strrewrite.commit()
+
+def promptUser(promptCallback,match):
+    if promptCallback is not None and \
+       promptCallback(match.filename, match.lineno, match.colno, match.colend):
+        return 1
+    return 0
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("../..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath("../.."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_extractMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,791 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+
+from bike.refactor.extractMethod import ExtractMethod, \
+     extractMethod, coords
+from bike import testdata
+from bike.testutils import *
+from bike.parsing.load import Cache
+
+def assertTokensAreSame(t1begin, t1end, tokens):
+    it = t1begin.clone()
+    pos = 0
+    while it != t1end:
+        assert it.deref() == tokens[pos]
+        it.incr()
+        pos+=1
+    assert pos == len(tokens)
+
+
+def helper(src,startcoords, endcoords, newname):
+    sourcenode = createAST(src)
+    extractMethod(tmpfile, startcoords, endcoords, newname)
+    return sourcenode.getSource()
+
+class TestExtractMethod(BRMTestCase):
+
+    def test_extractsPass(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(3, 8), coords(3, 12), "newMethod")
+        self.assertEqual(src,srcAfter)
+
+    def test_extractsPassWhenFunctionAllOnOneLine(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): pass # comment
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): self.newMethod() # comment
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(2, 24), coords(2, 28),"newMethod")
+        self.assertEqual(src,srcAfter)
+
+    def test_extractsPassFromForLoop(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+        """)                
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(4, 12), coords(4, 16), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_newMethodHasArgumentsForUsedTemporarys(self):
+
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self, c): 
+                a = something()
+                b = somethingelse()
+                print a + b + c + d
+                print \"hello\"
+                dosomethingelse(a, b)
+        """)                
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self, c): 
+                a = something()
+                b = somethingelse()
+                self.newMethod(a, b, c)
+                dosomethingelse(a, b)
+
+            def newMethod(self, a, b, c):
+                print a + b + c + d
+                print \"hello\"
+        """)
+
+        src = helper(srcBefore, coords(5, 8), coords(6, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_newMethodHasSingleArgument(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a = something()
+                print a
+                print \"hello\"
+                dosomethingelse(a, b)
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a = something()
+                self.newMethod(a)
+                dosomethingelse(a, b)
+
+            def newMethod(self, a):
+                print a
+                print \"hello\"
+        """)
+        src = helper(srcBefore, coords(4, 8), coords(5, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntHaveDuplicateArguments(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 3
+                print a
+                print a
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 3
+                self.newMethod(a)
+
+            def newMethod(self, a):
+                print a
+                print a
+        """)
+        src = helper(srcBefore, coords(4, 0), coords(6, 0), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractsQueryWhenFunctionAllOnOneLine(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self, a): print a # comment
+        """)
+
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self, a): self.newMethod(a) # comment
+
+            def newMethod(self, a):
+                print a
+        """)
+        src = helper(srcBefore, coords(2, 27), coords(2, 34), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_worksWhenAssignmentsToTuples(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a, b, c = 35, 36, 37
+                print a + b
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): 
+                a, b, c = 35, 36, 37
+                self.newMethod(a, b)
+
+            def newMethod(self, a, b):
+                print a + b
+        """)
+
+        src = helper(srcBefore, coords(4, 8), coords(4, 19), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_worksWhenUserSelectsABlockButDoesntSelectTheHangingDedent(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+
+        src = helper(srcBefore, coords(4, 8), coords(4, 16), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    def test_newMethodHasSingleReturnValue(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 35    # <-- extract me
+                print a
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = self.newMethod()
+                print a
+
+            def newMethod(self):
+                a = 35    # <-- extract me
+                return a
+        """)
+
+        src = helper(srcBefore, coords(3, 4),
+                         coords(3, 34), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+
+    def test_newMethodHasMultipleReturnValues(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a = 35
+                b = 352
+                print a + b
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                a, b = self.newMethod()
+                print a + b
+
+            def newMethod(self):
+                a = 35
+                b = 352
+                return a, b
+        """)
+        src = helper(srcBefore, coords(3, 8),
+                         coords(4, 15), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+
+    def test_worksWhenMovingCodeJustAfterDedent(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+                print \"hello\"
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                for i in foo:
+                    pass
+                self.newMethod()
+
+            def newMethod(self):
+                print \"hello\"
+        """)
+
+        src = helper(srcBefore, coords(5, 8),
+                         coords(5, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+    
+    def test_extractsPassWhenSelectionCoordsAreReversed(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                self.newMethod()
+
+            def newMethod(self):
+                pass
+        """)
+        src = helper(srcBefore, coords(3, 12), coords(3, 8), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_extractsExpression(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                a = 32
+                b = 2 + a * 1 + 2
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                a = 32
+                b = 2 + self.newMethod(a) + 2
+
+            def newMethod(self, a):
+                return a * 1
+        """)
+        src = helper(srcBefore, coords(4, 16), coords(4, 21), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_extractsExpression2(self):
+        srcBefore=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                g = 32
+                assert output.thingy(g) == \"bah\"
+        """)
+        srcAfter=trimLines("""
+        class MyClass:
+            def myMethod(self): # comment
+                g = 32
+                assert self.newMethod(g) == \"bah\"
+
+            def newMethod(self, g):
+                return output.thingy(g)
+        """)
+        src = helper(srcBefore, coords(4, 15), coords(4, 31), "newMethod")
+        self.assertEqual(srcAfter, src)
+
+
+
+class TestExtractFunction(BRMTestCase):
+    def runTarget(self, src, begincoords, endcoords, newname):
+        ast = createAST(src)
+        extractFunction(ast, begincoords, endcoords, newname)
+        return ast
+
+    def test_extractsFunction(self):        
+        srcBefore=trimLines("""
+        def myFunction(): # comment
+            a = 3
+            c = a + 99
+            b = c * 1
+            print b
+        """)
+        srcAfter=trimLines("""
+        def myFunction(): # comment
+            a = 3
+            b = newFunction(a)
+            print b
+
+        def newFunction(a):
+            c = a + 99
+            b = c * 1
+            return b
+        """)
+
+        src = helper(srcBefore, coords(3, 4),
+                         coords(4, 13), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractsAssignToAttribute(self):
+        srcBefore=trimLines("""
+        def simulateLoad(path):
+            item = foo()
+            item.decl = line
+        """)
+        srcAfter=trimLines("""
+        def simulateLoad(path):
+            item = foo()
+            newFunction(item)
+
+        def newFunction(item):
+            item.decl = line
+        """)
+
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_extractsFromFirstBlockOfIfElseStatement(self):
+        srcBefore=trimLines("""
+        def foo():
+            if bah:
+                print \"hello1\"
+                print \"hello2\"
+                
+            elif foo:
+                pass
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            if bah:
+                newFunction()
+                print \"hello2\"
+                
+            elif foo:
+                pass
+
+        def newFunction():
+            print \"hello1\"
+        """)
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+
+    def test_extractsAugAssign(self):
+        srcBefore=trimLines("""
+        def foo():
+            a = 3
+            a += 1
+            print a
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3
+            a = newFunction(a)
+            print a
+
+        def newFunction(a):
+            a += 1
+            return a
+        """)
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+    def test_extractsForLoopUsingLoopVariable(self):
+        srcBefore=trimLines("""
+        def foo():
+            for i in range(1, 3):
+                print i
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            for i in range(1, 3):
+                newFunction(i)
+
+        def newFunction(i):
+            print i
+        """)
+
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractWhileLoopVariableIncrement(self):
+        srcBefore=trimLines("""
+        def foo():
+            a = 0
+            while a != 3:
+                a = a+1
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 0
+            while a != 3:
+                a = newFunction(a)
+
+        def newFunction(a):
+            a = a+1
+            return a
+        """)
+        src = helper(srcBefore, coords(4, 0),
+                         coords(5, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+    def test_extractAssignedVariableUsedInOuterForLoop(self):
+        srcBefore=trimLines("""
+        def foo():
+            b = 0
+            for a in range(1, 3):
+                b = b+1
+                while b != 2:
+                    print a
+                    b += 1
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            b = 0
+            for a in range(1, 3):
+                b = b+1
+                while b != 2:
+                    b = newFunction(a, b)
+
+        def newFunction(a, b):
+            print a
+            b += 1
+            return b
+        """)
+
+        src = helper(srcBefore, coords(6, 0),
+                         coords(8, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+
+    def test_extractsConditionalFromExpression(self):
+        srcBefore=trimLines("""
+        def foo():
+            if 123+3:
+                print aoue
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            if newFunction():
+                print aoue
+
+        def newFunction():
+            return 123+3
+        """)
+        src = helper(srcBefore, coords(2, 7),
+                         coords(2, 12), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+    def test_extractCodeAfterCommentInMiddleOfFnDoesntRaiseParseException(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            print 1
+            # comment
+            print 2
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            print 1
+            # comment
+            newFunction()
+
+        def newFunction():
+            print 2
+        """)
+        src = helper(srcBefore, coords(4, 0),
+                         coords(5, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+        
+
+    def test_canExtractQueryFromNestedIfStatement(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            if foo: # comment
+                if bah:
+                    pass
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            if foo: # comment
+                if newFunction():
+                    pass
+
+        def newFunction():
+            return bah
+        """)
+        src = helper(srcBefore, coords(3, 11),
+                         coords(3, 14), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+
+    def test_doesntMessUpTheNextFunctionOrClass(self):
+        srcBefore=trimLines("""
+        def myFunction():
+            a = 3
+            print \"hello\"+a  # extract me
+            
+        class MyClass:
+            def myMethod(self):
+                b = 12      # extract me
+                c = 3       # and me
+                d = 2       # and me
+                print b, c
+        """)
+        srcAfter=trimLines("""
+        def myFunction():
+            a = 3
+            newFunction(a)
+
+        def newFunction(a):
+            print \"hello\"+a  # extract me
+            
+        class MyClass:
+            def myMethod(self):
+                b = 12      # extract me
+                c = 3       # and me
+                d = 2       # and me
+                print b, c
+        """)
+
+        # extract code on one line
+        src = helper(srcBefore, coords(3, 4),
+                         coords(3, 34), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+        # extract code on 2 lines (most common user method)
+        resetRoot()
+        Cache.instance.reset()
+        Root()
+        src = helper(srcBefore, coords(3, 0),
+                         coords(4, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntBallsUpIndentWhenTheresALineWithNoSpacesInIt(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            if 1:
+                pass
+
+            pass
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            newFunction()
+
+        def newFunction():
+            if 1:
+                pass
+            
+            pass
+        """)
+        src = helper(srcBefore, coords(2, 4),
+                     coords(5, 8), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntHaveToBeInsideAFunction(self):
+        srcBefore=trimLines(r"""
+        a = 1
+        print a + 2
+        f(b)	
+        """)
+        srcAfter=trimLines(r"""
+        a = 1
+        newFunction(a)
+
+        def newFunction(a):
+            print a + 2
+            f(b)	
+        """)
+        src = helper(srcBefore, coords(2, 0),
+                         coords(3, 4), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_doesntBarfWhenEncountersMethodCalledOnCreatedObj(self):
+        srcBefore=trimLines(r"""
+        results = QueryEngine(q).foo()
+        """)
+        srcAfter=trimLines(r"""
+        newFunction()
+
+        def newFunction():
+            results = QueryEngine(q).foo()
+        """)
+        src = helper(srcBefore, coords(1, 0),
+                         coords(2, 0), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+    def test_worksIfNoLinesBeforeExtractedCode(self):
+        srcBefore=trimLines(r"""
+        print a + 2
+        f(b)	
+        """)
+        srcAfter=trimLines(r"""
+        newFunction()
+
+        def newFunction():
+            print a + 2
+            f(b)	
+        """)
+        src = helper(srcBefore, coords(1, 0),
+                         coords(2, 4), "newFunction")
+        self.assertEqual(srcAfter, src)
+
+
+class TestGetRegionAsString(BRMTestCase):
+    def test_getsHighlightedSingleLinePassStatement(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 8),
+                             coords(3, 12), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(len(em.extractedLines), 1)
+        self.assertEqual(em.extractedLines[0], "pass\n")
+        
+    def test_getsSingleLinePassStatementWhenWholeLineIsHighlighted(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 0),
+                             coords(3, 12), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(len(em.extractedLines), 1)
+        self.assertEqual(em.extractedLines[0], "pass\n")
+
+
+    def test_getsMultiLineRegionWhenJustRegionIsHighlighted(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                print 'hello'
+                pass
+        """)
+        region=trimLines("""
+        print 'hello'
+        pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 8),
+                             coords(4, 12), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(em.extractedLines, region.splitlines(1))
+
+    def test_getsMultiLineRegionWhenRegionLinesAreHighlighted(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                print 'hello'
+                pass
+
+        """)
+        region=trimLines("""
+        print 'hello'
+        pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 0),
+                             coords(5, 0), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(em.extractedLines, region.splitlines(1))
+
+    def test_getsHighlightedSubstringOfLine(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                if a == 3:
+                    pass
+        """)
+        region=trimLines("""
+        a == 3
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 11),
+                             coords(3, 17), "foobah")
+        em.getRegionToBuffer()
+        self.assertEqual(em.extractedLines, region.splitlines(1))
+
+
+class TestGetTabwidthOfParentFunction(BRMTestCase):
+    def test_getsTabwidthForSimpleMethod(self):
+        src=trimLines("""
+        class MyClass:
+            def myMethod(self):
+                pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(3, 11),
+                             coords(3, 17), "foobah")
+        self.assertEqual(em.getTabwidthOfParentFunction(), 4)
+
+    def test_getsTabwidthForFunctionAtRootScope(self):
+        src=trimLines("""
+        def myFn(self):
+            pass
+        """)
+        sourcenode = createAST(src)
+        em = ExtractMethod(sourcenode, coords(2, 0),
+                             coords(2, 9), "foobah")
+        self.assertEqual(em.getTabwidthOfParentFunction(), 0)
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_extractVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from bike.testutils import *
+from bike.refactor.extractVariable import coords, extractLocalVariable
+
+class TestExtractLocalVariable(BRMTestCase):
+    def test_worksOnSimpleCase(self):
+        srcBefore=trimLines("""
+        def foo():
+            print 3 + 2
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3 + 2
+            print a
+        """)
+        sourcenode = createAST(srcBefore)
+        extractLocalVariable(tmpfile,coords(2,10),coords(2,15),'a')
+        self.assertEqual(sourcenode.getSource(),srcAfter)
+
+    def test_worksIfCoordsTheWrongWayRound(self):
+        srcBefore=trimLines("""
+        def foo():
+            print 3 + 2
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            a = 3 + 2
+            print a
+        """)
+        sourcenode = createAST(srcBefore)
+        extractLocalVariable(tmpfile,coords(2,15),coords(2,10),'a')
+        self.assertEqual(sourcenode.getSource(),srcAfter)
+
+        
+if __name__ == "__main__":
+    unittest.main()
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_inlineVariable.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from bike.testutils import trimLines,createAST, BRMTestCase
+from inlineVariable import inlineLocalVariable_old
+
+class TestInlineLocalVariable(BRMTestCase):
+
+    def test_worksWhenUserDoesItAgainstReference(self):
+        srcBefore=r"""
+        def foo():
+            b = 'hello'
+            print b
+        """
+        srcAfter=r"""
+        def foo():
+            print 'hello'
+        """
+
+        self.helper( srcBefore, 3, 10, srcAfter )
+
+    def test_worksWhenInlinedCodeIsOverTwoLines(self):
+        srcBefore=r"""
+        def foo():
+            b = 3 + \
+                2
+            print b
+        """
+
+        srcAfter=r"""
+        def foo():
+            print 3 + \
+                2
+        """
+
+        self.helper(srcBefore, 2, 4, srcAfter)
+
+    ''' Needs Adding Again 
+    def test_addsBracketsWhenInlinedCodeHasPresidenceOverSurroundingCode(self):
+        srcBefore=trimLines(r"""
+        def foo():
+            b = 3 + 2
+            print 3 * b
+        """)
+        srcAfter=trimLines(r"""
+        def foo():
+            print 3 * (3 + 2)
+        """)
+        assert 0
+    '''
+
+    def test_worksWithMultipleInstancesOfVariableOnLine(self):
+        srcBefore=r"""
+        def foo():
+            x = 11
+            print x, x
+        """
+
+        srcAfter=r"""
+        def foo():
+            print 11, 11
+        """
+        
+        self.helper(srcBefore, 2, 4, srcAfter)
+
+    def test_worksWithMultipleMultilineCode(self):
+        srcBefore=r"""
+        def foo():
+            b = 3 + \
+                2
+            print b
+            print b
+        """
+
+        srcAfter=r"""
+        def foo():
+            print 3 + \
+                2
+            print 3 + \
+                2
+        """
+
+        self.helper(srcBefore, 2, 4, srcAfter)
+
+    ''' Can't do this without some hairy logic to deduce how to inline
+        the variables. E.g. how do you inline a,b = foo() ?
+
+    def test_handlesTupleAssignment(self):
+        srcBefore=r"""
+        def foo():
+            x, y = 1, 2
+            print x
+            print y
+        """
+
+        srcAfter=r"""
+        def foo():
+            y = 2
+            print 1
+            print y
+        """
+        
+        self.helper(srcBefore, 2, 4, srcAfter)
+    '''
+
+
+    def helper(self, srcBefore, y, x, srcAfter):
+        sourcenode = createAST(trimLines(srcBefore))
+        inlineLocalVariable_old(sourcenode,y,x)
+        self.assertEqual(sourcenode.getSource(),trimLines(srcAfter))
+
+if __name__ == "__main__":
+    unittest.main()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_moveToModule.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+import setpath
+from bike.testutils import *
+from bike.transformer.save import save
+
+from moveToModule import *
+
+class TestMoveClass(BRMTestCase):
+    def test_movesTheText(self):
+        src1=trimLines("""
+        def before(): pass
+        class TheClass:
+            pass
+        def after(): pass
+        """)
+        src1after=trimLines("""
+        def before(): pass
+        def after(): pass
+        """)
+        src2after=trimLines("""
+        class TheClass:
+            pass
+        """)
+        
+        try:
+            createPackageStructure(src1, "")
+            moveClassToNewModule(pkgstructureFile1,2,
+                                 pkgstructureFile2)
+            save()
+            self.assertEqual(src1after,file(pkgstructureFile1).read())
+            self.assertEqual(src2after,file(pkgstructureFile2).read())
+        finally:
+            removePackageStructure()
+
+class TestMoveFunction(BRMTestCase):
+    def test_importsNameReference(self):
+        src1=trimLines("""
+        a = 'hello'
+        def theFunction(self):
+            print a
+        """)
+        src2after=trimLines("""
+        from a.foo import a
+        def theFunction(self):
+            print a
+        """)
+        self.helper(src1, src2after)
+        
+
+
+    def test_importsExternalReference(self):
+        src0=("""
+        a = 'hello'
+        """)
+        src1=trimLines("""
+        from top import a
+        def theFunction(self):
+            print a
+        """)
+        src2after=trimLines("""
+        from top import a
+        def theFunction(self):
+            print a
+        """)
+        try:
+            createPackageStructure(src1, "", src0)
+            moveFunctionToNewModule(pkgstructureFile1,2,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src2after,file(pkgstructureFile2).read())
+        finally:
+            removePackageStructure()
+
+    def test_doesntImportRefCreatedInFunction(self):
+        src1=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        src2after=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        
+        self.helper(src1, src2after)
+
+
+    def test_doesntImportRefCreatedInFunction(self):
+        src1=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        src2after=trimLines("""
+        def theFunction(self):
+            a = 'hello'
+            print a
+        """)
+        
+        self.helper(src1, src2after)
+
+
+    def test_addsImportStatementToOriginalFileIfRequired(self):
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        b = theFunction()
+        """)
+        
+        src1after=trimLines("""
+        from a.b.bah import theFunction
+        b = theFunction()
+        """)
+        try:
+            createPackageStructure(src1,"")
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src1after,file(pkgstructureFile1).read())
+        finally:
+            removePackageStructure()
+
+    def test_updatesFromImportStatementsInOtherModules(self):
+        src0=trimLines("""
+        from a.foo import theFunction
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        """)
+        
+        src0after=trimLines("""
+        from a.b.bah import theFunction
+        print theFunction()
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+
+    def test_updatesFromImportMultiplesInOtherModules(self):
+        src0=trimLines("""
+        from a.foo import something,theFunction,somethingelse #comment
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        something = ''
+        somethingelse = 0
+        """)
+        
+        src0after=trimLines("""
+        from a.foo import something,somethingelse #comment
+        from a.b.bah import theFunction
+        print theFunction()
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+        
+    def test_updatesFromImportMultiplesInTargetModule(self):
+        src0=trimLines("""
+        from a.foo import something,theFunction,somethingelse #comment
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        something = ''
+        somethingelse = 0
+        """)
+        
+        src0after=trimLines("""
+        from a.foo import something,somethingelse #comment
+        print theFunction()
+        def theFunction(self):
+            pass
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile0)
+            save()
+            #print file(pkgstructureFile0).read()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+
+
+    def test_updatesFromImportInTargetModule(self):
+        src0=trimLines("""
+        from a.foo import theFunction
+        print theFunction()
+        """)
+        src1=trimLines("""
+        def theFunction(self):
+            pass
+        """)
+        
+        src0after=trimLines("""
+        print theFunction()
+        def theFunction(self):
+            pass
+        """)
+        try:
+            createPackageStructure(src1,"",src0)
+            moveFunctionToNewModule(pkgstructureFile1,1,
+                                    pkgstructureFile0)
+            save()
+            self.assertEqual(src0after,file(pkgstructureFile0).read())
+        finally:
+            removePackageStructure()
+
+
+
+    def helper(self, src1, src2after):
+        try:
+            createPackageStructure(src1, "")
+            moveFunctionToNewModule(pkgstructureFile1,2,
+                                    pkgstructureFile2)
+            save()
+            self.assertEqual(src2after,file(pkgstructureFile2).read())
+        finally:
+            removePackageStructure()
+        
+
+        
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_rename.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from bike import testdata
+from rename import rename
+from bike.testutils import *
+
+class TestRenameTemporary(BRMTestCase):
+    def test_renamesSimpleReferencesGivenAssignment(self):
+        src=trimLines("""
+        def foo():
+            a = 3
+            print a
+        """)
+        srcAfter=trimLines("""
+        def foo():
+            b = 3
+            print b
+        """)
+        src = self.helper(src,"",2,4,"b")
+        self.assertEqual(srcAfter,src)
+
+    def helper(self, src, classsrc, line, col, newname):
+        try:
+            createPackageStructure(src,classsrc)
+            filename = pkgstructureFile1
+            rename(filename,line,col,newname)
+            # modify me once save is moved
+            #return readFile(filename)
+            from bike.transformer.save import outputqueue
+            return outputqueue[filename]
+        finally:
+            removePackageStructure()
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_renameClass.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from rename import rename
+from bike.transformer.save import save
+from bike.testutils import *
+import compiler
+
+class RenameClassTests:
+
+    def testRenamesClassDcl(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            def theMethod():
+                pass
+        """)
+
+        src = self.rename(srcBefore, 1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. a = TheClass()
+    def testRenamesClassReference(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        a = NewName()
+        """)
+        src = self.rename(srcBefore, 1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. a = TheClass.TheClass()
+    def testRenamesClassReferenceWhenScopeIsSameNameAsClass(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            class NewName:
+                pass
+        a = TheClass.NewName()
+        """)
+        src = self.rename(srcBefore, 2,10, "NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. a = TheClass.TheClass()
+    def testRenamesClassReferenceWhenChildIsSameNameAsClass(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            class TheClass:
+                pass
+        a = TheClass.TheClass()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            class TheClass:
+                pass
+        a = NewName.TheClass()
+        """)
+        src = self.rename(srcBefore, 1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+
+    # a = TheClass() + TheClass()
+    def testRenamesClassReferenceWhenTwoRefsInTheSameLine(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        a = TheClass() + TheClass()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        a = NewName() + NewName()
+        """)
+        src = self.rename(srcBefore,1,6, "NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassReferenceInInstanceCreation(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self): pass
+        TheClass().theMethod()
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            def theMethod(self): pass
+        NewName().theMethod()
+        """)
+        src = self.rename(srcBefore,1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    # i.e. if renaming TheClass, shouldnt rename a.b.c.TheClass
+    def testDoesntRenameBugusClassReferenceOnEndOfGetattrNest(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass        
+        a.b.c.TheClass    # Shouldn't be renamed
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass        
+        a.b.c.TheClass    # Shouldn't be renamed
+        """)
+        src = self.rename(srcBefore,1,6,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassRefUsedInExceptionRaise(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        raise TheClass, \"hello mum\"
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        raise NewName, \"hello mum\"
+        """)
+        src = self.rename(srcBefore, 1,6, "NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassReferenceNameInInheritenceSpec(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            pass
+        class DerivedClass(TheClass):
+            pass
+        """)
+        srcAfter=trimLines("""
+        class NewName:
+            pass
+        class DerivedClass(NewName):
+            pass
+        """)
+        src = self.rename(srcBefore, 1,6, "NewName")
+        self.assertEqual(srcAfter,src)
+
+
+
+class RenameClassTests_importsClass:
+
+    def testRenamesClassReferenceInInstanceCreationWithFQN(self):
+        srcBefore=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.NewName()
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesClassReferencesInInheritenceSpecs(self):
+
+        srcBefore=trimLines("""
+        import b
+        class DerivedClass(b.bah.TheClass):
+            pass
+        """)
+        srcAfter=trimLines("""
+        import b
+        class DerivedClass(b.bah.NewName):
+            pass
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesFromImportReferenceWhenInBodyOfClass(self):
+        srcBefore=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+        srcAfter=trimLines("""
+        class AnotherClass:
+            from b.bah import NewName
+            NewName.baz = 0
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+
+    def testRenamesReferenceToClassImportedInSameClassScope(self):
+        srcBefore=trimLines("""
+        class AnotherClass:
+            from b.bah import TheClass
+            TheClass.baz = 0
+        """)
+        srcAfter=trimLines("""
+        class AnotherClass:
+            from b.bah import NewName
+            NewName.baz = 0
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesReferenceToClassImportedWithFromImportStar(self):
+        srcBefore=trimLines("""
+        from a.b.bah import *
+        a = TheClass()
+        """)
+        srcAfter=trimLines("""
+        from a.b.bah import *
+        a = NewName()
+        """)
+        src = self.renameClass(srcBefore,"NewName")
+        self.assertEqual(srcAfter,src)
+
+class TestRenameClass(BRMTestCase, RenameClassTests):
+
+    def rename(self, src, line, col, newname):
+        createPackageStructure(src,"pass")
+        rename(pkgstructureFile1,line,col, newname)
+        save()
+        return file(pkgstructureFile1).read()
+
+
+class TestRenameClassReferenceWithDirectoryStructure(BRMTestCase,
+                                         RenameClassTests_importsClass):
+
+    def renameClass(self, src, newname):
+        createPackageStructure(src,TheClassTestdata)
+        rename(pkgstructureFile2,1,6, newname)
+        save()
+        return file(pkgstructureFile1).read()
+
+
+TheClassTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_renameFunction.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from rename import rename
+from bike import testdata
+from bike.testutils import *
+from bike.transformer.save import save
+import compiler
+
+class RenameFunctionTests:
+    def runTarget(self, src, klassfqn, newname):
+        # see concrete subclasses for implementation
+        pass
+
+    def testRenamesFunctionDcl(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            pass
+        """)
+        srcAfter=trimLines("""
+        def newName():
+            pass
+        """)
+        src = self.rename(srcBefore,1,4,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def testDoesntBarfWhenFunctionIncludesBrackettedExpression(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            return ('\\n').strip()
+        """)
+        srcAfter=trimLines("""
+        def newName():
+            return ('\\n').strip()
+        """)
+        src = self.rename(srcBefore,1,4, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+
+
+class RenameFunctionTests_importsFunction:
+
+    def testRenamesImportedFunctionReference(self):
+        srcBefore=trimLines("""
+        import b.bah
+        b.bah.theFunction()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        b.bah.newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesFunctionReferenceImportedWithFromClause(self):
+        srcBefore=trimLines("""
+        from b.bah import theFunction
+        theFunction()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import newName
+        newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def testRenamesFunctionRefInImportClause(self):
+        srcBefore=trimLines("""
+        import b.bah
+        b.bah.theFunction()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        b.bah.newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def testRenamesFunctionRefInImportFromClause(self):
+        srcBefore=trimLines("""
+        from b.bah import theFunction
+        theFunction()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import newName
+        newName()
+        """)
+        src = self.renameFunction(srcBefore,"newName")
+        self.assertEqual(srcAfter,src)
+
+
+
+class TestRenameFunction(BRMTestCase, RenameFunctionTests):
+    def rename(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        rename(tmpfile,line,col, newname)
+        save()
+        return file(tmpfile).read()
+
+
+class TestRenameFunctionReferenceWithDirectoryStructure(BRMTestCase, RenameFunctionTests_importsFunction):
+
+    def renameFunction(self, src, newname):
+        createPackageStructure(src,FunctionTestdata)
+        rename(pkgstructureFile2,1,4, newname)
+        save()
+        return file(pkgstructureFile1).read()
+
+FunctionTestdata = trimLines("""
+def theFunction():
+    pass
+""")
+
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/test_renameMethod.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,710 @@
+#!/usr/bin/env python
+import setpath
+import unittest
+from rename import rename
+import compiler
+from bike import testdata
+
+from bike.testutils import*
+
+from bike.transformer.save import save
+
+class RenameMethodTests:
+    
+    def test_renamesTheMethod(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameMethodOfSameNameOnOtherClasses(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        class b:
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        class b:
+            def theMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameOtherMethodsOfSameClass(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                a=b
+            def aMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                a=b
+            def aMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodWhenClassNestedInFunction(self):
+        srcBefore=trimLines("""
+        def theFunction():
+            class TheClass:
+                def theMethod(self):
+                    pass
+        """)
+        srcAfter=trimLines("""
+        def theFunction():
+            class TheClass:
+                def newName(self):
+                    pass
+        """)
+        src = self.rename(srcBefore,3,12,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntBarfOnInheritanceHierarchies(self):
+        srcBefore=trimLines("""
+        from b.bah import DifferentClass
+        class TheClass(foo.bah):
+            def theMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+
+    def test_renamesMethodWhenMethodCallFromOtherMethodInSameClass(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+            def anotherMethod(self):
+                self.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+            def anotherMethod(self):
+                self.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntBarfOnNestedClasses(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            class AnotherClass:
+                pass
+            def theMethod(self):
+                pass
+        """)
+        src = self.rename(srcBefore,4,8,"newName")
+
+    def test_renamesMethodWhenBaseClassesArentInAST(self):
+        srcBefore=trimLines("""
+        class TheClass(notInAst):
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class TheClass(notInAst):
+            def newName(self):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodInRelatedClasses(self):
+        srcBefore=trimLines("""
+        class root:
+            def theMethod(self):
+                pass
+
+        class a(root):
+            def theMethod(self):
+                pass
+
+        class b(root):
+            pass
+
+        class TheClass(b):
+            def theMethod(self):
+                pass
+        """)
+        srcAfter=trimLines("""
+        class root:
+            def newName(self):
+                pass
+
+        class a(root):
+            def newName(self):
+                pass
+
+        class b(root):
+            pass
+
+        class TheClass(b):
+            def newName(self):
+                pass
+        """)
+        src = self.rename(srcBefore,13,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def test_renameMethodDoesntBarfOnNoneAsDefaultArgToMethod(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self, root, flist, stack=None):
+                pass
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+
+
+
+class RenameMethodTests_ImportsClass:
+    def test_renamesMethodOnDerivedClassInstance(self):
+        srcBefore = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+
+        class DerivedDerivedClass(DerivedClass):
+            def theMethod(self):
+                print 'hello'
+        """)
+        srcAfter = trimLines("""
+        from b.bah import TheClass as BaseClass
+        
+        class DerivedClass(BaseClass):
+            pass
+
+        class DerivedDerivedClass(DerivedClass):
+            def newName(self):
+                print 'hello'
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+        
+class RenameMethodReferenceTests:
+    # Generic tests. These tests are designed to be run in the context of a ui
+    #  and in a package hierarchy structure
+
+    def test_doesntBarfWhenConfrontedWithComplexReturnTypes(self):
+        src = trimLines("""
+        import a
+        class TheClass:
+            def theMethod(self):
+                 pass
+                 
+        def bah():
+            return a[35]
+            
+        b = bah()
+        b.theMethod()
+        """)
+        self.rename(src,3,8,"newName")
+
+    def test_doesntbarfWhenCallMadeOnInstanceReturnedFromFnCall(self):
+        srcBefore=trimLines("""
+        from foo import e
+        class TheClass:
+            def theMethod(self):
+                pass
+        ast = e().f(src)
+        """)
+        self.rename(srcBefore,3,8,"newName")
+
+    def test_doesntStackOverflowOnRecursiveFunctions(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+
+        def foo(a):
+            return foo(a)
+        """)
+        self.rename(srcBefore,2,8,"newName")
+
+    def test_renamesMethodReferenceOfInstanceCreatedInParentScopeAfterFunction(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = TheClass()
+        def foo():
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        a = TheClass()
+        def foo():
+            a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+ 
+    def test_renamesMethodReferenceOfInstanceObtainedByCallingFunction(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName():
+                pass
+        def foo():
+            b = TheClass()
+            return b
+        a = foo()
+        a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOfInstanceCreatedInAnotherFunction(self):
+
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        def bah():
+            return TheClass()
+        def foo():
+            a = bah()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName():
+                pass
+        def bah():
+            return TheClass()
+        def foo():
+            a = bah()
+            a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOfInstanceCreatedInSubsequentFunction(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.theMethod()
+            
+        def bah():
+            return TheClass()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName():
+                pass
+        class NotTheClass:
+            def theMethod():
+                pass
+            
+        def foo():
+            a = bah()
+            a.newName()
+            
+        def bah():
+            return TheClass()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOnInstanceThatIsAnAttributeOfSelf(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        
+        class AnotherClass:
+            def __init__(self):
+                self.a = TheClass()
+            def anotherFn(self):
+                self.a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        
+        class AnotherClass:
+            def __init__(self):
+                self.a = TheClass()
+            def anotherFn(self):
+                self.a.newName()
+        """)
+        src = self.rename(srcBefore,2,8,"newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntBarfOnGetattrThatItCantDeduceTypeOf(self):
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        a = TheClass
+        
+        a.b.bah = 3
+        """)
+        self.rename(srcBefore,2,8,"newName")
+
+
+class RenameMethodReferenceTests_ImportsClass:
+
+    def test_renamesReferenceOfClassImportedAsAnotherName(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass as MyTheClass        
+        def foo():
+            a = MyTheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass as MyTheClass        
+        def foo():
+            a = MyTheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore,2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesReferenceWhenObjectCreationAndReferenceInModuleScope(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def test_renamesReferenceWhenObjectCreatedInSameFunctionAsReference(self):
+        srcBefore=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        def foo():
+            a = b.bah.TheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntrenameDifferentMethodReferenceWhenObjectCreatedInSameScope(self):
+        srcBefore=trimLines("""
+        import b.bah.TheClass
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 4,8, "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_doesntrenameMethodReferenceWhenDifferentObjectCreatedInSameScope(self):
+        srcBefore=trimLines("""
+        import b.bah.TheClass
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 8,8,"newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOfImportedClass(self):
+        srcBefore=trimLines("""
+        import b.bah
+        
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        import b.bah
+        
+        def foo():
+            a = b.bah.TheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameReferenceOfDifferentImportedClass(self):
+        srcBefore=trimLines("""
+        from b.bah import DifferentClass
+        
+        def foo():
+            a = b.bah.TheClass()
+            a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 8,8,
+                                           "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOfClassImportedWithFromClause(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            a = TheClass()
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass
+        
+        def foo():
+            a = TheClass()
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntrenameReferenceOfClassImportedWithDifferentAsClause(self):
+        srcBefore = trimLines("""
+        from b.bah import TheClass as MyClass
+        
+        def foo():
+            a = TheClass()
+            a.theMethod()
+        """)
+
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOfClassImportedWithFromFooImportStar(self):
+        srcBefore=trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import *
+        a = TheClass()
+        a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_renamesMethodReferenceOfInstanceCreatedInParentScope(self):
+        srcBefore=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        def foo():
+            a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        from b.bah import TheClass
+        a = TheClass()
+        def foo():
+            a.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+    def test_doesntRenameMethodWhenObjectCreatedInChildScopeToMethodReference(self):
+        srcBefore = trimLines("""
+        from b.bah import TheClass
+        a = AnotherClass()
+        def foo():
+            a = TheClass()
+        a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcBefore,src)
+
+    def test_renamesReferenceOnDerivedClassInstance(self):
+        srcBefore=trimLines("""
+        import b
+        class DerivedClass(b.bah.TheClass):
+            pass
+        class DerivedDerivedClass(DerivedClass):
+            pass
+        theInstance = DerivedDerivedClass()
+        theInstance.theMethod()
+        """)
+        srcAfter=trimLines("""
+        import b
+        class DerivedClass(b.bah.TheClass):
+            pass
+        class DerivedDerivedClass(DerivedClass):
+            pass
+        theInstance = DerivedDerivedClass()
+        theInstance.newName()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+
+# tests that cover stuff not renamed automatically
+# (I.e. are renamed after user manually expresses desire to do so)
+class RenameMethodAfterPromptTests:
+    def test_renamesReferenceWhenMethodCallDoneOnInstanceCreation(self):
+
+        srcBefore=trimLines("""
+        class TheClass:
+            def theMethod(self): pass
+        TheClass().theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self): pass
+        TheClass().newName()
+        """)
+        src = self.renameMethod(srcBefore,2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+    def test_renamesReferenceInMiddleOfBiggerCompoundCall(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod(self): return AnotherClass()
+        TheClass().theMethod().anotherMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self): return AnotherClass()
+        TheClass().newName().anotherMethod()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+class TestRenameMethodWithSingleModule(BRMTestCase, RenameMethodTests, RenameMethodReferenceTests):
+    # template method 
+    def rename(self, src, line, col, newname):
+        try:
+            createPackageStructure(src, "pass")
+            rename(pkgstructureFile1,line,col,newname)
+            save()
+            return file(pkgstructureFile1).read()
+        finally:
+            removePackageStructure()
+
+
+class TestRenameMethodWithDirectoryStructure(RenameMethodTests, RenameMethodReferenceTests, BRMTestCase):
+
+    def rename(self, src, line, col, newname):
+        try:
+            createPackageStructure("pass",src)
+            rename(pkgstructureFile2,line,col,newname)
+            save()
+            return file(pkgstructureFile2).read()
+        finally:
+            removePackageStructure()
+
+
+class TestRenameMethodReferenceWithDirectoryStructure(BRMTestCase, RenameMethodTests_ImportsClass, RenameMethodReferenceTests_ImportsClass):
+
+    def renameMethod(self, src, line, col, newname):
+        try:
+            createPackageStructure(src,MethodTestdata)
+            rename(pkgstructureFile2,line,col,newname)
+            save()
+            return file(pkgstructureFile1).read()
+        finally:
+            removePackageStructure()
+
+class TestRenameMethodStuffCorrectlyAfterPromptReturnsTrue(BRMTestCase, 
+                                                      RenameMethodAfterPromptTests):
+
+    def callback(self, filename, line, colbegin, colend):
+        return 1
+
+
+    def renameMethod(self, src, line, col, newname):
+        createPackageStructure(src, MethodTestdata)
+        rename(pkgstructureFile1,line,col,newname,self.callback)
+        save()
+        return file(pkgstructureFile1).read()
+
+
+
+class TestDoesntRenameMethodIfPromptReturnsFalse(BRMTestCase):
+    def callback(self, filename, line, colbegin, colend):
+        return 0
+
+    def renameMethod(self, src, line, col, newname):
+        createPackageStructure(src, MethodTestdata)
+        rename(pkgstructureFile1,line,col,newname,self.callback)
+        save()
+        return file(pkgstructureFile1).read()
+
+    def test_doesntRenameMethodIfPromptReturnsFalse(self):
+        srcBefore = trimLines("""
+        class TheClass:
+            def theMethod(self):
+                pass
+        b = TheClass()
+        b.theMethod()
+        a = someFunction()
+        a.theMethod()
+        """)
+        srcAfter=trimLines("""
+        class TheClass:
+            def newName(self):
+                pass
+        b = TheClass()
+        b.newName()
+        a = someFunction()
+        a.theMethod()
+        """)
+        src = self.renameMethod(srcBefore, 2,8, "newName")
+        self.assertEqual(srcAfter,src)
+
+
+MethodTestdata = trimLines("""
+class TheClass:
+    def theMethod(self):
+        pass
+    def differentMethod(self):
+        pass
+
+class DifferentClass:
+    def theMethod(self):
+        pass
+""")
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/testall.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+import setpath
+from test_renameMethod import *
+from test_renameClass import *
+from test_renameFunction import *
+from test_rename import *
+from test_extractMethod import *
+from test_inlineVariable import *
+from test_extractVariable import *
+from test_moveToModule import *
+
+if __name__ == "__main__":
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/refactor/utils.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,24 @@
+import re
+
+def getLineSeperator(line):
+    if line.endswith("\r\n"):
+        linesep = "\r\n"          # windoze
+    else:
+        linesep = line[-1]   # mac or unix
+    return linesep
+
+
+def getTabWidthOfLine(line):
+    match = re.match("\s+",line)
+    if match is None:
+        return 0
+    else:
+        return match.end(0)
+
+def reverseCoordsIfWrongWayRound(startcoords,endcoords):
+    if(startcoords.line > endcoords.line) or \
+         (startcoords.line == endcoords.line and \
+          startcoords.column > endcoords.column):
+        return endcoords,startcoords
+    else:
+        return startcoords,endcoords
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/setpath.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,5 @@
+import sys,os
+if not os.path.abspath("..") in sys.path:
+    from bike import log
+    print >> log.warning, "Appending to the system path. This should only happen in unit tests"
+    sys.path.append(os.path.abspath(".."))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/sadness/bike/bike/test_bikefacade.py	Mon Nov 22 14:32:21 2010 -0500
@@ -0,0 +1,377 @@
+#!/usr/bin/env python
+import unittest
+import setpath
+import sys
+
+from bike import testdata
+from bike.testutils import *
+import bike
+from bike.refactor.test_renameFunction import RenameFunctionTests, RenameFunctionTests_importsFunction, FunctionTestdata
+from bike.refactor.test_renameClass import RenameClassTests, RenameClassTests_importsClass, TheClassTestdata
+from bike.refactor.test_renameMethod import RenameMethodTests, RenameMethodTests_ImportsClass, RenameMethodReferenceTests, RenameMethodReferenceTests_ImportsClass, RenameMethodAfterPromptTests, TestDoesntRenameMethodIfPromptReturnsFalse,MethodTestdata
+from bike.refactor import test_extractMethod
+import bikefacade
+from bike import UndoStackEmptyException
+from bike.query.getTypeOf import getTypeOf
+
+class TestPathFunctions(BRMTestCase):
+    def test_setCompletePythonPath_removesDuplicates(self):
+        origpath = sys.path
+        try:
+            sys.path = ["foobah"]
+            ctx = bike.init()
+            ctx._setCompletePythonPath(sys.path[-1])
+            self.assertEqual(1,ctx._getCurrentSearchPath().count(sys.path[-1]))
+        finally:
+            sys.path = origpath
+
+
+    def test_setNonLibPathonPath_removesLibDirectories(self):
+        origpath = sys.path
+        try:
+            writeTmpTestFile("pass")
+            libdir = os.path.join(sys.prefix,"lib","python"+sys.version[:3])
+            sys.path = [libdir,os.path.join(libdir,"site-packages")]
+            ctx = bike.init()
+            ctx._setNonLibPythonPath(tmproot)
+            self.assertEqual([tmproot],ctx._getCurrentSearchPath())
+        finally:
+            sys.path = origpath
+
+class TestRenameMethodAfterPrompt(BRMTestCase,RenameMethodAfterPromptTests):
+    def callback(self, filename, line, colstart, colend):
+        return 1
+
+    def renameMethod(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        ctx.setRenameMethodPromptCallback(self.callback)
+        ctx.renameByCoordinates(tmpfile,line,col,newname)
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        return newsrc
+
+class TestDoesntRenameMethodIfPromptReturnsFalse(TestDoesntRenameMethodIfPromptReturnsFalse):
+
+    def callback(self, filename, line, colstart, colend):
+        return 0
+
+    def renameMethod(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        ctx.setRenameMethodPromptCallback(self.callback)
+        ctx.renameByCoordinates(tmpfile,line,col,newname)
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        return newsrc
+
+
+class TestRenameByCoordinates2(RenameMethodTests,RenameMethodReferenceTests, RenameClassTests,RenameFunctionTests,BRMTestCase):
+    def rename(self, src, line, col, newname):
+        writeTmpTestFile(src)
+        ctx = bike.init()
+        ctx.renameByCoordinates(os.path.abspath(tmpfile),line,col,newname)
+        ctx.save()
+        newsrc = readFile(tmpfile)
+        return newsrc
+
+
+class TestRenameByCoordinatesWithDirectoryStructure(
+                                RenameClassTests_importsClass,
+                                RenameFunctionTests_importsFunction,
+                                RenameMethodTests_ImportsClass,
+                                RenameMethodReferenceTests_ImportsClass,
+                                BRMTestCase):
+    def renameClass(self, src, newname):
+        try:
+            createPackageStructure(src, TheClassTestdata)
+            ctx = bike.init()
+            ctx.renameByCoordinates(pkgstructureFile2,1,6,newname)
+            ctx.save()
+            newsrc = readFile(pkgstructureFile1)
+            return newsrc
+        finally:
+            removePackageStructure()
+
+
+    def renameMethod(self, src, line, col, newname):
+        try:
+            createPackageStructure(src, MethodTestdata)
+            ctx = bike.init()
+            ctx.renameByCoordinates(pkgstructureFile2,line,col,newname)
+            ctx.save()
+            newsrc = readFile(pkgstructureFile1)
+            return newsrc
+        finally:
+            removePackageStructure()
+
+    def renameFunction(self, src, newname):
+        try:
+            createPackageStructure(src, FunctionTestdata)
+            ctx = bike.init()
+            ctx.renameByCoordinates(pkgstructureFile2,1,4,newname)
+            ctx.save()
+            newsrc = readFile(pkgstructureFile1)
+            return newsrc
+        finally:
+            removePackageStructure()
+
+
+
+class Test_deducePackageOfFile(BRMTestCase):
+    def test_returnsEmptyStringIfFileNotInPackage(self):
+        try:
+            # this doesnt have __init__.py file, so
+            # isnt package
+            os.makedirs("a")
+            writeFile(os.path.join("a","foo.py"),"pass")
+            pkg = bikefacade._deducePackageOfFile(os.path.join("a","foo.py"))
+            assert pkg == ""
+        finally:
+            os.remove(os.path.join("a","foo.py"))
+            os.removedirs(os.path.join("a"))
+
+    def test_returnsNestedPackage(self):
+        try:
+            os.makedirs(os.path.join("a","b"))
+            writeFile(os.path.join("a","__init__.py"),"# ")
+            writeFile(os.path.join("a","b","__init__.py"),"# ")
+            writeFile(os.path.join("a","b","foo.py"),"pass")
+            pkg = bikefacade._deducePackageOfFile(os.path.join("a","b","foo.py"))
+            assert pkg == "a.b"
+        finally:
+            os.remove(os.path.join("a","__init__.py"))
+            os.remove(os.path.join("a","b","__init__.py"))
+            os.remove(os.path.join("a","b","foo.py"))