Bug#756752: tracker.debian.org: Access package screenshots
On Wed, Aug 27, 2014 at 4:51 PM, Raphael Hertzog <hertzog@debian.org> wrote:
> PackageExtractedInfo.objects.filter(key='screenshots').delete()
Oh! For some reason I had miss-conceptualized PackageExtractedInfo
objects. I thought that the object contained multiple key/values, and
that that would select and delete the entire object including the
'general' key.
Update patch attached, which is now much quicker!
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 c55d99f72a61bb175613fbf544b9db3fb8edb53e 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
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Updated based on Raphaël's suggestions.
---
distro_tracker/vendor/debian/tests.py | 172 +++++++++++++++++++++++++
distro_tracker/vendor/debian/tracker_panels.py | 25 ++++
distro_tracker/vendor/debian/tracker_tasks.py | 57 ++++++++
3 files changed, 254 insertions(+)
diff --git a/distro_tracker/vendor/debian/tests.py b/distro_tracker/vendor/debian/tests.py
index c98fe7f..6c3764d 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,52 @@ class DebtagsLinkTest(TestCase):
self.assertNotIn('edit tags', response_content)
+class ScreenshotsLinkTest(TestCase):
+ """
+ Tests that the screenshots link is added to source package pages.
+ """
+ def setUp(self):
+ self.package_name = SourcePackageName.objects.create(name='dummy')
+ self.package = SourcePackage.objects.create(
+ source_package_name=self.package_name,
+ version='1.0.0')
+ PackageExtractedInfo.objects.create(
+ package=self.package.source_package_name,
+ key='screenshots',
+ value={'screenshots': 'true'}
+ )
+
+ 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):
+ response = self.get_package_page_response(self.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='other')
+ package = SourcePackage.objects.create(
+ source_package_name=package_name,
+ version='1.0.0')
+ 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 +4828,128 @@ 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"
+ }]}
+ """
+ PackageExtractedInfo.objects.create(
+ package=self.dummy_package,
+ key='general',
+ value={
+ 'name': 'dummy',
+ 'maintainer': {
+ 'email': 'jane@example.com',
+ }
+ }
+ )
+ self.other_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"
+ }]}
+ """
+
+ 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()
+
+ with self.assertRaises(PackageExtractedInfo.DoesNotExist):
+ info = other_package.packageextractedinfo_set.get(key='screenshots')
+
+ 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(0,
+ PackageExtractedInfo.objects.filter(key='screenshots').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()
+
+ set_mock_response(mock_requests, text=self.other_json_data)
+ self.run_task()
+
+ with self.assertRaises(PackageExtractedInfo.DoesNotExist):
+ info = self.dummy_package.packageextractedinfo_set.get(
+ key='screenshots')
+
+ def test_other_extractedinfo_keys_not_dropped(self, mock_requests):
+ """
+ Ensure that other PackageExtractedInfo keys are not dropped when
+ deleting the screenshot key.
+ """
+ set_mock_response(mock_requests, text=self.json_data)
+ self.run_task()
+
+ set_mock_response(mock_requests, text=self.other_json_data)
+ self.run_task()
+
+ info = self.dummy_package.packageextractedinfo_set.get(key='general')
+
+ self.assertEqual(info.value['name'], 'dummy')
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..a423ba8 100644
--- a/distro_tracker/vendor/debian/tracker_tasks.py
+++ b/distro_tracker/vendor/debian/tracker_tasks.py
@@ -2206,3 +2206,60 @@ 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()
+
+ 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
+
+ with transaction.atomic():
+ PackageExtractedInfo.objects.filter(key='screenshots').delete()
+
+ extracted_info = []
+ for package in packages_with_screenshots:
+ try:
+ screenshot_info = package.packageextractedinfo_set.get(
+ key=self.EXTRACTED_INFO_KEY)
+ screenshot_info.value['screenshots'] = 'true'
+ except PackageExtractedInfo.DoesNotExist:
+ screenshot_info = PackageExtractedInfo(
+ key=self.EXTRACTED_INFO_KEY,
+ package=package,
+ value={'screenshots': 'true'})
+
+ extracted_info.append(screenshot_info)
+
+ PackageExtractedInfo.objects.bulk_create(extracted_info)
--
1.9.1
Reply to: