[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#756752: tracker.debian.org: Access package screenshots



tag 756752 + patch
thanks

The attached patch adds links to screenshots.debian.net when they
exist. It's slower that I'd like. It might be nice if
PackageExtractedInfo grew a delete_obsolete_items() like ActionItem so
it wasn't necessary to loop through everything..

Thanks,

-- Andrew Starr-Bochicchio

   Ubuntu Developer <https://launchpad.net/~andrewsomething>
   Debian Developer <http://qa.debian.org/developer.php?login=asb>
   PGP/GPG Key ID: D53FDCB1
From bd946e414dfe591610c422ac5b8cb285e37c756c Mon Sep 17 00:00:00 2001
From: Andrew Starr-Bochicchio <a.starr.b@gmail.com>
Date: Mon, 25 Aug 2014 11:18:15 -0700
Subject: [PATCH] Add link to screenshots if they exist on
 screenshots.debian.net

---
 distro_tracker/vendor/debian/tests.py          | 152 +++++++++++++++++++++++++
 distro_tracker/vendor/debian/tracker_panels.py |  25 ++++
 distro_tracker/vendor/debian/tracker_tasks.py  |  61 ++++++++++
 3 files changed, 238 insertions(+)

diff --git a/distro_tracker/vendor/debian/tests.py b/distro_tracker/vendor/debian/tests.py
index c98fe7f..d18b133 100644
--- a/distro_tracker/vendor/debian/tests.py
+++ b/distro_tracker/vendor/debian/tests.py
@@ -63,6 +63,7 @@ from distro_tracker.vendor.debian.tracker_tasks import UpdateExcusesTask
 from distro_tracker.vendor.debian.tracker_tasks import UpdateDebciStatusTask
 from distro_tracker.vendor.debian.tracker_tasks import UpdateDebianDuckTask
 from distro_tracker.vendor.debian.tracker_tasks import UpdateAutoRemovalsStatsTask
+from distro_tracker.vendor.debian.tracker_tasks import UpdatePackageScreenshotsTask
 from distro_tracker.vendor.debian.models import DebianContributor
 from distro_tracker.vendor.debian.models import UbuntuPackage
 from distro_tracker.vendor.debian.tracker_tasks import UpdateLintianStatsTask
@@ -2579,6 +2580,57 @@ class DebtagsLinkTest(TestCase):
         self.assertNotIn('edit tags', response_content)
 
 
+class ScreenshotsLinkTest(TestCase):
+    """
+    Tests that the screenshots link is added to source package pages.
+    """
+    def get_package_page_response(self, package_name):
+        package_page_url = reverse('dtracker-package-page', kwargs={
+            'package_name': package_name,
+        })
+        return self.client.get(package_page_url)
+
+    def test_source_package_with_screenshot(self):
+        package_name = SourcePackageName.objects.create(name='dummy')
+        package = SourcePackage.objects.create(
+            source_package_name=package_name,
+            version='1.0.0')
+        PackageExtractedInfo.objects.create(
+            package=package.source_package_name,
+            key='screenshots',
+            value={'screenshots': 'true'}
+        )
+
+        response = self.get_package_page_response(package.name)
+
+        response_content = response.content.decode('utf8')
+        self.assertIn('screenshots', response_content)
+
+    def test_source_package_without_screenshot(self):
+        package_name = SourcePackageName.objects.create(name='dummy')
+        package = SourcePackage.objects.create(
+            source_package_name=package_name,
+            version='1.0.0')
+        PackageExtractedInfo.objects.create(
+            package=package.source_package_name,
+            key='screenshots',
+            value={}
+        )
+
+        response = self.get_package_page_response(package.name)
+
+        response_content = response.content.decode('utf8')
+        self.assertNotIn('screenshots', response_content)
+
+    def test_pseudo_package(self):
+        package = PseudoPackageName.objects.create(name='somepackage')
+
+        response = self.get_package_page_response(package.name)
+
+        response_content = response.content.decode('utf-8')
+        self.assertNotIn('screenshots', response_content)
+
+
 class UpdatePiupartsTaskTests(TestCase):
     suites = []
 
@@ -4781,3 +4833,103 @@ class UpdateAutoRemovalsStatsTaskTest(TestCase):
 
         self.run_task()
         self.assertEqual(0, self.dummy_package.action_items.count())
+
+
+@mock.patch('distro_tracker.core.utils.http.requests')
+class UpdatePackageScreenshotsTaskTest(TestCase):
+    """
+    Tests for the :class:`distro_tracker.vendor.debian.tracker_tasks.UpdatePackageScreenshotsTask` task.
+    """
+    def setUp(self):
+        self.dummy_package = SourcePackageName.objects.create(name='dummy')
+        self.json_data = """{
+            "packages": [{
+                "maintainer": "Jane Doe",
+                "name": "dummy",
+                "url": "http://screenshots.debian.net/package/dummy";,
+                "section": "universe/games",
+                "maintainer_email": "jane@example.com",
+                "homepage": "http://example.com/packages/dummy";,
+                "description": "a game that you can play"
+            }]}
+        """
+
+    def run_task(self):
+        """
+        Runs the debci status update task.
+        """
+        task = UpdatePackageScreenshotsTask()
+        task.execute()
+
+    def test_extractedinfo_item_for_without_screenshot(self, mock_requests):
+        """
+        Tests that packages without screenshots don't claim to have them.
+        """
+        set_mock_response(mock_requests, text=self.json_data)
+        other_package = SourcePackageName.objects.create(name='other-package')
+
+        self.run_task()
+
+        info = other_package.packageextractedinfo_set.get(key='screenshots')
+
+        self.assertEqual(info.value['screenshots'], 'false')
+
+    def test_no_extractedinfo_for_unknown_package(self, mock_requests):
+        """
+        Tests that UpdatePackageScreenshotsTask doesn't fail with an unknown package.
+        """
+        data = """{
+            "packages": [{
+                "maintainer": "John Doe",
+                "name": "other",
+                "url": "http://screenshots.debian.net/package/other";,
+                "section": "universe/games",
+                "maintainer_email": "john@example.com",
+                "homepage": "http://example.com/packages/other";,
+                "description": "yet another game that you can play"
+            }]}
+        """
+        set_mock_response(mock_requests, text=data)
+
+        self.run_task()
+
+        self.assertEqual(1, PackageExtractedInfo.objects.count())
+
+    def test_extractedinfo_for_package_with_screenshots(self, mock_requests):
+        """
+        Tests that PackageExtractedInfo for a package with a screenshot is
+        correct.
+        """
+        set_mock_response(mock_requests, text=self.json_data)
+
+        self.run_task()
+
+        info = self.dummy_package.packageextractedinfo_set.get(key='screenshots')
+
+        self.assertEqual(info.value['screenshots'], 'true')
+
+    def test_extractedinfo_is_dropped_when_no_more_screenshot(self, mock_requests):
+        """
+        Tests that PackageExtractedInfo is dropped if screenshot goes away.
+        """
+        set_mock_response(mock_requests, text=self.json_data)
+        self.run_task()
+
+        json_data =  """{
+            "packages": [{
+                "maintainer": "John Doe",
+                "name": "other",
+                "url": "http://screenshots.debian.net/package/other";,
+                "section": "universe/games",
+                "maintainer_email": "john@example.com",
+                "homepage": "http://example.com/packages/other";,
+                "description": "yet another game that you can play"
+            }]}
+        """
+        set_mock_response(mock_requests, text=json_data)
+
+        self.run_task()
+
+        info = self.dummy_package.packageextractedinfo_set.get(key='screenshots')
+
+        self.assertEqual(info.value['screenshots'], 'false')
diff --git a/distro_tracker/vendor/debian/tracker_panels.py b/distro_tracker/vendor/debian/tracker_panels.py
index d995f16..7080116 100644
--- a/distro_tracker/vendor/debian/tracker_panels.py
+++ b/distro_tracker/vendor/debian/tracker_panels.py
@@ -170,6 +170,31 @@ class DebtagsLink(LinksPanel.ItemProvider):
         ]
 
 
+class ScreenshotsLink(LinksPanel.ItemProvider):
+    """
+    Add a link to screenshots.debian.net
+    """
+    SOURCES_URL_TEMPLATE = \
+        'http://screenshots.debian.net/package/{package}'
+
+    def get_panel_items(self):
+        if not isinstance(self.package, SourcePackageName):
+            return
+        try:
+            infos = self.package.packageextractedinfo_set.get(key='screenshots')
+        except PackageExtractedInfo.DoesNotExist:
+            return
+        if infos.value['screenshots'] == 'true':
+            return [
+                LinksPanel.SimpleLinkItem(
+                    'screenshots',
+                    self.SOURCES_URL_TEMPLATE.format(package=self.package.name)
+                )
+            ]
+        else:
+            return
+
+
 class TransitionsPanel(BasePanel):
     template_name = 'debian/transitions-panel.html'
     panel_importance = 2
diff --git a/distro_tracker/vendor/debian/tracker_tasks.py b/distro_tracker/vendor/debian/tracker_tasks.py
index 7376cb3..c674862 100644
--- a/distro_tracker/vendor/debian/tracker_tasks.py
+++ b/distro_tracker/vendor/debian/tracker_tasks.py
@@ -2206,3 +2206,64 @@ class UpdateAutoRemovalsStatsTask(BaseTask):
 
         for package in packages:
             self.update_action_item(package, autoremovals_stats[package.name])
+
+
+class UpdatePackageScreenshotsTask(BaseTask):
+    """
+    Check if a screenshot exists on screenshots.debian.net, and add a
+    key to PackageExtractedInfo if it does.
+    """
+    EXTRACTED_INFO_KEY = 'screenshots'
+
+    def __init__(self, force_update=False, *args, **kwargs):
+        super(UpdatePackageScreenshotsTask, self).__init__(*args, **kwargs)
+        self.force_update = force_update
+
+    def set_parameters(self, parameters):
+        if 'force_update' in parameters:
+            self.force_update = parameters['force_update']
+
+    def _get_screenshots(self):
+        url = 'https://screenshots.debian.net/json/packages'
+        cache = HttpCache(settings.DISTRO_TRACKER_CACHE_DIRECTORY)
+        response, updated = cache.update(url, force=self.force_update)
+        response.raise_for_status()
+        if not updated:
+            return
+
+        data = json.loads(response.text)
+        return data
+
+    def execute(self):
+        content = self._get_screenshots()
+        all_packages = SourcePackageName.objects.all()
+
+        packages_with_screenshots = []
+        for item in content['packages']:
+            try:
+                package = SourcePackageName.objects.get(name=item['name'])
+                packages_with_screenshots.append(package)
+            except SourcePackageName.DoesNotExist:
+                pass
+
+        for package in all_packages:
+            try:
+                screenshot_info = package.packageextractedinfo_set.get(
+                    key=self.EXTRACTED_INFO_KEY)
+                if package in packages_with_screenshots:
+                    screenshot_info.value['screenshots'] = 'true'
+                else:
+                    screenshot_info.value['screenshots'] = 'false'
+            except PackageExtractedInfo.DoesNotExist:
+                if package in packages_with_screenshots:
+                    screenshot_info = PackageExtractedInfo(
+                        key=self.EXTRACTED_INFO_KEY,
+                        package=package,
+                        value={'screenshots': 'true'})
+                else:
+                    screenshot_info = PackageExtractedInfo(
+                        key=self.EXTRACTED_INFO_KEY,
+                        package=package,
+                        value={'screenshots': 'false'})
+
+            screenshot_info.save()
-- 
1.9.1


Reply to: