title: Cython Metaclass .pxd: How should I implement `__eq__()`?
body: <p>I am trying to augment an existing python source with a cython <code>.pxd</code>, as Stefan Behnel illustrates in slides 32 to 35 of <a href="http://www.behnel.de/cython200910/talk.html" rel="nofollow">"Using the Cython Compiler to write fast Python code"</a>.</p>
  
  <p>As part of the exercise, I keep hitting a wall with the <code>__eq__()</code> method in my metaclass.  I wish I could choose a simpler case to start Cython, but my production code isn't that simple.  I cooked up a "minimal, complete example" to illustrate the problem... see the code at the bottom of the question.</p>
  
  <p>Short story...</p>
  
  <ul>
  <li>If I use <code>cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):</code>, cython complains that <em><code>Special methods must be declared with 'def', not 'cdef'</code></em></li>
  <li>If I use <code>def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):</code>, cython complains that <em><code>function definition in pxd file must be declared 'cdef inline'</code></em></li>
  </ul>
  
  <p>So cython gives me confusing guidance...</p>
  
  <p><strong>Questions</strong>:</p>
  
  <ul>
  <li>I know that pure-python <code>.pxd</code> files have restrictions; is defining <code>__richcmp__()</code> in my <code>.pxd</code> a valid way to use a <code>.pxd</code> to augment pure python?</li>
  <li>If this is a valid way to use a <code>.pxd</code>, how can I fix this to compile correctly?</li>
  <li>If this is wrong, can a <code>.pxd</code> augment my pure python metaclass, without re-writing the whole metaclass in a <code>.pyx</code> file? (example: <a href="https://github.com/gnmerritt/poker/blob/f4919fcc86d387344478b0881de9369c515e244c/pokeher/cards.pyx" rel="nofollow"><code>class Card</code> in this project</a>)</li>
  </ul>
  
  <p>This is my <code>.pxd</code>...</p>
  
  <pre><code>### File: car_abc.pxd
  # cython: infer_types=True
  cimport cython
  
  cdef class Japan_Car_ABC:
      cpdef public char* model
      cpdef public char* color
  
      def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
          """Ref: http://docs.cython.org/src/userguide/special_methods.html#rich-comparisons"""
          if op==2:
              # op==2 is __eq__() in pure python
              if self.model==other.model:
                  return True
              return False
          else:
              err_msg = "op {0} isn't implemented yet".format(op)
              raise NotImplementedError(err_msg)
  </code></pre>
  
  <hr>
  
  <p><strong>Informational</strong>:</p>
  
  <p>car_abc.py:</p>
  
  <pre><code>### File: car_abc.py
  from abc import ABCMeta
  
  class Japan_Car_ABC(object):
      __metaclass__ = ABCMeta
  
      def __init__(self, model="", color=""):
          self.model = model
          self.color = color
  
      def __eq__(self, other):
          if self.model==other.model:
              return True
          return False
  
      def __hash__(self):
          return hash(self.model)
  </code></pre>
  
  <p>car.py:</p>
  
  <pre><code>from car_abc import Japan_Car_ABC
  
  class Lexus(Japan_Car_ABC):
      def __init__(self, *args, **kwargs):
          bling = kwargs.pop("bling", True)     # bling keyword (default: True)
          super(Lexus, self).__init__(*args, **kwargs)
          self.bling = bling
  
  class Toyota(Japan_Car_ABC):
      def __init__(self, *args, **kwargs):
          super(Toyota, self).__init__(*args, **kwargs)
  
  
  if __name__=="__main__":
      gloria_car = Lexus(model="ES350", color="White")
      jeff_car = Toyota(model="Camry", color="Silver")
      print("gloria_car.model: {0}".format(gloria_car.model))
      print("jeff_car.model: {0}".format(jeff_car.model))
      print("gloria_car==jeff_car: {0}".format(gloria_car==jeff_car))
  </code></pre>
  
  <p>setup.py:</p>
  
  <pre><code>from distutils.core import setup
  from distutils.extension import Extension
  from Cython.Distutils import build_ext
  
  ext_modules = [Extension("car_abc", ["car_abc.py"]),
      #Extension("car", ["car.py"]),
      ]
  
  setup(
      name = "really build this thing",
      cmdclass = {'build_ext': build_ext},
      ext_modules = ext_modules
  )
  </code></pre>