warn XPathSelector deprecation on subclassing and direct instance

This commit is contained in:
Daniel Graña 2014-01-03 17:32:40 -02:00
parent 3e42646ce1
commit b3be6e210d
2 changed files with 115 additions and 45 deletions

View File

@ -1,47 +1,50 @@
"""
XPath selectors based on lxml
"""
from scrapy.utils.deprecate import create_deprecated_class
from .unified import Selector, SelectorList
__all__ = ['HtmlXPathSelector', 'XmlXPathSelector', 'XPathSelector',
'XPathSelectorList']
def _xpathselector_css(self, *a, **kw):
raise RuntimeError('.css() method not available for %s, '
'instantiate scrapy.selector.Selector '
'instead' % type(self).__name__)
class XPathSelector(Selector):
__slots__ = ()
_default_type = 'html'
XPathSelector = create_deprecated_class(
'XPathSelector',
Selector,
{
'__slots__': (),
'_default_type': 'html',
'css': _xpathselector_css,
},
new_class_path='scrapy.selector.Selector',
old_class_path='scrapy.selector.XPathSelector',
)
def __init__(self, *a, **kw):
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn('%s is deprecated, instantiate scrapy.selector.Selector '
'instead' % type(self).__name__,
category=ScrapyDeprecationWarning, stacklevel=1)
super(XPathSelector, self).__init__(*a, **kw)
XmlXPathSelector = create_deprecated_class(
'XmlXPathSelector',
XPathSelector,
clsdict={
'__slots__': (),
'_default_type': 'xml',
},
new_class_path='scrapy.selector.Selector',
old_class_path='scrapy.selector.XmlXPathSelector',
)
def css(self, *a, **kw):
raise RuntimeError('.css() method not available for %s, '
'instantiate scrapy.selector.Selector '
'instead' % type(self).__name__)
HtmlXPathSelector = create_deprecated_class(
'HtmlXPathSelector',
XPathSelector,
clsdict={
'__slots__': (),
'_default_type': 'html',
},
new_class_path='scrapy.selector.Selector',
old_class_path='scrapy.selector.HtmlXPathSelector',
)
class XmlXPathSelector(XPathSelector):
__slots__ = ()
_default_type = 'xml'
class HtmlXPathSelector(XPathSelector):
__slots__ = ()
_default_type = 'html'
class XPathSelectorList(SelectorList):
def __init__(self, *a, **kw):
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
warnings.warn('XPathSelectorList is deprecated, instantiate '
'scrapy.selector.SelectorList instead',
category=ScrapyDeprecationWarning, stacklevel=1)
super(XPathSelectorList, self).__init__(*a, **kw)
XPathSelectorList = create_deprecated_class('XPathSelectorList', SelectorList)

View File

@ -1,4 +1,5 @@
import re
import inspect
import warnings
import weakref
from twisted.trial import unittest
@ -301,17 +302,83 @@ class DeprecatedXpathSelectorTest(unittest.TestCase):
text = '<div><img src="a.jpg"><p>Hello</div>'
def test_warnings(self):
for cls in XPathSelector, HtmlXPathSelector, XPathSelector:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
hs = cls(text=self.text)
assert len(w) == 1, w
assert issubclass(w[0].category, ScrapyDeprecationWarning)
assert 'deprecated' in str(w[-1].message)
hs.select("//div").extract()
assert issubclass(w[1].category, ScrapyDeprecationWarning)
assert 'deprecated' in str(w[-1].message)
def test_warnings_xpathselector(self):
cls = XPathSelector
with warnings.catch_warnings(record=True) as w:
class UserClass(cls):
pass
# subclassing must issue a warning
self.assertEqual(len(w), 1, str(cls))
self.assertIn('scrapy.selector.Selector', str(w[0].message))
# subclass instance doesn't issue a warning
usel = UserClass(text=self.text)
self.assertEqual(len(w), 1)
# class instance must issue a warning
sel = cls(text=self.text)
self.assertEqual(len(w), 2, str((cls, [x.message for x in w])))
self.assertIn('scrapy.selector.Selector', str(w[1].message))
# subclass and instance checks
self.assertTrue(issubclass(cls, Selector))
self.assertTrue(isinstance(sel, Selector))
self.assertTrue(isinstance(usel, Selector))
def test_warnings_xmlxpathselector(self):
cls = XmlXPathSelector
with warnings.catch_warnings(record=True) as w:
class UserClass(cls):
pass
# subclassing must issue a warning
self.assertEqual(len(w), 1, str(cls))
self.assertIn('scrapy.selector.Selector', str(w[0].message))
# subclass instance doesn't issue a warning
usel = UserClass(text=self.text)
self.assertEqual(len(w), 1)
# class instance must issue a warning
sel = cls(text=self.text)
self.assertEqual(len(w), 2, str((cls, [x.message for x in w])))
self.assertIn('scrapy.selector.Selector', str(w[1].message))
# subclass and instance checks
self.assertTrue(issubclass(cls, Selector))
self.assertTrue(issubclass(cls, XPathSelector))
self.assertTrue(isinstance(sel, Selector))
self.assertTrue(isinstance(usel, Selector))
self.assertTrue(isinstance(sel, XPathSelector))
self.assertTrue(isinstance(usel, XPathSelector))
def test_warnings_htmlxpathselector(self):
cls = HtmlXPathSelector
with warnings.catch_warnings(record=True) as w:
class UserClass(cls):
pass
# subclassing must issue a warning
self.assertEqual(len(w), 1, str(cls))
self.assertIn('scrapy.selector.Selector', str(w[0].message))
# subclass instance doesn't issue a warning
usel = UserClass(text=self.text)
self.assertEqual(len(w), 1)
# class instance must issue a warning
sel = cls(text=self.text)
self.assertEqual(len(w), 2, str((cls, [x.message for x in w])))
self.assertIn('scrapy.selector.Selector', str(w[1].message))
# subclass and instance checks
self.assertTrue(issubclass(cls, Selector))
self.assertTrue(issubclass(cls, XPathSelector))
self.assertTrue(isinstance(sel, Selector))
self.assertTrue(isinstance(usel, Selector))
self.assertTrue(isinstance(sel, XPathSelector))
self.assertTrue(isinstance(usel, XPathSelector))
def test_xpathselector(self):
with warnings.catch_warnings(record=True):