Hello community,

here is the log from the commit of package python-soupsieve for 
openSUSE:Factory checked in at 2019-07-30 13:04:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-soupsieve (Old)
 and      /work/SRC/openSUSE:Factory/.python-soupsieve.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-soupsieve"

Tue Jul 30 13:04:54 2019 rev:5 rq:717581 version:1.9.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-soupsieve/python-soupsieve.changes        
2019-05-22 10:54:35.607151662 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-soupsieve.new.4126/python-soupsieve.changes  
    2019-07-30 13:04:55.662395156 +0200
@@ -1,0 +2,8 @@
+Mon Jul 22 12:54:14 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 1.9.2:
+  * FIX: Shortcut last descendant calculation if possible for performance.
+  * FIX: Fix issue where Doctype strings can be mistaken for a normal text 
node in some cases.
+  * FIX: A top level tag is not a :root tag if it has sibling text nodes or 
tag nodes. This is an issue that mostly manifests when using html.parser as the 
parser will allow multiple root nodes.
+
+-------------------------------------------------------------------

Old:
----
  soupsieve-1.9.1.tar.gz

New:
----
  soupsieve-1.9.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-soupsieve.spec ++++++
--- /var/tmp/diff_new_pack.lzneg2/_old  2019-07-30 13:04:56.442394989 +0200
+++ /var/tmp/diff_new_pack.lzneg2/_new  2019-07-30 13:04:56.442394989 +0200
@@ -26,12 +26,12 @@
 %bcond_with test
 %endif
 Name:           python-soupsieve%{psuffix}
-Version:        1.9.1
+Version:        1.9.2
 Release:        0
 Summary:        A modern CSS selector implementation for BeautifulSoup
 License:        MIT
 Group:          Development/Libraries/Python
-URL:            http://facelessuser.github.io/soupsieve/
+URL:            https://github.com/facelessuser/soupsieve
 Source:         
https://files.pythonhosted.org/packages/source/s/soupsieve/soupsieve-%{version}.tar.gz
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
@@ -58,13 +58,12 @@
 %install
 %if !%{with test}
 %python_install
-%python_expand rm -rf %{buildroot}%{$python_sitelib}/tests
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 %endif
 
 %check
 %if %{with test}
-%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib} 
py.test-%{$python_bin_suffix} -v tests
+%pytest tests
 %endif
 
 %if !%{with test}

++++++ soupsieve-1.9.1.tar.gz -> soupsieve-1.9.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/PKG-INFO new/soupsieve-1.9.2/PKG-INFO
--- old/soupsieve-1.9.1/PKG-INFO        2019-04-13 23:14:18.000000000 +0200
+++ new/soupsieve-1.9.2/PKG-INFO        2019-06-23 23:55:59.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: soupsieve
-Version: 1.9.1
+Version: 1.9.2
 Summary: A modern CSS selector implementation for Beautiful Soup.
 Home-page: https://github.com/facelessuser/soupsieve
 Author: Isaac Muse
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/docs/src/markdown/about/changelog.md 
new/soupsieve-1.9.2/docs/src/markdown/about/changelog.md
--- old/soupsieve-1.9.1/docs/src/markdown/about/changelog.md    2019-04-13 
23:13:06.000000000 +0200
+++ new/soupsieve-1.9.2/docs/src/markdown/about/changelog.md    2019-06-23 
23:54:37.000000000 +0200
@@ -1,5 +1,11 @@
 # Changelog
 
+## 1.9.2
+
+- **FIX**: Shortcut last descendant calculation if possible for performance.
+- **FIX**: Fix issue where `Doctype` strings can be mistaken for a normal text 
node in some cases.
+- **FIX**: A top level tag is not a `:root` tag if it has sibling text nodes 
or tag nodes. This is an issue that mostly manifests when using `html.parser` 
as the parser will allow multiple root nodes.
+
 ## 1.9.1
 
 - **FIX**: `:root`, `:contains()`, `:default`, `:indeterminate`, `:lang()`, 
and `:dir()` will properly account for HTML
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/docs/src/markdown/api.md 
new/soupsieve-1.9.2/docs/src/markdown/api.md
--- old/soupsieve-1.9.1/docs/src/markdown/api.md        2019-04-13 
23:13:06.000000000 +0200
+++ new/soupsieve-1.9.2/docs/src/markdown/api.md        2019-06-23 
23:54:37.000000000 +0200
@@ -31,11 +31,8 @@
 special. The `type` attribute's value is always case insensitive. This is 
generally how most browsers treat `type`. If
 you need `type` to be sensitive, you can use the `s` flag: `#!css 
[type="submit" s]`.
 
-As far as the API is concerned, Soup Sieve mimics Beautiful Soup's original 
API at the time of writing this, which is
-why the names `select` and `select_one` are used. As of today, Beautiful Soup 
has agreed to include Soup Sieve as the
-official select library which is slated for the 4.7.0 release.
-
-Soup Sieve will always be available as an external API as well for more 
controlled tag selection if needed.
+While Soup Sieve access is exposed through Beautiful Soup's API, Soup Sieve's 
API can always be imported and accessed
+directly for more controlled tag selection if needed.
 
 ## Flags
 
@@ -62,19 +59,6 @@
 SoupSieve(pattern='p:has(#id) > span.some-class:contains(text)', 
namespaces=None, custom=None, flags=1)
 ```
 
-### `soupsieve.REVERSE`
-
-When calling `filter`, `select`, `iselect`, or `select_one`, searches will be 
preformed in reverse order, causing the
-elements to be returned/yielded in reverse order.
-
-```pycon3
->>> import soupsieve as sv
->>> sv.select('p', soup)
-[<p class="a">Cat</p>, <p class="b">Dog</p>, <p class='c"'>Mouse</p>]
->>> sv.select('p', soup, flags=sv.REVERSE)
-[<p class='c"'>Mouse</p>, <p class="b">Dog</p>, <p class="a">Cat</p>]
-```
-
 ## `soupsieve.select_one()`
 
 ```py3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/soupsieve/__meta__.py 
new/soupsieve-1.9.2/soupsieve/__meta__.py
--- old/soupsieve-1.9.1/soupsieve/__meta__.py   2019-04-13 23:13:06.000000000 
+0200
+++ new/soupsieve-1.9.2/soupsieve/__meta__.py   2019-06-23 23:54:37.000000000 
+0200
@@ -186,5 +186,5 @@
     return Version(major, minor, micro, release, pre, post, dev)
 
 
-__version_info__ = Version(1, 9, 1, "final")
+__version_info__ = Version(1, 9, 2, "final")
 __version__ = __version_info__._get_canonical()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/soupsieve/css_match.py 
new/soupsieve-1.9.2/soupsieve/css_match.py
--- old/soupsieve-1.9.1/soupsieve/css_match.py  2019-04-13 23:13:06.000000000 
+0200
+++ new/soupsieve-1.9.2/soupsieve/css_match.py  2019-06-23 23:54:37.000000000 
+0200
@@ -113,11 +113,11 @@
         return isinstance(obj, bs4.Declaration)
 
     @staticmethod
-    def is_cdata(obj):  # pragma: no cover
+    def is_cdata(obj):
         """Is CDATA."""
 
         import bs4
-        return isinstance(obj, bs4.Declaration)
+        return isinstance(obj, bs4.CData)
 
     @staticmethod
     def is_processing_instruction(obj):  # pragma: no cover
@@ -138,7 +138,7 @@
         """Is special string."""
 
         import bs4
-        return isinstance(obj, (bs4.Comment, bs4.Declaration, bs4.CData, 
bs4.ProcessingInstruction))
+        return isinstance(obj, (bs4.Comment, bs4.Declaration, bs4.CData, 
bs4.ProcessingInstruction, bs4.Doctype))
 
     @classmethod
     def is_content_string(cls, obj):
@@ -217,10 +217,13 @@
                 is_tag = self.is_tag(child)
 
                 if no_iframe and is_tag and self.is_iframe(child):
-                    last_child = child
-                    while self.is_tag(last_child) and last_child.contents:
-                        last_child = last_child.contents[-1]
-                    next_good = last_child.next_element
+                    if child.next_sibling is not None:
+                        next_good = child.next_sibling
+                    else:
+                        last_child = child
+                        while self.is_tag(last_child) and last_child.contents:
+                            last_child = last_child.contents[-1]
+                        next_good = last_child.next_element
                     yield child
                     if next_good is None:
                         break
@@ -251,20 +254,20 @@
         return el.prefix
 
     @classmethod
-    def get_next_tag(cls, el):
+    def get_next(cls, el, tags=True):
         """Get next sibling tag."""
 
         sibling = el.next_sibling
-        while not cls.is_tag(sibling) and sibling is not None:
+        while tags and not cls.is_tag(sibling) and sibling is not None:
             sibling = sibling.next_sibling
         return sibling
 
     @classmethod
-    def get_previous_tag(cls, el):
+    def get_previous(cls, el, tags=True):
         """Get previous sibling tag."""
 
         sibling = el.previous_sibling
-        while not cls.is_tag(sibling) and sibling is not None:
+        while tags and not cls.is_tag(sibling) and sibling is not None:
             sibling = sibling.previous_sibling
         return sibling
 
@@ -660,12 +663,12 @@
             if parent:
                 found = self.match_selectors(parent, relation)
         elif relation[0].rel_type == REL_SIBLING:
-            sibling = self.get_previous_tag(el)
+            sibling = self.get_previous(el)
             while not found and sibling:
                 found = self.match_selectors(sibling, relation)
-                sibling = self.get_previous_tag(sibling)
+                sibling = self.get_previous(sibling)
         elif relation[0].rel_type == REL_CLOSE_SIBLING:
-            sibling = self.get_previous_tag(el)
+            sibling = self.get_previous(el)
             if sibling and self.is_tag(sibling):
                 found = self.match_selectors(sibling, relation)
         return found
@@ -690,12 +693,12 @@
         elif relation[0].rel_type == REL_HAS_CLOSE_PARENT:
             found = self.match_future_child(el, relation)
         elif relation[0].rel_type == REL_HAS_SIBLING:
-            sibling = self.get_next_tag(el)
+            sibling = self.get_next(el)
             while not found and sibling:
                 found = self.match_selectors(sibling, relation)
-                sibling = self.get_next_tag(sibling)
+                sibling = self.get_next(sibling)
         elif relation[0].rel_type == REL_HAS_CLOSE_SIBLING:
-            sibling = self.get_next_tag(el)
+            sibling = self.get_next(el)
             if sibling and self.is_tag(sibling):
                 found = self.match_selectors(sibling, relation)
         return found
@@ -736,7 +739,28 @@
     def match_root(self, el):
         """Match element as root."""
 
-        return self.is_root(el)
+        is_root = self.is_root(el)
+        if is_root:
+            sibling = self.get_previous(el, tags=False)
+            while is_root and sibling is not None:
+                if (
+                    self.is_tag(sibling) or (self.is_content_string(sibling) 
and sibling.strip()) or
+                    self.is_cdata(sibling)
+                ):
+                    is_root = False
+                else:
+                    sibling = self.get_previous(sibling, tags=False)
+        if is_root:
+            sibling = self.get_next(el, tags=False)
+            while is_root and sibling is not None:
+                if (
+                    self.is_tag(sibling) or (self.is_content_string(sibling) 
and sibling.strip()) or
+                    self.is_cdata(sibling)
+                ):
+                    is_root = False
+                else:
+                    sibling = self.get_next(sibling, tags=False)
+        return is_root
 
     def match_scope(self, el):
         """Match element as scope."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/soupsieve.egg-info/PKG-INFO 
new/soupsieve-1.9.2/soupsieve.egg-info/PKG-INFO
--- old/soupsieve-1.9.1/soupsieve.egg-info/PKG-INFO     2019-04-13 
23:14:18.000000000 +0200
+++ new/soupsieve-1.9.2/soupsieve.egg-info/PKG-INFO     2019-06-23 
23:55:59.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: soupsieve
-Version: 1.9.1
+Version: 1.9.2
 Summary: A modern CSS selector implementation for Beautiful Soup.
 Home-page: https://github.com/facelessuser/soupsieve
 Author: Isaac Muse
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/soupsieve-1.9.1/tests/test_level3/test_root.py 
new/soupsieve-1.9.2/tests/test_level3/test_root.py
--- old/soupsieve-1.9.1/tests/test_level3/test_root.py  2019-04-13 
23:13:06.000000000 +0200
+++ new/soupsieve-1.9.2/tests/test_level3/test_root.py  2019-06-23 
23:54:37.000000000 +0200
@@ -118,6 +118,82 @@
             ids.append(el['id'])
         self.assertEqual(sorted(ids), sorted(['div2']))
 
+    def test_no_root_double_tag(self):
+        """Test when there is no root due to double root tags."""
+
+        markup = """
+        <div id="1"></div>
+        <div id="2"></div>
+        """
+
+        soup = self.soup(markup, 'html.parser')
+        self.assertEqual(soup.select(':root'), [])
+
+    def test_no_root_text(self):
+        """Test when there is no root due to HTML text."""
+
+        markup = """
+        text
+        <div id="1"></div>
+        """
+
+        soup = self.soup(markup, 'html.parser')
+        self.assertEqual(soup.select(':root'), [])
+
+    def test_no_root_cdata(self):
+        """Test when there is no root due to CDATA and tag."""
+
+        markup = """
+        <![CDATA[test]]>
+        <div id="1"></div>
+        """
+
+        soup = self.soup(markup, 'html.parser')
+        self.assertEqual(soup.select(':root'), [])
+
+    def test_root_whitespace(self):
+        """Test when there is root and white space."""
+
+        markup = """
+
+        <div id="1"></div>
+        """
+
+        ids = []
+        soup = self.soup(markup, 'html.parser')
+        for el in soup.select(':root'):
+            ids.append(el['id'])
+        self.assertEqual(sorted(ids), sorted(['1']))
+
+    def test_root_preprocess(self):
+        """Test when there is root and pre-processing statement."""
+
+        markup = """
+        <?php ?>
+        <div id="1"></div>
+        """
+
+        ids = []
+        soup = self.soup(markup, 'html.parser')
+        for el in soup.select(':root'):
+            ids.append(el['id'])
+        self.assertEqual(sorted(ids), sorted(['1']))
+
+    def test_root_doctype(self):
+        """Test when there is root and doc type."""
+
+        markup = """
+        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd";>
+        <div id="1"></div>
+        """
+
+        ids = []
+        soup = self.soup(markup, 'html.parser')
+        for el in soup.select(':root'):
+            ids.append(el['id'])
+        self.assertEqual(sorted(ids), sorted(['1']))
+
 
 class TestRootQuirks(TestRoot):
     """Test root selectors with quirks."""


Reply via email to