@property decorator doesn't raise exceptions

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sat Oct 25 06:45:02 CEST 2008


On Fri, 24 Oct 2008 01:47:10 -0700, Rafe wrote:

> Hi,
> 
> I've encountered a problem which is making debugging less obvious than
> it should be. The @property decorator doesn't always raise exceptions.

I don't think that's the problem. I think properties do correctly raise 
all exceptions that occur inside them, at least built-in exceptions.

I wrote a test that raises exceptions inside properties and they (almost) 
all are raised normally.

Whatever your problem is, it isn't that properties don't raise exceptions.

For those who are interested, the test program I used follows.


# test module

def get_exceptions():
    import __builtin__
    list_of_exceptions = []
    for key in dir(__builtin__):  
    # do not use __builtins__ -- note the 's'.
        obj = getattr(__builtin__, key)
        if not isinstance(obj, type):
            continue
        if issubclass(obj, Exception):
            list_of_exceptions.append(obj)
    return list_of_exceptions

def builder(list_of_exceptions):
    class PropertyTester(object):
        """Do properties raise exceptions? Let's find out."""
    for exception in list_of_exceptions:
        name = exception.__name__
        @property
        def func(self, exception=exception):
        # Make sure we bind a local copy to exception.
            raise exception
        setattr(PropertyTester, name, func)
    return PropertyTester()

def testRaises(obj, exception_type, verbose):
    """Test that appropriate exception is raised when accessing an 
attribute."""
    name = exception_type.__name__
    try:
        getattr(obj, name)
    except exception_type:
        if verbose:
            print "Passed: expected exception %s raised correctly" \
            % exception_type
    except Exception, e:
        print "Failed: expected %s but got %r" % (exception_type, e)
    else:
        print "Failed: expected %s but got no exception at all" \
        % exception_type

if __name__ == '__main__':
    import sys
    if sys.argv[1:] == ['verbose']:
        verbose = True
    else:
        verbose = False
    exceptions = get_exceptions()
    tester = builder(exceptions)
    for exception in exceptions:
        testRaises(tester, exception, verbose)



-- 
Steven



More information about the Python-list mailing list