Issue 1:
Looking at core.ops. _comp_method_SERIES and whether we can have the datetime and timedelta cases defer to Index subclass implementations, a couple questions come up:

https://github.com/pandas-dev/pandas/blob/master/pandas/core/ops.py#L744

def na_op(x, y):
# dispatch to the categorical if we have a categorical
# in either operand
if is_categorical_dtype(x):
return op(x, y)
elif is_categorical_dtype(y) and not is_scalar(y):
return op(y, x)

This return op(y, x) looks weird. Should it be a reverse-op? e.g if op is operator.ge, should this become return operator.le(y, x)? Maybe this is irrelevant if categorical comparisons are only defined for __eq__ and __ne__? If that is the explanation, there should be a comment.

Special casing for PeriodIndex:

if isinstance(other, ABCPeriodIndex):
# temp workaround until fixing GH 13637
# tested in test_nat_comparisons
# (pandas.tests.series.test_operators.TestSeriesOperators)
return self._constructor(na_op(self.values,
other.astype(object).values),
index=self.index)

I couldn't tell from #13637 what the connection was. Commenting this out did not appear to break anything in the tests. Anyone know if this is still relevant?

Update I forgot to mention the question mentioned in the Issue title. Most cases return self._constructor(res, index=self.index, name=whatever), but one case returns self._constructor(na_op(self.values, np.asarray(other)), index=self.index).__finalize__(self). Why is __finalize__ called in this case but not others?

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