From bf301b73284153f8f6de0be5eb47dbaa197a9d3e Mon Sep 17 00:00:00 2001 From: Nikolaos-Digenis Karagiannis Date: Mon, 17 Nov 2014 19:30:08 +0200 Subject: [PATCH] encode invalid xpath with unicode_escape under PY2 The exception quotes an xpath string which may be unicode. --- scrapy/selector/unified.py | 4 +++- tests/test_selector.py | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/scrapy/selector/unified.py b/scrapy/selector/unified.py index c0eefb85e..90dcfd686 100644 --- a/scrapy/selector/unified.py +++ b/scrapy/selector/unified.py @@ -3,6 +3,7 @@ XPath selectors based on lxml """ from lxml import etree +import six from scrapy.utils.misc import extract_regex from scrapy.utils.trackref import object_ref @@ -95,7 +96,8 @@ class Selector(object_ref): result = xpathev(query, namespaces=self.namespaces, smart_strings=self._lxml_smart_strings) except etree.XPathError: - raise ValueError("Invalid XPath: %s" % query) + msg = u"Invalid XPath: %s" % query + raise ValueError(msg if six.PY3 else msg.encode("unicode_escape")) if type(result) is not list: result = [result] diff --git a/tests/test_selector.py b/tests/test_selector.py index 9b8613319..a46f7635c 100644 --- a/tests/test_selector.py +++ b/tests/test_selector.py @@ -1,6 +1,7 @@ import re import warnings import weakref +import six from twisted.trial import unittest from scrapy.exceptions import ScrapyDeprecationWarning from scrapy.http import TextResponse, HtmlResponse, XmlResponse @@ -242,17 +243,19 @@ class SelectorTestCase(unittest.TestCase): self.assertEqual(xs.xpath('.').extract(), [u'lala']) def test_invalid_xpath(self): + "Test invalid xpath raises ValueError with the invalid xpath" response = XmlResponse(url="http://example.com", body="") x = self.sscls(response) xpath = "//test[@foo='bar]" - try: - x.xpath(xpath) - except ValueError as e: - assert xpath in str(e), "Exception message does not contain invalid xpath" - except Exception: - raise AssertionError("A invalid XPath does not raise ValueError") - else: - raise AssertionError("A invalid XPath does not raise an exception") + self.assertRaisesRegexp(ValueError, re.escape(xpath), x.xpath, xpath) + + def test_invalid_xpath_unicode(self): + "Test *Unicode* invalid xpath raises ValueError with the invalid xpath" + response = XmlResponse(url="http://example.com", body="") + x = self.sscls(response) + xpath = u"//test[@foo='\u0431ar]" + encoded = xpath if six.PY3 else xpath.encode('unicode_escape') + self.assertRaisesRegexp(ValueError, re.escape(encoded), x.xpath, xpath) def test_http_header_encoding_precedence(self): # u'\xa3' = pound symbol in unicode