Globalsub: Replace objects Globally =================================== Globalsub is a tool for use in testing. It allows you to scan all namespaces in the Python interpreter to find references to a given object and replace those references with references to another object. It then allows you to return the references back to the original object when you are finished. Interactive Usage:: >>> import globalsub >>> def x(): ... print 'x' ... >>> def y(): ... print 'y' ... >>> globalsub.subs( x, y ) >>> x() y >>> y() y >>> globalsub.restore( x ) >>> x() x >>> y() y Test Case Usage:: import globalsub import somemodule import settings class MyTests( unittest.TestCase ): def setUp( self ): # stub out the function so that it is never run during this # test suite... # default subs is a function that takes *args, **named and returns None globalsub.subs( somemodule.should_never_run ) def tearDown( self ): # we always subs'd this, we always restore it globalsub.restore( somemodule.should_never_run ) # we *may* have subs'd these, restoring them doesn't hurt us... globalsub.restore( somemodule.whatever ) globalsub.restore( settings.PATH_TO_EXECUTABLE ) def test_something_specific( self ): def fake_whatever( *args, **named ): return ['this'] globalsub.subs( somemodule.whatever, fake_whatever ) def test_with_a_mockproc( self ): globalsub.subs( settings.PATH_TO_EXECUTABLE, 'fake-executable' ) Referencing the Original Object:: holder = [ original_function ] def fake_function( *args, **named ): result = holder[0]( *args, **named ) return result.replace( 'a', 'b' ) globalsub.subs( original_function, fake_function ) How it Works ------------ :py:func:`globalsub.subs` uses the gc module to find all references to a given object. It tracks each object which is holding a reference to the *replacement*, along with the original object (in a list internally), then replaces all (dictionary) references to the object with the replacement object (using the :py:func:`globalsub.global_replace` function). :py:func:`globalsub.restore` uses the substituted object's metadata to do the inverse replacement, using the filter-set of references which were to the replacement object (rather than the original) to avoid unintentionally replacing the replacement with the original. Installation ------------ Standard Python library installation from `PyPI`_: .. code-block:: bash $> source my-virtual-env/bin/activate $> pip install globalsub To help contribute/develop globalsub, install `bzr`_ and then use the following command: .. code-block:: bash $> pip install -e bzr+http://bazaar.launchpad.net/~mcfletch/globalsub/trunk#egg=globalsub Which will install globalsub into your VirtualEnv's src directory in an editable format. The `LaunchPad Project`_ can be used to report bugs, or you can contact the `author`_ directly. .. _PyPI: http://pypi.python.org/pypi/globalsub/ .. _bzr: http://bazaar.canonical.com/ .. _`LaunchPad Project`: https://launchpad.net/globalsub .. _author: http://www.vrplumber.com Limitations ----------- The implementation has the following major limitations: * will only replace references in dictionaries (not lists, not tuples) * replaces *all* references, so if you replace the digit 1, every reference to the shared small integer object will be replaced with your replacement object * can only handle a couple of built-in types (str/unicode being the useful ones, normally) * you must call restore on the *substituted* object, not the original object, so if you store references to objects in lists "subs all these" you are going to have to store the result of the subs calls to do the restoration * you cannot use the same object twice as the substituted object, as only the *last* item replaced can be restored Contents: .. toctree:: :maxdepth: 2 globalsub Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search`