Issue 1:
class PDMixIn(object):

@property
def _constructor(self):
return self.__class__

class DF(PDMixIn, pd.DataFrame):
_metadata = ['my_prop']

def __init__(self, *args, **kwargs):
my_prop = kwargs.pop('my_prop', 'some_prop')
super().__init__(*args, *kwargs)
self.my_prop = my_prop

df = DF(my_prop='new_prop')
print(df.my_prop)
# 'new_prop'

# But after adding 1
df = df + 1
print(df.my_prop)
# 'some_prop'

Seems like DF is losing property value after addition I found similar behaviour for sub and others.

I was able to solve the problem by adding following code to PDMixIn

def __add__(self, other):
result = pd.DataFrame.__add__(self, other)
return self._constructor(result).__finalize__(self)

df = df + 1
print(df.my_prop)
# 'new_prop'

INSTALLED VERSIONS

commit: None

python: 3.6.3.final.0

python-bits: 64

OS: Windows

OS-release: 10

machine: AMD64

processor: Intel64 Family 6 Model 78 Stepping 3, GenuineIntel

byteorder: little

LC_ALL: None

LANG: en_US.UTF-8

LOCALE: None.None

pandas: 0.22.0

pytest: 3.3.0

pip: 9.0.1

setuptools: 36.5.0.post20170921

Cython: 0.27.3

numpy: 1.13.3

scipy: 1.0.0

pyarrow: None

xarray: None

IPython: 6.2.1

sphinx: 1.6.3

patsy: 0.4.1

dateutil: 2.6.1

pytz: 2017.3

blosc: None

bottleneck: 1.2.1

tables: 3.4.2

numexpr: 2.6.4

feather: None

matplotlib: 2.1.1

openpyxl: 2.4.9

xlrd: 1.1.0

xlwt: 1.3.0

xlsxwriter: 1.0.2

lxml: 4.1.1

bs4: 4.6.0

html5lib: 1.0.1

sqlalchemy: 1.1.13

pymysql: None

psycopg2: 2.7.3.2 (dt dec pq3 ext lo64)

jinja2: 2.10

s3fs: None

fastparquet: None

pandas_gbq: None

pandas_datareader: None

Issue 2:
#!/bin/env python
"""
Example bug in derived Pandas Series.

__finalized__ is not called in arithmetic binary operators, but it is in in some booleans cases.

>>> m = MySeries([1, 2, 3], name='test')
>>> m.x = 42
>>> n=m[:2]
>>> n
0 1
1 2
dtype: int64
>>> n.x
42
>>> o=n+1
>>> o
0 2
1 3
dtype: int64
>>> o.x
Traceback (most recent call last):
...
AttributeError: 'MySeries' object has no attribute 'x'
>>> m = MySeries([True, False, True], name='test2')
>>> m.x = 42
>>> n=m[:2]
>>> n
0 True
1 False
dtype: bool
>>> n.x
42
>>> o=n ^ True
>>> o
0 False
1 True
dtype: bool
>>> o.x
42
>>> p = n ^ o
>>> p
0 True
1 True
dtype: bool
>>> p.x
42

"""

import pandas as pd

class MySeries(pd.Series):
_metadata = ['x']

@property
def _constructor(self):
return MySeries

if __name__ == "__main__":
import doctest
doctest.testmod()

Expected Output

In all cases, the metadata 'x' should be transferred from the passed values when applying binary operators.

When the right-hand value is a constant, the left-hand value metadata should be used in finalize for arithmetic operators, just like it is for Boolean binary operators.

When two series are used in binary operators, some resolution should be possible in finalize.

I would pass the second (right-hand) value by calling finalize(self, other=other), leaving the resolution to the derived class implementer, but there might be a smarter approach.

output of pd.show_versions()

pd.show_versions()

INSTALLED VERSIONS

commit: None

python: 2.7.6.final.0

python-bits: 64

OS: Linux

OS-release: 3.19.0-59-generic

machine: x86_64

processor: x86_64

byteorder: little

LC_ALL: None

LANG: en_US.UTF-8

pandas: 0.18.1

nose: 1.3.7

pip: None

setuptools: 20.2.2

Cython: 0.24

numpy: 1.11.0

scipy: 0.17.0

statsmodels: 0.6.1

xarray: None

IPython: 4.0.1

sphinx: 1.3.1

patsy: 0.4.0

dateutil: 2.4.2

pytz: 2015.7

blosc: None

bottleneck: 1.0.0

tables: 3.2.2

numexpr: 2.5.2

matplotlib: 1.5.0

openpyxl: 2.2.6

xlrd: 0.9.4

xlwt: 1.0.0

xlsxwriter: 0.7.7

lxml: 3.4.4

bs4: 4.4.1

html5lib: 0.9999999

httplib2: None

apiclient: None

sqlalchemy: 1.0.9

pymysql: None

psycopg2: None

jinja2: 2.8

boto: 2.38.0

pandas_datareader: None