title: How to dynamically create module level functions from methods in a class
body: <p>I am trying to dynamically create module level functions from the methods in a class. So for every method in a class, I want to create a function with the same name which creates an instance of the class and then calls the method.</p>
  
  <p>The reason I want to do this is so I can take an object-oriented approach to creating Fabric files. Since Fabric will call module level functions but not methods of a class, this is my work-around.</p>
  
  <p>I have used the following links to get me started</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/1911281/how-do-you-get-list-of-methods-in-a-python-class">How do I get list of methods in a Python class?</a></li>
  <li><a href="https://stackoverflow.com/questions/1621350/dynamically-adding-functions-to-a-python-module">dynamically adding functions to a Python module</a></li>
  <li><a href="https://stackoverflow.com/questions/2933470/how-do-i-call-setattr-on-the-current-module">How do I call setattr() on the current module?</a></li>
  <li><a href="http://effbot.org/zone/python-getattr.htm" rel="nofollow noreferrer">http://effbot.org/zone/python-getattr.htm</a></li>
  <li><a href="https://stackoverflow.com/questions/3061/calling-a-function-from-a-string-with-the-functions-name-in-python">Calling a function of a module from a string with the function&#39;s name in Python</a></li>
  <li><a href="https://stackoverflow.com/questions/1142068/how-to-modify-the-local-namespace-in-python">How to modify the local namespace in python</a></li>
  </ul>
  
  <p>And I have come up with the following code</p>
  
  <pre><code>import inspect
  import sys
  import types
  
  class TestClass(object):
      def __init__(self):
          pass
  
      def method1(self, arg1):
          print 'method 1 %s' % arg1
  
      def method2(self):
          print 'method 2'
  
  def fabric_class_to_function_magic(module_name):
      # get the module as an object
      print module_name
      module_obj = sys.modules[module_name]
      print dir(module_obj)
  
      # Iterate over the methods of the class and dynamically create a function
      # for each method that calls the method and add it to the current module
      for method in inspect.getmembers(TestClass, predicate=inspect.ismethod):
          print
          print method
          method_name, method_obj = method
  
          # create a new template function which calls the method
          def newfunc_template(*args, **kwargs):
              tc = TestClass()
              func = getattr(tc, method_name)
              return func(*args, **kwargs)
  
          # create the actual function
          print 'code: ', newfunc_template.func_code
          print 'method_name: ', method_name
          newfunc = types.FunctionType(newfunc_template.func_code,
                                       {'TestClass': TestClass,
                                        'getattr': getattr,
                                        'method_name': method_name,
                                        },
                                       name=method_name,
                                       argdefs=newfunc_template.func_defaults,
                                       closure=newfunc_template.func_closure,
                                       )
  
          # add the new function to the current module
          setattr(module_obj, method_name, newfunc)
  
  # test the dynamically created module level function
  thismodule = sys.modules[__name__]
  print dir(thismodule)
  fabric_class_to_function_magic(__name__)
  print dir(thismodule)
  method1('arg1')
  method2()
  </code></pre>
  
  <p>And I get the following error</p>
  
  <pre><code>['TestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'sys', 'thismodule', 'types']
  __main__
  ['TestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'sys', 'thismodule', 'types']
  
  ('__init__', &lt;unbound method TestClass.__init__&gt;)
  code:  &lt;code object newfunc_template at 0x7f8800a28d50, file "test.py", line 85&gt;
  method_name:  __init__
  
  ('method1', &lt;unbound method TestClass.method1&gt;)
  code:  &lt;code object newfunc_template at 0x7f8800a28d50, file "test.py", line 85&gt;
  method_name:  method1
  
  ('method2', &lt;unbound method TestClass.method2&gt;)
  code:  &lt;code object newfunc_template at 0x7f8800a28d50, file "test.py", line 85&gt;
  method_name:  method2
  ['TestClass', '__builtins__', '__doc__', '__file__', '__init__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'method1', 'method2', 'sys', 'thismodule', 'types']
  Traceback (most recent call last):
    File "test.py", line 111, in &lt;module&gt;
      method1('arg1')
    File "test.py", line 88, in newfunc_template
      return func(*args, **kwargs)
  TypeError: method2() takes exactly 1 argument (2 given)
  </code></pre>
  
  <p>It seems to be reusing the reference to the function? Any ideas?</p>
  
  <p>UPDATE: Here is the working code with Ned Batchelder's fix</p>
  
  <pre><code>def fabric_class_to_function_magic(module_name):
      # get the module as an object
      module_obj = sys.modules[module_name]
  
      # Iterate over the methods of the class and dynamically create a function
      # for each method that calls the method and add it to the current module
      for method in inspect.getmembers(TestClass, predicate=inspect.ismethod):
          method_name, method_obj = method
  
          # get the bound method
          tc = TestClass()
          func = getattr(tc, method_name)
  
          # add the function to the current module
          setattr(module_obj, method_name, func)
  </code></pre>
  
  <p>UPDATE 2: Here is my blog post on the subject: <a href="http://www.saltycrane.com/blog/2010/09/class-based-fabric-scripts-metaprogramming-hack/" rel="nofollow noreferrer">http://www.saltycrane.com/blog/2010/09/class-based-fabric-scripts-metaprogramming-hack/</a></p>