Gael Pasgrimaud avatar Gael Pasgrimaud committed a7fab59

now use standalone cssselect

Comments (0)

Files changed (2)

pyquery/cssselectpatch.py

 # Copyright (C) 2008 - Olivier Lauzanne <olauzanne@gmail.com>
 #
 # Distributed under the BSD license, see LICENSE.txt
-from lxml.cssselect import Pseudo, XPathExpr, XPathExprOr, Function, css_to_xpath, Element
-from lxml import cssselect
+from cssselect import xpath as cssselect_xpath
 
-class JQueryPseudo(Pseudo):
+
+class JQueryTranslator(cssselect_xpath.HTMLTranslator):
     """This class is used to implement the css pseudo classes
     (:first, :last, ...) that are not defined in the css standard,
     but are defined in the jquery API.
     """
-    def _xpath_first(self, xpath):
+
+    def xpath_first_pseudo(self, xpath):
         """Matches the first selected element.
         """
         xpath.add_post_condition('position() = 1')
         return xpath
 
-    def _xpath_last(self, xpath):
+    def xpath_last_pseudo(self, xpath):
         """Matches the last selected element.
         """
         xpath.add_post_condition('position() = last()')
         return xpath
 
-    def _xpath_even(self, xpath):
+    def xpath_even_pseudo(self, xpath):
         """Matches even elements, zero-indexed.
         """
         # the first element is 1 in xpath and 0 in python and js
         xpath.add_post_condition('position() mod 2 = 1')
         return xpath
 
-    def _xpath_odd(self, xpath):
+    def xpath_odd_pseudo(self, xpath):
         """Matches odd elements, zero-indexed.
         """
         xpath.add_post_condition('position() mod 2 = 0')
         return xpath
 
-    def _xpath_checked(self, xpath):
+    def xpath_checked_pseudo(self, xpath):
         """Matches odd elements, zero-indexed.
         """
         xpath.add_condition("@checked and name(.) = 'input'")
         return xpath
 
-    def _xpath_selected(self, xpath):
+    def xpath_selected_pseudo(self, xpath):
         """Matches all elements that are selected.
         """
         xpath.add_condition("@selected and name(.) = 'option'")
         return xpath
 
-    def _xpath_disabled(self, xpath):
+    def xpath_disabled_pseudo(self, xpath):
         """Matches all elements that are disabled.
         """
         xpath.add_condition("@disabled")
         return xpath
 
-    def _xpath_enabled(self, xpath):
+    def xpath_enabled_pseudo(self, xpath):
         """Matches all elements that are enabled.
         """
         xpath.add_condition("not(@disabled) and name(.) = 'input'")
         return xpath
 
-    def _xpath_file(self, xpath):
+    def xpath_file_pseudo(self, xpath):
         """Matches all input elements of type file.
         """
         xpath.add_condition("@type = 'file' and name(.) = 'input'")
         return xpath
 
-    def _xpath_input(self, xpath):
+    def xpath_input_pseudo(self, xpath):
         """Matches all input elements.
         """
         xpath.add_condition("(name(.) = 'input' or name(.) = 'select') "
         + "or (name(.) = 'textarea' or name(.) = 'button')")
         return xpath
 
-    def _xpath_button(self, xpath):
+    def xpath_button_pseudo(self, xpath):
         """Matches all button input elements and the button element.
         """
         xpath.add_condition("(@type = 'button' and name(.) = 'input') "
             + "or name(.) = 'button'")
         return xpath
 
-    def _xpath_radio(self, xpath):
+    def xpath_radio_pseudo(self, xpath):
         """Matches all radio input elements.
         """
         xpath.add_condition("@type = 'radio' and name(.) = 'input'")
         return xpath
 
-    def _xpath_text(self, xpath):
+    def xpath_text_pseudo(self, xpath):
         """Matches all text input elements.
         """
         xpath.add_condition("@type = 'text' and name(.) = 'input'")
         return xpath
 
-    def _xpath_checkbox(self, xpath):
+    def xpath_checkbox_pseudo(self, xpath):
         """Matches all checkbox input elements.
         """
         xpath.add_condition("@type = 'checkbox' and name(.) = 'input'")
         return xpath
 
-    def _xpath_password(self, xpath):
+    def xpath_password_pseudo(self, xpath):
         """Matches all password input elements.
         """
         xpath.add_condition("@type = 'password' and name(.) = 'input'")
         return xpath
 
-    def _xpath_submit(self, xpath):
+    def xpath_submit_pseudo(self, xpath):
         """Matches all submit input elements.
         """
         xpath.add_condition("@type = 'submit' and name(.) = 'input'")
         return xpath
 
-    def _xpath_image(self, xpath):
+    def xpath_image_pseudo(self, xpath):
         """Matches all image input elements.
         """
         xpath.add_condition("@type = 'image' and name(.) = 'input'")
         return xpath
 
-    def _xpath_reset(self, xpath):
+    def xpath_reset_pseudo(self, xpath):
         """Matches all reset input elements.
         """
         xpath.add_condition("@type = 'reset' and name(.) = 'input'")
         return xpath
 
-    def _xpath_header(self, xpath):
+    def xpath_header_pseudo(self, xpath):
         """Matches all header elelements (h1, ..., h6)
         """
         # this seems kind of brute-force, is there a better way?
-        xpath.add_condition("(name(.) = 'h1' or name(.) = 'h2' or name (.) = 'h3') "
+        xpath.add_condition(
+                "(name(.) = 'h1' or name(.) = 'h2' or name (.) = 'h3') "
         + "or (name(.) = 'h4' or name (.) = 'h5' or name(.) = 'h6')")
         return xpath
 
-    def _xpath_parent(self, xpath):
+    def xpath_parent_pseudo(self, xpath):
         """Match all elements that contain other elements
         """
         xpath.add_condition("count(child::*) > 0")
         return xpath
 
-    def _xpath_empty(self, xpath):
+    def xpath_empty_pseudo(self, xpath):
         """Match all elements that do not contain other elements
         """
         xpath.add_condition("count(child::*) = 0")
         return xpath
 
-cssselect.Pseudo = JQueryPseudo
-
-class JQueryFunction(Function):
-    """Represents selector:name(expr) that are present in JQuery but not in the
-    css standard.
-    """
-    def _xpath_eq(self, xpath, expr):
+    def xpath_eq_function(self, xpath, function):
         """Matches a single element by its index.
         """
-        xpath.add_post_condition('position() = %s' % int(expr+1))
+        xpath.add_post_condition(
+                'position() = %s' % (int(function.arguments) + 1))
         return xpath
 
-    def _xpath_gt(self, xpath, expr):
+    def xpath_gt_function(self, xpath, function):
         """Matches all elements with an index over the given one.
         """
-        xpath.add_post_condition('position() > %s' % int(expr+1))
+        xpath.add_post_condition(
+                'position() > %s' % (int(function.arguments) + 1))
         return xpath
 
-    def _xpath_lt(self, xpath, expr):
+    def xpath_lt_function(self, xpath, function):
         """Matches all elements with an index below the given one.
         """
-        xpath.add_post_condition('position() < %s' % int(expr+1))
+        xpath.add_post_condition(
+                'position() < %s' % (int(function.arguments) + 1))
         return xpath
 
-    def _xpath_contains(self, xpath, expr):
+    def xpath_contains_function(self, xpath, function):
         """Matches all elements that contain the given text
         """
-        xpath.add_post_condition("contains(text(), '%s')" % str(expr))
+        xpath.add_post_condition(
+                "contains(text(), '%s')" % str(function.arguments))
         return xpath
 
-cssselect.Function = JQueryFunction
 
-class AdvancedXPathExpr(XPathExpr):
-    def __init__(self, prefix=None, path=None, element='*', condition=None,
-                 post_condition=None, star_prefix=False):
-        self.prefix = prefix
+XPathExprOrig = cssselect_xpath.XPathExpr
+
+
+class XPathExpr(XPathExprOrig):
+
+    def __init__(self, path='', element='*', condition='', star_prefix=False):
         self.path = path
         self.element = element
         self.condition = condition
-        self.post_condition = post_condition
-        self.star_prefix = star_prefix
+        self.post_condition = None
 
     def add_post_condition(self, post_condition):
         if self.post_condition:
             self.post_condition = post_condition
 
     def __str__(self):
-        path = XPathExpr.__str__(self)
+        path = XPathExprOrig.__str__(self)
         if self.post_condition:
-            path = '(%s)[%s]' % (path, self.post_condition)
+            path = '%s[%s]' % (path, self.post_condition)
         return path
 
     def join(self, combiner, other):
-        XPathExpr.join(self, combiner, other)
+        res = XPathExprOrig.join(self, combiner, other)
         self.post_condition = other.post_condition
+        return res
 
-cssselect.XPathExpr = AdvancedXPathExpr
+cssselect_xpath.XPathExpr = XPathExpr
 
-class AdvancedXPathExprOr(XPathExprOr):
-    def __init__(self, items, prefix=None):
-        self.prefix = prefix = prefix or ''
-        self.items = items
-        self.prefix_prepended = False
-
-    def __str__(self):
-        if not self.prefix_prepended:
-            # We cannot prepend the prefix at __init__ since it's legal to
-            # modify it after construction. And because __str__ can be called
-            # multiple times we have to take care not to prepend it twice.
-            prefix = self.prefix or ''
-            for item in self.items:
-                item.prefix = prefix+(item.prefix or '')
-            self.prefix_prepended = True
-        return ' | '.join([str(i) for i in self.items])
-
-cssselect.XPathExprOr = AdvancedXPathExprOr
-
-class JQueryElement(Element):
-    """
-    Represents namespace|element
-    """
-    
-    def xpath(self):
-        if self.namespace == '*':
-            el = self.element
-        else:
-            # FIXME: Should we lowercase here?
-            el = '%s:%s' % (self.namespace, self.element)
-        return AdvancedXPathExpr(element=el)
-        
-cssselect.Element = JQueryElement
 
 def selector_to_xpath(selector, prefix='descendant-or-self::'):
     """JQuery selector to xpath.
     """
     selector = selector.replace('[@', '[')
-    return css_to_xpath(selector, prefix)
+    return JQueryTranslator().css_to_xpath(selector, prefix)
 # Distributed under the BSD license, see LICENSE.txt
 
 from setuptools import setup, find_packages
-import sys, os
+import os
+
 
 def read(*names):
     values = dict()
     for name in names:
-        filename = name+'.txt'
+        filename = name + '.txt'
         if os.path.isfile(filename):
-            value = open(name+'.txt').read()
+            value = open(name + '.txt').read()
         else:
             value = ''
         values[name] = value
     return values
 
-long_description="""
+
+long_description = """
 %(README)s
 
 See http://packages.python.org/pyquery/ for the full documentation
       include_package_data=True,
       zip_safe=False,
       install_requires=[
-          'lxml>=2.1'
+          'lxml>=2.1',
+          'cssselect',
       ],
       test_requires=['nose'],
       test_suite='nose.collector',
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.