From 07cb3e526def018c96c840ed24360f7f906f6946 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 +++- scrapy/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 b8a3678a8..e5d904e08 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/scrapy/tests/test_selector.py b/scrapy/tests/test_selector.py index d60521cbc..ca9aa7081 100644 --- a/scrapy/tests/test_selector.py +++ b/scrapy/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 @@ -188,17 +189,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