Skip to content

Instantly share code, notes, and snippets.

@nramirezuy
Created August 15, 2014 16:36
Show Gist options
  • Save nramirezuy/3780bb83e87d4cf79227 to your computer and use it in GitHub Desktop.
Save nramirezuy/3780bb83e87d4cf79227 to your computer and use it in GitHub Desktop.
diff --git a/scrapy/selector/unified.py b/scrapy/selector/unified.py
index b8a3678..6ce1de1 100644
--- a/scrapy/selector/unified.py
+++ b/scrapy/selector/unified.py
@@ -46,10 +46,40 @@ def _response_from_text(text, st):
body=unicode_to_str(text, 'utf-8'))
+import threading
+data = threading.local()
+data.selector = None
+class SelectorContext(object):
+
+ def __init__(self, selector):
+ self._selector = selector
+ self._last = None
+
+ def __enter__(self):
+ self._last = data.selector
+ data.selector = self._selector
+
+ def __exit__(self, type, value, traceback):
+ data.selector = self._last
+
+from functools import wraps
+
+
+def selectorcontext(func):
+ @wraps(func)
+ def wrapper(**kwargs):
+ if 'selector' not in kwargs:
+ selector = data.selector
+ if selector is not None:
+ kwargs['selector'] = selector
+ return func(**kwargs)
+ return wrapper
+
+
class Selector(object_ref):
__slots__ = ['response', 'text', 'namespaces', 'type', '_expr', '_root',
- '__weakref__', '_parser', '_csstranslator', '_tostring_method']
+ '__weakref__', '_parser', '_csstranslator', '_tostring_method', '_contextmanager']
_default_type = None
_default_namespaces = {
@@ -84,6 +114,15 @@ class Selector(object_ref):
self.namespaces.update(namespaces)
self._root = _root
self._expr = _expr
+ self._contextmanager = None
+
+ def __enter__(self):
+ self._contextmanager = SelectorContext(self)
+ self._contextmanager.__enter__()
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self._contextmanager.__exit__(type, value, traceback)
def xpath(self, query):
try:
@@ -163,10 +202,24 @@ class Selector(object_ref):
class SelectorList(list):
+ def __init__(self, *args, **kwargs):
+ super(SelectorList, self).__init__(*args, **kwargs)
+ self._contextmanager = None
+
def __getslice__(self, i, j):
return self.__class__(list.__getslice__(self, i, j))
+ def __enter__(self):
+ self._contextmanager = SelectorContext(self)
+ self._contextmanager.__enter__()
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self._contextmanager.__exit__(type, value, traceback)
+
def xpath(self, xpath):
+ if self._contextmanager is not None:
+ return self._contextmanager._selector.xpath(xpath)
return self.__class__(flatten([x.xpath(xpath) for x in self]))
def css(self, xpath):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment