# Buggy code
def inject_binary_ops(cls, inplace=False):
    for name in CMP_BINARY_OPS + NUM_BINARY_OPS:
        setattr(cls, op_str(name), cls._binary_op(get_op(name)))

    for name, f in [("eq", array_eq), ("ne", array_ne)]:
        setattr(cls, op_str(name), cls._binary_op(f))

    # patch in fillna
    f = _func_slash_method_wrapper(fillna)
    method = cls._binary_op(f, join="left", drop_missing_vars=False)
    setattr(cls, "_fillna", method)

    for name in NUM_BINARY_OPS:
        # only numeric operations have in-place and reflexive variants
        setattr(cls, op_str("r" + name), cls._binary_op(get_op(name), reflexive=True))
        if inplace:
            setattr(cls, op_str("i" + name), cls._inplace_binary_op(get_op("i" + name)))


# Traceback (AttributeError)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/Users/shoyer/miniconda/envs/rapid/lib/python2.7/site-packages/IPython/core/formatters.pyc in __call__(self, obj)
693                 type_pprinters=self.type_printers,
694                 deferred_pprinters=self.deferred_printers)
--> 695             printer.pretty(obj)
696             printer.flush()
697             return stream.getvalue()

/Users/shoyer/miniconda/envs/rapid/lib/python2.7/site-packages/IPython/lib/pretty.pyc in pretty(self, obj)
399                             if callable(meth):
400                                 return meth(obj, self, cycle)
--> 401             return _default_pprint(obj, self, cycle)
402         finally:
403             self.end_group()

/Users/shoyer/miniconda/envs/rapid/lib/python2.7/site-packages/IPython/lib/pretty.pyc in _default_pprint(obj, p, cycle)
519     if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
520         # A user-provided repr. Find newlines and replace them with p.break_()
--> 521         _repr_pprint(obj, p, cycle)
522         return
523     p.begin_group(1, '<')

/Users/shoyer/miniconda/envs/rapid/lib/python2.7/site-packages/IPython/lib/pretty.pyc in _repr_pprint(obj, p, cycle)
701     """A pprint that just redirects to the normal repr function."""
702     # Find newlines and replace them with p.break_()
--> 703     output = repr(obj)
704     for idx,output_line in enumerate(output.splitlines()):
705         if idx:

/Users/shoyer/dev/xray/xray/core/dataset.pyc in __repr__(self)
1043
1044     def __repr__(self):
-> 1045         return formatting.dataset_repr(self)
1046
1047     def isel(self, **indexers):

/Users/shoyer/dev/xray/xray/core/formatting.pyc in dataset_repr(ds)
231
232     summary.append(coords_repr(ds.coords, col_width=col_width))
--> 233     summary.append(vars_repr(ds.data_vars, col_width=col_width))
234     if ds.attrs:
235         summary.append(attrs_repr(ds.attrs))

/Users/shoyer/dev/xray/xray/core/formatting.pyc in _mapping_repr(mapping, title, summarizer, col_width)
170     summary = ['%s:' % title]
171     if mapping:
--> 172         summary += [summarizer(k, v, col_width) for k, v in mapping.items()]
173     else:
174         summary += [EMPTY_REPR]

/Users/shoyer/miniconda/envs/rapid/lib/python2.7/_abcoll.pyc in items(self)
412     def items(self):
413         "D.items() -> list of D's (key, value) pairs, as 2-tuples"
--> 414         return [(key, self[key]) for key in self]
415
416     def values(self):

/Users/shoyer/dev/xray/xray/core/dataset.pyc in __getitem__(self, key)
371     def __getitem__(self, key):
372         if key not in self._dataset._coord_names:
--> 373             return self._dataset[key]
374         else:
375             raise KeyError(key)

/Users/shoyer/dev/xray/xray/core/dataset.pyc in __getitem__(self, key)
751         key = np.asarray(key)
752         if key.ndim == 0:
--> 753             return DataArray._new_from_dataset(self, key.item())
754         else:
755             return self._copy_listed(key)

/Users/shoyer/dev/xray/xray/core/dataarray.pyc in _new_from_dataset(cls, dataset, name)
198         """
199         obj = object.__new__(cls)
--> 200         obj._dataset = dataset._copy_listed([name], keep_attrs=False)
201         if name not in obj._dataset:
202             # handle virtual variables

/Users/shoyer/dev/xray/xray/core/dataset.pyc in _copy_listed(self, names, keep_attrs)
680         needed_dims = set()
681         for v in variables.values():
--> 682             needed_dims.update(v._dims)
683         for k in self._coord_names:
684             if set(self._variables[k]._dims) <= needed_dims:

AttributeError: 'NotImplementedType' object has no attribute '_dims'

# Fixed code
def inject_binary_ops(cls, inplace=False):
    for name in CMP_BINARY_OPS + NUM_BINARY_OPS:
        setattr(cls, op_str(name), cls._binary_op(get_op(name)))

    for name, f in [("eq", array_eq), ("ne", array_ne)]:
        setattr(cls, op_str(name), cls._binary_op(f))

    # patch in fillna
    f = _func_slash_method_wrapper(fillna)
    method = cls._binary_op(f, join="left", drop_na_vars=False)
    setattr(cls, "_fillna", method)

    for name in NUM_BINARY_OPS:
        # only numeric operations have in-place and reflexive variants
        setattr(cls, op_str("r" + name), cls._binary_op(get_op(name), reflexive=True))
        if inplace:
            setattr(cls, op_str("i" + name), cls._inplace_binary_op(get_op("i" + name)))