<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Unittests for management commands.
"""
import os
import shutil
import calaccess_processed
from datetime import date
import time
from django.conf import settings
from django.core.management import call_command
from django.core.management.base import CommandError
from django.db.models import Count
from django.test import TestCase, override_settings
from django.utils.timezone import now
from email.utils import formatdate
from calaccess_raw.models import RawDataVersion
from calaccess_processed.management.commands import CalAccessCommand
from calaccess_processed import corrections
from calaccess_processed.models import (
    ProcessedDataVersion,
    ScrapedCandidateProxy,
)
from calaccess_scraped.models import Candidate as ScrapedCandidate
from calaccess_scraped.models import Proposition as ScrapedProposition
from opencivicdata.core.models import Person
from opencivicdata.elections.models import (
    BallotMeasureContest,
    Candidacy,
    CandidateContest,
    RetentionContest,
)
import requests_mock

class NoProcessedDataTest(TestCase):
    """
    Tests to run with no data loaded.
    """
    def test_no_raw_data(self):
        """
        Confirm process command will not run without data.
        """
        with self.assertRaises(CommandError):
            call_command("processcalaccessdata", verbosity=3, noinput=True)

@override_settings(
    CALACCESS_DATA_DIR=os.path.join(settings.BASE_DIR, 'test-data')
)
@override_settings(
    MEDIA_ROOT=os.path.join(settings.BASE_DIR, 'test-data', ".media")
)
@override_settings(CALACCESS_STORE_ARCHIVE=True)
class ProcessedDataTest(TestCase):
    """
    Run and test management commands.
    """
    fixtures = [
        'divisions.json',
        'candidate_election.json',
        'candidate.json',
        'incumbent_election.json',
        'incumbent.json',
        'proposition_election.json',
        'proposition.json',
    ]

    @classmethod
    @requests_mock.Mocker()
    def setUpClass(cls, m):
        """
        Load data for other tests.
        """
        super(ProcessedDataTest, cls).setUpClass()
        # fake a previous raw data download
        download_dir = os.path.join(settings.CALACCESS_DATA_DIR, 'download')
        os.path.exists(download_dir) or os.mkdir(download_dir)
        zip_path = os.path.join(
            settings.CALACCESS_DATA_DIR,
            'dbwebexport.zip',
        )
        shutil.copy(zip_path, download_dir)
        rdv = RawDataVersion.objects.create(
            release_datetime=now(),
            update_start_datetime=now(),
            download_start_datetime=now(),
            download_finish_datetime=now(),
            expected_size=os.stat(zip_path).st_size,
        )
        # mock an SoS HEAD response
        imf_datetime = formatdate(
            time.mktime(rdv.release_datetime.timetuple()),
            usegmt=True,
        )
        headers = {
            'Content-Length': str(rdv.expected_size),
            'Accept-Ranges': 'bytes',
            'Last-Modified': imf_datetime,
            'Connection': 'keep-alive',
            'Date': imf_datetime,
            'Content-Type': 'application/zip',
            'ETag': '2320c8-30619331-c54f7dc0',
            'Server': 'Apache/2.2.3 (Red Hat)',
        }
        m.register_uri(
            'HEAD',
            'http://campaignfinance.cdn.sos.ca.gov/dbwebexport.zip',
            headers=headers,
        )

        call_command("updatecalaccessrawdata", verbosity=3, noinput=True)
        call_command("processcalaccessdata", verbosity=3, noinput=True)

    def test_scraped_propositions(self):
        """
        Test the scraped propostions loaded into the database.
        """
        # Confirm count of scraped propositions with a name that doesn't
        # include "RECALL" equals the count of loaded BallotMeasureContest.
        self.assertEqual(
            ScrapedProposition.objects.exclude(
                name__icontains='RECALL'
            ).count(),
            BallotMeasureContest.objects.count(),
        )
        # Confirm count of scraped propositions with a name that includes "RECALL"
        # equals the count of loaded RetentionContest.
        self.assertEqual(
            ScrapedProposition.objects.filter(
                name__icontains='RECALL'
            ).count(),
            RetentionContest.objects.count(),
        )

    def test_scraped_candidates(self):
        """
        Test the scraped candidates loaded into the database.
        """
        # Confirm that the count of scraped candidates equals the count loaded
        # into Candidacy with a scraped source
        # minus one, since Jim Fitzgerald didn't really run in the
        # Dem primary in 2008
        self.assertEqual(
            ScrapedCandidate.objects.count() - 1,
            Candidacy.objects.filter(
                sources__url__contains='http://cal-access.sos.ca.gov/Campaign/Candidates/list.aspx?view=certified' # noqa
            ).count(),
        )
        # For each CandidateContest...
        for contest in CandidateContest.objects.all():
            # Confirm there isn't more than one incumbent
            self.assertTrue(
                contest.candidacies.filter(is_incumbent=True).count() <= 1,
                msg="Multiple incumbents in {}!".format(contest),
            )

            # Confirm there aren't multiple Candidacies with the same person_id
            person_id_groups_q = contest.candidacies.values(
                'person_id',
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            self.assertTrue(
                person_id_groups_q.count() == 0,
                msg="Multiple candidacies with same person_id in {}!".format(
                    contest
                ),
            )

            # Confirm there aren't multiple Candidacies with the same filer_id
            filer_id_groups_q = contest.candidacies.filter(
                person__identifiers__scheme='calaccess_filer_id'
            ).values(
                'person__identifiers__identifier'
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            self.assertTrue(
                filer_id_groups_q.count() == 0,
                msg="Multiple candidacies with same filer_id in {}!".format(
                    contest
                ),
            )

            # Confirm there aren't multiple Candidacies with the same candidate_name
            # unless party_id is different or person's filer_id is different
            candidate_name_groups_q = contest.candidacies.values(
                'candidate_name',
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            # loop over each group of multiple candidacies sharing the same candidate_name
            for group in candidate_name_groups_q.all():
                candidacies_q = contest.candidacies.filter(
                    candidate_name=group['candidate_name'],
                )

                filer_id_party_groups_q = candidacies_q.filter(
                    person__identifiers__scheme='calaccess_filer_id'
                ).order_by(
                    'person__identifiers__identifier',
                    'party',
                ).values(
                    'person__identifiers__identifier',
                    'party',
                ).distinct()

                # confirm that count of candidacies equals count of
                # distinct filer_id/party groups
                self.assertEqual(
                    candidacies_q.count(),
                    filer_id_party_groups_q.count(),
                    msg='{0} candidacies in {1} with candidate_name "{2}" have {3} '
                        'distinct filer_id/party combos!'.format(
                        candidacies_q.count(),
                        contest,
                        group['candidate_name'],
                        filer_id_party_groups_q.count(),
                    ),
                )

            # Confirm there aren't multiple Candidacies with the same person.name
            # unless party_id is different or person's filer_id is different
            person_name_groups_q = contest.candidacies.values(
                'person__name',
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            # loop over each group of multiple candidacies sharing the same candidate_name
            for group in person_name_groups_q.all():
                candidacies_q = contest.candidacies.filter(
                    person__name=group['person__name'],
                )

                filer_id_party_groups_q = candidacies_q.filter(
                    person__identifiers__scheme='calaccess_filer_id'
                ).order_by(
                    'person__identifiers__identifier',
                    'party',
                ).values(
                    'person__identifiers__identifier',
                    'party',
                ).distinct()

                # confirm that count of candidacies equals count of
                # distinct filer_id/party groups
                self.assertEqual(
                    candidacies_q.count(),
                    filer_id_party_groups_q.count(),
                    msg='{0} candidacies in {1} with person__name "{2}" have {3} '
                        'distinct filer_id/party combos!'.format(
                        candidacies_q.count(),
                        contest,
                        group['person__name'],
                        filer_id_party_groups_q.count(),
                    ),
                )

        # For each Person...
        for person in Person.objects.all():
            # Confirm name is same as most recent candidate_name
            latest_candidate_name = person.candidacies.latest(
                'contest__election__date'
            ).candidate_name

            self.assertEqual(
                person.name,
                latest_candidate_name,
                msg='Person.name "{0}" doesn\'t match latest candidate_name "{1}!'.format(
                    person.name,
                    latest_candidate_name,
                )
            )

    def test_processed_version_completed(self):
        """
        Test that the processed version was completed.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')
        self.assertTrue(processed_version.update_completed)

    def test_processed_version_zip_archived(self):
        """
        Test that the processed version zip was archived.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')
        self.assertTrue(processed_version.zip_archive)

    def test_processed_version_zip_size(self):
        """
        Test that the processed version zip_size is same as zip file's size.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')
        self.assertEqual(
            processed_version.zip_size,
            os.path.getsize(processed_version.zip_archive.path)
        )

    def test_processed_file_finished(self):
        """
        Test that each processed file was marked finished.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            self.assertTrue(df.process_finish_datetime)

    def test_processed_file_archived(self):
        """
        Test that each processed file was archived.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            self.assertTrue(df.file_archive)

    def test_processed_file_size(self):
        """
        Test that each processed file_size is the same as file's size.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            self.assertEqual(
                df.file_size,
                os.path.getsize(df.file_archive.path)
            )

    def test_processed_file_records_count(self):
        """
        Test that each processed records_count is the same as rows in file.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            df.file_archive.open()
            row_count = sum(1 for _ in df.file_archive) - 1
            df.file_archive.close()

            self.assertEqual(
                df.records_count,
                row_count
            )

    def test_base_command(self):
        """
        Test options on base commands.
        """
        c = CalAccessCommand()
        c.handle()
        c.header("")
        c.log("")
        c.success("")
        c.warn("")
        c.failure("")
        c.duration()

    def test_2016_primary_date(self):
        """
        Confirm correct calculation of 2016 primary date.
        """
        self.assertEqual(
            date(2016, 6, 7),
            calaccess_processed.get_expected_election_date(2016, 'PRIMARY'),
        )

    def test_2016_general_date(self):
        """
        Confirm correct calculation of 2016 general date.
        """
        self.assertEqual(
            date(2016, 11, 8),
            calaccess_processed.get_expected_election_date(2016, 'GENERAL'),
        )

    def test_2014_primary_date(self):
        """
        Confirm correct calculation of 2014 primary date.
        """
        self.assertEqual(
            date(2014, 6, 3),
            calaccess_processed.get_expected_election_date(2014, 'PRIMARY'),
        )

    def test_2010_general_date(self):
        """
        Confirm correct calculation of 2010 general date.
        """
        self.assertEqual(
            date(2010, 11, 2),
            calaccess_processed.get_expected_election_date(2010, 'GENERAL'),
        )

    def test_correction(self):
        """
        Test that we can retrieve a correction directly.
        """
        correx = corrections.candidate_party(
            "WINSTON, ALMA MARIE",
            "2014",
            "PRIMARY",
            "GOVERNOR"
        )
        self.assertEqual(correx.name, "REPUBLICAN")

    def test_correction_assignment_by_proxy(self):
        """
        Test that a correction is properly being applied when parties are retrieved.
        """
        obj = ScrapedCandidateProxy.objects.get(name='WINSTON, ALMA MARIE')
        self.assertEqual(obj.get_party().name, 'REPUBLICAN')

    def test_flat_file_row_counts(self):
        """
        Test that count of rows in flat files is same as row count in base model.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        flat_processed_files = [
            df for df in processed_version.files.all() if df.is_flat
        ]

        for df in flat_processed_files:
            # get count from archived file of flat model
            df.file_archive.open()
            flat_row_count = sum(1 for _ in df.file_archive) - 1
            df.file_archive.close()

            # get count from archived file of the base model
            base_model_name = df.model().base_model._meta.object_name
            base_model_df = processed_version.files.get(
                file_name='base_model_name'
            )
            base_model_df.file_archive.open()
            flat_row_count = sum(1 for _ in base_model_df.file_archive) - 1
            base_model_df.file_archive.close()

            self.assertEqual(
                flat_row_count,
                base_row_count,
            )
<commit_msg>fix tests<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Unittests for management commands.
"""
import os
import shutil
import calaccess_processed
from datetime import date
import time
from django.conf import settings
from django.core.management import call_command
from django.core.management.base import CommandError
from django.db.models import Count
from django.test import TestCase, override_settings
from django.utils.timezone import now
from email.utils import formatdate
from calaccess_raw.models import RawDataVersion
from calaccess_processed.management.commands import CalAccessCommand
from calaccess_processed import corrections
from calaccess_processed.models import (
    ProcessedDataVersion,
    ScrapedCandidateProxy,
)
from calaccess_scraped.models import Candidate as ScrapedCandidate
from calaccess_scraped.models import Proposition as ScrapedProposition
from opencivicdata.core.models import Person
from opencivicdata.elections.models import (
    BallotMeasureContest,
    Candidacy,
    CandidateContest,
    RetentionContest,
)
import requests_mock

class NoProcessedDataTest(TestCase):
    """
    Tests to run with no data loaded.
    """
    def test_no_raw_data(self):
        """
        Confirm process command will not run without data.
        """
        with self.assertRaises(CommandError):
            call_command("processcalaccessdata", verbosity=3, noinput=True)

@override_settings(
    CALACCESS_DATA_DIR=os.path.join(settings.BASE_DIR, 'test-data')
)
@override_settings(
    MEDIA_ROOT=os.path.join(settings.BASE_DIR, 'test-data', ".media")
)
@override_settings(CALACCESS_STORE_ARCHIVE=True)
class ProcessedDataTest(TestCase):
    """
    Run and test management commands.
    """
    fixtures = [
        'divisions.json',
        'candidate_election.json',
        'candidate.json',
        'incumbent_election.json',
        'incumbent.json',
        'proposition_election.json',
        'proposition.json',
    ]

    @classmethod
    @requests_mock.Mocker()
    def setUpClass(cls, m):
        """
        Load data for other tests.
        """
        super(ProcessedDataTest, cls).setUpClass()
        # fake a previous raw data download
        download_dir = os.path.join(settings.CALACCESS_DATA_DIR, 'download')
        os.path.exists(download_dir) or os.mkdir(download_dir)
        zip_path = os.path.join(
            settings.CALACCESS_DATA_DIR,
            'dbwebexport.zip',
        )
        shutil.copy(zip_path, download_dir)
        rdv = RawDataVersion.objects.create(
            release_datetime=now(),
            update_start_datetime=now(),
            download_start_datetime=now(),
            download_finish_datetime=now(),
            expected_size=os.stat(zip_path).st_size,
        )
        # mock an SoS HEAD response
        imf_datetime = formatdate(
            time.mktime(rdv.release_datetime.timetuple()),
            usegmt=True,
        )
        headers = {
            'Content-Length': str(rdv.expected_size),
            'Accept-Ranges': 'bytes',
            'Last-Modified': imf_datetime,
            'Connection': 'keep-alive',
            'Date': imf_datetime,
            'Content-Type': 'application/zip',
            'ETag': '2320c8-30619331-c54f7dc0',
            'Server': 'Apache/2.2.3 (Red Hat)',
        }
        m.register_uri(
            'HEAD',
            'http://campaignfinance.cdn.sos.ca.gov/dbwebexport.zip',
            headers=headers,
        )

        call_command("updatecalaccessrawdata", verbosity=3, noinput=True)
        call_command("processcalaccessdata", verbosity=3, noinput=True)

    def test_scraped_propositions(self):
        """
        Test the scraped propostions loaded into the database.
        """
        # Confirm count of scraped propositions with a name that doesn't
        # include "RECALL" equals the count of loaded BallotMeasureContest.
        self.assertEqual(
            ScrapedProposition.objects.exclude(
                name__icontains='RECALL'
            ).count(),
            BallotMeasureContest.objects.count(),
        )
        # Confirm count of scraped propositions with a name that includes "RECALL"
        # equals the count of loaded RetentionContest.
        self.assertEqual(
            ScrapedProposition.objects.filter(
                name__icontains='RECALL'
            ).count(),
            RetentionContest.objects.count(),
        )

    def test_scraped_candidates(self):
        """
        Test the scraped candidates loaded into the database.
        """
        # Confirm that the count of scraped candidates equals the count loaded
        # into Candidacy with a scraped source
        # minus one, since Jim Fitzgerald didn't really run in the
        # Dem primary in 2008
        self.assertEqual(
            ScrapedCandidate.objects.count() - 1,
            Candidacy.objects.filter(
                sources__url__contains='http://cal-access.sos.ca.gov/Campaign/Candidates/list.aspx?view=certified' # noqa
            ).count(),
        )
        # For each CandidateContest...
        for contest in CandidateContest.objects.all():
            # Confirm there isn't more than one incumbent
            self.assertTrue(
                contest.candidacies.filter(is_incumbent=True).count() <= 1,
                msg="Multiple incumbents in {}!".format(contest),
            )

            # Confirm there aren't multiple Candidacies with the same person_id
            person_id_groups_q = contest.candidacies.values(
                'person_id',
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            self.assertTrue(
                person_id_groups_q.count() == 0,
                msg="Multiple candidacies with same person_id in {}!".format(
                    contest
                ),
            )

            # Confirm there aren't multiple Candidacies with the same filer_id
            filer_id_groups_q = contest.candidacies.filter(
                person__identifiers__scheme='calaccess_filer_id'
            ).values(
                'person__identifiers__identifier'
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            self.assertTrue(
                filer_id_groups_q.count() == 0,
                msg="Multiple candidacies with same filer_id in {}!".format(
                    contest
                ),
            )

            # Confirm there aren't multiple Candidacies with the same candidate_name
            # unless party_id is different or person's filer_id is different
            candidate_name_groups_q = contest.candidacies.values(
                'candidate_name',
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            # loop over each group of multiple candidacies sharing the same candidate_name
            for group in candidate_name_groups_q.all():
                candidacies_q = contest.candidacies.filter(
                    candidate_name=group['candidate_name'],
                )

                filer_id_party_groups_q = candidacies_q.filter(
                    person__identifiers__scheme='calaccess_filer_id'
                ).order_by(
                    'person__identifiers__identifier',
                    'party',
                ).values(
                    'person__identifiers__identifier',
                    'party',
                ).distinct()

                # confirm that count of candidacies equals count of
                # distinct filer_id/party groups
                self.assertEqual(
                    candidacies_q.count(),
                    filer_id_party_groups_q.count(),
                    msg='{0} candidacies in {1} with candidate_name "{2}" have {3} '
                        'distinct filer_id/party combos!'.format(
                        candidacies_q.count(),
                        contest,
                        group['candidate_name'],
                        filer_id_party_groups_q.count(),
                    ),
                )

            # Confirm there aren't multiple Candidacies with the same person.name
            # unless party_id is different or person's filer_id is different
            person_name_groups_q = contest.candidacies.values(
                'person__name',
            ).annotate(
                row_count=Count('id'),
            ).order_by().filter(row_count__gt=1)

            # loop over each group of multiple candidacies sharing the same candidate_name
            for group in person_name_groups_q.all():
                candidacies_q = contest.candidacies.filter(
                    person__name=group['person__name'],
                )

                filer_id_party_groups_q = candidacies_q.filter(
                    person__identifiers__scheme='calaccess_filer_id'
                ).order_by(
                    'person__identifiers__identifier',
                    'party',
                ).values(
                    'person__identifiers__identifier',
                    'party',
                ).distinct()

                # confirm that count of candidacies equals count of
                # distinct filer_id/party groups
                self.assertEqual(
                    candidacies_q.count(),
                    filer_id_party_groups_q.count(),
                    msg='{0} candidacies in {1} with person__name "{2}" have {3} '
                        'distinct filer_id/party combos!'.format(
                        candidacies_q.count(),
                        contest,
                        group['person__name'],
                        filer_id_party_groups_q.count(),
                    ),
                )

        # For each Person...
        for person in Person.objects.all():
            # Confirm name is same as most recent candidate_name
            latest_candidate_name = person.candidacies.latest(
                'contest__election__date'
            ).candidate_name

            self.assertEqual(
                person.name,
                latest_candidate_name,
                msg='Person.name "{0}" doesn\'t match latest candidate_name "{1}!'.format(
                    person.name,
                    latest_candidate_name,
                )
            )

    def test_processed_version_completed(self):
        """
        Test that the processed version was completed.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')
        self.assertTrue(processed_version.update_completed)

    def test_processed_version_zip_archived(self):
        """
        Test that the processed version zip was archived.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')
        self.assertTrue(processed_version.zip_archive)

    def test_processed_version_zip_size(self):
        """
        Test that the processed version zip_size is same as zip file's size.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')
        self.assertEqual(
            processed_version.zip_size,
            os.path.getsize(processed_version.zip_archive.path)
        )

    def test_processed_file_finished(self):
        """
        Test that each processed file was marked finished.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            self.assertTrue(df.process_finish_datetime)

    def test_processed_file_archived(self):
        """
        Test that each processed file was archived.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            self.assertTrue(df.file_archive)

    def test_processed_file_size(self):
        """
        Test that each processed file_size is the same as file's size.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            self.assertEqual(
                df.file_size,
                os.path.getsize(df.file_archive.path)
            )

    def test_processed_file_records_count(self):
        """
        Test that each processed records_count is the same as rows in file.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        for df in processed_version.files.all():
            df.file_archive.open()
            row_count = sum(1 for _ in df.file_archive) - 1
            df.file_archive.close()

            self.assertEqual(
                df.records_count,
                row_count
            )

    def test_base_command(self):
        """
        Test options on base commands.
        """
        c = CalAccessCommand()
        c.handle()
        c.header("")
        c.log("")
        c.success("")
        c.warn("")
        c.failure("")
        c.duration()

    def test_2016_primary_date(self):
        """
        Confirm correct calculation of 2016 primary date.
        """
        self.assertEqual(
            date(2016, 6, 7),
            calaccess_processed.get_expected_election_date(2016, 'PRIMARY'),
        )

    def test_2016_general_date(self):
        """
        Confirm correct calculation of 2016 general date.
        """
        self.assertEqual(
            date(2016, 11, 8),
            calaccess_processed.get_expected_election_date(2016, 'GENERAL'),
        )

    def test_2014_primary_date(self):
        """
        Confirm correct calculation of 2014 primary date.
        """
        self.assertEqual(
            date(2014, 6, 3),
            calaccess_processed.get_expected_election_date(2014, 'PRIMARY'),
        )

    def test_2010_general_date(self):
        """
        Confirm correct calculation of 2010 general date.
        """
        self.assertEqual(
            date(2010, 11, 2),
            calaccess_processed.get_expected_election_date(2010, 'GENERAL'),
        )

    def test_correction(self):
        """
        Test that we can retrieve a correction directly.
        """
        correx = corrections.candidate_party(
            "WINSTON, ALMA MARIE",
            "2014",
            "PRIMARY",
            "GOVERNOR"
        )
        self.assertEqual(correx.name, "REPUBLICAN")

    def test_correction_assignment_by_proxy(self):
        """
        Test that a correction is properly being applied when parties are retrieved.
        """
        obj = ScrapedCandidateProxy.objects.get(name='WINSTON, ALMA MARIE')
        self.assertEqual(obj.get_party().name, 'REPUBLICAN')

    def test_flat_file_row_counts(self):
        """
        Test that count of rows in flat files is same as row count in base model.
        """
        processed_version = ProcessedDataVersion.objects.latest('process_start_datetime')

        flat_processed_files = [
            df for df in processed_version.files.all() if df.is_flat
        ]

        for df in flat_processed_files:
            # get count from archived file of flat model
            df.file_archive.open()
            flat_row_count = sum(1 for _ in df.file_archive) - 1
            df.file_archive.close()

            # get count from archived file of the base model
            base_model_name = df.model().base_model._meta.object_name
            base_model_df = processed_version.files.get(
                file_name=base_model_name
            )
            base_model_df.file_archive.open()
            base_row_count = sum(1 for _ in base_model_df.file_archive) - 1
            base_model_df.file_archive.close()

            self.assertEqual(
                flat_row_count,
                base_row_count,
            )
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- encoding: utf-8 -*-
#
#    Module Writen to OpenERP, Open Source Management Solution
#
#    Copyright (c) 2014 Vauxoo - http://www.vauxoo.com/
#    All Rights Reserved.
#    info Vauxoo (info@vauxoo.com)
#
#    Coded by: vauxoo consultores (info@vauxoo.com)
#
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
"""
This module is used to create new fields in the inherited classes.
"""
from openerp.osv import fields, osv
import logging
import os
import stat

_logger = logging.getLogger(__name__)

def get_depends(modules, addons_paths, depends=None):
    if depends is None:
        depends = []
    for module in modules.split(','):
        if not module in depends:
            depends.append( module )
            for addons_path in addons_paths.split(','):
                addons_path = addons_path.strip()
                fname_openerp = os.path.join( addons_path, module, '__openerp__.py' )
                if os.path.isfile( fname_openerp ):
                    module_depends_list = eval( open(fname_openerp, "r").read() ).get('depends', [])
                    if module_depends_list:
                        module_depends_str = ','.join( module_depends_list )
                        get_depends(module_depends_str, addons_paths, depends=depends)
    return depends

class RunbotRepo(osv.osv):
    """
    Added pylint_config field to use a configuration of pylint by repository,
    to use for each build of repository.
    """

    _inherit = 'runbot.repo'

    _columns = {
        'pylint_config': fields.many2one('pylint.conf',
                                         string='Pylint Config'),
        'check_pylint': fields.boolean(string='Check pylint'),
    }

class RunbotBranch(osv.osv):
    """
    Added pylint_config field to use a configuration of pylint by repository,
    to use for each build of repository.
    """

    _inherit = 'runbot.branch'

    def get_module_list(self, cr, uid, ids, sha=None, context=None):
        repo_paths_list = []
        for branch in self.browse(cr, uid, ids, context=context):
            command_git = ['ls-tree', sha or branch.branch_name, '--name-only']
            if branch.repo_id.type == 'main':
                command_git.append('addons/')
            repo_paths_str = branch.repo_id.git(command_git)
            repo_paths_list = repo_paths_str and repo_paths_str.rstrip().replace('addons/', '').split('\n') or []
        return repo_paths_list

class RunbotBuild(osv.osv):
    """
    Added pylint_config field, used by default the configuration of repository.
    """

    _inherit = "runbot.build"

    _columns = {
        'pylint_config': fields.many2one('pylint.conf',
                                         string='Pylint Config'),
    }

    def create(self, cr, uid, values, context=None):
        """
        This method set configuration of pylint.
        """
        new_id = super(RunbotBuild, self).create(cr, uid, values,
                                                             context=context)
        if values.get('branch_id', False) and not values\
                                                    .has_key('pylint_config'):
            branch_id = self.pool.get('runbot.branch').browse(cr, uid,
                                                         values['branch_id'])
            self.write(
                cr, uid, [new_id],
                 {'pylint_config': branch_id.repo_id and \
                 branch_id.repo_id.pylint_config and \
                 branch_id.repo_id.pylint_config.id or False}, context=context)
        return new_id

    """
    def get_module_depends(self, cr, uid, build_id, modules, context=None):
        import pdb;pdb.set_trace()
        dict_tmp = {}
        list_dependences = []
        build = self.browse(cr, uid, [build_id], context=context)[0]
        base_path = build.server('addons')

        for module in modules.split(',')
            module = module.strip()
            list_dependences.append( module )

        mod_openerp = os.path.join(base_path, module, '__openerp__.py')
        if os.path.isfile(mod_openerp):
            list_depends = eval( open(mod_openerp, "r").read() ).get('depends', False)
            for depend in list_depends:
                if not os.path.join(base_path, depend) in list_dependences:
                    list_dependences.append(os.path.join(base_path, depend))
                list_dependences.extend([element for element in self.get_module_depends(cr, uid, build_id, depend) if element not in list_dependences])
        return list_dependences
    """

    def get_repo_build_paths(self, cr, uid, build_id, repo_id, filter_files=None, \
            filter_dirs=None, isdir=True, check_module_depends=True, context=None):
        if filter is None:
            filter = []
        repo_pool = self.pool['runbot.repo']
        repo = repo_pool.browse(cr, uid, [repo_id], context=context)[0]
        build = self.browse(cr, uid, [build_id], context=context)[0]
        #TODO: Add version or sha and replace by master
        version_build = build.branch_id and build.branch_id.branch_base_name or build.branch_id.branch_name
        #import pdb;pdb.set_trace()
        command_git = ['ls-tree', version_build, '--name-only']
        if repo.type == 'main':
            command_git.append('addons/')
        repo_paths_str = repo.git(command_git)
        repo_paths_list = repo_paths_str and repo_paths_str.rstrip().replace('addons/', '').split('\n') or []
        paths = []
        if repo_paths_list:
            #if repo.type == 'main':
            base_path = build.server('addons')
            if base_path:
                for repo_path in repo_paths_list:
                    repo_full_path = os.path.join(base_path, repo_path)
                    if os.path.isdir(repo_full_path) and isdir:
                        paths.append( repo_full_path )
                    elif os.path.isfile(repo_full_path) and \
                           (os.path.splitext(repo_full_path)[1] in filter_files or not filter_files):
                        paths.append( repo_full_path )
        return paths

    def job_01_pylint(self, cr, uid, build, lock_path, log_path, args=None):
        #TODO: Comment this function. Uncomment only to test pylint script fast.
        build._log('pylint_script', 'Start pylint script before all test')
        build.checkout()
        return self.job_15_pylint(cr, uid, build, lock_path, log_path, args=args)

    def job_15_pylint(self, cr, uid, build, lock_path, log_path, args=None):
        """
        This method is used to run pylint test, getting parameters of the
        pylint configuration, the parameters errors and files to ignore has
        send in list structures to method _run_test_pylint.

        :param build: object build of runbot.
        :param lock_path: path of lock file, this parameter is string.
        :param log_path: path of log file, this parameter is string, where are
                            has saved the log of test.
        :param args: this parameter not is required, not is used.
        """
        if args == None:
            args = {}
        build._log('pylint_script', 'Start pylint script')
        params_extra = []
        errors = []
        paths_to_test = []
        ignore = []
        result = False
        dep = []
        repo_paths = []
        repo_depen = []
        if build.pylint_config:
            if build.pylint_config.conf_file:
                path_pylint_conf = os.path\
                    .join(os.path.split(build.server())[0], \
                    build.pylint_config.conf_file)

                dep = get_depends(build.modules, build.server('addons'))

                repo_module_to_check_pylint = []
                for build_line in build.line_ids:
                    if build_line.repo_id.check_pylint:
                        branch_ls = build_line.branch_id.get_module_list( build_line.sha )
                        repo_module_to_check_pylint.extend( branch_ls )
                modules_to_check_pylint = list( set(dep) & set(repo_module_to_check_pylint) )
                fname_pylint_run_sh = os.path.join( build.server(), 'pylint_run.sh')
                with open( fname_pylint_run_sh, "w" ) as f_pylint_run_sh:
                    f_pylint_run_sh.write("#!/bin/bash\n")
                    for module_to_check_pylint in modules_to_check_pylint:
                        cmd = "pylint --rcfile=%s %s"%( path_pylint_conf, \
                            os.path.join(build.server('addons'), module_to_check_pylint ))
                        f_pylint_run_sh.write( cmd + '\n' )
                st = os.stat(fname_pylint_run_sh)
                os.chmod(fname_pylint_run_sh, st.st_mode | stat.S_IEXEC)

                os.environ['PYTHONPATH'] += ":" + build.server()
                spawn_return = build.spawn([fname_pylint_run_sh], lock_path, log_path, cpu_limit=2100,
                                        env=os.environ)
                return spawn_return
            """
            #TODO: check print and pdb sentence
            if build.pylint_config and build.pylint_config.check_print or \
                 build.pylint_config and build.pylint_config.check_pdb:
                self.pool.get("pylint.conf")._search_print_pdb(cr,
                                                     uid, build, repo_depen)
            """
        return result
<commit_msg>Update runbot.py<commit_after>#!/usr/bin/python
# -*- encoding: utf-8 -*-
#
#    Module Writen to OpenERP, Open Source Management Solution
#
#    Copyright (c) 2014 Vauxoo - http://www.vauxoo.com/
#    All Rights Reserved.
#    info Vauxoo (info@vauxoo.com)
#
#    Coded by: vauxoo consultores (info@vauxoo.com)
#
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
"""
This module is used to create new fields in the inherited classes.
"""
from openerp.osv import fields, osv
import logging
import os
import stat

_logger = logging.getLogger(__name__)

def get_depends(modules, addons_paths, depends=None):
    if depends is None:
        depends = []
    for module in modules.split(','):
        if not module in depends:
            depends.append( module )
            for addons_path in addons_paths.split(','):
                addons_path = addons_path.strip()
                fname_openerp = os.path.join( addons_path, module, '__openerp__.py' )
                if os.path.isfile( fname_openerp ):
                    module_depends_list = eval( open(fname_openerp, "r").read() ).get('depends', [])
                    if module_depends_list:
                        module_depends_str = ','.join( module_depends_list )
                        get_depends(module_depends_str, addons_paths, depends=depends)
    return depends

class RunbotRepo(osv.osv):
    """
    Added pylint_config field to use a configuration of pylint by repository,
    to use for each build of repository.
    """

    _inherit = 'runbot.repo'

    _columns = {
        'pylint_config': fields.many2one('pylint.conf',
                                         string='Pylint Config'),
        'check_pylint': fields.boolean(string='Check pylint'),
    }

class RunbotBranch(osv.osv):
    """
    Added pylint_config field to use a configuration of pylint by repository,
    to use for each build of repository.
    """

    _inherit = 'runbot.branch'

    def get_module_list(self, cr, uid, ids, sha=None, context=None):
        repo_paths_list = []
        for branch in self.browse(cr, uid, ids, context=context):
            command_git = ['ls-tree', sha or branch.branch_name, '--name-only']
            if branch.repo_id.type == 'main':
                command_git.append('addons/')
            repo_paths_str = branch.repo_id.git(command_git)
            repo_paths_list = repo_paths_str and repo_paths_str.rstrip().replace('addons/', '').split('\n') or []
        return repo_paths_list

class RunbotBuild(osv.osv):
    """
    Added pylint_config field, used by default the configuration of repository.
    """

    _inherit = "runbot.build"

    _columns = {
        'pylint_config': fields.many2one('pylint.conf',
                                         string='Pylint Config'),
    }

    def create(self, cr, uid, values, context=None):
        """
        This method set configuration of pylint.
        """
        new_id = super(RunbotBuild, self).create(cr, uid, values,
                                                             context=context)
        if values.get('branch_id', False) and not values\
                                                    .has_key('pylint_config'):
            branch_id = self.pool.get('runbot.branch').browse(cr, uid,
                                                         values['branch_id'])
            self.write(
                cr, uid, [new_id],
                 {'pylint_config': branch_id.repo_id and \
                 branch_id.repo_id.pylint_config and \
                 branch_id.repo_id.pylint_config.id or False}, context=context)
        return new_id

    """
    def get_module_depends(self, cr, uid, build_id, modules, context=None):
        import pdb;pdb.set_trace()
        dict_tmp = {}
        list_dependences = []
        build = self.browse(cr, uid, [build_id], context=context)[0]
        base_path = build.server('addons')

        for module in modules.split(',')
            module = module.strip()
            list_dependences.append( module )

        mod_openerp = os.path.join(base_path, module, '__openerp__.py')
        if os.path.isfile(mod_openerp):
            list_depends = eval( open(mod_openerp, "r").read() ).get('depends', False)
            for depend in list_depends:
                if not os.path.join(base_path, depend) in list_dependences:
                    list_dependences.append(os.path.join(base_path, depend))
                list_dependences.extend([element for element in self.get_module_depends(cr, uid, build_id, depend) if element not in list_dependences])
        return list_dependences
    """

    def get_repo_build_paths(self, cr, uid, build_id, repo_id, filter_files=None, \
            filter_dirs=None, isdir=True, check_module_depends=True, context=None):
        if filter is None:
            filter = []
        repo_pool = self.pool['runbot.repo']
        repo = repo_pool.browse(cr, uid, [repo_id], context=context)[0]
        build = self.browse(cr, uid, [build_id], context=context)[0]
        #TODO: Add version or sha and replace by master
        version_build = build.branch_id and build.branch_id.branch_base_name or build.branch_id.branch_name
        #import pdb;pdb.set_trace()
        command_git = ['ls-tree', version_build, '--name-only']
        if repo.type == 'main':
            command_git.append('addons/')
        repo_paths_str = repo.git(command_git)
        repo_paths_list = repo_paths_str and repo_paths_str.rstrip().replace('addons/', '').split('\n') or []
        paths = []
        if repo_paths_list:
            #if repo.type == 'main':
            base_path = build.server('addons')
            if base_path:
                for repo_path in repo_paths_list:
                    repo_full_path = os.path.join(base_path, repo_path)
                    if os.path.isdir(repo_full_path) and isdir:
                        paths.append( repo_full_path )
                    elif os.path.isfile(repo_full_path) and \
                           (os.path.splitext(repo_full_path)[1] in filter_files or not filter_files):
                        paths.append( repo_full_path )
        return paths
    """
    def job_01_pylint(self, cr, uid, build, lock_path, log_path, args=None):
        #TODO: Comment this function. Uncomment only to test pylint script fast.
        build._log('pylint_script', 'Start pylint script before all test')
        build.checkout()
        return self.job_15_pylint(cr, uid, build, lock_path, log_path, args=args)
    """
    def job_15_pylint(self, cr, uid, build, lock_path, log_path, args=None):
        """
        This method is used to run pylint test, getting parameters of the
        pylint configuration, the parameters errors and files to ignore has
        send in list structures to method _run_test_pylint.

        :param build: object build of runbot.
        :param lock_path: path of lock file, this parameter is string.
        :param log_path: path of log file, this parameter is string, where are
                            has saved the log of test.
        :param args: this parameter not is required, not is used.
        """
        if args == None:
            args = {}
        build._log('pylint_script', 'Start pylint script')
        params_extra = []
        errors = []
        paths_to_test = []
        ignore = []
        result = False
        dep = []
        repo_paths = []
        repo_depen = []
        if build.pylint_config:
            if build.pylint_config.conf_file:
                path_pylint_conf = os.path\
                    .join(os.path.split(build.server())[0], \
                    build.pylint_config.conf_file)

                dep = get_depends(build.modules, build.server('addons'))

                repo_module_to_check_pylint = []
                for build_line in build.line_ids:
                    if build_line.repo_id.check_pylint:
                        branch_ls = build_line.branch_id.get_module_list( build_line.sha )
                        repo_module_to_check_pylint.extend( branch_ls )
                modules_to_check_pylint = list( set(dep) & set(repo_module_to_check_pylint) )
                fname_pylint_run_sh = os.path.join( build.server(), 'pylint_run.sh')
                with open( fname_pylint_run_sh, "w" ) as f_pylint_run_sh:
                    f_pylint_run_sh.write("#!/bin/bash\n")
                    for module_to_check_pylint in modules_to_check_pylint:
                        cmd = "pylint --rcfile=%s %s"%( path_pylint_conf, \
                            os.path.join(build.server('addons'), module_to_check_pylint ))
                        f_pylint_run_sh.write( cmd + '\n' )
                st = os.stat(fname_pylint_run_sh)
                os.chmod(fname_pylint_run_sh, st.st_mode | stat.S_IEXEC)

                os.environ['PYTHONPATH'] += ":" + build.server()
                spawn_return = build.spawn([fname_pylint_run_sh], lock_path, log_path, cpu_limit=2100,
                                        env=os.environ)
                return spawn_return
            """
            #TODO: check print and pdb sentence
            if build.pylint_config and build.pylint_config.check_print or \
                 build.pylint_config and build.pylint_config.check_pdb:
                self.pool.get("pylint.conf")._search_print_pdb(cr,
                                                     uid, build, repo_depen)
            """
        return result
<|endoftext|>


<commit_before>import pytest
from bambi.priors import Prior, Family, PriorFactory
from os.path import dirname, join
import json

def test_prior_class():
    prior = Prior('CheeseWhiz', holes=0, taste=-10)
    assert prior.name == 'CheeseWhiz'
    assert isinstance(prior.args, dict)
    assert prior.args['taste'] == -10
    prior.update(taste=-100, return_to_store=1)
    assert prior.args['return_to_store'] == 1

def test_family_class():
    prior = Prior('CheeseWhiz', holes=0, taste=-10)
    family = Family('cheese', prior, link='ferment', parent='holes')
    for name in ['name', 'prior', 'link', 'parent']:
        assert hasattr(family, name)

def test_prior_factory_init_from_default_config():
    pf = PriorFactory()
    for d in ['dists', 'terms', 'families']:
        assert hasattr(pf, d)
        assert isinstance(getattr(pf, d), dict)
    assert 'normal' in pf.dists
    assert 'fixed' in pf.terms
    assert 'gaussian' in pf.families

def test_prior_factory_init_from_config():
    config_file = join(dirname(__file__), 'data', 'sample_priors.json')
    pf = PriorFactory(config_file)
    for d in ['dists', 'terms', 'families']:
        assert hasattr(pf, d)
        assert isinstance(getattr(pf, d), dict)
    config_dict = json.load(open(config_file, 'r'))
    pf = PriorFactory(config_dict)
    for d in ['dists', 'terms', 'families']:
        assert hasattr(pf, d)
        assert isinstance(getattr(pf, d), dict)
    assert 'feta' in pf.dists
    assert 'hard' in pf.families
    assert 'yellow' in pf.terms

def test_prior_retrieval():
    config_file = join(dirname(__file__), 'data', 'sample_priors.json')
    pf = PriorFactory(config_file)
    prior = pf.get(dist='asiago')
    assert prior.name == 'Asiago'
    assert isinstance(prior, Prior)
    assert prior.args['hardness'] == 10
    with pytest.raises(KeyError):
        assert prior.args['holes'] == 4
    family = pf.get(family='hard')
    assert isinstance(family, Family)
    assert family.link == 'grate'
    backup = family.prior.args['backup']
    assert isinstance(backup, Prior)
    assert backup.args['flavor'] == 10000
    prior = pf.get(term='yellow')
    assert prior.name == 'Swiss'
<commit_msg>improved test coverage of priors.py<commit_after>import pytest
from bambi.priors import Prior, Family, PriorFactory
from os.path import dirname, join
import json

def test_prior_class():
    prior = Prior('CheeseWhiz', holes=0, taste=-10)
    assert prior.name == 'CheeseWhiz'
    assert isinstance(prior.args, dict)
    assert prior.args['taste'] == -10
    prior.update(taste=-100, return_to_store=1)
    assert prior.args['return_to_store'] == 1

def test_family_class():
    prior = Prior('CheeseWhiz', holes=0, taste=-10)
    family = Family('cheese', prior, link='ferment', parent='holes')
    for name in ['name', 'prior', 'link', 'parent']:
        assert hasattr(family, name)

def test_prior_factory_init_from_default_config():
    pf = PriorFactory()
    for d in ['dists', 'terms', 'families']:
        assert hasattr(pf, d)
        assert isinstance(getattr(pf, d), dict)
    assert 'normal' in pf.dists
    assert 'fixed' in pf.terms
    assert 'gaussian' in pf.families

def test_prior_factory_init_from_config():
    config_file = join(dirname(__file__), 'data', 'sample_priors.json')
    pf = PriorFactory(config_file)
    for d in ['dists', 'terms', 'families']:
        assert hasattr(pf, d)
        assert isinstance(getattr(pf, d), dict)
    config_dict = json.load(open(config_file, 'r'))
    pf = PriorFactory(config_dict)
    for d in ['dists', 'terms', 'families']:
        assert hasattr(pf, d)
        assert isinstance(getattr(pf, d), dict)
    assert 'feta' in pf.dists
    assert 'hard' in pf.families
    assert 'yellow' in pf.terms
    pf = PriorFactory(dists=config_dict['dists'])
    assert 'feta' in pf.dists
    pf = PriorFactory(terms=config_dict['terms'])
    assert 'yellow' in pf.terms
    pf = PriorFactory(families=config_dict['families'])
    assert 'hard' in pf.families

def test_prior_retrieval():
    config_file = join(dirname(__file__), 'data', 'sample_priors.json')
    pf = PriorFactory(config_file)
    prior = pf.get(dist='asiago')
    assert prior.name == 'Asiago'
    assert isinstance(prior, Prior)
    assert prior.args['hardness'] == 10
    with pytest.raises(KeyError):
        assert prior.args['holes'] == 4
    family = pf.get(family='hard')
    assert isinstance(family, Family)
    assert family.link == 'grate'
    backup = family.prior.args['backup']
    assert isinstance(backup, Prior)
    assert backup.args['flavor'] == 10000
    prior = pf.get(term='yellow')
    assert prior.name == 'Swiss'

    # Test exception raising
    with pytest.raises(ValueError):
        pf.get(dist='apple')
    with pytest.raises(ValueError):
        pf.get(term='banana')
    with pytest.raises(ValueError):
        pf.get(family='cantaloupe')
<|endoftext|>


<commit_before>from unittest import skip

from django.core import mail
from django.core.management import call_command
from django.core.urlresolvers import reverse
from django.test.utils import override_settings

from wizard_builder.forms import PageForm

from .. import test_base
from ...delivery import forms, models

class NewReportFlowTest(test_base.ReportFlowHelper):

    def test_report_creation_renders_create_form(self):
        response = self.client.get(reverse('report_new'))
        form = response.context['form']
        self.assertIsInstance(form, forms.ReportCreateForm)

    def test_report_creation_redirects_to_wizard_view(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        self.assertEqual(
            response.redirect_chain[0][0],
            reverse('report_update', kwargs={'step': 0, 'uuid': uuid}),
        )

    def test_report_creation_renders_wizard_form(self):
        response = self.client_post_report_creation()
        form = response.context['form']
        self.assertIsInstance(form, PageForm)

    def test_report_creation_adds_key_to_session(self):
        self.assertEqual(
            self.client.session.get('secret_key'),
            None,
        )
        self.client_post_report_creation()
        self.assertEqual(
            self.client.session.get('secret_key'),
            self.secret_key,
        )

    def test_access_form_rendered_when_no_key_in_session(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        page_1_path = reverse(
            'report_update', kwargs={
                'step': 0, 'uuid': uuid})
        self.client_clear_secret_key()

        response = self.client.get(page_1_path)
        form = response.context['form']

        self.assertIsInstance(form, forms.ReportAccessForm)

    def test_can_reenter_secret_key(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        page_1_path = reverse(
            'report_update', kwargs={
                'step': 0, 'uuid': uuid})
        self.client_clear_secret_key()

        response = self.client_post_report_access(page_1_path)
        self.assertRedirects(response, page_1_path)

    def test_access_form_returns_correct_report(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        self.client_clear_secret_key()

        response = self.client_post_report_access(
            response.redirect_chain[0][0])

        self.assertEqual(response.context['report'].uuid, uuid)

    def test_report_not_accessible_with_incorrect_key(self):
        response = self.client_post_report_creation()
        self.client_clear_secret_key()

        self.secret_key = 'wrong key'
        response = self.client_post_report_access(
            response.redirect_chain[0][0])
        form = response.context['form']

        self.assertFalse(getattr(form, 'decrypted_report', False))
        self.assertIsInstance(form, forms.ReportAccessForm)

class ReportMetaFlowTest(test_base.ReportFlowHelper):

    def test_report_action_no_key(self):
        self.client_post_report_creation()
        self.assertTrue(self.report.pk)
        self.client_clear_secret_key()
        self.client_post_report_delete()
        self.assertTrue(self.assert_report_exists())

    def test_report_action_invalid_key(self):
        self.client_post_report_creation()
        self.assertTrue(self.report.pk)
        self.client_clear_secret_key()
        self.secret_key = 'wrong key'
        self.client_post_report_delete()
        self.assertTrue(self.assert_report_exists())

    def test_report_delete(self):
        self.client_post_report_creation()
        self.assertTrue(self.report.pk)
        response = self.client_post_report_delete()
        self.assertEqual(response.status_code, 200)
        self.assertFalse(self.assert_report_exists())

    def test_export_returns_pdf(self):
        self.client_post_report_creation()
        response = self.client_get_report_view_pdf()
        self.assertEqual(response.status_code, 200)
        self.assertEquals(
            response.get('Content-Disposition'),
            'inline; filename="report.pdf"',
        )

    @skip('temporariy disabled')
    def test_match_report_entry(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.assertTrue(
            models.MatchReport.objects.filter(report=self.report).count(),
        )

    @skip('temporariy disabled')
    def test_match_report_withdrawl(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.client_get_matching_withdraw()
        self.assertFalse(
            models.MatchReport.objects.filter(report=self.report).count(),
        )

    @skip('temporariy disabled')
    @override_settings(
        CALLISTO_NOTIFICATION_API='tests.callistocore.forms.SiteAwareNotificationApi')
    def test_match_sends_report_immediately(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.match_report_email_assertions()

    @skip('temporariy disabled')
    @override_settings(MATCH_IMMEDIATELY=False)
    @override_settings(
        CALLISTO_NOTIFICATION_API='tests.callistocore.forms.SiteAwareNotificationApi')
    def test_match_sends_report_delayed(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.assertEqual(len(mail.outbox), 0)
        call_command('find_matches')
        self.match_report_email_assertions()
<commit_msg>action views require a key now<commit_after>from unittest import skip

from django.core import mail
from django.core.management import call_command
from django.core.urlresolvers import reverse
from django.test.utils import override_settings

from wizard_builder.forms import PageForm

from .. import test_base
from ...delivery import forms, models

class NewReportFlowTest(test_base.ReportFlowHelper):

    def test_report_creation_renders_create_form(self):
        response = self.client.get(reverse('report_new'))
        form = response.context['form']
        self.assertIsInstance(form, forms.ReportCreateForm)

    def test_report_creation_redirects_to_wizard_view(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        self.assertEqual(
            response.redirect_chain[0][0],
            reverse('report_update', kwargs={'step': 0, 'uuid': uuid}),
        )

    def test_report_creation_renders_wizard_form(self):
        response = self.client_post_report_creation()
        form = response.context['form']
        self.assertIsInstance(form, PageForm)

    def test_report_creation_adds_key_to_session(self):
        self.assertEqual(
            self.client.session.get('secret_key'),
            None,
        )
        self.client_post_report_creation()
        self.assertEqual(
            self.client.session.get('secret_key'),
            self.secret_key,
        )

    def test_access_form_rendered_when_no_key_in_session(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        page_1_path = reverse(
            'report_update', kwargs={
                'step': 0, 'uuid': uuid})
        self.client_clear_secret_key()

        response = self.client.get(page_1_path)
        form = response.context['form']

        self.assertIsInstance(form, forms.ReportAccessForm)

    def test_can_reenter_secret_key(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        page_1_path = reverse(
            'report_update', kwargs={
                'step': 0, 'uuid': uuid})
        self.client_clear_secret_key()

        response = self.client_post_report_access(page_1_path)
        self.assertRedirects(response, page_1_path)

    def test_access_form_returns_correct_report(self):
        response = self.client_post_report_creation()
        uuid = response.context['report'].uuid
        self.client_clear_secret_key()

        response = self.client_post_report_access(
            response.redirect_chain[0][0])

        self.assertEqual(response.context['report'].uuid, uuid)

    def test_report_not_accessible_with_incorrect_key(self):
        response = self.client_post_report_creation()
        self.client_clear_secret_key()

        self.secret_key = 'wrong key'
        response = self.client_post_report_access(
            response.redirect_chain[0][0])
        form = response.context['form']

        self.assertFalse(getattr(form, 'decrypted_report', False))
        self.assertIsInstance(form, forms.ReportAccessForm)

class ReportMetaFlowTest(test_base.ReportFlowHelper):

    def test_report_action_invalid_key(self):
        self.client_post_report_creation()
        self.assertTrue(self.report.pk)
        self.client_clear_secret_key()
        self.secret_key = 'wrong key'
        self.client_post_report_delete()
        self.assertTrue(self.assert_report_exists())

    def test_report_delete(self):
        self.client_post_report_creation()
        self.assertTrue(self.report.pk)
        response = self.client_post_report_delete()
        self.assertEqual(response.status_code, 200)
        self.assertFalse(self.assert_report_exists())

    def test_export_returns_pdf(self):
        self.client_post_report_creation()
        response = self.client_get_report_view_pdf()
        self.assertEqual(response.status_code, 200)
        self.assertEquals(
            response.get('Content-Disposition'),
            'inline; filename="report.pdf"',
        )

    @skip('temporariy disabled')
    def test_match_report_entry(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.assertTrue(
            models.MatchReport.objects.filter(report=self.report).count(),
        )

    @skip('temporariy disabled')
    def test_match_report_withdrawl(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.client_get_matching_withdraw()
        self.assertFalse(
            models.MatchReport.objects.filter(report=self.report).count(),
        )

    @skip('temporariy disabled')
    @override_settings(
        CALLISTO_NOTIFICATION_API='tests.callistocore.forms.SiteAwareNotificationApi')
    def test_match_sends_report_immediately(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.match_report_email_assertions()

    @skip('temporariy disabled')
    @override_settings(MATCH_IMMEDIATELY=False)
    @override_settings(
        CALLISTO_NOTIFICATION_API='tests.callistocore.forms.SiteAwareNotificationApi')
    def test_match_sends_report_delayed(self):
        self.client_post_report_creation()
        self.client_post_matching_enter()
        self.assertEqual(len(mail.outbox), 0)
        call_command('find_matches')
        self.match_report_email_assertions()
<|endoftext|>


<commit_before>from django.conf import settings
from django.conf.urls import include, patterns, url
from django.contrib import admin
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView, TemplateView
from fluent_pages.sitemaps import PageSitemap

from icekit.admin_forms import PasswordResetForm

admin.autodiscover()

sitemaps = {
    'pages': PageSitemap,
}

urlpatterns = patterns(
    '',

    # Test error templates.
    url(r'^404/$', TemplateView.as_view(template_name='404.html')),
    url(r'^500/$', TemplateView.as_view(template_name='500.html')),

    # Redirects for updated paths in the redactor package that don't match the
    # `django-wysiwyg` template.
    url(r'^css/redactor.css$',
        RedirectView.as_view(
            url=settings.STATIC_URL + 'redactor/redactor/redactor.css',
            permanent=True)),
    url(r'^redactor.min.js$',
        RedirectView.as_view(
            url=settings.STATIC_URL + 'redactor/redactor/redactor.min.js',
            permanent=True)),

    # Sitemap.
    url(r'^sitemap\.xml$',
        'django.contrib.sitemaps.views.sitemap',
        {'sitemaps': sitemaps}),

    # Installed apps.
    url(r'^api/pages/', include('icekit.pages_api.urls')),
    url(r'^forms/', include('forms_builder.forms.urls')),
    url(r'^search/', include('haystack.urls')),

    # Get admin URLs prefix from settings.
    # Handle admin and front-end authentication separately.
    url(getattr(settings, 'ICEKIT_ADMIN_URL_PREFIX', r'^admin/'), include(patterns(
        '',
        url(r'^doc/', include('django.contrib.admindocs.urls')),

        # Password reset.
        url(r'^password/reset/$',
            'django.contrib.auth.views.password_reset',
            {
                'post_reset_redirect': 'admin_password_reset_done',
                'email_template_name': 'icekit/admin/password_reset_email.html',
                'password_reset_form': PasswordResetForm,  # Staff use only
            },
            name='admin_password_reset'
        ),
        url(r'^password/reset/done/$',
            'django.contrib.auth.views.password_reset_done',
            name='admin_password_reset_done'
        ),
        url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
            'django.contrib.auth.views.password_reset_confirm',
            {
                'post_reset_redirect': 'admin_password_reset_complete'
            },
            name='admin_password_reset_confirm'
        ),
        url(r'^password/done/$',
            'django.contrib.auth.views.password_reset_complete',
            {
                'extra_context': {
                    'login_url': reverse_lazy('admin:index')  # Redirect staff to the admin login
                }
            },
            name='admin_password_reset_complete'
        ),

        # Admin.
        url(r'^', include(admin.site.urls)),
    ))),

    # Get front-end authentication URLs prefix from settings.
    url(getattr(settings, 'ICEKIT_LOGIN_URL_PREFIX', r''), include(patterns(
        '',

        # Authentication.
        url(r'^login/$',
            'django.contrib.auth.views.login',
            {
                'template_name': 'icekit/auth/login.html',
            },
            name='login'
        ),
        url(r'^logout/$',
            'django.contrib.auth.views.logout',
            {
                'template_name': 'icekit/auth/logged_out.html',
            },
            name='logout'
        ),

        # Password change.
        url(r'^password/change/$',
            'django.contrib.auth.views.password_change',
            {
                'template_name': 'icekit/auth/password_change_form.html',
            },
            name='password_change'
        ),
        url(r'^password/change/done/$',
            'django.contrib.auth.views.password_change_done',
            {
                'template_name': 'icekit/auth/password_change_done.html',
            },
            name='password_change_done'
        ),

        # Password reset.
        url(r'^password/reset/$',
            'django.contrib.auth.views.password_reset',
            {
                'template_name': 'icekit/auth/password_reset.html',
                'email_template_name': 'icekit/auth/password_reset_email.html',
                'subject_template_name': 'icekit/auth/password_reset_subject.txt',
            },
            name='password_reset'
        ),
        url(r'^password/reset/done/$',
            'django.contrib.auth.views.password_reset_done',
            {
                'template_name': 'icekit/auth/password_reset_done.html',
            },
            name='password_reset_done'
        ),
        url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
            'django.contrib.auth.views.password_reset_confirm',
            {
                'template_name': 'icekit/auth/password_reset_confirm.html',
            },
            name='password_reset_confirm'
        ),
        url(r'^password/done/$',
            'django.contrib.auth.views.password_reset_complete',
            {
                'template_name': 'icekit/auth/password_reset_complete.html',
            },
            name='password_reset_complete'
        ),
    ))),

    # Catch all, fluent page dispatcher.
    url(r'^', include('fluent_pages.urls')),
)
<commit_msg>Expose ICEKit Events at /events/ using default primitive views<commit_after>from django.conf import settings
from django.conf.urls import include, patterns, url
from django.contrib import admin
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView, TemplateView
from fluent_pages.sitemaps import PageSitemap

from icekit.admin_forms import PasswordResetForm

admin.autodiscover()

sitemaps = {
    'pages': PageSitemap,
}

urlpatterns = patterns(
    '',

    # Test error templates.
    url(r'^404/$', TemplateView.as_view(template_name='404.html')),
    url(r'^500/$', TemplateView.as_view(template_name='500.html')),

    # Redirects for updated paths in the redactor package that don't match the
    # `django-wysiwyg` template.
    url(r'^css/redactor.css$',
        RedirectView.as_view(
            url=settings.STATIC_URL + 'redactor/redactor/redactor.css',
            permanent=True)),
    url(r'^redactor.min.js$',
        RedirectView.as_view(
            url=settings.STATIC_URL + 'redactor/redactor/redactor.min.js',
            permanent=True)),

    # Sitemap.
    url(r'^sitemap\.xml$',
        'django.contrib.sitemaps.views.sitemap',
        {'sitemaps': sitemaps}),

    # Installed apps.
    url(r'^api/pages/', include('icekit.pages_api.urls')),
    url(r'^forms/', include('forms_builder.forms.urls')),
    url(r'^search/', include('haystack.urls')),
    url(r'^events/', include('icekit_events.urls')),

    # Get admin URLs prefix from settings.
    # Handle admin and front-end authentication separately.
    url(getattr(settings, 'ICEKIT_ADMIN_URL_PREFIX', r'^admin/'), include(patterns(
        '',
        url(r'^doc/', include('django.contrib.admindocs.urls')),

        # Password reset.
        url(r'^password/reset/$',
            'django.contrib.auth.views.password_reset',
            {
                'post_reset_redirect': 'admin_password_reset_done',
                'email_template_name': 'icekit/admin/password_reset_email.html',
                'password_reset_form': PasswordResetForm,  # Staff use only
            },
            name='admin_password_reset'
        ),
        url(r'^password/reset/done/$',
            'django.contrib.auth.views.password_reset_done',
            name='admin_password_reset_done'
        ),
        url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
            'django.contrib.auth.views.password_reset_confirm',
            {
                'post_reset_redirect': 'admin_password_reset_complete'
            },
            name='admin_password_reset_confirm'
        ),
        url(r'^password/done/$',
            'django.contrib.auth.views.password_reset_complete',
            {
                'extra_context': {
                    'login_url': reverse_lazy('admin:index')  # Redirect staff to the admin login
                }
            },
            name='admin_password_reset_complete'
        ),

        # Admin.
        url(r'^', include(admin.site.urls)),
    ))),

    # Get front-end authentication URLs prefix from settings.
    url(getattr(settings, 'ICEKIT_LOGIN_URL_PREFIX', r''), include(patterns(
        '',

        # Authentication.
        url(r'^login/$',
            'django.contrib.auth.views.login',
            {
                'template_name': 'icekit/auth/login.html',
            },
            name='login'
        ),
        url(r'^logout/$',
            'django.contrib.auth.views.logout',
            {
                'template_name': 'icekit/auth/logged_out.html',
            },
            name='logout'
        ),

        # Password change.
        url(r'^password/change/$',
            'django.contrib.auth.views.password_change',
            {
                'template_name': 'icekit/auth/password_change_form.html',
            },
            name='password_change'
        ),
        url(r'^password/change/done/$',
            'django.contrib.auth.views.password_change_done',
            {
                'template_name': 'icekit/auth/password_change_done.html',
            },
            name='password_change_done'
        ),

        # Password reset.
        url(r'^password/reset/$',
            'django.contrib.auth.views.password_reset',
            {
                'template_name': 'icekit/auth/password_reset.html',
                'email_template_name': 'icekit/auth/password_reset_email.html',
                'subject_template_name': 'icekit/auth/password_reset_subject.txt',
            },
            name='password_reset'
        ),
        url(r'^password/reset/done/$',
            'django.contrib.auth.views.password_reset_done',
            {
                'template_name': 'icekit/auth/password_reset_done.html',
            },
            name='password_reset_done'
        ),
        url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
            'django.contrib.auth.views.password_reset_confirm',
            {
                'template_name': 'icekit/auth/password_reset_confirm.html',
            },
            name='password_reset_confirm'
        ),
        url(r'^password/done/$',
            'django.contrib.auth.views.password_reset_complete',
            {
                'template_name': 'icekit/auth/password_reset_complete.html',
            },
            name='password_reset_complete'
        ),
    ))),

    # Catch all, fluent page dispatcher.
    url(r'^', include('fluent_pages.urls')),
)
<|endoftext|>