title: Subclassing a class with __slots__
body: <p>I'm trying to subclass Scrapy's <code>XPathSelector</code> and patch in support for CSS3 selectors.</p>
  
  <p><code>XPathSelector</code> is defined like this:</p>
  
  <pre><code>class XPathSelector(object_ref):
      __slots__ = ['doc', 'xmlNode', 'expr', '__weakref__']
  
      def __init__(self, response=None, text=None, node=None, parent=None, expr=None):
          if parent is not None:
              self.doc = parent.doc
          ...
  </code></pre>
  
  <p>I subclass <code>XPathSelector</code> and override <code>__init__</code>:</p>
  
  <pre><code>class CSSSelector(XPathSelector):
      def __init__(self, *args, **kwargs):
          translator = kwargs.get('translator', 'html').lower()
  
          if 'translator' in kwargs:
              del kwargs['translator']
  
          super(XPathSelector, self).__init__(*args, **kwargs)
  </code></pre>
  
  <p>When I try to use <code>CSSSelector</code>, I get <code>AttributeError</code>s errors for <code>doc</code>, <code>xmlNode</code> and <code>expr</code>. Manually adding in those slots into <code>CSSSelector</code> doesn't help either.</p>
  
  <p>What is the proper way to subclass a class with <code>__slot__</code>s?</p>
  
  <hr>
  
  <p>My complete code is here:</p>
  
  <pre><code>"""
  Extends `XPathSelector` to allow CSS3 selectors via the `cssselect` library.
  """
  
  from cssselect import HTMLTranslator, GenericTranslator
  from scrapy.selector import XPathSelector, XPathSelectorList
  
  __all__ = ['CSSSelector', 'CSSSelectorList']
  
  class CSSSelector(XPathSelector):
      __slots__ = ['doc', 'xmlNode', 'expr', 'translator']
  
      def __init__(self, *args, **kwargs):
          translator = kwargs.get('translator', 'html').lower()
  
          if 'translator' in kwargs:
              del kwargs['translator']
  
          super(CSSSelector, self).__init__(*args, **kwargs)
  
          if translator == 'html':
              self.translator = HTMLTranslator()
          elif translator == 'xhtml':
              self.translator = HTMLTranslator(xhtml=True)
          elif translator == 'xml':
              self.translator = GenericTranslator()
          else:
              raise ValueError("Invalid translator: %s. Valid translators are 'html' (default), 'xhtml' and 'xml'." % translator)
  
      def _select_xpath(self, xpath):
          if hasattr(self.xmlNode, 'xpathEval'):
              self.doc.xpathContext.setContextNode(self.xmlNode)
              xpath = unicode_to_str(xpath, 'utf-8')
  
              try:
                  xpath_result = self.doc.xpathContext.xpathEval(xpath)
              except libxml2.xpathError:
                  raise ValueError("Invalid XPath: %s" % xpath)
  
              if hasattr(xpath_result, '__iter__'):
                  return CSSSelectorList([self.__class__(node=node, parent=self, expr=xpath) for node in xpath_result])
              else:
                  return CSSSelectorList([self.__class__(node=xpath_result, parent=self, expr=xpath)])
          else:
              return CSSSelectorList([])
  
      def select(self, selector):
          xpath = self.translator.css_to_xpath(selector)
  
          return self._select_xpath(xpath)
  
      def attribute(self, name):
          return self._select_xpath('self::@' + name)
  
      def text(self):
          return self._select_xpath('self::text()')
  
  class CSSSelectorList(XPathSelectorList):
      def attribute(self, name):
          return [x.attribute(name) for x in self]
  
      def text(self, name):
          return [x.text() for x in self]
  </code></pre>
  
  <p>I can initialize the class just fine:</p>
  
  <pre><code>&gt;&gt;&gt; css_selector = CSSSelector(response)
  </code></pre>
  
  <p>But I get <code>AttributeError</code>s all over the place:</p>
  
  <pre><code>&gt;&gt;&gt; css_selector.select('title')
  ---------------------------------------------------------------------------
  AttributeError                            Traceback (most recent call last)
  &lt;ipython-input-150-d21b0f17d4cc&gt; in &lt;module&gt;()
  ----&gt; 1 css_selector.select('title')
  
  &lt;ipython-input-147-c855c7eaf9fa&gt; in select(self, selector)
       57 
       58 
  ---&gt; 59         return self._select_xpath(xpath)
       60 
       61 
  
  &lt;ipython-input-147-c855c7eaf9fa&gt; in _select_xpath(self, xpath)
       34 
       35     def _select_xpath(self, xpath):
  ---&gt; 36         if hasattr(self.xmlNode, 'xpathEval'):
       37             self.doc.xpathContext.setContextNode(self.xmlNode)
       38             xpath = unicode_to_str(xpath, 'utf-8')
  
  AttributeError: xmlNode
  </code></pre>