Repository: pandas-dev/pandas

Issue:
AttributeError raised inside property of DataFrame hides error source.
When an `AttributeError` is raised inside a property in DataFrame, regular attribute access fails and `__getattr__` in `NDFrame` is called.
Since the property's attribute name is neither in `_internal_names_set` nor `_info_axis`, a new exception is risen and the original stack trace is lost.

``` python
import pandas as pd

class A(pd.DataFrame):    
    @property
    def foo(self):
        return 1 / 0

    @property
    def bar(self):
        return self.i_dont_exist

>>> a = A()

>>> a.foo
ZeroDivisionError

>>> a.bar
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-35-0eea75f4bdee> in <module>()
     12 #a.foo  # ZeroDivisionError
     13 
---> 14 a.bar  # AttributeError: 'A' object has no attribute 'bar'
     15 
     16 #a.i_dont_exist  # AttributeError: 'str' object has no attribute 'isnull'

/usr/local/lib/python2.7/dist-packages/pandas/core/generic.pyc in __getattr__(self, name)
   2148                 return self[name]
   2149             raise AttributeError("'%s' object has no attribute '%s'" %
-> 2150                                  (type(self).__name__, name))
   2151 
   2152     def __setattr__(self, name, value):

AttributeError: 'A' object has no attribute 'bar'

>>> a.i_dont_exist  # a.bar should include this in the stack trace:
AttributeError: 'A' object has no attribute 'i_dont_exist'
```

``` python
>>> pd.show_versions()
INSTALLED VERSIONS
------------------
commit: None
python: 2.7.9.final.0
python-bits: 64
OS: Linux
OS-release: 3.19.0-39-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8

pandas: 0.16.2
nose: 1.3.7
Cython: 0.23.4
numpy: 1.10.1
scipy: 0.16.0
statsmodels: None
IPython: 4.0.0
sphinx: None
patsy: None
dateutil: 2.4.2
pytz: 2015.6
bottleneck: None
tables: None
numexpr: None
matplotlib: 1.4.3
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: 4.3.2
html5lib: 0.999
httplib2: 0.9
apiclient: None
sqlalchemy: None
pymysql: None
psycopg2: None
```



Discussion:
I am not entirely sure why this happens. The exception (on the inner property) is somehow not propogating up the stack. care to have a look and investigate?

this can be fixed by always falling back on `object.__getattribute__` in `NDFrame`... I will run tests and see if anything fails


Resolving patch:
diff --git a/pandas/core/generic.py b/pandas/core/generic.py
--- a/pandas/core/generic.py
+++ b/pandas/core/generic.py
@@ -2356,8 +2356,7 @@ def __getattr__(self, name):
         else:
             if name in self._info_axis:
                 return self[name]
-            raise AttributeError("'%s' object has no attribute '%s'" %
-                                 (type(self).__name__, name))
+            return object.__getattribute__(self, name)
 
     def __setattr__(self, name, value):
         """After regular attribute access, try setting the name


Test patch:
diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py
--- a/pandas/tests/test_frame.py
+++ b/pandas/tests/test_frame.py
@@ -15878,6 +15878,17 @@ class SubclassedPanel(Panel):
                                    dtype='int64')
         tm.assert_panel_equal(result, expected)
 
+    def test_subclass_attr_err_propagation(self):
+        # GH 11808
+        class A(DataFrame):
+
+            @property
+            def bar(self):
+                return self.i_dont_exist
+        with tm.assertRaisesRegexp(AttributeError, '.*i_dont_exist.*'):
+            A().bar
+
+
 def skip_if_no_ne(engine='numexpr'):
     if engine == 'numexpr':
         try: