title: Diagnosing errors when duck-typing fails
body: <p>I have a "factory" that creates instances of classes using a tuple of arguments:</p>
  
  <pre><code>def factory(cls, arg):
    return cls(*arg)
  
  class Foo(object):
    def __init__(self, a, b):
      pass
  
  a = (1,2)
  f = factory(Foo, a)
  </code></pre>
  
  <p>This works well, so then I decided (for various reasons beyond the scope of this question) to add support for classes that don't take any arguments as a fallback so that this can be used more widely within existing code. So I needed to detect the availability of a 2-arg vs 0-arg constructor and fallback appropriately. Duck-typing seems like the "Pythonic" answer and works beautifully:</p>
  
  <pre><code>def factory(cls, arg):
    try:
      return cls(*arg)
    except TypeError:
      print("Missing 2-arg, falling back to 0-arg ctor")
      return cls()
  
  class Foo(object):
    def __init__(self,a,b):
      pass
  
  class Bar(object):
    def __init__(self,a):
      pass
  
  a = (1,2)
  f = factory(Foo, a)
  b = factory(Bar, a)
  </code></pre>
  
  <p>The problem comes however when there's an error inside one of the <code>__init__</code> functions. I tried to be helpful and warn when neither the 0-arg nor 2-arg <code>__init__</code> exist:</p>
  
  <pre><code>def factory(cls, arg):
    try:
      return cls(*arg)
    except TypeError:
      print("%s Missing 2-arg, falling back to 0-arg ctor" % str(cls))
      return cls()
  
  class Foo(object):
    def __init__(self,a,b):
      iter(a) # Oops, TypeError
  
  a = (1,2)
  try:
    f = factory(Foo, a)
  except TypeError: # 0-arg must be missing too
    print("Neither 2-arg nor 0-arg ctor exist, that's all we support, sorry")
  </code></pre>
  
  <p>But there's a fatal flaw here - I can't distinguish between a <code>TypeError</code> that was raised because no appropriate <code>__init__</code> existed and a <code>TypeError</code> that was raised because of a problem deeper in the <code>__init__</code>.</p>
  
  <p>I'm not looking for ways to fix <code>Foo</code> or <code>Bar</code>, rather ways to understand the failures more precicely at the level of the "factory" or its callers.</p>
  
  <p>How can I programatically tell if the <code>TypeError</code> was the result of no overload matching, or a failure elsewhere? The best idea I have right now is programatically walking the stack trace and looking at line numbers, which is hideous at best.</p>