Hi, Raphael Hertzog écrivait: > I merged an enhanced version of your patch:
Great! > I'm waiting your patch for the cleanup left to be done. Here it follows. (Note I tried and failed in getting rid of methods import_key_from_test_file and get_test_file_path in tests_utils, tests_models and tests_management) Cheers, Christophe --- distro_tracker/accounts/tests.py | 2 +- distro_tracker/auto_news/tests.py | 2 - distro_tracker/core/tests/common.py | 123 ----------------------- distro_tracker/core/tests/tests_management.py | 4 +- distro_tracker/core/tests/tests_models.py | 15 +-- distro_tracker/core/tests/tests_retrieve_data.py | 4 +- distro_tracker/core/tests/tests_utils.py | 4 +- distro_tracker/extract_source_files/tests.py | 8 +- distro_tracker/mail/tests/tests_mail_news.py | 5 - distro_tracker/test/utils.py | 109 ++++++++++++++++++++ distro_tracker/vendor/debian/tests.py | 14 +-- functional_tests/tests.py | 2 +- 12 files changed, 121 insertions(+), 171 deletions(-) delete mode 100644 distro_tracker/core/tests/common.py create mode 100644 distro_tracker/test/utils.py diff --git a/distro_tracker/accounts/tests.py b/distro_tracker/accounts/tests.py index 417e5d6..50b560d 100644 --- a/distro_tracker/accounts/tests.py +++ b/distro_tracker/accounts/tests.py @@ -11,7 +11,7 @@ Tests for the :mod:`distro_tracker.accounts` app. """ from __future__ import unicode_literals -from django.test import TestCase +from distro_tracker.test import TestCase from distro_tracker.accounts.models import User from distro_tracker.accounts.models import UserEmail from distro_tracker.core.models import EmailSettings diff --git a/distro_tracker/auto_news/tests.py b/distro_tracker/auto_news/tests.py index 46f38d4..a68d2f3 100644 --- a/distro_tracker/auto_news/tests.py +++ b/distro_tracker/auto_news/tests.py @@ -23,7 +23,6 @@ from distro_tracker.core.tasks import Job from distro_tracker.core.tasks import JobState from distro_tracker.core.tasks import Event from distro_tracker.auto_news.tracker_tasks import GenerateNewsFromRepositoryUpdates -from distro_tracker.core.tests.common import temporary_media_dir class GenerateNewsFromRepositoryUpdatesTest(TestCase): @@ -543,7 +542,6 @@ class GenerateNewsFromRepositoryUpdatesTest(TestCase): news = News.objects.all()[0] self.assertEqual(news.content, expected_content) - @temporary_media_dir def test_changelog_entry_in_news_content(self): """ Tests that the news item created for new source package versions diff --git a/distro_tracker/core/tests/common.py b/distro_tracker/core/tests/common.py deleted file mode 100644 index 86febb1..0000000 --- a/distro_tracker/core/tests/common.py +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2013 The Distro Tracker Developers -# See the COPYRIGHT file at the top-level directory of this distribution and -# at http://deb.li/DTAuthors -# -# This file is part of Distro Tracker. It is subject to the license terms -# in the LICENSE file found in the top-level directory of this -# distribution and at http://deb.li/DTLicense. No part of Distro Tracker, -# including this file, may be copied, modified, propagated, or distributed -# except according to the terms contained in the LICENSE file. -from distro_tracker.core.models import Architecture -from distro_tracker.accounts.models import UserEmail -from distro_tracker.core.models import ContributorName -from distro_tracker.core.models import SourcePackage -from distro_tracker.core.models import SourcePackageName -from distro_tracker.core.models import BinaryPackageName - -import shutil -import tempfile -import contextlib - - -@contextlib.contextmanager -def make_temp_directory(suffix=''): - """ - Helper context manager which creates a temporary directory on enter and - cleans it up on exit. - """ - temp_dir_name = tempfile.mkdtemp(suffix=suffix) - try: - yield temp_dir_name - finally: - shutil.rmtree(temp_dir_name) - - -def temporary_media_dir(meth): - """ - Method decorator which creates a temporary media directory which is - automatically cleaned up once the method exits. - """ - def wrap(self, *args, **kwargs): - with make_temp_directory('-dtracker-media') as temp_media_dir: - with self.settings(MEDIA_ROOT=temp_media_dir): - meth(self, *args, **kwargs) - - return wrap - - -def create_source_package(arguments): - """ - Creates and returns a new :class:`SourcePackage <distro_tracker.core.models.SourcePackage>` - instance based on the parameters given in the arguments. - - It takes care to automatically create any missing maintainers, package - names, etc. - """ - kwargs = {} - if 'maintainer' in arguments: - maintainer = arguments['maintainer'] - maintainer_email = UserEmail.objects.get_or_create( - email=maintainer['email'])[0] - kwargs['maintainer'] = ContributorName.objects.get_or_create( - contributor_email=maintainer_email, - name=maintainer.get('name', ''))[0] - if 'name' in arguments: - name = arguments['name'] - kwargs['source_package_name'] = ( - SourcePackageName.objects.get_or_create(name=name)[0]) - if 'version' in arguments: - kwargs['version'] = arguments['version'] - if 'directory' in arguments: - kwargs['directory'] = arguments['directory'] - if 'dsc_file_name' in arguments: - kwargs['dsc_file_name'] = arguments['dsc_file_name'] - - src_pkg = SourcePackage.objects.create(**kwargs) - - # Now add m2m fields - if 'architectures' in arguments: - architectures = arguments['architectures'] - src_pkg.architectures = Architecture.objects.filter( - name__in=architectures) - if 'binary_packages' in arguments: - binaries = [] - for binary in arguments['binary_packages']: - binaries.append( - BinaryPackageName.objects.get_or_create(name=binary)[0]) - src_pkg.binary_packages = binaries - if 'uploaders' in arguments: - for uploader in arguments['uploaders']: - contributor = ContributorName.objects.get_or_create( - contributor_email=UserEmail.objects.get_or_create( - email=uploader)[0])[0] - src_pkg.uploaders.add(contributor) - - src_pkg.save() - return src_pkg - - -def set_mock_response(mock_requests, text="", headers=None, status_code=200): - """ - Helper method which sets a mock response to the given mock requests - module. - - It takes care to correctly set the return value of all useful requests - module functions. - - :param mock_requests: A mock requests module. - :param text: The text of the response. - :param headers: The headers of the response. - :param status_code: The status code of the response. - """ - if headers is None: - headers = {} - mock_response = mock_requests.models.Response() - mock_response.headers = headers - mock_response.status_code = status_code - mock_response.ok = status_code < 400 - mock_response.text = text - mock_response.content = text.encode('utf-8') - mock_response.iter_lines.return_value = text.splitlines() - mock_requests.get.return_value = mock_response diff --git a/distro_tracker/core/tests/tests_management.py b/distro_tracker/core/tests/tests_management.py index fcfdfdf..b499a57 100644 --- a/distro_tracker/core/tests/tests_management.py +++ b/distro_tracker/core/tests/tests_management.py @@ -22,8 +22,7 @@ from distro_tracker.core.models import SourcePackageName from distro_tracker.core.models import EmailNews from distro_tracker.core.models import News from distro_tracker.core.utils import message_from_bytes -from distro_tracker.core.tests.common import make_temp_directory -from distro_tracker.core.tests.common import temporary_media_dir +from distro_tracker.test.utils import make_temp_directory import os import gpgme @@ -135,7 +134,6 @@ class UpdateNewsSignaturesCommandTest(TestCase): 'tests-data', file_name) - @temporary_media_dir def test_signatures_added(self): """ Tests that signatures are correctly added to the news which previously diff --git a/distro_tracker/core/tests/tests_models.py b/distro_tracker/core/tests/tests_models.py index 8db096a..f78c31d 100644 --- a/distro_tracker/core/tests/tests_models.py +++ b/distro_tracker/core/tests/tests_models.py @@ -18,7 +18,6 @@ from distro_tracker.test import TestCase from django.test.utils import override_settings from django.core.files.base import ContentFile from django.core.exceptions import ValidationError, ObjectDoesNotExist -from distro_tracker.core.tests.common import temporary_media_dir from django.core.urlresolvers import reverse from distro_tracker.core.models import Subscription, EmailSettings, PackageName, BinaryPackageName from distro_tracker.core.models import BinaryPackage @@ -40,8 +39,8 @@ from distro_tracker.core.models import MembershipPackageSpecifics from distro_tracker.core.utils import message_from_bytes from distro_tracker.core.utils.email_messages import get_decoded_message_payload from distro_tracker.accounts.models import User, UserEmail -from .common import make_temp_directory -from .common import create_source_package +from distro_tracker.test.utils import make_temp_directory +from distro_tracker.test.utils import create_source_package from email import message_from_string @@ -972,7 +971,6 @@ class SourcePackageTests(TestCase): """ self.assertIsNone(self.source_package.main_entry) - @temporary_media_dir def test_changelog_entry_only(self): """ Tests that the @@ -998,7 +996,6 @@ class SourcePackageTests(TestCase): self.source_package.get_changelog_entry(), changelog_entry) - @temporary_media_dir def test_changelog_entry_beginning(self): """ Tests that the @@ -1030,7 +1027,6 @@ class SourcePackageTests(TestCase): self.source_package.get_changelog_entry(), changelog_entry) - @temporary_media_dir def test_changelog_entry_not_first(self): """ Tests that the @@ -1061,7 +1057,6 @@ class SourcePackageTests(TestCase): self.source_package.get_changelog_entry(), changelog_entry) - @temporary_media_dir def test_changelog_entry_regex_meta_chars(self): """ Tests that the @@ -1276,7 +1271,6 @@ class NewsTests(TestCase): self.assertEqual(news.content, expected_content) - @temporary_media_dir def test_content_from_file(self): """ Tests that the :meth:`distro_tracker.core.models.News.content` property returns @@ -1317,7 +1311,6 @@ class NewsTests(TestCase): self.assertEqual(news._db_content, expected_content) self.assertFalse(news.news_file) - @temporary_media_dir def test_create_file_content(self): """ Tests the :meth:`distro_tracker.core.models.NewsManager.create` method when it @@ -1333,7 +1326,6 @@ class NewsTests(TestCase): self.assertIsNone(news._db_content) self.assertEqual(news.content, expected_content) - @temporary_media_dir def test_create_email_news_signature(self): """ Tests that the signature information is correctly extracted when @@ -1368,7 +1360,6 @@ class NewsTests(TestCase): # email self.assertEqual(sender_name, news.created_by) - @temporary_media_dir def test_create_email_news_unknown_encoding_utf8(self): """ Tests that creating an email news item from a message which does not @@ -1396,7 +1387,6 @@ class NewsTests(TestCase): content, get_decoded_message_payload(msg_from_news)) - @temporary_media_dir def test_create_email_news_unknown_encoding_latin1(self): """ Tests that creating an email news item from a message which does not @@ -1425,7 +1415,6 @@ class NewsTests(TestCase): content, get_decoded_message_payload(msg_from_news, 'latin-1')) - @temporary_media_dir def test_email_news_render(self): """ Tests that an email news is correctly rendered when the encoding of the diff --git a/distro_tracker/core/tests/tests_retrieve_data.py b/distro_tracker/core/tests/tests_retrieve_data.py index 0f32dad..ee1eb24 100644 --- a/distro_tracker/core/tests/tests_retrieve_data.py +++ b/distro_tracker/core/tests/tests_retrieve_data.py @@ -32,11 +32,11 @@ from distro_tracker.core.models import Team from distro_tracker.core.retrieve_data import UpdateRepositoriesTask from distro_tracker.core.retrieve_data import UpdateTeamPackagesTask from distro_tracker.core.retrieve_data import retrieve_repository_info -from distro_tracker.core.tests.common import set_mock_response +from distro_tracker.test.utils import create_source_package +from distro_tracker.test.utils import set_mock_response from distro_tracker.accounts.models import User, UserEmail from distro_tracker.core.tasks import BaseTask -from .common import create_source_package import os import sys diff --git a/distro_tracker/core/tests/tests_utils.py b/distro_tracker/core/tests/tests_utils.py index 1e74ba3..70ef13c 100644 --- a/distro_tracker/core/tests/tests_utils.py +++ b/distro_tracker/core/tests/tests_utils.py @@ -21,8 +21,8 @@ from django.utils import six from django.utils.http import http_date from django.utils.functional import curry from django.utils.six.moves import mock -from distro_tracker.core.tests.common import set_mock_response -from distro_tracker.core.tests.common import make_temp_directory +from distro_tracker.test.utils import set_mock_response +from distro_tracker.test.utils import make_temp_directory from distro_tracker.core.models import Repository from distro_tracker.core.utils import verp from distro_tracker.core.utils import message_from_bytes diff --git a/distro_tracker/extract_source_files/tests.py b/distro_tracker/extract_source_files/tests.py index bae5621..5c708e3 100644 --- a/distro_tracker/extract_source_files/tests.py +++ b/distro_tracker/extract_source_files/tests.py @@ -19,8 +19,7 @@ from django.core.files.base import ContentFile from distro_tracker.core.models import SourcePackage, SourcePackageName from distro_tracker.core.models import ExtractedSourceFile from distro_tracker.core.tasks import JobState, Event, Job -from distro_tracker.core.tests.common import make_temp_directory -from distro_tracker.core.tests.common import temporary_media_dir +from distro_tracker.test.utils import make_temp_directory from distro_tracker.extract_source_files.tracker_tasks import ExtractSourcePackageFiles from django.utils.six.moves import mock @@ -68,7 +67,6 @@ class ExtractSourcePackageFilesTest(TestCase): self.task.execute() @mock.patch('distro_tracker.extract_source_files.tracker_tasks.AptCache.retrieve_source') - @temporary_media_dir def test_create_extracted_files(self, mock_cache): """ Tests that the task creates an @@ -103,7 +101,6 @@ class ExtractSourcePackageFilesTest(TestCase): self.assertEqual('changelog', extracted_file.name) @mock.patch('distro_tracker.extract_source_files.tracker_tasks.AptCache.retrieve_source') - @temporary_media_dir def test_create_extracted_files_only_wanted_files(self, mock_cache): """ Tests that the task creates an @@ -148,7 +145,6 @@ class ExtractSourcePackageFilesTest(TestCase): self.assertIn(wanted_file, extracted_names) @mock.patch('distro_tracker.extract_source_files.tracker_tasks.AptCache.retrieve_source') - @temporary_media_dir def test_task_is_initial_no_existing_files(self, mock_cache): """ Tests the task when it is run as the initial task, but there are no @@ -191,7 +187,6 @@ class ExtractSourcePackageFilesTest(TestCase): @mock.patch('distro_tracker.extract_source_files.tracker_tasks.AptCache.retrieve_source') - @temporary_media_dir def test_task_is_initial_existing_files(self, mock_cache): """ Tests the task when it is run as the initial task, but some files for @@ -242,7 +237,6 @@ class ExtractSourcePackageFilesTest(TestCase): self.assertEqual(original_content, content) @mock.patch('distro_tracker.extract_source_files.tracker_tasks.AptCache.retrieve_source') - @temporary_media_dir def test_task_is_initial_existing_file_remove(self, mock_cache): """ Tests the task when it is run as the initial task, but some of the diff --git a/distro_tracker/mail/tests/tests_mail_news.py b/distro_tracker/mail/tests/tests_mail_news.py index 6a4bc1d..e025c8d 100644 --- a/distro_tracker/mail/tests/tests_mail_news.py +++ b/distro_tracker/mail/tests/tests_mail_news.py @@ -20,7 +20,6 @@ from django.utils.six.moves import mock from django.utils.encoding import force_bytes from distro_tracker.core.models import SourcePackageName, SourcePackage from distro_tracker.core.models import News -from distro_tracker.core.tests.common import temporary_media_dir from distro_tracker.mail.mail_news import process from distro_tracker.mail.management.commands.tracker_receive_news import ( Command as MailNewsCommand) @@ -50,7 +49,6 @@ class BasicNewsGeneration(TestCase): def process_mail(self): process(force_bytes(self.message.as_string(), 'utf-8')) - @temporary_media_dir def test_creates_news_from_email(self): """ Tets that a news is created from an email with the correct header @@ -73,7 +71,6 @@ class BasicNewsGeneration(TestCase): # The content type is set to render email messages self.assertEqual(news.content_type, 'message/rfc822') - @temporary_media_dir def test_create_news_url_from_email(self): """ Tests that when an X-Distro-Tracker-Url header is given the news content is the @@ -96,7 +93,6 @@ class BasicNewsGeneration(TestCase): self.assertEqual(url, news.title) self.assertIn(url, news.content.strip()) - @temporary_media_dir def test_create_news_package_does_not_exist(self): """ Tests that when the package given in X-Distro-Tracker-Package does not exist, no @@ -116,7 +112,6 @@ class BasicNewsGeneration(TestCase): self.assertEqual(0, News.objects.count()) @mock.patch('distro_tracker.mail.mail_news.vendor.call') - @temporary_media_dir def test_create_news_calls_vendor_function(self, mock_vendor_call): """ Tests that the vendor-provided function is called during the processing diff --git a/distro_tracker/test/utils.py b/distro_tracker/test/utils.py new file mode 100644 index 0000000..18ffe28 --- /dev/null +++ b/distro_tracker/test/utils.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- + +# Copyright 2013 The Distro Tracker Developers +# See the COPYRIGHT file at the top-level directory of this distribution and +# at http://deb.li/DTAuthors +# +# This file is part of Distro Tracker. It is subject to the license terms +# in the LICENSE file found in the top-level directory of this +# distribution and at http://deb.li/DTLicense. No part of Distro Tracker, +# including this file, may be copied, modified, propagated, or distributed +# except according to the terms contained in the LICENSE file. +from distro_tracker.core.models import Architecture +from distro_tracker.accounts.models import UserEmail +from distro_tracker.core.models import ContributorName +from distro_tracker.core.models import SourcePackage +from distro_tracker.core.models import SourcePackageName +from distro_tracker.core.models import BinaryPackageName + +import shutil +import tempfile +import contextlib + + +@contextlib.contextmanager +def make_temp_directory(suffix=''): + """ + Helper context manager which creates a temporary directory on enter and + cleans it up on exit. + """ + temp_dir_name = tempfile.mkdtemp(suffix=suffix) + try: + yield temp_dir_name + finally: + shutil.rmtree(temp_dir_name) + +def create_source_package(arguments): + """ + Creates and returns a new :class:`SourcePackage <distro_tracker.core.models.SourcePackage>` + instance based on the parameters given in the arguments. + + It takes care to automatically create any missing maintainers, package + names, etc. + """ + kwargs = {} + if 'maintainer' in arguments: + maintainer = arguments['maintainer'] + maintainer_email = UserEmail.objects.get_or_create( + email=maintainer['email'])[0] + kwargs['maintainer'] = ContributorName.objects.get_or_create( + contributor_email=maintainer_email, + name=maintainer.get('name', ''))[0] + if 'name' in arguments: + name = arguments['name'] + kwargs['source_package_name'] = ( + SourcePackageName.objects.get_or_create(name=name)[0]) + if 'version' in arguments: + kwargs['version'] = arguments['version'] + if 'directory' in arguments: + kwargs['directory'] = arguments['directory'] + if 'dsc_file_name' in arguments: + kwargs['dsc_file_name'] = arguments['dsc_file_name'] + + src_pkg = SourcePackage.objects.create(**kwargs) + + # Now add m2m fields + if 'architectures' in arguments: + architectures = arguments['architectures'] + src_pkg.architectures = Architecture.objects.filter( + name__in=architectures) + if 'binary_packages' in arguments: + binaries = [] + for binary in arguments['binary_packages']: + binaries.append( + BinaryPackageName.objects.get_or_create(name=binary)[0]) + src_pkg.binary_packages = binaries + if 'uploaders' in arguments: + for uploader in arguments['uploaders']: + contributor = ContributorName.objects.get_or_create( + contributor_email=UserEmail.objects.get_or_create( + email=uploader)[0])[0] + src_pkg.uploaders.add(contributor) + + src_pkg.save() + return src_pkg + + +def set_mock_response(mock_requests, text="", headers=None, status_code=200): + """ + Helper method which sets a mock response to the given mock requests + module. + + It takes care to correctly set the return value of all useful requests + module functions. + + :param mock_requests: A mock requests module. + :param text: The text of the response. + :param headers: The headers of the response. + :param status_code: The status code of the response. + """ + if headers is None: + headers = {} + mock_response = mock_requests.models.Response() + mock_response.headers = headers + mock_response.status_code = status_code + mock_response.ok = status_code < 400 + mock_response.text = text + mock_response.content = text.encode('utf-8') + mock_response.iter_lines.return_value = text.splitlines() + mock_requests.get.return_value = mock_response diff --git a/distro_tracker/vendor/debian/tests.py b/distro_tracker/vendor/debian/tests.py index d1f3f9b..5efec5b 100644 --- a/distro_tracker/vendor/debian/tests.py +++ b/distro_tracker/vendor/debian/tests.py @@ -27,7 +27,8 @@ from django.utils.functional import curry from distro_tracker.mail.tests.tests_dispatch import DispatchTestHelperMixin, DispatchBaseTest from distro_tracker.accounts.models import User from distro_tracker.accounts.models import UserEmail -from distro_tracker.core.tests.common import make_temp_directory +from distro_tracker.test.utils import make_temp_directory +from distro_tracker.test.utils import set_mock_response from distro_tracker.core.utils.email_messages import message_from_bytes from distro_tracker.core.models import ActionItem, ActionItemType from distro_tracker.core.models import News @@ -40,8 +41,6 @@ from distro_tracker.core.models import SourcePackage from distro_tracker.core.models import PseudoPackageName from distro_tracker.core.models import SourcePackageName from distro_tracker.core.models import Repository -from distro_tracker.core.tests.common import set_mock_response -from distro_tracker.core.tests.common import temporary_media_dir from distro_tracker.core.tasks import run_task from distro_tracker.core.retrieve_data import UpdateRepositoriesTask from distro_tracker.vendor.debian.rules import get_package_information_site_url @@ -676,7 +675,6 @@ class DebianNewsFromEmailTest(TestCase): """ return '{pkg} REMOVED from testing'.format(pkg=pkg) - @temporary_media_dir def test_source_upload_news(self): """ Tests the news created when a notification of a new source upload is @@ -696,7 +694,6 @@ class DebianNewsFromEmailTest(TestCase): self.assertEqual(subject, news.title) self.assertIn(content, news.content) - @temporary_media_dir def test_source_upload_package_does_not_exist(self): """ Tests that no news are created when the notification of a new source @@ -711,7 +708,6 @@ class DebianNewsFromEmailTest(TestCase): self.assertEqual(0, News.objects.count()) - @temporary_media_dir def test_dak_rm_news(self): """ Tests that a dak rm message creates a news. @@ -738,7 +734,6 @@ class DebianNewsFromEmailTest(TestCase): ver=self.package.version)) self.assertEqual(news.created_by, sender) - @temporary_media_dir def test_dak_rm_no_package(self): """ Tests that a dak rm message referencing a package which Distro @@ -761,7 +756,6 @@ class DebianNewsFromEmailTest(TestCase): self.assertEqual(0, News.objects.count()) - @temporary_media_dir def test_dak_not_rm(self): """ Tests that a message with an X-DAK header different from ``dak rm`` @@ -784,7 +778,6 @@ class DebianNewsFromEmailTest(TestCase): self.assertEqual(0, News.objects.count()) - @temporary_media_dir def test_multiple_removes(self): """ Tests that multiple news items are created when the dak rm message @@ -812,7 +805,6 @@ class DebianNewsFromEmailTest(TestCase): self.assertEqual(2, News.objects.count()) - @temporary_media_dir def test_testing_watch_news(self): """ Tests that an email received from the Testing Watch is turned into a @@ -837,7 +829,6 @@ class DebianNewsFromEmailTest(TestCase): self.assertEqual(subject, news.title) self.assertIn(content, news.content) - @temporary_media_dir def test_testing_watch_package_no_exist(self): """ Tests that an email received from the Testing Watch which references @@ -4138,7 +4129,6 @@ class ImportOldNewsTests(TestCase): return msg - @temporary_media_dir def test_news_created(self): packages = ['dpkg', 'dummy', 'asdf', '000'] email = 'u...@domain.com' diff --git a/functional_tests/tests.py b/functional_tests/tests.py index 74b50e9..ef152fc 100644 --- a/functional_tests/tests.py +++ b/functional_tests/tests.py @@ -12,7 +12,7 @@ Functional tests for Distro Tracker. """ from __future__ import unicode_literals -from django.test import LiveServerTestCase +from distro_tracker.test import LiveServerTestCase from django.core.urlresolvers import reverse from django.contrib.auth import get_user_model from django.core import mail -- 2.0.1 -- To UNSUBSCRIBE, email to debian-qa-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: https://lists.debian.org/20140713131556.GA27794@atitude.localdomain