Hello community,

here is the log from the commit of package python-podcastparser for 
openSUSE:Factory checked in at 2020-07-16 12:17:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-podcastparser (Old)
 and      /work/SRC/openSUSE:Factory/.python-podcastparser.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-podcastparser"

Thu Jul 16 12:17:36 2020 rev:4 rq:821147 version:0.6.5

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-podcastparser/python-podcastparser.changes    
    2019-06-03 18:55:30.000425969 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-podcastparser.new.3592/python-podcastparser.changes
      2020-07-16 12:20:24.315083194 +0200
@@ -1,0 +2,9 @@
+Wed Jul 15 14:36:39 UTC 2020 - [email protected]
+
+- version update to 0.6.5
+  * no upstream changelog
+- added patches
+  fix https://github.com/gpodder/podcastparser/pull/21
+  + python-podcastparser-remove-nose.patch
+
+-------------------------------------------------------------------

Old:
----
  podcastparser-0.6.4.tar.gz

New:
----
  podcastparser-0.6.5.tar.gz
  python-podcastparser-remove-nose.patch

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

Other differences:
------------------
++++++ python-podcastparser.spec ++++++
--- /var/tmp/diff_new_pack.jJ9Bng/_old  2020-07-16 12:20:26.955085864 +0200
+++ /var/tmp/diff_new_pack.jJ9Bng/_new  2020-07-16 12:20:26.955085864 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-podcastparser
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,14 +18,18 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-podcastparser
-Version:        0.6.4
+Version:        0.6.5
 Release:        0
 Summary:        A podcast parser
 License:        ISC
 Group:          Development/Libraries/Python
 URL:            https://github.com/gpodder/podcastparser
 Source:         
https://files.pythonhosted.org/packages/source/p/podcastparser/podcastparser-%{version}.tar.gz
+# https://github.com/gpodder/podcastparser/pull/21
+Patch0:         python-podcastparser-remove-nose.patch
 BuildRequires:  %{python_module nose}
+BuildRequires:  %{python_module pytest-cov}
+BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module xml}
 BuildRequires:  fdupes
@@ -39,6 +43,7 @@
 
 %prep
 %setup -q -n podcastparser-%{version}
+%patch0 -p1
 
 %build
 %python_build
@@ -48,7 +53,7 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-%python_expand nosetests-%{$python_bin_suffix}
+%pytest
 
 %files %{python_files}
 %license LICENSE

++++++ podcastparser-0.6.4.tar.gz -> podcastparser-0.6.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podcastparser-0.6.4/LICENSE 
new/podcastparser-0.6.5/LICENSE
--- old/podcastparser-0.6.4/LICENSE     2018-08-19 18:16:16.000000000 +0200
+++ new/podcastparser-0.6.5/LICENSE     2020-04-07 22:01:05.000000000 +0200
@@ -1,5 +1,7 @@
 
-Copyright (c) 2012, 2013, 2014, 2018, Thomas Perl <[email protected]>
+Copyright (c) 2012, 2013, 2014, 2018, 2020 Thomas Perl <[email protected]>
+Copyright (c) 2016, 2017, 2018, 2019, 2020 Eric Le Lay <[email protected]>
+Copyright (c) 2020 E.S. Rosenberg <[email protected]>
 
 Permission to use, copy, modify, and/or distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podcastparser-0.6.4/PKG-INFO 
new/podcastparser-0.6.5/PKG-INFO
--- old/podcastparser-0.6.4/PKG-INFO    2018-08-19 18:16:34.000000000 +0200
+++ new/podcastparser-0.6.5/PKG-INFO    2020-04-07 22:02:14.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: podcastparser
-Version: 0.6.4
+Version: 0.6.5
 Summary:  Simplified, fast RSS parser 
 Home-page: http://gpodder.org/podcastparser/
 Author: Thomas Perl
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podcastparser-0.6.4/doc/index.rst 
new/podcastparser-0.6.5/doc/index.rst
--- old/podcastparser-0.6.4/doc/index.rst       2018-08-19 18:16:16.000000000 
+0200
+++ new/podcastparser-0.6.5/doc/index.rst       2020-04-07 21:57:03.000000000 
+0200
@@ -102,6 +102,12 @@
     Episode website.
 
 **rss/channel/item/description**
+    Episode description.
+    If it contains html, it's returned as description_html.
+    Otherwise it's returned as description (whitespace is squashed).
+    See Mozilla's article `Why RSS Content Module is Popular`
+
+**rss/channel/item/itunes:summary**
     Episode description (whitespace is squashed).
 
 **rss/channel/item/itunes:subtitle**
@@ -109,6 +115,7 @@
 
 **rss/channel/item/content:encoded**
     Episode description in HTML.
+    Best source for description_html.
 
 **rss/channel/item/itunes:duration**
     Episode duration.
@@ -122,6 +129,9 @@
 **rss/channel/item/atom:link@rel=enclosure**
     File download URL (@href), size (@length) and mime type (@type).
 
+**rss/channel/item/itunes:image**
+    Episode art URL.
+
 **rss/channel/item/media:content**
     File download URL (@url), size (@fileSize) and mime type (@type).
 
@@ -134,6 +144,7 @@
 **rss/channel/item/psc:chapters/psc:chapter**
     Chapter entry (@start, @title, @href and @image).
 
+.. _Why RSS Content Module is Popular: 
https://developer.mozilla.org/en-US/docs/Web/RSS/Article/Why_RSS_Content_Module_is_Popular_-_Including_HTML_Contents
 
 Atom
 ----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podcastparser-0.6.4/podcastparser.py 
new/podcastparser-0.6.5/podcastparser.py
--- old/podcastparser-0.6.4/podcastparser.py    2018-08-19 18:16:16.000000000 
+0200
+++ new/podcastparser-0.6.5/podcastparser.py    2020-04-07 22:01:22.000000000 
+0200
@@ -1,7 +1,9 @@
 # -*- coding: utf-8 -*-
 #
 # Podcastparser: A simple, fast and efficient podcast parser
-# Copyright (c) 2012, 2013, 2014, 2018, Thomas Perl <[email protected]>
+# Copyright (c) 2012, 2013, 2014, 2018, 2020 Thomas Perl <[email protected]>
+# Copyright (c) 2016, 2017, 2018, 2019, 2020 Eric Le Lay <[email protected]>
+# Copyright (c) 2020 E.S. Rosenberg <[email protected]>
 #
 # Permission to use, copy, modify, and/or distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -20,7 +22,7 @@
 
 # Will be parsed by setup.py to determine package metadata
 __author__ = 'Thomas Perl <[email protected]>'
-__version__ = '0.6.4'
+__version__ = '0.6.5'
 __website__ = 'http://gpodder.org/podcastparser/'
 __license__ = 'ISC License'
 
@@ -235,20 +237,42 @@
             handler.set_episode_attr('description', squash_whitespace(text))
 
 
+class RSSItemDescription(Target):
+    """
+    RSS 2.0 almost encourages to put html content in item/description
+    but content:encoded is the better source of html content and itunes:summary
+    is known to contain the short textual description of the item.
+    So use a heuristic to attribute text to either description or 
description_html,
+    without overriding existing values.
+    """
+    WANT_TEXT = True
+
+    def __init__(self):
+        self._want_content = False
+
+    def end(self, handler, text):
+        if is_html(text):
+            if not handler.get_episode_attr('description_html'):
+                handler.set_episode_attr('description_html', text.strip())
+        elif not handler.get_episode_attr('description'):
+            # don't overwrite itunes:summary?
+            handler.set_episode_attr('description', squash_whitespace(text))
+
+
 class PodloveChapters(Target):
     SUPPORTED_VERSIONS = ('1.1', '1.2')
 
     def start(self, handler, attrs):
         version = attrs.get('version', '1.1')
         if version not in PodloveChapters.SUPPORTED_VERSIONS:
-            logger.warn('Possible incompatible chapters version: %s', version)
+            logger.warning('Possible incompatible chapters version: %s', 
version)
 
 
 class PodloveChapter(Target):
     def start(self, handler, attrs):
         # Both the start and title attributes are mandatory
         if attrs.get('start') is None or attrs.get('title') is None:
-            logger.warn('Invalid chapter (missing start and/or and title)')
+            logger.warning('Invalid chapter (missing start and/or and title)')
             return
 
         chapter = {
@@ -361,7 +385,7 @@
             namespace_uri = self.lookup(namespace)
             if namespace_uri is None:
                 # Use of "itunes:duration" without xmlns:itunes="..."
-                logger.warn('No namespace defined for "%s:%s"', namespace,
+                logger.warning('No namespace defined for "%s:%s"', namespace,
                             name)
                 return '%s:%s' % (namespace, name)
 
@@ -369,7 +393,7 @@
             prefix = self.NAMESPACES.get(namespace_uri)
             if prefix is None and namespace:
                 # Proper use of namespaces, but unknown namespace
-                # logger.warn('Unknown namespace: %s', namespace_uri)
+                # logger.warning('Unknown namespace: %s', namespace_uri)
                 # We prefix the tag name here to make sure that it does not
                 # match any other tag below if we can't recognize the namespace
                 name = '!%s:%s' % (namespace, name)
@@ -466,7 +490,7 @@
         try:
             seconds = int(value)
         except ValueError:
-            logger.warn('Could not parse time value: "%s"', value)
+            logger.warning('Could not parse time value: "%s"', value)
             return 0
 
     return (int(hours) * 60 + int(minutes)) * 60 + int(seconds)
@@ -554,7 +578,7 @@
             pubtimeseconds = int(mktime_tz(parsed))
             return pubtimeseconds
         except(OverflowError,ValueError):
-            logger.warn('bad pubdate %s is before epoch or after end of time 
(2038)',parsed)
+            logger.warning('bad pubdate %s is before epoch or after end of 
time (2038)',parsed)
             return 0
         
     try:
@@ -596,7 +620,7 @@
     'rss/channel/item/guid': EpisodeGuid('guid'),
     'rss/channel/item/title': EpisodeAttr('title', squash_whitespace),
     'rss/channel/item/link': EpisodeAttrRelativeLink('link'),
-    'rss/channel/item/description': EpisodeAttr('description', 
squash_whitespace),
+    'rss/channel/item/description': RSSItemDescription(),
     'rss/channel/item/itunes:summary': EpisodeAttr('description', 
squash_whitespace),
     'rss/channel/item/media:description': EpisodeAttr('description', 
squash_whitespace),
     'rss/channel/item/itunes:subtitle': EpisodeAttr('subtitle', 
squash_whitespace),
@@ -604,6 +628,7 @@
     'rss/channel/item/itunes:duration': EpisodeAttr('total_time', parse_time),
     'rss/channel/item/pubDate': EpisodeAttr('published', parse_pubdate),
     'rss/channel/item/atom:link': AtomLink(),
+    'rss/channel/item/itunes:image': EpisodeAttrFromHref('episode_art_url'),
 
     'rss/channel/item/media:content': Enclosure('fileSize'),
     'rss/channel/item/enclosure': Enclosure('length'),
@@ -614,7 +639,7 @@
     'atom:feed': PodcastItem(),
     'atom:feed/atom:title': PodcastAttr('title', squash_whitespace),
     'atom:feed/atom:subtitle': PodcastAttr('description', squash_whitespace),
-    'atom:feed/atom:icon': PodcastAttr('cover_url'),
+    'atom:feed/atom:icon': PodcastAttrRelativeLink('cover_url'),
     'atom:feed/atom:link': PodcastAtomLink(),
     'atom:feed/atom:entry': EpisodeItem(),
     'atom:feed/atom:entry/atom:id': EpisodeAttr('guid'),
@@ -691,12 +716,12 @@
             del entry['chapters']
 
         # Ensures `description` does not contain HTML
-        if 'description' in entry and is_html(entry['description']):
+        if is_html(entry['description']):
             if 'description_html' not in entry:
                 entry['description_html'] = entry['description']
             entry['description'] = ''
 
-        # Sets `description` to stripped `description_html` when absent
+        # Sets `description` to stripped `description_html` when empty
         if 'description_html' in entry and not entry['description']:
             entry['description'] = remove_html_tags(entry['description_html'])
 
@@ -853,12 +878,17 @@
     # urlunsplit might return "a slighty different, but equivalent URL"
     return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
 
+HTML_TEST = re.compile('<[a-z][a-z0-9]*(?:\s.*?>|\/?>)', re.IGNORECASE | 
re.DOTALL)
 def is_html(text):
+    """Heuristically tell if text is HTML
+
+    By looking for an open tag (more or less:)
+    >>> is_html('<h1>HELLO</h1>')
+    True
+    >>> is_html('a < b < c')
+    False
     """
-    Tests whether the given string contains HTML encoded data
-    """
-    html_test = re.compile(r'<[a-z][\s\S]*>', re.IGNORECASE)
-    return bool(html_test.search(text))
+    return bool(HTML_TEST.search(text))
 
 def remove_html_tags(html):
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podcastparser-0.6.4/tests/data/atom_relative_cover.json 
new/podcastparser-0.6.5/tests/data/atom_relative_cover.json
--- old/podcastparser-0.6.4/tests/data/atom_relative_cover.json 1970-01-01 
01:00:00.000000000 +0100
+++ new/podcastparser-0.6.5/tests/data/atom_relative_cover.json 2020-04-07 
21:57:03.000000000 +0200
@@ -0,0 +1,5 @@
+{
+  "title": "atom_relative_cover",
+  "cover_url": "file://tests/favicon.ico",
+  "episodes": []
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podcastparser-0.6.4/tests/data/atom_relative_cover.rss 
new/podcastparser-0.6.5/tests/data/atom_relative_cover.rss
--- old/podcastparser-0.6.4/tests/data/atom_relative_cover.rss  1970-01-01 
01:00:00.000000000 +0100
+++ new/podcastparser-0.6.5/tests/data/atom_relative_cover.rss  2020-04-07 
21:57:03.000000000 +0200
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom";>
+  
<id>https://catalog.feedbooks.com/publicdomain/category/FBFIC000000/sub.atom</id>
+  <icon>/favicon.ico</icon>
+</feed>
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podcastparser-0.6.4/tests/data/itunes_episode_image.json 
new/podcastparser-0.6.5/tests/data/itunes_episode_image.json
--- old/podcastparser-0.6.4/tests/data/itunes_episode_image.json        
1970-01-01 01:00:00.000000000 +0100
+++ new/podcastparser-0.6.5/tests/data/itunes_episode_image.json        
2020-04-07 21:57:03.000000000 +0200
@@ -0,0 +1,16 @@
+{
+  "title": "itunes_episode_image",
+  "episodes": [
+    {
+      "guid": "file://tests/data/a",
+      "title": "Namespace Test",
+      "enclosures": [],
+      "payment_url": null,
+      "episode_art_url": "http://example.com/episode/1.jpg";,
+      "link": "file://tests/data/a",
+      "published": 0,
+      "description": "",
+      "total_time": 0
+    }
+  ]
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podcastparser-0.6.4/tests/data/itunes_episode_image.rss 
new/podcastparser-0.6.5/tests/data/itunes_episode_image.rss
--- old/podcastparser-0.6.4/tests/data/itunes_episode_image.rss 1970-01-01 
01:00:00.000000000 +0100
+++ new/podcastparser-0.6.5/tests/data/itunes_episode_image.rss 2020-04-07 
21:57:03.000000000 +0200
@@ -0,0 +1,9 @@
+<rss xmlns:it="http://www.itunes.com/dtds/podcast-1.0.dtd";>
+  <channel>
+    <item>
+      <title>Namespace Test</title>
+      <guid>a</guid>
+      <itunes:image href="http://example.com/episode/1.jpg"; />
+    </item>
+  </channel>
+</rss>

++++++ python-podcastparser-remove-nose.patch ++++++
Index: podcastparser-0.6.5/test_podcastparser.py
===================================================================
--- podcastparser-0.6.5.orig/test_podcastparser.py      2020-04-07 
22:00:53.000000000 +0200
+++ podcastparser-0.6.5/test_podcastparser.py   2020-07-15 16:18:39.885076713 
+0200
@@ -29,14 +29,14 @@ except ImportError:
     from io import StringIO
 
 
-from nose.tools import assert_equal
-from nose.tools import assert_raises
-
+import pytest
 import podcastparser
 
 
-def test_rss_parsing():
-    def test_parse_rss(rss_filename):
+class TestPodcastparser:
+    # test RSS parsing
+    @pytest.mark.parametrize("rss_filename", glob.glob(os.path.join('tests', 
'data', '*.rss')))
+    def test_parse_rss(self, rss_filename):
         basename, _ = os.path.splitext(rss_filename)
         json_filename = basename + '.json'
 
@@ -53,21 +53,16 @@ def test_rss_parsing():
         parsed = podcastparser.parse('file://' + normalized_rss_filename,
                                      open(rss_filename), **params)
 
-        assert_equal.__self__.maxDiff = None
-        assert_equal(expected, parsed)
-
-    for rss_filename in glob.glob(os.path.join('tests', 'data', '*.rss')):
-        yield test_parse_rss, rss_filename
-
-def test_invalid_roots():
-    def test_fail_parse(feed):
-        with assert_raises(podcastparser.FeedParseError):
-            podcastparser.parse('file://example.com/feed.xml', StringIO(feed))
+        assert expected == parsed
 
+    # test invalid roots
     feeds = [
         '<html><body/></html>',
         '<foo xmlns="http://example.com/foo.xml";><bar/></foo>',
         '<baz:foo xmlns:baz="http://example.com/baz.xml";><baz:bar/></baz:foo>',
     ]
-    for feed in feeds:
-        yield test_fail_parse, feed
+    @pytest.mark.parametrize("feed", feeds)
+    def test_fail_parse(self, feed):
+        with pytest.raises(podcastparser.FeedParseError):
+            podcastparser.parse('file://example.com/feed.xml', StringIO(feed))
+
Index: podcastparser-0.6.5/README.md
===================================================================
--- podcastparser-0.6.5.orig/README.md  2017-10-30 13:12:24.000000000 +0100
+++ podcastparser-0.6.5/README.md       2020-07-15 16:18:39.885076713 +0200
@@ -7,4 +7,4 @@ easy and reliable way of parsing RSS- an
 
 ## Automated Tests
 
-To run the unit tests you need 
[`nose`](http://nose.readthedocs.io/en/latest/).  If you have `nose` installed, 
use the `nosetests` command in the repository's root directory to run the tests.
+To run the unit tests you need [`pytest`](https://docs.pytest.org/).  If you 
have `pytest` installed, use the `pytest` command in the repository's root 
directory to run the tests.
Index: podcastparser-0.6.5/makefile
===================================================================
--- podcastparser-0.6.5.orig/makefile   2017-10-30 13:12:24.000000000 +0100
+++ podcastparser-0.6.5/makefile        2020-07-15 16:19:05.461229009 +0200
@@ -2,7 +2,7 @@ PACKAGE := podcastparser
 
 PYTHON ?= python
 FIND ?= find
-NOSETESTS ?= $(PYTHON) -m nose
+PYTEST ?= $(PYTHON) -m pytest
 
 help:
        @echo ""
@@ -12,7 +12,7 @@ help:
        @echo ""
 
 test:
-       $(NOSETESTS)
+       $(PYTEST)
 
 clean:
        $(FIND) . -name '*.pyc' -o -name __pycache__ -exec $(RM) -r '{}' +
Index: podcastparser-0.6.5/requirements-test.txt
===================================================================
--- podcastparser-0.6.5.orig/requirements-test.txt      2017-10-30 
13:12:24.000000000 +0100
+++ podcastparser-0.6.5/requirements-test.txt   2020-07-15 16:19:27.093357818 
+0200
@@ -1,2 +1,3 @@
-nose
+pytest
+pytest-cov
 coverage
Index: podcastparser-0.6.5/PKG-INFO
===================================================================
--- podcastparser-0.6.5.orig/PKG-INFO   2020-04-07 22:02:14.000000000 +0200
+++ podcastparser-0.6.5/PKG-INFO        2020-07-15 16:20:37.889779388 +0200
@@ -15,6 +15,6 @@ Description: podcastparser: Simple, fast
         
         ## Automated Tests
         
-        To run the unit tests you need 
[`nose`](http://nose.readthedocs.io/en/latest/).  If you have `nose` installed, 
use the `nosetests` command in the repository's root directory to run the tests.
+        To run the unit tests you need [`pytest`](http://docs.pytest.org/).  
If you have `pytest` installed, use the `pytest` command in the repository's 
root directory to run the tests.
         
 Platform: UNKNOWN
Index: podcastparser-0.6.5/pytest.ini
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ podcastparser-0.6.5/pytest.ini      2020-07-15 16:22:39.186501697 +0200
@@ -0,0 +1,3 @@
+[pytest]
+addopts = --cov=podcastparser --cov-report html --doctest-modules
+
Index: podcastparser-0.6.5/setup.cfg
===================================================================
--- podcastparser-0.6.5.orig/setup.cfg  2017-10-30 13:12:24.000000000 +0100
+++ podcastparser-0.6.5/setup.cfg       2020-07-15 16:21:02.817927825 +0200
@@ -1,9 +1,3 @@
-[nosetests]
-cover-erase = true
-with-coverage = true
-cover-package = podcastparser
-with-doctest = true
-
 [pep8]
 max-line-length = 120
 exclude = doc/conf.py

Reply via email to