diff --git a/cdk_stacks/aws_lambda_functions/power_off_at_day_end_function/power_off_helper.py b/cdk_stacks/aws_lambda_functions/power_off_at_day_end_function/power_off_helper.py index fbf9fceaf..abd1bf261 100644 --- a/cdk_stacks/aws_lambda_functions/power_off_at_day_end_function/power_off_helper.py +++ b/cdk_stacks/aws_lambda_functions/power_off_at_day_end_function/power_off_helper.py @@ -2,8 +2,6 @@ Powers off servers when called. """ -import random -import time import boto3 @@ -19,10 +17,9 @@ def reduce_alb_size(tag_name, tag_value, at_most=0, region="eu-west-2"): for asg in asg_list: name = asg["AutoScalingGroupName"] for tag in asg["Tags"]: - if tag["Key"] == "dc-environment": - if tag["Value"] == "production": - print(f"Not touching {name} as it's a production ASG") - continue + if tag["Key"] == "dc-environment" and tag["Value"] == "production": + print(f"Not touching {name} as it's a production ASG") + continue print(f"Updating {name} to MinSize={at_most} DesiredCapacity={at_most}") client.update_auto_scaling_group( AutoScalingGroupName=name, diff --git a/cdk_stacks/stacks/code_deploy.py b/cdk_stacks/stacks/code_deploy.py index 3c2fa7fb4..bc96109a3 100644 --- a/cdk_stacks/stacks/code_deploy.py +++ b/cdk_stacks/stacks/code_deploy.py @@ -1,22 +1,21 @@ -from aws_cdk.aws_cloudfront import PriceClass -from aws_cdk.core import Stack, Construct, Duration - -import aws_cdk.aws_ec2 as ec2 -import aws_cdk.aws_iam as iam -import aws_cdk.aws_elasticloadbalancingv2 as elbv2 -from aws_cdk.aws_ssm import StringParameter -import aws_cdk.aws_codedeploy as codedeploy +import aws_cdk.aws_certificatemanager as acm import aws_cdk.aws_cloudfront as cloudfront import aws_cdk.aws_cloudfront_origins as origins -import aws_cdk.aws_certificatemanager as acm +import aws_cdk.aws_codedeploy as codedeploy +import aws_cdk.aws_ec2 as ec2 +import aws_cdk.aws_elasticloadbalancingv2 as elbv2 +import aws_cdk.aws_iam as iam import aws_cdk.aws_route53 as route_53 import aws_cdk.aws_route53_targets as route_53_target +from aws_cdk.aws_cloudfront import PriceClass +from aws_cdk.aws_ssm import StringParameter +from aws_cdk.core import Construct, Duration, Stack from cdk_stacks.stacks.code_deploy_policies import ( - EE_DEPLOYER_POLICY, - EE_CODE_DEPLOY_POLICY, EE_CODE_DEPLOY_EC2_POLICY, EE_CODE_DEPLOY_LAUNCH_TEMPLATE_POLICY, + EE_CODE_DEPLOY_POLICY, + EE_DEPLOYER_POLICY, ) EE_IMAGE = "ami-014a706cddda2a79a" @@ -63,7 +62,7 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: self.cloudfront = self.create_cloudfront(self.alb) def create_code_deploy(self): - application = codedeploy.ServerApplication( + codedeploy.ServerApplication( self, "CodeDeployApplicationID", application_name="EECodeDeploy" ) @@ -73,7 +72,7 @@ def create_launch_template( security_group: ec2.SecurityGroup, role: iam.Role, ) -> ec2.LaunchTemplate: - lt = ec2.LaunchTemplate( + return ec2.LaunchTemplate( self, "ee-launch-template-id", instance_type=ec2.InstanceType("t3a.medium"), @@ -94,7 +93,6 @@ def create_launch_template( ) ], ) - return lt def create_target_group(self): return elbv2.ApplicationTargetGroup( @@ -390,7 +388,7 @@ def create_cloudfront(self, alb: elbv2.ApplicationLoadBalancer): hosted_zone = route_53.HostedZone.from_lookup( self, "EEDomain", domain_name=fqdn, private_zone=False ) - a_record = route_53.ARecord( + route_53.ARecord( self, "FQDN_A_RECORD_TO_CF", zone=hosted_zone, diff --git a/cdk_stacks/stacks/command_runner.py b/cdk_stacks/stacks/command_runner.py index f40ee50e8..8cb08418a 100644 --- a/cdk_stacks/stacks/command_runner.py +++ b/cdk_stacks/stacks/command_runner.py @@ -1,9 +1,9 @@ from aws_cdk import ( aws_events, aws_events_targets, + aws_iam, aws_lambda, aws_lambda_python, - aws_iam, core, ) from aws_cdk.core import Construct, Stack diff --git a/cdk_stacks/stacks/image_builder.py b/cdk_stacks/stacks/image_builder.py index 9aac4533d..7d62f9dff 100644 --- a/cdk_stacks/stacks/image_builder.py +++ b/cdk_stacks/stacks/image_builder.py @@ -2,12 +2,11 @@ import re from pathlib import Path -import yaml -from aws_cdk.core import Stack, Construct import aws_cdk.aws_iam as iam import aws_cdk.aws_imagebuilder as image_builder +import yaml from aws_cdk.aws_ssm import StringParameter - +from aws_cdk.core import Construct, Stack COMPONENTS = [ { @@ -157,13 +156,12 @@ def make_instance_profile(self): ) # create an instance profile to attach the role - instanceprofile = iam.CfnInstanceProfile( + return iam.CfnInstanceProfile( self, "EEImageInstanceProfile", instance_profile_name="EEImageInstanceProfile", roles=["EEImageRole"], ) - return instanceprofile def make_infra_config(self) -> image_builder.CfnInfrastructureConfiguration: """ diff --git a/cdk_stacks/stacks/power_off_at_end_of_day.py b/cdk_stacks/stacks/power_off_at_end_of_day.py index b1aa0cf60..35df329c2 100644 --- a/cdk_stacks/stacks/power_off_at_end_of_day.py +++ b/cdk_stacks/stacks/power_off_at_end_of_day.py @@ -8,9 +8,9 @@ from aws_cdk import ( aws_events, aws_events_targets, + aws_iam, aws_lambda, aws_lambda_python, - aws_iam, core, ) from aws_cdk.core import Construct, Stack diff --git a/deployscripts/create_deployment.py b/deployscripts/create_deployment.py index 3bfcfa8d3..c5fdb83d9 100644 --- a/deployscripts/create_deployment.py +++ b/deployscripts/create_deployment.py @@ -1,7 +1,8 @@ import os -import boto3 import time +import boto3 + session = boto3.Session(region_name=os.environ.get("AWS_REGION")) diff --git a/deployscripts/create_deployment_group.py b/deployscripts/create_deployment_group.py index 78c304560..2e608a262 100644 --- a/deployscripts/create_deployment_group.py +++ b/deployscripts/create_deployment_group.py @@ -1,7 +1,8 @@ import os +import time + import boto3 from botocore.exceptions import ClientError -import time session = boto3.Session() @@ -92,7 +93,7 @@ def create_default_asg(): for asg in client.describe_auto_scaling_groups()["AutoScalingGroups"] ] if "default" in existing_asgs: - return + return None return client.create_auto_scaling_group( AutoScalingGroupName="default", AvailabilityZones=[ @@ -199,6 +200,7 @@ def main(): # step as the instance needs to have initialised and be in ready state # before code deploy can create a start deployment time.sleep(60) + return None if __name__ == "__main__": diff --git a/docs/aws-resource-diagram.py b/docs/aws-resource-diagram.py index cc0f93556..fec3bbbca 100644 --- a/docs/aws-resource-diagram.py +++ b/docs/aws-resource-diagram.py @@ -1,21 +1,16 @@ from diagrams import Cluster, Diagram from diagrams.aws.compute import ( - Lambda, - EC2AutoScaling, - EC2Instances, EC2Ami, + EC2AutoScaling, EC2ImageBuilder, + EC2Instances, ) -from diagrams.aws.database import RDS from diagrams.aws.devtools import Codedeploy from diagrams.aws.general import InternetAlt1 from diagrams.aws.management import Config, Organizations -from diagrams.aws.network import ALB, Route53, CloudFront +from diagrams.aws.network import ALB, CloudFront, Route53 from diagrams.aws.security import CertificateManager -from diagrams.aws.storage import S3 from diagrams.generic.network import Subnet -from diagrams.onprem.database import PostgreSQL -from diagrams.programming.framework import Django with Diagram( "AWS deployment resources", filename="docs/aws-resources", show=False diff --git a/every_election/apps/api/filters.py b/every_election/apps/api/filters.py index 5ae90bd59..d73f8340b 100644 --- a/every_election/apps/api/filters.py +++ b/every_election/apps/api/filters.py @@ -2,7 +2,6 @@ from django.core.exceptions import ValidationError from django.db.models import Q from django.utils.timezone import now - from elections.models import Election from organisations.models import OrganisationGeography diff --git a/every_election/apps/api/management/commands/export_boundaries.py b/every_election/apps/api/management/commands/export_boundaries.py index eb7ba79de..93527e461 100644 --- a/every_election/apps/api/management/commands/export_boundaries.py +++ b/every_election/apps/api/management/commands/export_boundaries.py @@ -1,10 +1,10 @@ +import contextlib import os import os.path import subprocess from datetime import datetime import geojson - from django.conf import settings from django.core.management.base import BaseCommand from elections.models import Election @@ -53,7 +53,7 @@ def add_arguments(self, parser): ) def handle(self, *args, **options): - try: + with contextlib.suppress(FileExistsError): os.mkdir(options["output"]) if not (options["from"] or options["to"]): diff --git a/every_election/apps/api/serializers.py b/every_election/apps/api/serializers.py index b9b158294..2bb055251 100644 --- a/every_election/apps/api/serializers.py +++ b/every_election/apps/api/serializers.py @@ -1,14 +1,7 @@ -from rest_framework import serializers -from rest_framework_gis.serializers import ( - GeoFeatureModelSerializer, - GeometrySerializerMethodField, -) -from uk_election_ids.datapackage import VOTING_SYSTEMS - from elections.models import ( Election, - ElectionType, ElectionSubType, + ElectionType, ModerationStatuses, ) from organisations.models import ( @@ -16,6 +9,12 @@ OrganisationDivision, OrganisationDivisionSet, ) +from rest_framework import serializers +from rest_framework_gis.serializers import ( + GeoFeatureModelSerializer, + GeometrySerializerMethodField, +) +from uk_election_ids.datapackage import VOTING_SYSTEMS class OrganisationHyperlinkedIdentityField( @@ -256,3 +255,12 @@ class Meta: fields = election_fields depth = 1 + model = Election + extra_kwargs = { + "url": {"view_name": "election-geo", "lookup_field": "pk"} + } + + geo_field = "geography_model" + + fields = election_fields + depth = 1 diff --git a/every_election/apps/api/tests/test_api_election_endpoint.py b/every_election/apps/api/tests/test_api_election_endpoint.py index 6abc2a748..2d45e7b8e 100644 --- a/every_election/apps/api/tests/test_api_election_endpoint.py +++ b/every_election/apps/api/tests/test_api_election_endpoint.py @@ -1,11 +1,10 @@ import json -import pytest from datetime import datetime, timedelta from urllib.parse import urlencode +import pytest import vcr -from rest_framework.test import APITestCase - +from elections.models import ElectionType, MetaData from elections.tests.factories import ( ElectionWithStatusFactory, ModerationHistoryFactory, @@ -13,13 +12,13 @@ related_status, ) from organisations.tests.factories import ( - OrganisationFactory, - OrganisationDivisionSetFactory, + DivisionGeographyFactory, OrganisationDivisionFactory, + OrganisationDivisionSetFactory, + OrganisationFactory, OrganisationGeographyFactory, - DivisionGeographyFactory, ) -from elections.models import ElectionType, MetaData +from rest_framework.test import APITestCase class TestElectionAPIQueries(APITestCase): @@ -49,7 +48,7 @@ def test_election_endpoint_current(self): assert len(data["results"]) == 1 assert data["results"][0]["election_id"] == id_current - assert data["results"][0]["current"] == True + assert data["results"][0]["current"] is True def test_election_endpoint_future(self): ElectionWithStatusFactory( @@ -561,8 +560,8 @@ def test_election_intersects_local_authority_filter(self): ) data = resp.json() self.assertSetEqual( - set(["overlaps", "same", "contains", "within"]), - set([e["election_title"] for e in data["results"]]), + {"overlaps", "same", "contains", "within"}, + {e["election_title"] for e in data["results"]}, ) # BIG_TEST1 has an area bigger than 2. So should hoover up everything @@ -572,6 +571,6 @@ def test_election_intersects_local_authority_filter(self): ) data = resp.json() self.assertSetEqual( - set(["overlaps", "same", "contains", "within"]), - set([e["election_title"] for e in data["results"]]), + {"overlaps", "same", "contains", "within"}, + {e["election_title"] for e in data["results"]}, ) diff --git a/every_election/apps/api/tests/test_api_organisation_endpoint.py b/every_election/apps/api/tests/test_api_organisation_endpoint.py index 21921d805..e10ee1b69 100644 --- a/every_election/apps/api/tests/test_api_organisation_endpoint.py +++ b/every_election/apps/api/tests/test_api_organisation_endpoint.py @@ -1,9 +1,10 @@ from datetime import date -from rest_framework.test import APITestCase + from organisations.tests.factories import ( OrganisationFactory, OrganisationGeographyFactory, ) +from rest_framework.test import APITestCase class TestOrganisationAPIEndpoint(APITestCase): diff --git a/every_election/apps/api/views.py b/every_election/apps/api/views.py index b800a3835..f92548e2a 100644 --- a/every_election/apps/api/views.py +++ b/every_election/apps/api/views.py @@ -1,27 +1,27 @@ from collections import OrderedDict from datetime import datetime +from api import filters from django.db.models import Prefetch from django.http import Http404 +from elections.models import Election, ElectionSubType, ElectionType +from elections.query_helpers import PostcodeError +from organisations.models import Organisation, OrganisationDivision from rest_framework import viewsets from rest_framework.decorators import action -from rest_framework.response import Response from rest_framework.exceptions import APIException +from rest_framework.response import Response from uk_election_ids.election_ids import validate -from elections.models import Election, ElectionType, ElectionSubType -from elections.query_helpers import PostcodeError -from organisations.models import Organisation, OrganisationDivision from .serializers import ( + ElectionGeoSerializer, ElectionSerializer, - ElectionTypeSerializer, ElectionSubTypeSerializer, - OrganisationSerializer, + ElectionTypeSerializer, OrganisationDivisionSerializer, OrganisationGeoSerializer, - ElectionGeoSerializer, + OrganisationSerializer, ) -from api import filters class APIPostcodeException(APIException): @@ -120,8 +120,7 @@ def get_queryset(self): queryset = queryset.filter(group_type=None) else: queryset = queryset.filter(group_type=identifier_type) - queryset = queryset.order_by() - return queryset + return queryset.order_by() def retrieve(self, request, *args, **kwargs): if not validate(kwargs["election_id"]): @@ -247,4 +246,4 @@ def filter(self, request, **kwargs): class OrganisationDivisionViewSet(viewsets.ReadOnlyModelViewSet): queryset = OrganisationDivision.objects.all() serializer_class = OrganisationDivisionSerializer - filterset_fields = ["modified"] + filterset_fields = ["modified"] \ No newline at end of file diff --git a/every_election/apps/core/management/commands/import_onspd_remote.py b/every_election/apps/core/management/commands/import_onspd_remote.py index 90a6d8ac6..0f02e5166 100644 --- a/every_election/apps/core/management/commands/import_onspd_remote.py +++ b/every_election/apps/core/management/commands/import_onspd_remote.py @@ -1,18 +1,20 @@ import os -import psutil import shutil import tempfile import urllib.request + +import psutil import sqlparse from django.core.management.base import BaseCommand -from django.db import connection -from django.db import transaction +from django.db import connection, transaction from storage.zipfile import unzip +from uk_geo_utils.helpers import get_onspd_model from uk_geo_utils.management.commands.import_onspd import ( - Command as LocalImporter, HEADERS, ) -from uk_geo_utils.helpers import get_onspd_model +from uk_geo_utils.management.commands.import_onspd import ( + Command as LocalImporter, +) class Command(BaseCommand): diff --git a/every_election/apps/core/migrations/0001_initial.py b/every_election/apps/core/migrations/0001_initial.py index 5b69531ed..47111be2e 100644 --- a/every_election/apps/core/migrations/0001_initial.py +++ b/every_election/apps/core/migrations/0001_initial.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import migrations from django.contrib.auth.models import Group, User +from django.db import migrations def add_moderator_group(apps, schema_editor): diff --git a/every_election/apps/core/mixins.py b/every_election/apps/core/mixins.py index 7f0bcfe8b..d6fc167a0 100644 --- a/every_election/apps/core/mixins.py +++ b/every_election/apps/core/mixins.py @@ -5,10 +5,8 @@ import requests from django_extensions.db.models import TimeStampedModel - from storage.s3wrapper import S3Wrapper - """ Generic mixins for reading from files in a Django management command. The files can be a local file, a URL or on an S3 bucket. @@ -41,7 +39,8 @@ def add_arguments(self, parser): ) def read_from_local(self, filename): - return open(filename, "rt") + with open(filename, "rt"): + return filename def read_from_url(self, url): tmp = tempfile.NamedTemporaryFile() @@ -59,6 +58,7 @@ def load_data(self, options): return self.read_from_url(options["url"]) if options["s3"]: return self.read_from_s3(options["s3"]) + return None class ReadFromCSVMixin(ReadFromFileMixin): @@ -66,9 +66,9 @@ class ReadFromCSVMixin(ReadFromFileMixin): DELIMITER = "," def read_from_local(self, filename): - f = open(filename, "rt", encoding=self.ENCODING) - reader = csv.DictReader(f, delimiter=self.DELIMITER) - return list(reader) + with open(filename, "rt", encoding=self.ENCODING) as f: + reader = csv.DictReader(f, delimiter=self.DELIMITER) + return list(reader) def read_from_url(self, url): r = requests.get(url) diff --git a/every_election/apps/core/tests/test_jsonb_set.py b/every_election/apps/core/tests/test_jsonb_set.py index 6d852c867..7732cee7c 100644 --- a/every_election/apps/core/tests/test_jsonb_set.py +++ b/every_election/apps/core/tests/test_jsonb_set.py @@ -1,7 +1,6 @@ +from core.models import JsonbSet from django.db.models import Value from django.test import TestCase - -from core.models import JsonbSet from elections.models import Election from elections.tests.factories import ElectionFactory diff --git a/every_election/apps/core/tests/test_urls.py b/every_election/apps/core/tests/test_urls.py index 54f59a359..deba615e9 100644 --- a/every_election/apps/core/tests/test_urls.py +++ b/every_election/apps/core/tests/test_urls.py @@ -1,4 +1,5 @@ import json + from django.test import TestCase from django_extensions.management.commands.show_urls import Command @@ -6,10 +7,7 @@ class UrlTests(TestCase): def is_exception(self, url): exceptions = [".txt", ".ics", "/admin/"] - for exception in exceptions: - if exception in url: - return True - return False + return any(exception in url for exception in exceptions) def test_trailing_slashes(self): c = Command() diff --git a/every_election/apps/core/views.py b/every_election/apps/core/views.py index ac0d148b0..f7d66db44 100644 --- a/every_election/apps/core/views.py +++ b/every_election/apps/core/views.py @@ -1,7 +1,6 @@ from datetime import datetime from django.views.generic import TemplateView - from elections.models import Election diff --git a/every_election/apps/election_snooper/forms.py b/every_election/apps/election_snooper/forms.py index e4c54e140..8c9bcbaee 100644 --- a/every_election/apps/election_snooper/forms.py +++ b/every_election/apps/election_snooper/forms.py @@ -1,12 +1,12 @@ from django import forms - -from .models import SnoopedElection from elections.models import ( ModerationHistory, ModerationStatus, ModerationStatuses, ) +from .models import SnoopedElection + class ReviewElectionForm(forms.ModelForm): class Meta: diff --git a/every_election/apps/election_snooper/helpers.py b/every_election/apps/election_snooper/helpers.py index effc4f4b7..9963fafbc 100644 --- a/every_election/apps/election_snooper/helpers.py +++ b/every_election/apps/election_snooper/helpers.py @@ -3,9 +3,8 @@ import textwrap import warnings -from django.conf import settings - import requests +from django.conf import settings def post_to_slack(message): diff --git a/every_election/apps/election_snooper/management/commands/snoop.py b/every_election/apps/election_snooper/management/commands/snoop.py index eee429309..4336886d3 100644 --- a/every_election/apps/election_snooper/management/commands/snoop.py +++ b/every_election/apps/election_snooper/management/commands/snoop.py @@ -1,5 +1,4 @@ from django.core.management.base import BaseCommand - from election_snooper.snoopers.aldc import ALDCScraper from election_snooper.snoopers.customsearch import CustomSearchScraper diff --git a/every_election/apps/election_snooper/migrations/0004_auto_20170627_1405.py b/every_election/apps/election_snooper/migrations/0004_auto_20170627_1405.py index a23cae7dc..f9986ec38 100644 --- a/every_election/apps/election_snooper/migrations/0004_auto_20170627_1405.py +++ b/every_election/apps/election_snooper/migrations/0004_auto_20170627_1405.py @@ -3,9 +3,10 @@ from __future__ import unicode_literals import datetime -from django.db import migrations, models + import django.utils.timezone import model_utils.fields +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/election_snooper/migrations/0005_auto_20170628_0749.py b/every_election/apps/election_snooper/migrations/0005_auto_20170628_0749.py index bfe3d7174..3c98a6941 100644 --- a/every_election/apps/election_snooper/migrations/0005_auto_20170628_0749.py +++ b/every_election/apps/election_snooper/migrations/0005_auto_20170628_0749.py @@ -2,9 +2,9 @@ # Generated by Django 1.10.6 on 2017-06-28 07:49 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import model_utils.fields +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/election_snooper/models.py b/every_election/apps/election_snooper/models.py index 63c2883ca..42d990e80 100644 --- a/every_election/apps/election_snooper/models.py +++ b/every_election/apps/election_snooper/models.py @@ -2,9 +2,8 @@ from django.db import models from django.urls import reverse - -from model_utils.models import StatusModel from model_utils import Choices +from model_utils.models import StatusModel class SnoopedElection(StatusModel): diff --git a/every_election/apps/election_snooper/snoopers/aldc.py b/every_election/apps/election_snooper/snoopers/aldc.py index 6796a93f2..5e310c5d5 100644 --- a/every_election/apps/election_snooper/snoopers/aldc.py +++ b/every_election/apps/election_snooper/snoopers/aldc.py @@ -1,8 +1,10 @@ +import contextlib from datetime import datetime -from .base import BaseSnooper from election_snooper.models import SnoopedElection +from .base import BaseSnooper + class ALDCScraper(BaseSnooper): snooper_name = "ALDC" @@ -30,7 +32,7 @@ def get_all(self): "detail": "\n".join([x.text for x in content]), "snooper_name": self.snooper_name, } - try: + with contextlib.suppress(ValueError): data["date"] = datetime.strptime(date, "%B %d, %Y") item, created = SnoopedElection.objects.update_or_create( diff --git a/every_election/apps/election_snooper/snoopers/base.py b/every_election/apps/election_snooper/snoopers/base.py index 6f45ffef2..2961e24b3 100644 --- a/every_election/apps/election_snooper/snoopers/base.py +++ b/every_election/apps/election_snooper/snoopers/base.py @@ -1,7 +1,5 @@ -import os -from bs4 import BeautifulSoup -from django.conf import settings import requests +from bs4 import BeautifulSoup from election_snooper.helpers import post_to_slack @@ -11,8 +9,7 @@ def get_page(self, url): def get_soup(self, url): req = self.get_page(url) - soup = BeautifulSoup(req.content, "html.parser") - return soup + return BeautifulSoup(req.content, "html.parser") def post_to_slack(self, item): message = """ diff --git a/every_election/apps/election_snooper/snoopers/customsearch.py b/every_election/apps/election_snooper/snoopers/customsearch.py index 8969c4ad3..83963751d 100644 --- a/every_election/apps/election_snooper/snoopers/customsearch.py +++ b/every_election/apps/election_snooper/snoopers/customsearch.py @@ -1,9 +1,9 @@ from urllib.parse import urlencode from django.conf import settings +from election_snooper.models import SnoopedElection from .base import BaseSnooper -from election_snooper.models import SnoopedElection class CustomSearchScraper(BaseSnooper): diff --git a/every_election/apps/election_snooper/urls.py b/every_election/apps/election_snooper/urls.py index 8c2bc8727..7d6529373 100644 --- a/every_election/apps/election_snooper/urls.py +++ b/every_election/apps/election_snooper/urls.py @@ -1,7 +1,6 @@ from django.urls import re_path from election_snooper import views - urlpatterns = [ re_path( r"^$", views.SnoopedElectionView.as_view(), name="snooped_election_view" diff --git a/every_election/apps/election_snooper/views/bot_review.py b/every_election/apps/election_snooper/views/bot_review.py index 861504ac8..763c8e21e 100644 --- a/every_election/apps/election_snooper/views/bot_review.py +++ b/every_election/apps/election_snooper/views/bot_review.py @@ -1,13 +1,13 @@ import urllib + +from core.helpers import user_is_moderator from django.contrib.auth.mixins import UserPassesTestMixin -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.http import HttpResponseRedirect from django.urls import reverse from django.views.generic import TemplateView - -from core.helpers import user_is_moderator -from election_snooper.models import SnoopedElection from election_snooper.forms import ReviewElectionForm +from election_snooper.models import SnoopedElection class SnoopedElectionView(UserPassesTestMixin, TemplateView): diff --git a/every_election/apps/election_snooper/views/human_review.py b/every_election/apps/election_snooper/views/human_review.py index d88f8f52c..599725987 100644 --- a/every_election/apps/election_snooper/views/human_review.py +++ b/every_election/apps/election_snooper/views/human_review.py @@ -1,12 +1,11 @@ -from django.db import transaction +from core.helpers import user_is_moderator from django.contrib.auth.mixins import UserPassesTestMixin +from django.db import transaction from django.http import HttpResponseRedirect from django.urls import reverse from django.views.generic import TemplateView - -from core.helpers import user_is_moderator -from elections.constraints import has_approved_parents, check_constraints from election_snooper.forms import ModerationHistoryForm +from elections.constraints import check_constraints, has_approved_parents from elections.models import Election, ModerationHistory, ModerationStatuses diff --git a/every_election/apps/elections/admin.py b/every_election/apps/elections/admin.py index ceea09c5d..7b3074145 100644 --- a/every_election/apps/elections/admin.py +++ b/every_election/apps/elections/admin.py @@ -1,10 +1,12 @@ import json from copy import deepcopy + from django import forms from django.contrib import admin from django.db import models from django.db.models import Manager from django.forms.widgets import Textarea + from .models import ( ElectedRole, Election, @@ -94,8 +96,7 @@ def has_add_permission(self, request): def get_readonly_fields(self, request, obj=None): if obj.identifier_type == "ballot": return self.readonly_fields - else: - return self.readonly_fields + ("cancelled",) + return self.readonly_fields + ("cancelled",) def render_change_form(self, request, context, *args, **kwargs): context["adminform"].form.fields["replaces"].queryset = ( @@ -193,11 +194,10 @@ def get_queryset(self): .order_by("-modified") .values("status")[:1] ) - qs = qs.annotate(latest_status=latest_statuses).exclude( + return qs.annotate(latest_status=latest_statuses).exclude( latest_status=models.F("current_status") ) - return qs class ElectionStatusProblem(Election): objects = ElectionStatusProblemManager() diff --git a/every_election/apps/elections/constants.py b/every_election/apps/elections/constants.py index 9e1a6baa6..5494bc386 100644 --- a/every_election/apps/elections/constants.py +++ b/every_election/apps/elections/constants.py @@ -1,6 +1,5 @@ from uk_election_ids.datapackage import ELECTION_TYPES - # These types exist in EE but don't have defined behaviour in the IdBuilder ELECTION_TYPES["ref"] = { "name": "Referendum", diff --git a/every_election/apps/elections/constraints.py b/every_election/apps/elections/constraints.py index 0ecbd2039..283f11d41 100644 --- a/every_election/apps/elections/constraints.py +++ b/every_election/apps/elections/constraints.py @@ -1,4 +1,4 @@ -from elections.models import ModerationHistory, ModerationStatuses, Election +from elections.models import Election, ModerationStatuses class ViolatedConstraint(Exception): diff --git a/every_election/apps/elections/forms.py b/every_election/apps/elections/forms.py index cac0260f2..37837137d 100644 --- a/every_election/apps/elections/forms.py +++ b/every_election/apps/elections/forms.py @@ -1,15 +1,11 @@ +from dc_utils import forms as dc_forms from django import forms from django.db import models from django.db.models import Q - -from organisations.models import Organisation -from organisations.models import OrganisationDivisionSet +from organisations.models import Organisation, OrganisationDivisionSet from .models import ElectionSubType, ElectionType -from dc_utils import forms as dc_forms - - # # Forms: # ElectionDateForm diff --git a/every_election/apps/elections/management/commands/add_election_types.py b/every_election/apps/elections/management/commands/add_election_types.py index 8e4017606..b5818e3f4 100644 --- a/every_election/apps/elections/management/commands/add_election_types.py +++ b/every_election/apps/elections/management/commands/add_election_types.py @@ -1,7 +1,6 @@ from django.core.management.base import BaseCommand - -from elections.models import ElectionType, ElectionSubType from elections import constants +from elections.models import ElectionSubType, ElectionType class Command(BaseCommand): diff --git a/every_election/apps/elections/management/commands/add_referendum.py b/every_election/apps/elections/management/commands/add_referendum.py index 97f788300..f85c14916 100644 --- a/every_election/apps/elections/management/commands/add_referendum.py +++ b/every_election/apps/elections/management/commands/add_referendum.py @@ -1,12 +1,11 @@ from django.core.management import BaseCommand - from elections.models import ( Election, ElectionType, ModerationHistory, ModerationStatuses, ) -from organisations.models.organisations import Organisation +from organisations.models import Organisation class Command(BaseCommand): diff --git a/every_election/apps/elections/management/commands/add_tags.py b/every_election/apps/elections/management/commands/add_tags.py index ef62a7962..42097cb42 100644 --- a/every_election/apps/elections/management/commands/add_tags.py +++ b/every_election/apps/elections/management/commands/add_tags.py @@ -1,11 +1,10 @@ import json +from core.mixins import ReadFromFileMixin +from core.models import JsonbSet from django.contrib.gis.gdal import DataSource from django.core.management import BaseCommand from django.db.models import Value - -from core.mixins import ReadFromFileMixin -from core.models import JsonbSet from elections.models import Election diff --git a/every_election/apps/elections/management/commands/attach_posts_per_election_from_csv.py b/every_election/apps/elections/management/commands/attach_posts_per_election_from_csv.py index a96d49074..1271bbca4 100644 --- a/every_election/apps/elections/management/commands/attach_posts_per_election_from_csv.py +++ b/every_election/apps/elections/management/commands/attach_posts_per_election_from_csv.py @@ -1,7 +1,6 @@ +from core.mixins import ReadFromCSVMixin from django.core.management.base import BaseCommand from django.db import transaction - -from core.mixins import ReadFromCSVMixin from elections.models import Election diff --git a/every_election/apps/elections/management/commands/elections_check_constraints.py b/every_election/apps/elections/management/commands/elections_check_constraints.py index a20eb760d..c2ab98511 100644 --- a/every_election/apps/elections/management/commands/elections_check_constraints.py +++ b/every_election/apps/elections/management/commands/elections_check_constraints.py @@ -1,6 +1,7 @@ import sys + from django.core.management.base import BaseCommand -from elections.constraints import check_constraints, ViolatedConstraint +from elections.constraints import ViolatedConstraint, check_constraints from elections.models import Election diff --git a/every_election/apps/elections/management/commands/sync_elections.py b/every_election/apps/elections/management/commands/sync_elections.py index 076aaeeb1..b2c0c5529 100644 --- a/every_election/apps/elections/management/commands/sync_elections.py +++ b/every_election/apps/elections/management/commands/sync_elections.py @@ -1,5 +1,6 @@ import tempfile import urllib.request + from django.conf import settings from django.core.management import call_command from django.core.management.base import BaseCommand diff --git a/every_election/apps/elections/managers.py b/every_election/apps/elections/managers.py index a50b5cf1f..dd0caa80c 100644 --- a/every_election/apps/elections/managers.py +++ b/every_election/apps/elections/managers.py @@ -2,14 +2,13 @@ from django.conf import settings from django.contrib.gis.db.models.functions import PointOnSurface +from django.contrib.gis.geos import GEOSGeometry, Point from django.db import models -from django.contrib.gis.geos import Point, GEOSGeometry from django.utils import timezone - from elections.query_helpers import get_point_from_postcode from organisations.models import ( - OrganisationGeographySubdivided, DivisionGeographySubdivided, + OrganisationGeographySubdivided, ) @@ -115,3 +114,5 @@ class PrivateElectionsManager(models.Manager.from_queryset(ElectionQuerySet)): """ use_in_migrations = True + + use_in_migrations = True diff --git a/every_election/apps/elections/migrations/0002_auto_20161011_0741.py b/every_election/apps/elections/migrations/0002_auto_20161011_0741.py index 58ee94233..c2f4c7d02 100644 --- a/every_election/apps/elections/migrations/0002_auto_20161011_0741.py +++ b/every_election/apps/elections/migrations/0002_auto_20161011_0741.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2016-10-11 07:41 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0003_initial_data.py b/every_election/apps/elections/migrations/0003_initial_data.py index 4799a3ef1..8635c4722 100644 --- a/every_election/apps/elections/migrations/0003_initial_data.py +++ b/every_election/apps/elections/migrations/0003_initial_data.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals from django.db import migrations - from elections.constants import ELECTION_TYPES diff --git a/every_election/apps/elections/migrations/0004_electedrole.py b/every_election/apps/elections/migrations/0004_electedrole.py index e86a41eef..710d45430 100644 --- a/every_election/apps/elections/migrations/0004_electedrole.py +++ b/every_election/apps/elections/migrations/0004_electedrole.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2016-10-11 18:45 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0005_auto_20161021_1609.py b/every_election/apps/elections/migrations/0005_auto_20161021_1609.py index aadbdc369..20c77e744 100644 --- a/every_election/apps/elections/migrations/0005_auto_20161021_1609.py +++ b/every_election/apps/elections/migrations/0005_auto_20161021_1609.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2016-10-21 16:09 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0010_election_elected_role.py b/every_election/apps/elections/migrations/0010_election_elected_role.py index cd6fe996d..9cac02a9e 100644 --- a/every_election/apps/elections/migrations/0010_election_elected_role.py +++ b/every_election/apps/elections/migrations/0010_election_elected_role.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2016-11-02 09:07 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0011_remove_field_requirements.py b/every_election/apps/elections/migrations/0011_remove_field_requirements.py index 4b1536868..79e14da05 100644 --- a/every_election/apps/elections/migrations/0011_remove_field_requirements.py +++ b/every_election/apps/elections/migrations/0011_remove_field_requirements.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-07 11:56 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0012_remove_ElectionDivisions.py b/every_election/apps/elections/migrations/0012_remove_ElectionDivisions.py index 68792d865..b03882922 100644 --- a/every_election/apps/elections/migrations/0012_remove_ElectionDivisions.py +++ b/every_election/apps/elections/migrations/0012_remove_ElectionDivisions.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-07 12:53 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0013_election_group.py b/every_election/apps/elections/migrations/0013_election_group.py index 2ae5bee8a..e723607d1 100644 --- a/every_election/apps/elections/migrations/0013_election_group.py +++ b/every_election/apps/elections/migrations/0013_election_group.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-07 15:53 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0014_auto_20170107_1605.py b/every_election/apps/elections/migrations/0014_auto_20170107_1605.py index 909d277e8..cf8c76664 100644 --- a/every_election/apps/elections/migrations/0014_auto_20170107_1605.py +++ b/every_election/apps/elections/migrations/0014_auto_20170107_1605.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-07 16:05 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0020_auto_20170110_1556.py b/every_election/apps/elections/migrations/0020_auto_20170110_1556.py index 7a2a45f43..218eddc68 100644 --- a/every_election/apps/elections/migrations/0020_auto_20170110_1556.py +++ b/every_election/apps/elections/migrations/0020_auto_20170110_1556.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-10 15:56 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0022_auto_20170125_1522.py b/every_election/apps/elections/migrations/0022_auto_20170125_1522.py index 886aa7e84..0ee408224 100644 --- a/every_election/apps/elections/migrations/0022_auto_20170125_1522.py +++ b/every_election/apps/elections/migrations/0022_auto_20170125_1522.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-25 15:22 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0025_election_geography.py b/every_election/apps/elections/migrations/0025_election_geography.py index c60aa24b4..e686d4811 100644 --- a/every_election/apps/elections/migrations/0025_election_geography.py +++ b/every_election/apps/elections/migrations/0025_election_geography.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-03-02 11:34 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0026_set_default_voting_system.py b/every_election/apps/elections/migrations/0026_set_default_voting_system.py index 4913819e4..a53ae46c5 100644 --- a/every_election/apps/elections/migrations/0026_set_default_voting_system.py +++ b/every_election/apps/elections/migrations/0026_set_default_voting_system.py @@ -4,8 +4,6 @@ from django.db import migrations -from elections import constants - class Migration(migrations.Migration): dependencies = [("elections", "0025_election_geography")] diff --git a/every_election/apps/elections/migrations/0028_auto_20170415_1319.py b/every_election/apps/elections/migrations/0028_auto_20170415_1319.py index 1910ca1bb..65553f140 100644 --- a/every_election/apps/elections/migrations/0028_auto_20170415_1319.py +++ b/every_election/apps/elections/migrations/0028_auto_20170415_1319.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2017-04-15 13:19 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0029_auto_20170415_1342.py b/every_election/apps/elections/migrations/0029_auto_20170415_1342.py index 777747584..d20ce6047 100644 --- a/every_election/apps/elections/migrations/0029_auto_20170415_1342.py +++ b/every_election/apps/elections/migrations/0029_auto_20170415_1342.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2017-04-15 13:42 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0031_auto_20170726_1333.py b/every_election/apps/elections/migrations/0031_auto_20170726_1333.py index 842da40b4..8c5b30045 100644 --- a/every_election/apps/elections/migrations/0031_auto_20170726_1333.py +++ b/every_election/apps/elections/migrations/0031_auto_20170726_1333.py @@ -2,9 +2,9 @@ # Generated by Django 1.10.7 on 2017-07-26 13:33 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import storages.backends.s3boto3 +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0032_auto_20170726_1526.py b/every_election/apps/elections/migrations/0032_auto_20170726_1526.py index abe33d424..4e2487132 100644 --- a/every_election/apps/elections/migrations/0032_auto_20170726_1526.py +++ b/every_election/apps/elections/migrations/0032_auto_20170726_1526.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2017-07-26 15:26 from __future__ import unicode_literals -from django.db import migrations, models import elections.models +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0034_auto_20170727_1146.py b/every_election/apps/elections/migrations/0034_auto_20170727_1146.py index d69915b2a..409a87a22 100644 --- a/every_election/apps/elections/migrations/0034_auto_20170727_1146.py +++ b/every_election/apps/elections/migrations/0034_auto_20170727_1146.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2017-07-27 11:46 from __future__ import unicode_literals -from django.db import migrations, models import elections.models +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0035_election_snooped_election.py b/every_election/apps/elections/migrations/0035_election_snooped_election.py index 9390025d3..19aba7c8e 100644 --- a/every_election/apps/elections/migrations/0035_election_snooped_election.py +++ b/every_election/apps/elections/migrations/0035_election_snooped_election.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2017-07-27 12:45 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0036_auto_20170727_1306.py b/every_election/apps/elections/migrations/0036_auto_20170727_1306.py index bf90122dd..f6093d9f3 100644 --- a/every_election/apps/elections/migrations/0036_auto_20170727_1306.py +++ b/every_election/apps/elections/migrations/0036_auto_20170727_1306.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2017-07-27 13:06 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0037_auto_20180126_1612.py b/every_election/apps/elections/migrations/0037_auto_20180126_1612.py index 81d9d8533..954be6a68 100644 --- a/every_election/apps/elections/migrations/0037_auto_20180126_1612.py +++ b/every_election/apps/elections/migrations/0037_auto_20180126_1612.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.7 on 2018-01-26 16:12 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0038_auto_20180309_1126.py b/every_election/apps/elections/migrations/0038_auto_20180309_1126.py index 5b4df9951..cef3efec9 100644 --- a/every_election/apps/elections/migrations/0038_auto_20180309_1126.py +++ b/every_election/apps/elections/migrations/0038_auto_20180309_1126.py @@ -2,9 +2,9 @@ # Generated by Django 1.11.11 on 2018-03-09 11:26 from __future__ import unicode_literals -from django.db.models import JSONField -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models +from django.db.models import JSONField class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0041_auto_20180607_1141.py b/every_election/apps/elections/migrations/0041_auto_20180607_1141.py index 1872713dd..d1c70bd44 100644 --- a/every_election/apps/elections/migrations/0041_auto_20180607_1141.py +++ b/every_election/apps/elections/migrations/0041_auto_20180607_1141.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.13 on 2018-06-07 11:41 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0043_auto_20180720_1631.py b/every_election/apps/elections/migrations/0043_auto_20180720_1631.py index 5b37635a5..9d8d01537 100644 --- a/every_election/apps/elections/migrations/0043_auto_20180720_1631.py +++ b/every_election/apps/elections/migrations/0043_auto_20180720_1631.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.14 on 2018-07-20 16:31 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0045_auto_20181001_1437.py b/every_election/apps/elections/migrations/0045_auto_20181001_1437.py index 23c1a5d19..5a7e68e5d 100644 --- a/every_election/apps/elections/migrations/0045_auto_20181001_1437.py +++ b/every_election/apps/elections/migrations/0045_auto_20181001_1437.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.15 on 2018-10-01 14:37 from __future__ import unicode_literals -from django.db import migrations import django.db.models.manager +from django.db import migrations class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0047_auto_20181005_1320.py b/every_election/apps/elections/migrations/0047_auto_20181005_1320.py index f7999af3d..9dac33c16 100644 --- a/every_election/apps/elections/migrations/0047_auto_20181005_1320.py +++ b/every_election/apps/elections/migrations/0047_auto_20181005_1320.py @@ -2,11 +2,11 @@ # Generated by Django 1.11.16 on 2018-10-05 13:20 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion import django.db.models.manager import django_extensions.db.fields import elections.managers +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0051_auto_20181005_1618.py b/every_election/apps/elections/migrations/0051_auto_20181005_1618.py index 385f2e64d..c00815307 100644 --- a/every_election/apps/elections/migrations/0051_auto_20181005_1618.py +++ b/every_election/apps/elections/migrations/0051_auto_20181005_1618.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.16 on 2018-10-05 16:18 from __future__ import unicode_literals -from django.db import migrations import elections.managers +from django.db import migrations class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0053_auto_20181008_1534.py b/every_election/apps/elections/migrations/0053_auto_20181008_1534.py index 550c77886..d0ef09f6b 100644 --- a/every_election/apps/elections/migrations/0053_auto_20181008_1534.py +++ b/every_election/apps/elections/migrations/0053_auto_20181008_1534.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.16 on 2018-10-08 15:34 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0054_auto_20181018_1024.py b/every_election/apps/elections/migrations/0054_auto_20181018_1024.py index 169a9d37c..3499f360d 100644 --- a/every_election/apps/elections/migrations/0054_auto_20181018_1024.py +++ b/every_election/apps/elections/migrations/0054_auto_20181018_1024.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.16 on 2018-10-18 10:24 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0055_auto_20181204_0918.py b/every_election/apps/elections/migrations/0055_auto_20181204_0918.py index c3bdd990f..40d2948e5 100644 --- a/every_election/apps/elections/migrations/0055_auto_20181204_0918.py +++ b/every_election/apps/elections/migrations/0055_auto_20181204_0918.py @@ -2,9 +2,9 @@ # Generated by Django 1.11.16 on 2018-12-04 09:18 from __future__ import unicode_literals +import django.db.models.deletion from django.conf import settings from django.db import migrations, models -import django.db.models.deletion class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0056_cleanup_group_types.py b/every_election/apps/elections/migrations/0056_cleanup_group_types.py index 9866b90b7..83a352a02 100644 --- a/every_election/apps/elections/migrations/0056_cleanup_group_types.py +++ b/every_election/apps/elections/migrations/0056_cleanup_group_types.py @@ -3,7 +3,6 @@ from django.db import migrations - group_type_map = { # These mayoral elections all have group_type='organisation', but they should # be None to bring them into line with the current convention for mayor/pcc diff --git a/every_election/apps/elections/migrations/0059_election_tags.py b/every_election/apps/elections/migrations/0059_election_tags.py index f63bf33c8..1735e0a8b 100644 --- a/every_election/apps/elections/migrations/0059_election_tags.py +++ b/every_election/apps/elections/migrations/0059_election_tags.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.16 on 2021-02-13 12:11 -from django.db.models import JSONField from django.db import migrations +from django.db.models import JSONField class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0060_auto_20210720_1438.py b/every_election/apps/elections/migrations/0060_auto_20210720_1438.py index 058a36fd0..a5f136016 100644 --- a/every_election/apps/elections/migrations/0060_auto_20210720_1438.py +++ b/every_election/apps/elections/migrations/0060_auto_20210720_1438.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.20 on 2021-07-20 14:38 -from django.db.models import JSONField from django.db import migrations +from django.db.models import JSONField class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0061_auto_20210928_1509.py b/every_election/apps/elections/migrations/0061_auto_20210928_1509.py index 11fe5a6ee..95fc83053 100644 --- a/every_election/apps/elections/migrations/0061_auto_20210928_1509.py +++ b/every_election/apps/elections/migrations/0061_auto_20210928_1509.py @@ -1,8 +1,8 @@ # Generated by Django 2.2.20 on 2021-09-28 15:09 -from django.db import migrations import django.utils.timezone import django_extensions.db.fields +from django.db import migrations class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0062_add_created_date.py b/every_election/apps/elections/migrations/0062_add_created_date.py index 4dc68a113..c88799b40 100644 --- a/every_election/apps/elections/migrations/0062_add_created_date.py +++ b/every_election/apps/elections/migrations/0062_add_created_date.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.20 on 2021-09-28 15:24 from django.db import migrations -from django.db.models import F, ExpressionWrapper, DateField +from django.db.models import DateField, ExpressionWrapper, F from django.utils.timezone import timedelta diff --git a/every_election/apps/elections/migrations/0069_add_current_status.py b/every_election/apps/elections/migrations/0069_add_current_status.py index 578a8e532..3b98e1237 100644 --- a/every_election/apps/elections/migrations/0069_add_current_status.py +++ b/every_election/apps/elections/migrations/0069_add_current_status.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2022-07-19 21:44 -from django.db import migrations, models import elections.models +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/elections/migrations/0070_populate_current_status.py b/every_election/apps/elections/migrations/0070_populate_current_status.py index 7f4101440..11640e05b 100644 --- a/every_election/apps/elections/migrations/0070_populate_current_status.py +++ b/every_election/apps/elections/migrations/0070_populate_current_status.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.27 on 2022-07-19 21:56 from django.db import migrations -from django.db.models import Subquery, OuterRef, F +from django.db.models import F, OuterRef, Subquery def populate_current_status(apps, schema_editor): diff --git a/every_election/apps/elections/migrations/0071_electionstatusproblem.py b/every_election/apps/elections/migrations/0071_electionstatusproblem.py index 68079ec83..d976cfae2 100644 --- a/every_election/apps/elections/migrations/0071_electionstatusproblem.py +++ b/every_election/apps/elections/migrations/0071_electionstatusproblem.py @@ -1,8 +1,8 @@ # Generated by Django 4.1.7 on 2023-03-15 13:31 -from django.db import migrations import django.db.models.manager import elections.managers +from django.db import migrations class Migration(migrations.Migration): diff --git a/every_election/apps/elections/models.py b/every_election/apps/elections/models.py index 9614d59d8..a52623b04 100644 --- a/every_election/apps/elections/models.py +++ b/every_election/apps/elections/models.py @@ -1,34 +1,32 @@ import tempfile import urllib.request - from datetime import date, timedelta from enum import Enum, unique from django.conf import settings from django.contrib.auth.models import User from django.contrib.gis.db.models.functions import Distance -from django.db.models import JSONField from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.files import File from django.db import models, transaction +from django.db.models import JSONField from django.db.models.fields.related_descriptors import ( create_reverse_many_to_one_manager, ) from django.db.models.signals import post_save from django.dispatch import receiver from django.urls import reverse - from django_extensions.db.models import TimeStampedModel from storages.backends.s3boto3 import S3Boto3Storage -from uk_election_ids.datapackage import VOTING_SYSTEMS, ID_REQUIREMENTS +from uk_election_ids.datapackage import ID_REQUIREMENTS, VOTING_SYSTEMS from uk_election_timetables.calendars import Country from uk_election_timetables.election_ids import ( - from_election_id, NoSuchElectionTypeError, + from_election_id, ) from uk_geo_utils.models import Onspd -from .managers import PublicElectionsManager, PrivateElectionsManager +from .managers import PrivateElectionsManager, PublicElectionsManager class ElectionType(models.Model): @@ -147,7 +145,8 @@ class Election(TimeStampedModel): max_length=100, null=True, choices=[ - (req, ID_REQUIREMENTS[req]["name"]) for req in ID_REQUIREMENTS + (req, ID_REQUIREMENTS[req]["name"]) + for req in ID_REQUIREMENTS ], ) @@ -175,7 +174,9 @@ def get_children(self, manager): voting_system = models.CharField( max_length=100, null=True, - choices=[(vs, VOTING_SYSTEMS[vs]["name"]) for vs in VOTING_SYSTEMS], + choices=[ + (vs, VOTING_SYSTEMS[vs]["name"]) for vs in VOTING_SYSTEMS + ], ) explanation = models.ForeignKey( "elections.Explanation", @@ -321,6 +322,7 @@ def get_ballots(self): election_id__endswith=date, group_type=None, ) + return None @property def group_seats_contested(self): @@ -337,8 +339,7 @@ def group_seats_contested(self): .aggregate(models.Sum("seats_contested")) .get("seats_contested__sum") ) - else: - return self.seats_contested + return self.seats_contested def __str__(self): return self.get_id() @@ -358,8 +359,7 @@ def get_example_postcode(self): .order_by("distance") .first() ) - else: - return None + return None @property def get_timetable(self): @@ -390,8 +390,7 @@ def get_timetable(self): def get_id(self): if self.election_id: return self.election_id - else: - return self.tmp_election_id + return self.tmp_election_id @property def geography(self): @@ -410,8 +409,8 @@ def get_division_geography(self): return self.division_geography if self.identifier_type == "ballot" and self.division: - # attach geography by division if possible - try: + # attach geography by division if possible + try: return self.division.geography except ObjectDoesNotExist: pass @@ -550,6 +549,7 @@ def save(self, **kwargs): self.election.current_status = self.status.short_label self.election.save() super().save(**kwargs) + return None class Meta: verbose_name_plural = "Moderation History" diff --git a/every_election/apps/elections/query_helpers.py b/every_election/apps/elections/query_helpers.py index c5b806245..a597a913d 100644 --- a/every_election/apps/elections/query_helpers.py +++ b/every_election/apps/elections/query_helpers.py @@ -3,11 +3,9 @@ from django.core.exceptions import ObjectDoesNotExist from django.forms import ValidationError - from localflavor.gb.forms import GBPostcodeField from uk_geo_utils.geocoders import OnspdGeocoder - logger = logging.getLogger(__name__) diff --git a/every_election/apps/elections/tests/base_tests.py b/every_election/apps/elections/tests/base_tests.py index 541e2e8f1..c873c3f04 100644 --- a/every_election/apps/elections/tests/base_tests.py +++ b/every_election/apps/elections/tests/base_tests.py @@ -1,12 +1,12 @@ from datetime import date +from elections.models import ElectedRole, ElectionType +from elections.utils import create_ids_for_each_ballot_paper from organisations.models import Organisation from organisations.tests.factories import ( OrganisationDivisionFactory, OrganisationDivisionSetFactory, ) -from elections.models import ElectionType, ElectedRole -from elections.utils import create_ids_for_each_ballot_paper class FuzzyInt(int): diff --git a/every_election/apps/elections/tests/factories.py b/every_election/apps/elections/tests/factories.py index 0e33813d4..66eaacbe6 100644 --- a/every_election/apps/elections/tests/factories.py +++ b/every_election/apps/elections/tests/factories.py @@ -1,20 +1,19 @@ import datetime -import factory +import factory from django.db.models import signals - from elections.models import ( + ElectedRole, Election, - ModerationHistory, ElectionType, - ElectedRole, + ModerationHistory, ModerationStatus, ModerationStatuses, ) from organisations.tests.factories import ( - OrganisationFactory, - OrganisationDivisionFactory, DivisionGeographyFactory, + OrganisationDivisionFactory, + OrganisationFactory, ) diff --git a/every_election/apps/elections/tests/test_admin.py b/every_election/apps/elections/tests/test_admin.py index 04fd53f08..e48450338 100644 --- a/every_election/apps/elections/tests/test_admin.py +++ b/every_election/apps/elections/tests/test_admin.py @@ -1,10 +1,8 @@ -import mock from unittest.mock import MagicMock -from elections import admin - +import mock from django.test import TestCase - +from elections import admin from elections.models import ModerationHistory diff --git a/every_election/apps/elections/tests/test_attach_posts_command.py b/every_election/apps/elections/tests/test_attach_posts_command.py index 3fc7f0a77..ea253aa3a 100644 --- a/every_election/apps/elections/tests/test_attach_posts_command.py +++ b/every_election/apps/elections/tests/test_attach_posts_command.py @@ -1,13 +1,12 @@ -from django.test import TestCase - from io import StringIO + import mock +from django.test import TestCase +from elections.management.commands import attach_posts_per_election_from_csv +from elections.models import Election from .factories import ElectionWithStatusFactory -from elections.models import Election -from elections.management.commands import attach_posts_per_election_from_csv - COMMAND_PATH = ( "elections.management.commands.attach_posts_per_election_from_csv.Command" ) diff --git a/every_election/apps/elections/tests/test_create_ids.py b/every_election/apps/elections/tests/test_create_ids.py index c9eebe2fe..25738d002 100644 --- a/every_election/apps/elections/tests/test_create_ids.py +++ b/every_election/apps/elections/tests/test_create_ids.py @@ -1,18 +1,17 @@ from datetime import date from django.test import TestCase - from elections.models import ( ElectedRole, Election, - ElectionType, ElectionSubType, + ElectionType, ) from organisations.models import Organisation from organisations.tests.factories import ( + DivisionGeographyFactory, OrganisationDivisionFactory, OrganisationDivisionSetFactory, - DivisionGeographyFactory, OrganisationGeographyFactory, ) @@ -372,9 +371,9 @@ def test_election_with_organisation_geography(self): for election in Election.private_objects.all(): if election.group_type == "organisation": - self.assertTrue(election.geography != None) + self.assertTrue(election.geography is not None) else: - self.assertTrue(election.geography == None) + self.assertTrue(election.geography is None) result = Election.private_objects.for_lat_lng( 51.50124158773981, -0.13715744018554688 @@ -412,9 +411,9 @@ def test_election_with_division_geography(self): for election in Election.private_objects.all(): if election.election_id == "local.test.test-div-2." + self.date_str: - self.assertTrue(election.geography != None) + self.assertTrue(election.geography is not None) else: - self.assertTrue(election.geography == None) + self.assertTrue(election.geography is None) result = Election.private_objects.for_lat_lng( 51.50124158773981, -0.13715744018554688 diff --git a/every_election/apps/elections/tests/test_election_builder.py b/every_election/apps/elections/tests/test_election_builder.py index 820c40d7f..d447992fa 100644 --- a/every_election/apps/elections/tests/test_election_builder.py +++ b/every_election/apps/elections/tests/test_election_builder.py @@ -1,19 +1,21 @@ from datetime import date + from django.test import TestCase +from election_snooper.models import SnoopedElection from elections.models import ( DEFAULT_STATUS, - Election, ElectedRole, + Election, ElectionSubType, ElectionType, ) from elections.utils import ElectionBuilder -from election_snooper.models import SnoopedElection from organisations.models import Organisation, OrganisationDivision from organisations.tests.factories import ( OrganisationDivisionFactory, OrganisationDivisionSetFactory, ) + from .base_tests import BaseElectionCreatorMixIn diff --git a/every_election/apps/elections/tests/test_election_constraints.py b/every_election/apps/elections/tests/test_election_constraints.py index 8877b1bbb..b1204f8f0 100644 --- a/every_election/apps/elections/tests/test_election_constraints.py +++ b/every_election/apps/elections/tests/test_election_constraints.py @@ -1,4 +1,9 @@ from django.test import TestCase +from elections.constraints import ( + has_approved_child, + has_approved_parents, + has_related_status, +) from elections.tests.factories import ( ElectionFactory, ElectionWithStatusFactory, @@ -6,11 +11,6 @@ ModerationStatusFactory, related_status, ) -from elections.constraints import ( - has_approved_child, - has_approved_parents, - has_related_status, -) class TestElectionModel(TestCase): diff --git a/every_election/apps/elections/tests/test_election_managers.py b/every_election/apps/elections/tests/test_election_managers.py index 2b45501ce..d66593ad4 100644 --- a/every_election/apps/elections/tests/test_election_managers.py +++ b/every_election/apps/elections/tests/test_election_managers.py @@ -1,8 +1,8 @@ from datetime import datetime, timedelta -from django.test import TestCase from django.contrib.gis.geos import Point - +from django.test import TestCase +from elections.models import Election from elections.tests.factories import ( ElectionFactory, ElectionWithStatusFactory, @@ -10,7 +10,6 @@ ModerationStatusFactory, related_status, ) -from elections.models import Election class TestElectionGeoQueries(TestCase): diff --git a/every_election/apps/elections/tests/test_election_model.py b/every_election/apps/elections/tests/test_election_model.py index 39e56bfcf..784e46ac5 100644 --- a/every_election/apps/elections/tests/test_election_model.py +++ b/every_election/apps/elections/tests/test_election_model.py @@ -1,7 +1,7 @@ -from freezegun import freeze_time +import contextlib -from django.utils import timezone from django.test import TestCase +from django.utils import timezone from elections.models import ( DEFAULT_STATUS, Election, @@ -10,6 +10,8 @@ ) from elections.tests.factories import ElectionFactory from elections.utils import ElectionBuilder +from freezegun import freeze_time + from .base_tests import BaseElectionCreatorMixIn @@ -73,7 +75,7 @@ def test_transaction_rollback_parent(self): # if we try to save parent_record self.election_group.organisation_id = "foo" - try: + with contextlib.suppress(ValueError): self.org_group.save() # the exception should have prevented both the @@ -88,7 +90,7 @@ def test_transaction_rollback_child(self): # if we try to save child_record self.org_group.organisation_id = "foo" - try: + with contextlib.suppress(ValueError): self.org_group.save() # the exception should have prevented both the diff --git a/every_election/apps/elections/tests/test_factories.py b/every_election/apps/elections/tests/test_factories.py index b93f7a178..e15e06dff 100644 --- a/every_election/apps/elections/tests/test_factories.py +++ b/every_election/apps/elections/tests/test_factories.py @@ -1,5 +1,4 @@ from django.test import TestCase - from elections.tests.factories import ElectionFactory diff --git a/every_election/apps/elections/tests/test_notice_directory.py b/every_election/apps/elections/tests/test_notice_directory.py index b3e440567..20aebd517 100644 --- a/every_election/apps/elections/tests/test_notice_directory.py +++ b/every_election/apps/elections/tests/test_notice_directory.py @@ -1,6 +1,6 @@ from django.test import TestCase -from elections.utils import get_notice_directory -from elections.utils import ElectionBuilder +from elections.utils import ElectionBuilder, get_notice_directory + from .base_tests import BaseElectionCreatorMixIn diff --git a/every_election/apps/elections/tests/test_utils.py b/every_election/apps/elections/tests/test_utils.py index 2bf38f039..cb563d589 100644 --- a/every_election/apps/elections/tests/test_utils.py +++ b/every_election/apps/elections/tests/test_utils.py @@ -1,6 +1,6 @@ import pytest -from elections.utils import get_voter_id_requirement from elections.tests.factories import ElectionFactory +from elections.utils import get_voter_id_requirement @pytest.mark.django_db diff --git a/every_election/apps/elections/tests/test_voting_systems.py b/every_election/apps/elections/tests/test_voting_systems.py index 22360f5b0..77d2cdaea 100644 --- a/every_election/apps/elections/tests/test_voting_systems.py +++ b/every_election/apps/elections/tests/test_voting_systems.py @@ -1,10 +1,9 @@ from django.test import TestCase - +from elections.models import ElectedRole from elections.utils import ElectionBuilder +from organisations.tests.factories import OrganisationFactory from .base_tests import BaseElectionCreatorMixIn -from elections.models import ElectedRole -from organisations.tests.factories import OrganisationFactory class TestElectoralSystems(BaseElectionCreatorMixIn, TestCase): @@ -18,7 +17,7 @@ def test_scotland_local_stv(self): election_id = ElectionBuilder( "local", "2017-05-04" ).build_election_group() - assert election_id.voting_system == None + assert election_id.voting_system is None # "Normal" UK local election is FPTP eng_org = OrganisationFactory(territory_code="ENG") diff --git a/every_election/apps/elections/urls.py b/every_election/apps/elections/urls.py index c9b7f0721..a446185e7 100644 --- a/every_election/apps/elections/urls.py +++ b/every_election/apps/elections/urls.py @@ -1,16 +1,15 @@ from django.urls import re_path +from elections.views.sync import get_election_fixture from .views import ( - AllElectionsView, CONDITION_DICT, - ElectionTypesView, FORMS, + AllElectionsView, + ElectionTypesView, IDCreatorWizard, ReferenceDefinitionView, SingleElection, ) -from elections.views.sync import get_election_fixture - id_creator_wizard = IDCreatorWizard.as_view( FORMS, diff --git a/every_election/apps/elections/utils.py b/every_election/apps/elections/utils.py index a3cb14e09..1d3d75291 100644 --- a/every_election/apps/elections/utils.py +++ b/every_election/apps/elections/utils.py @@ -1,26 +1,23 @@ from datetime import datetime from typing import Optional -from uk_election_ids.datapackage import VOTING_SYSTEMS -from uk_election_ids.metadata_tools import ( - VotingSystemMatcher, - IDRequirementsMatcher, -) - -from organisations.models import ( - Organisation, - OrganisationDivision, - OrganisationDivisionSet, -) from elections.models import ( - Election, ElectedRole, + Election, ElectionSubType, ElectionType, MetaData, ) - +from organisations.models import ( + Organisation, + OrganisationDivision, + OrganisationDivisionSet, +) from uk_election_ids.election_ids import IdBuilder +from uk_election_ids.metadata_tools import ( + IDRequirementsMatcher, + VotingSystemMatcher, +) CACHE = { "voting_systems": {}, @@ -73,17 +70,17 @@ def get_cached_valid_election_types(organisation): def get_cached_private_elections(date, election_id): - if not date in CACHE["private_elections"]: + if date not in CACHE["private_elections"]: qs = Election.private_objects.filter(poll_open_date=date) CACHE["private_elections"][date] = {e.election_id: e for e in qs} return CACHE["private_elections"][date].get(election_id) def get_cached_elected_role(organisation, election_type): - if not election_type in CACHE["elected_roles"]: + if election_type not in CACHE["elected_roles"]: CACHE["elected_roles"][election_type] = {} - if not organisation in CACHE["elected_roles"][election_type]: + if organisation not in CACHE["elected_roles"][election_type]: try: CACHE["elected_roles"][election_type][ organisation @@ -229,10 +226,9 @@ def get_elected_role(self): def get_voting_system(self): if not self.organisation: return None - slug = VotingSystemMatcher( + return VotingSystemMatcher( self.id.ids[-1], nation=self.organisation.territory_code ).get_voting_system() - return slug def get_seats_contested(self): if self.contest_type == "by": @@ -244,8 +240,7 @@ def get_seats_contested(self): if self.election_type.election_type != "local": if self.division and self.division.seats_total: return self.division.seats_total - else: - return 1 + return 1 """ If this is an all-up local election, we can fairly safely @@ -284,8 +279,7 @@ def to_title(self, id_type): ) if id_type == "subtype": return subtype_title - else: - parts.append(subtype_title) + parts.append(subtype_title) if self._use_org and self.organisation: if self.election_type.election_type == "mayor": @@ -315,24 +309,23 @@ def merge_dicts(d1, d2): ) if existing_election: return existing_election - else: - # return an instance of elections.models.Election - # but don't persist it to the DB yet. - # The calling code is responsible for calling .save() - return Election( - **merge_dicts( - record, - { - "poll_open_date": self.date, - "election_type": self.election_type, - "election_subtype": self.subtype, - "organisation": self.organisation, - "division": self.division, - "elected_role": self.get_elected_role(), - "voting_system": self.get_voting_system(), - }, - ) + # return an instance of elections.models.Election + # but don't persist it to the DB yet. + # The calling code is responsible for calling .save() + return Election( + **merge_dicts( + record, + { + "poll_open_date": self.date, + "election_type": self.election_type, + "election_subtype": self.subtype, + "organisation": self.organisation, + "division": self.division, + "elected_role": self.get_elected_role(), + "voting_system": self.get_voting_system(), + }, ) + ) def build_election_group(self): return self._build( @@ -453,10 +446,7 @@ def create_ids_for_each_ballot_paper(all_data, subtypes=None): # Special case where we have no divs for an org that should have them. # This is generally due to an upcoming ECO that's not been Made yet. # In this case, we want to make an org ID but no div IDs - if ( - all_data["election_type"].election_type == "local" - and f"{organisation.pk}_no_divs" in all_data - ): + if all_data["election_type"].election_type == "local" and f"{organisation.pk}_no_divs" in all_data: group_id = ( ElectionBuilder(all_data["election_type"], all_data["date"]) .with_organisation(organisation) @@ -504,7 +494,7 @@ def create_ids_for_each_ballot_paper(all_data, subtypes=None): for div, contest_type in div_data.items(): _, div_id, div_subtype = div.split("__") - if not div_subtype == subtype.election_subtype: + if div_subtype != subtype.election_subtype: continue org_div = OrganisationDivision.objects.get( @@ -537,7 +527,7 @@ def create_ids_for_each_ballot_paper(all_data, subtypes=None): % contest_type ) else: - all_division_ids = [div.split("__")[1] for div in div_data.keys()] + all_division_ids = [div.split("__")[1] for div in div_data] all_division_objects = { str(div.pk): div for div in OrganisationDivision.objects.filter( @@ -587,10 +577,7 @@ def get_notice_directory(elections): elif election.group_type == "organisation": organisation_group_id = election.election_id elif not election.group_type: - if ballot_count == 0: - ballot_id = election.election_id - else: - ballot_id = "" + ballot_id = election.election_id if ballot_count == 0 else "" ballot_count = ballot_count + 1 else: raise ValueError( @@ -599,9 +586,19 @@ def get_notice_directory(elections): if ballot_count == 1 and ballot_id: return ballot_id - elif organisation_group_id: + if organisation_group_id: + return organisation_group_id + if election_group_id: + return election_group_id + + # if we get here, something went wrong + # the function might have been called with an empty list + raise ValueError("Can't find an appropriate election id") + if ballot_count == 1 and ballot_id: + return ballot_id + if organisation_group_id: return organisation_group_id - elif election_group_id: + if election_group_id: return election_group_id # if we get here, something went wrong diff --git a/every_election/apps/elections/views/general.py b/every_election/apps/elections/views/general.py index e1e83c199..032114edd 100644 --- a/every_election/apps/elections/views/general.py +++ b/every_election/apps/elections/views/general.py @@ -1,13 +1,12 @@ from collections import OrderedDict +from core.helpers import user_is_moderator from django.contrib.auth.mixins import AccessMixin -from django.views.generic import ListView, DetailView, TemplateView from django.utils.html import mark_safe - -from core.helpers import user_is_moderator +from django.views.generic import DetailView, ListView, TemplateView from elections.constants import ELECTION_TYPES from elections.forms import NoticeOfElectionForm -from elections.models import ElectionType, Election, Document +from elections.models import Document, Election, ElectionType class ElectionTypesView(ListView): diff --git a/every_election/apps/elections/views/id_creator.py b/every_election/apps/elections/views/id_creator.py index 44bdce868..24c1af3ac 100644 --- a/every_election/apps/elections/views/id_creator.py +++ b/every_election/apps/elections/views/id_creator.py @@ -1,11 +1,18 @@ +from core.helpers import user_is_moderator +from django import forms from django.db import transaction from django.http import HttpResponseRedirect -from django import forms from django.utils.functional import cached_property -from formtools.wizard.views import NamedUrlSessionWizardView - -from core.helpers import user_is_moderator -from organisations.models import Organisation +from election_snooper.helpers import post_to_slack +from election_snooper.models import SnoopedElection +from elections.forms import ( + ElectionDateForm, + ElectionOrganisationDivisionForm, + ElectionOrganisationForm, + ElectionSourceForm, + ElectionSubTypeForm, + ElectionTypeForm, +) from elections.models import ( Document, ElectedRole, @@ -15,19 +22,10 @@ from elections.utils import ( create_ids_for_each_ballot_paper, get_notice_directory, + get_voter_id_requirement, ) -from elections.forms import ( - ElectionDateForm, - ElectionTypeForm, - ElectionSubTypeForm, - ElectionOrganisationForm, - ElectionOrganisationDivisionForm, - ElectionSourceForm, -) -from election_snooper.helpers import post_to_slack -from election_snooper.models import SnoopedElection -from elections.utils import get_voter_id_requirement - +from formtools.wizard.views import NamedUrlSessionWizardView +from organisations.models import Organisation FORMS = [ ("source", ElectionSourceForm), @@ -75,14 +73,13 @@ def select_organisation(wizard): return False qs = ElectedRole.objects.filter(election_type=election_type) - if qs.count() > 1: + if qs.count() < 1: return True - else: - wizard.storage.extra_data.update( - {"election_organisation": [qs[0].organisation.slug]} - ) + wizard.storage.extra_data.update( + {"election_organisation": [qs[0].organisation.slug]} + ) - return False + return False def select_subtype(wizard): @@ -121,6 +118,7 @@ def get_election_type(self): return self.get_cleaned_data_for_step("election_type").get( "election_type" ) + return None @cached_property def get_election_subtypes(self): @@ -128,6 +126,7 @@ def get_election_subtypes(self): return self.get_cleaned_data_for_step("election_subtype").get( "election_subtype" ) + return None @cached_property def get_organisations(self): @@ -136,12 +135,12 @@ def get_organisations(self): "election_organisation" ) if "election_organisation" in self.storage.extra_data: - qs = Organisation.objects.filter( + return Organisation.objects.filter( electedrole__election_type__election_type__in=self.storage.extra_data[ "election_organisation" ] ) - return qs + return None def get_election_date(self): election_date = self.get_cleaned_data_for_step("date") or {} @@ -195,7 +194,7 @@ def get_context_data(self, form, **kwargs): context = super().get_context_data(form=form, **kwargs) all_data = self.get_all_cleaned_data() # print("\n".join(str(all_data).split(','))) - if not "date" in all_data: + if "date" not in all_data: all_data["date"] = None all_data["election_organisation"] = self.get_organisations @@ -272,12 +271,11 @@ def done(self, form_list, **kwargs): for election in context["all_ids"]: # Mop up and pre-ECO metadata - if election.group_type == "organisation": - if ( - election.metadata - and election.metadata.description == "Pre-ECO election" - ): - election.metadata = None + if election.group_type == "organisation" and ( + election.metadata + and election.metadata.description == "Pre-ECO election" + ): + election.metadata = None election.requires_voter_id = get_voter_id_requirement(election) @@ -287,7 +285,7 @@ def done(self, form_list, **kwargs): not user_is_moderator(self.request.user) and len(context["all_ids"]) > 0 ): - ballots = [e for e in context["all_ids"] if e.group_type == None] + ballots = [e for e in context["all_ids"] if e.group_type is None] if len(ballots) == 1: message = """ New election {} suggested by anonymous user:\n diff --git a/every_election/apps/elections/views/sync.py b/every_election/apps/elections/views/sync.py index 31e62b0cc..6d80f24ca 100644 --- a/every_election/apps/elections/views/sync.py +++ b/every_election/apps/elections/views/sync.py @@ -1,10 +1,9 @@ import os + from django.conf import settings from django.http import HttpResponse def get_election_fixture(request): - with open( - os.path.join(settings.BASE_DIR, "data/elections.json") - ).read() as out: + with open(os.path.join(settings.BASE_DIR, "data/elections.json")).read() as out: return HttpResponse(out, status=200, content_type="application/json") diff --git a/every_election/apps/organisations/admin.py b/every_election/apps/organisations/admin.py index 7ca39d8e6..d3fec0988 100644 --- a/every_election/apps/organisations/admin.py +++ b/every_election/apps/organisations/admin.py @@ -9,12 +9,6 @@ OrganisationProblem, ) from organisations.views.admin.division_problem import DivisionProblemAdmin -from organisations.views.admin.organisation_problem import ( - OrganisationProblemAdmin, -) -from organisations.views.admin.organisation_geography_problem import ( - OrganisationGeographyProblemAdmin, -) from organisations.views.admin.organisation import OrganisationAdmin from organisations.views.admin.organisation_division import ( OrganisationDivisionAdmin, @@ -25,7 +19,12 @@ from organisations.views.admin.organisation_geography import ( OrganisationGeographyAdmin, ) - +from organisations.views.admin.organisation_geography_problem import ( + OrganisationGeographyProblemAdmin, +) +from organisations.views.admin.organisation_problem import ( + OrganisationProblemAdmin, +) admin.site.register(Organisation, OrganisationAdmin) admin.site.register(OrganisationDivision, OrganisationDivisionAdmin) diff --git a/every_election/apps/organisations/boundaries/boundaryline.py b/every_election/apps/organisations/boundaries/boundaryline.py index 845ed135a..4a18c0281 100644 --- a/every_election/apps/organisations/boundaries/boundaryline.py +++ b/every_election/apps/organisations/boundaries/boundaryline.py @@ -6,7 +6,6 @@ overlap_percent, ) - # Percentage overlap required for us to consider 2 divisions # 'the same' without manual investigation SANITY_CHECK_TOLERANCE = 97 @@ -24,7 +23,7 @@ def merge_features(self, features): for feat in features: if isinstance(feat.geom.geos, MultiPolygon): multipoly = feat.geom.geos - polygons = polygons + [poly for poly in multipoly] + polygons = polygons + list(multipoly) else: polygons.append(feat.geom.geos) @@ -92,12 +91,11 @@ def get_match_warning(self, div, match): + "but BoundaryLine shape for {code} only covers {percent:.2f}% " + "of {div}'s area. Manual review required." ) - warning = warning.format( + return warning.format( code=self.get_code_from_feature(match), div=div.official_identifier, percent=overlap, ) - return warning def get_division_code(self, div, org): filter_geom = OGRGeometry(org.geography.ewkt).transform( diff --git a/every_election/apps/organisations/boundaries/constants.py b/every_election/apps/organisations/boundaries/constants.py index fc935bdec..c5607bc62 100644 --- a/every_election/apps/organisations/boundaries/constants.py +++ b/every_election/apps/organisations/boundaries/constants.py @@ -1,6 +1,5 @@ from itertools import groupby - AREA_TYPE_TO_FILE = [ ("CED", "county_electoral_division_region.shp"), ("UTE", "unitary_electoral_division_region.shp"), @@ -27,7 +26,7 @@ def get_area_type_lookup(filter=lambda x: True, group=False): filtered = [a for a in AREA_TYPE_TO_FILE if filter(a[0])] - if group == True: + if group is True: lookup = {} for filename, types in groupby(filtered, lambda x: x[1]): lookup[tuple((rec[0] for rec in types))] = filename diff --git a/every_election/apps/organisations/boundaries/management/base.py b/every_election/apps/organisations/boundaries/management/base.py index 523ed2e5c..89473270c 100644 --- a/every_election/apps/organisations/boundaries/management/base.py +++ b/every_election/apps/organisations/boundaries/management/base.py @@ -1,7 +1,7 @@ import shutil -from django.core.management.base import BaseCommand from core.mixins import ReadFromFileMixin +from django.core.management.base import BaseCommand from organisations.models import ( DivisionGeography, OrganisationDivision, @@ -73,3 +73,6 @@ def import_div_geography(self, div, feature): self.stdout.write( "Importing boundary for area {}...saved".format(str(div)) ) + self.stdout.write( + "Importing boundary for area {}...saved".format(str(div)) + ) diff --git a/every_election/apps/organisations/boundaries/management/commands/boundaryline_backport_codes.py b/every_election/apps/organisations/boundaries/management/commands/boundaryline_backport_codes.py index 82f346d4c..cc6b9b1d0 100644 --- a/every_election/apps/organisations/boundaries/management/commands/boundaryline_backport_codes.py +++ b/every_election/apps/organisations/boundaries/management/commands/boundaryline_backport_codes.py @@ -17,11 +17,10 @@ from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.db import transaction - -from organisations.models import Organisation, OrganisationDivision from organisations.boundaries.boundaryline import BoundaryLine from organisations.boundaries.constants import get_area_type_lookup from organisations.boundaries.management.base import BaseBoundaryLineCommand +from organisations.models import Organisation, OrganisationDivision class Command(BaseBoundaryLineCommand): diff --git a/every_election/apps/organisations/boundaries/management/commands/boundaryline_import_boundaries.py b/every_election/apps/organisations/boundaries/management/commands/boundaryline_import_boundaries.py index a0d5f7f28..5144ffc18 100644 --- a/every_election/apps/organisations/boundaries/management/commands/boundaryline_import_boundaries.py +++ b/every_election/apps/organisations/boundaries/management/commands/boundaryline_import_boundaries.py @@ -14,20 +14,21 @@ import json import os import re + from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist -from organisations.models import ( - DivisionGeography, - OrganisationGeography, - OrganisationDivision, -) from organisations.boundaries.boundaryline import BoundaryLine from organisations.boundaries.constants import ( - get_area_type_lookup, SPECIAL_CASES, + get_area_type_lookup, ) -from organisations.boundaries.management.base import BaseBoundaryLineCommand from organisations.boundaries.helpers import split_code +from organisations.boundaries.management.base import BaseBoundaryLineCommand from organisations.constants import REGISTER_SUBTYPE_TO_BOUNDARYLINE_TYPE +from organisations.models import ( + DivisionGeography, + OrganisationDivision, + OrganisationGeography, +) from storage.shapefile import convert_geom_to_multipolygon @@ -225,7 +226,7 @@ def get_records(self, identifier, allow_multiple): def get_identifiers(self, options): if options["code"]: return [options["code"]] - with json.load(open(options["codes"])) as codes: + with json.load(open(options["codes"])) as codes: if not isinstance(codes, (list,)): raise ValueError("Root JSON element must be array []") return codes @@ -253,3 +254,8 @@ def handle(self, *args, **options): self.cleanup(self.base_dir) self.stdout.write("...done!") + + if self.cleanup_required: + self.cleanup(self.base_dir) + + self.stdout.write("...done!") diff --git a/every_election/apps/organisations/boundaries/osni.py b/every_election/apps/organisations/boundaries/osni.py index b7bcf0bad..e91d3fc00 100644 --- a/every_election/apps/organisations/boundaries/osni.py +++ b/every_election/apps/organisations/boundaries/osni.py @@ -1,8 +1,9 @@ import json import urllib.request from urllib.error import HTTPError -from retry import retry + from django.contrib.gis.geos import GEOSGeometry +from retry import retry from storage.shapefile import convert_geom_to_multipolygon @@ -29,8 +30,7 @@ def get_data_from_url(self, url): response.headers, response.fp, ) - data = response.read() - return data + return response.read() def __init__(self, url, gss_field, name_field): ds = json.loads(self.get_data_from_url(url).decode("utf-8")) diff --git a/every_election/apps/organisations/boundaries/tests/test_backport_codes.py b/every_election/apps/organisations/boundaries/tests/test_backport_codes.py index 732f0d242..9ecbdfd11 100644 --- a/every_election/apps/organisations/boundaries/tests/test_backport_codes.py +++ b/every_election/apps/organisations/boundaries/tests/test_backport_codes.py @@ -1,6 +1,7 @@ import os from datetime import date from io import StringIO + from django.test import TestCase from organisations.boundaries.management.commands.boundaryline_backport_codes import ( Command, @@ -48,8 +49,7 @@ def run_command_with_test_data(self): cmd.stdout = StringIO() cmd.handle(**self.opts) cmd.stdout.seek(0) - output = cmd.stdout.read() - return output + return cmd.stdout.read() def test_write(self): output = self.run_command_with_test_data() diff --git a/every_election/apps/organisations/boundaries/tests/test_import_boundaries.py b/every_election/apps/organisations/boundaries/tests/test_import_boundaries.py index 11bfcf468..2b05944e2 100644 --- a/every_election/apps/organisations/boundaries/tests/test_import_boundaries.py +++ b/every_election/apps/organisations/boundaries/tests/test_import_boundaries.py @@ -1,6 +1,7 @@ import os import tempfile from io import StringIO + from django.contrib.gis.geos import MultiPolygon from django.test import TestCase from organisations.boundaries.management.commands.boundaryline_import_boundaries import ( @@ -8,8 +9,8 @@ ) from organisations.models import ( DivisionGeography, - OrganisationGeography, OrganisationDivision, + OrganisationGeography, ) @@ -52,8 +53,7 @@ def run_command_with_test_data(self): cmd.stdout = StringIO() cmd.handle(**self.opts) cmd.stdout.seek(0) - output = cmd.stdout.read() - return output + return cmd.stdout.read() def test_import_division_not_found(self): # gss:X01000001 is not a valid division in our DB fixture @@ -241,3 +241,7 @@ def test_import_organisation(self): "imported in unit test", OrganisationGeography.objects.get(gss="E09000008").source, ) + self.assertEqual( + "imported in unit test", + OrganisationGeography.objects.get(gss="E09000008").source, + ) diff --git a/every_election/apps/organisations/boundaries/tests/test_osni_base_command.py b/every_election/apps/organisations/boundaries/tests/test_osni_base_command.py index 4b8f162a3..c24f2bc58 100644 --- a/every_election/apps/organisations/boundaries/tests/test_osni_base_command.py +++ b/every_election/apps/organisations/boundaries/tests/test_osni_base_command.py @@ -1,16 +1,16 @@ import json + from django.contrib.gis.geos import GEOSGeometry from django.test import TestCase from organisations.boundaries.management.base import BaseOsniCommand from organisations.models import DivisionGeography from organisations.tests.factories import ( DivisionGeographyFactory, - OrganisationFactory, OrganisationDivisionFactory, + OrganisationFactory, OrganisationGeographyFactory, ) - fake_record = { "geometry": GEOSGeometry( json.dumps( diff --git a/every_election/apps/organisations/boundaries/tests/test_osni_layer.py b/every_election/apps/organisations/boundaries/tests/test_osni_layer.py index d5693e0a7..839835095 100644 --- a/every_election/apps/organisations/boundaries/tests/test_osni_layer.py +++ b/every_election/apps/organisations/boundaries/tests/test_osni_layer.py @@ -3,7 +3,6 @@ from django.test import TestCase from organisations.boundaries.osni import OsniLayer - fake_data = b"""{ "type": "FeatureCollection", "features": [ diff --git a/every_election/apps/organisations/importers.py b/every_election/apps/organisations/importers.py index 263f9cb69..a7b918b29 100644 --- a/every_election/apps/organisations/importers.py +++ b/every_election/apps/organisations/importers.py @@ -3,14 +3,13 @@ import sys from difflib import ndiff +from django.conf import settings from django.contrib.gis.gdal import DataSource from django.db import transaction - -from django.conf import settings -from .models import ( - OrganisationDivisionSet, - OrganisationDivision, +from organisations.models import ( DivisionGeography, + OrganisationDivision, + OrganisationDivisionSet, ) from storage.shapefile import pre_process_layer @@ -76,9 +75,9 @@ def make_name_map(self, legislation_names, boundary_names): legislation_names = set(legislation_names) boundary_names = set(boundary_names) - missing_from_leg = sorted(list(boundary_names - legislation_names)) + missing_from_leg = sorted(boundary_names - legislation_names) map = {} - for name in sorted(list(legislation_names)): + for name in sorted(legislation_names): if name not in boundary_names: self.stdout.write( inspect.cleandoc( @@ -122,19 +121,21 @@ def check_names(self): % (len(legislation_names), len(boundary_names)) ) if legislation_names != boundary_names: - map_data = self.make_name_map(legislation_names, boundary_names) - if map_data: + diff = ndiff(legislation_names, boundary_names) + try: + map_data = self.make_name_map(legislation_names, boundary_names) self.stdout.write( "\nYou need to save this file as `name_map.json`:" ) self.stdout.write(json.dumps(map_data, indent=4)) raise MapCreationNeededException() - else: + except DiffException("legislation_names != boundary_names", diff): # create a 'diff' of the 2 lists # so we can work out what we need to fix self.stdout.write( "The names in the input file don't match the names in the legislation" ) + return True diff --git a/every_election/apps/organisations/management/commands/copy_divisions.py b/every_election/apps/organisations/management/commands/copy_divisions.py index 28b67cfd4..86afda2e9 100644 --- a/every_election/apps/organisations/management/commands/copy_divisions.py +++ b/every_election/apps/organisations/management/commands/copy_divisions.py @@ -1,6 +1,6 @@ from django.core.management.base import BaseCommand from django.db import transaction -from organisations.models import OrganisationDivisionSet, OrganisationDivision +from organisations.models import OrganisationDivision, OrganisationDivisionSet class Command(BaseCommand): diff --git a/every_election/apps/organisations/management/commands/import_divisionsets_from_csv.py b/every_election/apps/organisations/management/commands/import_divisionsets_from_csv.py index f20574dff..78f68e532 100644 --- a/every_election/apps/organisations/management/commands/import_divisionsets_from_csv.py +++ b/every_election/apps/organisations/management/commands/import_divisionsets_from_csv.py @@ -14,21 +14,20 @@ import datetime +from core.mixins import ReadFromCSVMixin from django.conf import settings from django.core.management.base import BaseCommand from django.db import transaction from django.utils.text import slugify - +from organisations.constants import ( + ORG_CURIE_TO_MAPIT_AREA_TYPE, + PARENT_TO_CHILD_AREAS, +) from organisations.models import ( Organisation, OrganisationDivision, OrganisationDivisionSet, ) -from organisations.constants import ( - ORG_CURIE_TO_MAPIT_AREA_TYPE, - PARENT_TO_CHILD_AREAS, -) -from core.mixins import ReadFromCSVMixin class Command(ReadFromCSVMixin, BaseCommand): @@ -68,15 +67,14 @@ def get_org_from_line(self, line): line["Start Date"], "%Y-%m-%d" ).date(), ) - else: - # If we haven't got a start date for the divisionset, see if we can - # work out the org without needing one (mostly we can). - # If we throw an exception here, we will need to call this again - # with a start date on this divisionset - return Organisation.objects.get( - organisation_type="local-authority", - official_identifier=line["Organisation ID"], - ) + # If we haven't got a start date for the divisionset, see if we can + # work out the org without needing one (mostly we can). + # If we throw an exception here, we will need to call this again + # with a start date on this divisionset + return Organisation.objects.get( + organisation_type="local-authority", + official_identifier=line["Organisation ID"], + ) def get_start_date(self, org): # Given an org, work out the start date for a new division set @@ -153,7 +151,7 @@ def create_div_from_line(self, div_set, identifier, line): if not seats_total: seats_total = 1 - div = OrganisationDivision( + return OrganisationDivision( official_identifier=identifier, temp_id=identifier, name=line["Name"], @@ -181,3 +179,8 @@ def save_all(self): # https://github.com/django/django/commit/519016e5f25d7c0a040015724f9920581551cab0 record.divisionset = record.divisionset record.save() + # hack: see https://code.djangoproject.com/ticket/29085 + # This should fix it when we use Django>=3.03: + # https://github.com/django/django/commit/519016e5f25d7c0a040015724f9920581551cab0 + record.divisionset = record.divisionset + record.save() diff --git a/every_election/apps/organisations/management/commands/import_lgbce.py b/every_election/apps/organisations/management/commands/import_lgbce.py index eaa903734..f3b2c279f 100644 --- a/every_election/apps/organisations/management/commands/import_lgbce.py +++ b/every_election/apps/organisations/management/commands/import_lgbce.py @@ -18,13 +18,14 @@ import json import os import shutil + from botocore.exceptions import ClientError from django.conf import settings from django.contrib.gis.gdal import DataSource from django.core.management.base import BaseCommand from organisations.importers import ( - DivisionSetGeographyImporter, DiffException, + DivisionSetGeographyImporter, MapCreationNeededException, ) from organisations.models import Organisation, OrganisationDivisionSet @@ -118,7 +119,8 @@ def get_name_map(self, filepath): # by adding a name_map.json file to the same S3 directory # where the shape files are saved f = s3.get_file(basepath + "/name_map.json") - return json.load(open(f.name)) + with json.load(open(f.name)) as name: + return name except ClientError as e: if int(e.response["Error"]["Code"]) == 404: # if we didn't find any name map file, return an empty map diff --git a/every_election/apps/organisations/management/commands/import_seats_total_for_divisionset.py b/every_election/apps/organisations/management/commands/import_seats_total_for_divisionset.py index 244b23170..4e1e3d854 100644 --- a/every_election/apps/organisations/management/commands/import_seats_total_for_divisionset.py +++ b/every_election/apps/organisations/management/commands/import_seats_total_for_divisionset.py @@ -1,7 +1,6 @@ -from django.core.management.base import BaseCommand - from core.mixins import ReadFromCSVMixin -from organisations.models import OrganisationDivisionSet, OrganisationDivision +from django.core.management.base import BaseCommand +from organisations.models import OrganisationDivision, OrganisationDivisionSet class Command(ReadFromCSVMixin, BaseCommand): @@ -31,7 +30,7 @@ def handle(self, *args, **options): division_names = set( division_set.divisions.values_list("name", flat=True) ) - csv_names = set([r["name"] for r in csv_data]) + csv_names = {r["name"] for r in csv_data} if division_names != csv_names: self.stderr.write("Name mismatch") self.stderr.write("==============") diff --git a/every_election/apps/organisations/management/commands/list_divisions_without_geography.py b/every_election/apps/organisations/management/commands/list_divisions_without_geography.py index 66879e8d0..dc5f29bb8 100644 --- a/every_election/apps/organisations/management/commands/list_divisions_without_geography.py +++ b/every_election/apps/organisations/management/commands/list_divisions_without_geography.py @@ -1,7 +1,6 @@ from datetime import datetime from django.core.management.base import BaseCommand - from organisations.models import Organisation, OrganisationDivision diff --git a/every_election/apps/organisations/management/commands/ni_import_district_electoral_areas.py b/every_election/apps/organisations/management/commands/ni_import_district_electoral_areas.py index 9389d3557..d5d830d5d 100644 --- a/every_election/apps/organisations/management/commands/ni_import_district_electoral_areas.py +++ b/every_election/apps/organisations/management/commands/ni_import_district_electoral_areas.py @@ -1,17 +1,15 @@ import datetime +from core.mixins import ReadFromCSVMixin from django.core.management.base import BaseCommand from django.db import transaction from django.utils.text import slugify - from organisations.models import ( Organisation, OrganisationDivision, OrganisationDivisionSet, ) -from core.mixins import ReadFromCSVMixin - class Command(ReadFromCSVMixin, BaseCommand): """ @@ -87,3 +85,6 @@ def save_all(self): # https://github.com/django/django/commit/519016e5f25d7c0a040015724f9920581551cab0 record.divisionset = record.divisionset record.save() + # https://github.com/django/django/commit/519016e5f25d7c0a040015724f9920581551cab0 + record.divisionset = record.divisionset + record.save() diff --git a/every_election/apps/organisations/management/commands/populate_subdivided_tables.py b/every_election/apps/organisations/management/commands/populate_subdivided_tables.py index 092653375..901b34805 100644 --- a/every_election/apps/organisations/management/commands/populate_subdivided_tables.py +++ b/every_election/apps/organisations/management/commands/populate_subdivided_tables.py @@ -1,8 +1,8 @@ -from django.db import connection from django.core.management.base import BaseCommand +from django.db import connection from organisations.models import ( - OrganisationGeographySubdivided, DivisionGeographySubdivided, + OrganisationGeographySubdivided, ) @@ -15,3 +15,5 @@ def handle(self, *args, **options): cursor.execute(OrganisationGeographySubdivided.POPULATE_SQL) self.stdout.write("Divs") cursor.execute(DivisionGeographySubdivided.POPULATE_SQL) + self.stdout.write("Divs") + cursor.execute(DivisionGeographySubdivided.POPULATE_SQL) diff --git a/every_election/apps/organisations/management/commands/set_division_territory_code.py b/every_election/apps/organisations/management/commands/set_division_territory_code.py index dfcea789f..e0a63a2c2 100644 --- a/every_election/apps/organisations/management/commands/set_division_territory_code.py +++ b/every_election/apps/organisations/management/commands/set_division_territory_code.py @@ -1,7 +1,6 @@ from typing import List from django.core.management.base import BaseCommand - from organisations.models import Organisation, OrganisationDivision GSS_TO_NATION = { @@ -144,7 +143,7 @@ def assign_by_centre(self): divisionset__organisation__slug__in=["parl", "europarl"] ) ) - codes = set([parent.territory_code for parent in parents]) + codes = {parent.territory_code for parent in parents} if len(codes) > 1: self.stdout.write( f"WARNING: {division} has more than one territory: {parents} / {codes}" diff --git a/every_election/apps/organisations/management/commands/update_end_dates.py b/every_election/apps/organisations/management/commands/update_end_dates.py index 009ed85b1..09de22d42 100644 --- a/every_election/apps/organisations/management/commands/update_end_dates.py +++ b/every_election/apps/organisations/management/commands/update_end_dates.py @@ -22,10 +22,9 @@ import datetime from collections import namedtuple +from core.mixins import ReadFromCSVMixin from django.conf import settings from django.core.management.base import BaseCommand - -from core.mixins import ReadFromCSVMixin from organisations.models import Organisation, OrganisationDivisionSet diff --git a/every_election/apps/organisations/migrations/0006_organisationdivision.py b/every_election/apps/organisations/migrations/0006_organisationdivision.py index 8330da20a..cf68293ea 100644 --- a/every_election/apps/organisations/migrations/0006_organisationdivision.py +++ b/every_election/apps/organisations/migrations/0006_organisationdivision.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2016-10-11 19:18 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0012_auto_20170111_1441.py b/every_election/apps/organisations/migrations/0012_auto_20170111_1441.py index e9d26c31f..15551b9ce 100644 --- a/every_election/apps/organisations/migrations/0012_auto_20170111_1441.py +++ b/every_election/apps/organisations/migrations/0012_auto_20170111_1441.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-01-11 14:41 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0021_remove_old_police_forces.py b/every_election/apps/organisations/migrations/0021_remove_old_police_forces.py index a1001fcd2..1795792bb 100644 --- a/every_election/apps/organisations/migrations/0021_remove_old_police_forces.py +++ b/every_election/apps/organisations/migrations/0021_remove_old_police_forces.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals from django.db import migrations - from organisations import constants diff --git a/every_election/apps/organisations/migrations/0022_divisiongeography.py b/every_election/apps/organisations/migrations/0022_divisiongeography.py index e64df1cac..99d3eb446 100644 --- a/every_election/apps/organisations/migrations/0022_divisiongeography.py +++ b/every_election/apps/organisations/migrations/0022_divisiongeography.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import django.contrib.gis.db.models.fields -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0023_auto_20170203_1802.py b/every_election/apps/organisations/migrations/0023_auto_20170203_1802.py index dbee4cf61..fb85e9ff6 100644 --- a/every_election/apps/organisations/migrations/0023_auto_20170203_1802.py +++ b/every_election/apps/organisations/migrations/0023_auto_20170203_1802.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.2 on 2017-02-03 18:02 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0024_auto_20170210_1537.py b/every_election/apps/organisations/migrations/0024_auto_20170210_1537.py index aa59a6961..853daecff 100644 --- a/every_election/apps/organisations/migrations/0024_auto_20170210_1537.py +++ b/every_election/apps/organisations/migrations/0024_auto_20170210_1537.py @@ -2,7 +2,6 @@ # Generated by Django 1.10.2 on 2017-02-10 15:37 from __future__ import unicode_literals -import django.contrib.gis.db.models.fields from django.db import migrations diff --git a/every_election/apps/organisations/migrations/0026_auto_20171207_1417.py b/every_election/apps/organisations/migrations/0026_auto_20171207_1417.py index de76e0a15..786387411 100644 --- a/every_election/apps/organisations/migrations/0026_auto_20171207_1417.py +++ b/every_election/apps/organisations/migrations/0026_auto_20171207_1417.py @@ -13,8 +13,6 @@ class Migration(migrations.Migration): operations = [ migrations.AlterUniqueTogether( name="organisationdivision", - unique_together={ - ("organisation", "divisionset", "official_identifier") - }, + unique_together={("organisation", "divisionset", "official_identifier")}, ) ] diff --git a/every_election/apps/organisations/migrations/0027_auto_20171208_1049.py b/every_election/apps/organisations/migrations/0027_auto_20171208_1049.py index 6ca7acd79..4604c57a6 100644 --- a/every_election/apps/organisations/migrations/0027_auto_20171208_1049.py +++ b/every_election/apps/organisations/migrations/0027_auto_20171208_1049.py @@ -2,8 +2,8 @@ # Generated by Django 1.10.6 on 2017-12-08 10:49 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0028_auto_20171214_1331.py b/every_election/apps/organisations/migrations/0028_auto_20171214_1331.py index ded099049..a30ca8265 100644 --- a/every_election/apps/organisations/migrations/0028_auto_20171214_1331.py +++ b/every_election/apps/organisations/migrations/0028_auto_20171214_1331.py @@ -16,6 +16,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name="organisationdivisionset", - unique_together=set([("organisation", "start_date")]), + unique_together={("organisation", "start_date")}, ), ] diff --git a/every_election/apps/organisations/migrations/0030_auto_20171230_1602.py b/every_election/apps/organisations/migrations/0030_auto_20171230_1602.py index 31053a2ec..fedc9f958 100644 --- a/every_election/apps/organisations/migrations/0030_auto_20171230_1602.py +++ b/every_election/apps/organisations/migrations/0030_auto_20171230_1602.py @@ -11,6 +11,6 @@ class Migration(migrations.Migration): operations = [ migrations.AlterUniqueTogether( name="organisationdivisionset", - unique_together=set([("organisation", "end_date")]), + unique_together={("organisation", "end_date")}, ) ] diff --git a/every_election/apps/organisations/migrations/0032_auto_20180531_1000.py b/every_election/apps/organisations/migrations/0032_auto_20180531_1000.py index 4fde4a821..832a1d1d5 100644 --- a/every_election/apps/organisations/migrations/0032_auto_20180531_1000.py +++ b/every_election/apps/organisations/migrations/0032_auto_20180531_1000.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import datetime + from django.db import migrations, models diff --git a/every_election/apps/organisations/migrations/0033_auto_20180605_0911.py b/every_election/apps/organisations/migrations/0033_auto_20180605_0911.py index 9a5aba8f6..bc8a75509 100644 --- a/every_election/apps/organisations/migrations/0033_auto_20180605_0911.py +++ b/every_election/apps/organisations/migrations/0033_auto_20180605_0911.py @@ -15,8 +15,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name="organisation", - unique_together={ - ("official_identifier", "organisation_type", "end_date") - }, + unique_together={("official_identifier", "organisation_type", "end_date")}, ), ] diff --git a/every_election/apps/organisations/migrations/0037_organisationgeography.py b/every_election/apps/organisations/migrations/0037_organisationgeography.py index 315ae7c62..7292f501c 100644 --- a/every_election/apps/organisations/migrations/0037_organisationgeography.py +++ b/every_election/apps/organisations/migrations/0037_organisationgeography.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import django.contrib.gis.db.models.fields -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0039_auto_20180607_0957.py b/every_election/apps/organisations/migrations/0039_auto_20180607_0957.py index 5619a7238..f68a57401 100644 --- a/every_election/apps/organisations/migrations/0039_auto_20180607_0957.py +++ b/every_election/apps/organisations/migrations/0039_auto_20180607_0957.py @@ -18,6 +18,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name="organisationgeography", - unique_together=set([("organisation", "end_date")]), + unique_together={("organisation", "end_date")}, ), ] diff --git a/every_election/apps/organisations/migrations/0043_auto_20180607_1337.py b/every_election/apps/organisations/migrations/0043_auto_20180607_1337.py index 1af1c03a2..5bb53e13e 100644 --- a/every_election/apps/organisations/migrations/0043_auto_20180607_1337.py +++ b/every_election/apps/organisations/migrations/0043_auto_20180607_1337.py @@ -2,8 +2,8 @@ # Generated by Django 1.11.13 on 2018-06-07 13:37 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0044_auto_20180619_1200.py b/every_election/apps/organisations/migrations/0044_auto_20180619_1200.py index b9d9e5360..fb521eec8 100644 --- a/every_election/apps/organisations/migrations/0044_auto_20180619_1200.py +++ b/every_election/apps/organisations/migrations/0044_auto_20180619_1200.py @@ -12,15 +12,12 @@ class Migration(migrations.Migration): migrations.AlterUniqueTogether( name="organisation", unique_together={ - ("official_identifier", "organisation_type", "start_date"), - ("official_identifier", "organisation_type", "end_date"), - }, + ("official_identifier", "organisation_type", "start_date"), + ("official_identifier", "organisation_type", "end_date"), + }, ), migrations.AlterUniqueTogether( name="organisationgeography", - unique_together={ - ("organisation", "end_date"), - ("organisation", "start_date"), - }, + unique_together={("organisation", "end_date"), ("organisation", "start_date")}, ), ] diff --git a/every_election/apps/organisations/migrations/0061_auto_20210928_1509.py b/every_election/apps/organisations/migrations/0061_auto_20210928_1509.py index a3a83dd8d..7f6414f44 100644 --- a/every_election/apps/organisations/migrations/0061_auto_20210928_1509.py +++ b/every_election/apps/organisations/migrations/0061_auto_20210928_1509.py @@ -1,8 +1,8 @@ # Generated by Django 2.2.20 on 2021-09-28 15:09 -from django.db import migrations import django.utils.timezone import django_extensions.db.fields +from django.db import migrations class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/migrations/0062_add_created_date.py b/every_election/apps/organisations/migrations/0062_add_created_date.py index c3e3afb1c..e3629a324 100644 --- a/every_election/apps/organisations/migrations/0062_add_created_date.py +++ b/every_election/apps/organisations/migrations/0062_add_created_date.py @@ -1,7 +1,6 @@ # Generated by Django 2.2.20 on 2021-09-28 16:03 from django.db import migrations - from django.db.models import F, OuterRef, Subquery diff --git a/every_election/apps/organisations/migrations/0064_organisationgeographysubdivided_and_more.py b/every_election/apps/organisations/migrations/0064_organisationgeographysubdivided_and_more.py index fc67d6573..54c5a5a83 100644 --- a/every_election/apps/organisations/migrations/0064_organisationgeographysubdivided_and_more.py +++ b/every_election/apps/organisations/migrations/0064_organisationgeographysubdivided_and_more.py @@ -1,8 +1,8 @@ # Generated by Django 4.1.7 on 2023-03-28 14:32 import django.contrib.gis.db.models.fields -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/every_election/apps/organisations/models/__init__.py b/every_election/apps/organisations/models/__init__.py index 19e5bd07f..108b7c22c 100644 --- a/every_election/apps/organisations/models/__init__.py +++ b/every_election/apps/organisations/models/__init__.py @@ -1,29 +1,23 @@ -from organisations.models.organisations import ( - Organisation, - OrganisationGeography, - OrganisationGeographySubdivided, +from organisations.models.admin import ( + DivisionProblem, + OrganisationGeographyProblem, + OrganisationProblem, ) from organisations.models.divisions import ( - OrganisationDivisionSet, - OrganisationDivision, DivisionGeography, DivisionGeographySubdivided, + OrganisationDivision, + OrganisationDivisionSet, ) -from organisations.models.admin import ( - DivisionProblem, - OrganisationProblem, - OrganisationGeographyProblem, +from organisations.models.organisations import ( + Organisation, + OrganisationGeography, + OrganisationGeographySubdivided, ) __all__ = [ - "DivisionProblem", - "OrganisationProblem", - "OrganisationGeographyProblem", - "Organisation", - "OrganisationGeography", - "OrganisationGeographySubdivided", - "OrganisationDivisionSet", - "OrganisationDivision", - "DivisionGeography", - "DivisionGeographySubdivided", + "DivisionProblem", "OrganisationProblem", "OrganisationGeographyProblem", + "Organisation", "OrganisationGeography", "OrganisationGeographySubdivided", + "OrganisationDivisionSet", "OrganisationDivision", "DivisionGeography", + "DivisionGeographySubdivided" ] diff --git a/every_election/apps/organisations/models/admin.py b/every_election/apps/organisations/models/admin.py index 252720d02..81d8667c8 100644 --- a/every_election/apps/organisations/models/admin.py +++ b/every_election/apps/organisations/models/admin.py @@ -6,10 +6,12 @@ """ from datetime import datetime + from django.contrib.gis.db.models import Q from django.db.models import Manager -from .organisations import Organisation, OrganisationGeography + from .divisions import OrganisationDivision +from .organisations import Organisation, OrganisationGeography INVALID_SOURCES = ("unknown", "lgbce", "") @@ -23,7 +25,7 @@ def get_queryset(self): # so we'll ignore DivisionSets with a future start_date in this report qs = qs.filter(divisionset__start_date__lte=datetime.today()) - qs = qs.filter( + return qs.filter( ( # we always want divisions to have # an associated geography record @@ -44,7 +46,6 @@ def get_queryset(self): & ~Q(division_type="NIE") ) ) - return qs class DivisionProblem(OrganisationDivision): @@ -87,7 +88,7 @@ class OrganisationProblemManager(Manager): def get_queryset(self): qs = super().get_queryset() - qs = qs.filter( + return qs.filter( ( # we always want Organisations to have at least # one related OrganisationGeography record @@ -113,7 +114,6 @@ def get_queryset(self): ) ) - return qs class OrganisationProblem(Organisation): objects = OrganisationProblemManager() @@ -149,7 +149,7 @@ class OrganisationGeographyProblemManager(Manager): def get_queryset(self): qs = super().get_queryset() - qs = qs.filter( + return qs.filter( ( # OrganisationGeographies should have a GSS code...mostly Q(gss="") @@ -167,7 +167,6 @@ def get_queryset(self): ) ) - return qs class OrganisationGeographyProblem(OrganisationGeography): objects = OrganisationGeographyProblemManager() diff --git a/every_election/apps/organisations/models/divisions.py b/every_election/apps/organisations/models/divisions.py index ccac02d03..b4f6ea2bf 100644 --- a/every_election/apps/organisations/models/divisions.py +++ b/every_election/apps/organisations/models/divisions.py @@ -1,6 +1,5 @@ -from django.contrib.gis.db import models - from core.mixins import UpdateElectionsTimestampedModel +from django.contrib.gis.db import models from .mixins import DateConstraintMixin, DateDisplayMixin diff --git a/every_election/apps/organisations/models/mixins.py b/every_election/apps/organisations/models/mixins.py index 2bb8fb822..e20e9c63b 100644 --- a/every_election/apps/organisations/models/mixins.py +++ b/every_election/apps/organisations/models/mixins.py @@ -8,8 +8,7 @@ def active_period_text(self): text = f"{self.start_date.strftime('%d %b %Y')}" if self.end_date: return f"{text} to {self.end_date.strftime('%d %b %Y')}" - else: - return f"{text} onwards" + return f"{text} onwards" class DateConstraintMixin: diff --git a/every_election/apps/organisations/models/organisations.py b/every_election/apps/organisations/models/organisations.py index 9f5632205..eaa4d6654 100644 --- a/every_election/apps/organisations/models/organisations.py +++ b/every_election/apps/organisations/models/organisations.py @@ -1,9 +1,8 @@ +from core.mixins import UpdateElectionsTimestampedModel from django.contrib.gis.db import models from django.urls import reverse - from model_utils import Choices -from core.mixins import UpdateElectionsTimestampedModel from .mixins import DateConstraintMixin, DateDisplayMixin @@ -109,7 +108,7 @@ def format_geography_link(self): def get_geography(self, date): if len(self.geographies.all()) == 0: - return None + return None elif len(self.geographies.all()) == 1: return self.geographies.all()[0] else: @@ -123,6 +122,8 @@ def get_geography(self, date): "date %s is after organisation end_date (%s)" % (date.isoformat(), self.end_date.isoformat()) ) + + try: return self.geographies.get( (models.Q(start_date__lte=date) | models.Q(start_date=None)) diff --git a/every_election/apps/organisations/tests/factories.py b/every_election/apps/organisations/tests/factories.py index d6fd79a63..dfbc75842 100644 --- a/every_election/apps/organisations/tests/factories.py +++ b/every_election/apps/organisations/tests/factories.py @@ -1,13 +1,13 @@ from datetime import date -import factory +import factory from organisations.models import ( + DivisionGeography, + DivisionGeographySubdivided, Organisation, - OrganisationDivisionSet, OrganisationDivision, + OrganisationDivisionSet, OrganisationGeography, - DivisionGeography, - DivisionGeographySubdivided, OrganisationGeographySubdivided, ) @@ -121,3 +121,6 @@ def subdivide(self: OrganisationGeography, create, extracted, **kwargs): SubdividedOrganisationGeographyFactory( organisation_geography=self, geography=geom ) + SubdividedOrganisationGeographyFactory( + organisation_geography=self, geography=geom + ) diff --git a/every_election/apps/organisations/tests/test_admin.py b/every_election/apps/organisations/tests/test_admin.py index 1ecb848d3..c41c1a3b2 100644 --- a/every_election/apps/organisations/tests/test_admin.py +++ b/every_election/apps/organisations/tests/test_admin.py @@ -1,19 +1,17 @@ from django.test import TestCase - +from elections.tests.factories import ElectedRoleFactory from organisations.models import ( DivisionProblem, - OrganisationProblem, OrganisationGeographyProblem, + OrganisationProblem, ) - from organisations.tests.factories import ( DivisionGeographyFactory, - OrganisationFactory, OrganisationDivisionFactory, OrganisationDivisionSetFactory, + OrganisationFactory, OrganisationGeographyFactory, ) -from elections.tests.factories import ElectedRoleFactory class OrganisationProblemTests(TestCase): diff --git a/every_election/apps/organisations/tests/test_division_sets.py b/every_election/apps/organisations/tests/test_division_sets.py index 0e7158fde..e24d8c0ab 100644 --- a/every_election/apps/organisations/tests/test_division_sets.py +++ b/every_election/apps/organisations/tests/test_division_sets.py @@ -1,11 +1,10 @@ import pytest - +from elections.tests.factories import ElectedRoleFactory +from elections.utils import ElectionBuilder from organisations.tests.factories import ( - OrganisationDivisionSetFactory, OrganisationDivisionFactory, + OrganisationDivisionSetFactory, ) -from elections.utils import ElectionBuilder -from elections.tests.factories import ElectedRoleFactory def test_division_set_by_date(db): diff --git a/every_election/apps/organisations/tests/test_factories.py b/every_election/apps/organisations/tests/test_factories.py index b74f9f83c..236c74595 100644 --- a/every_election/apps/organisations/tests/test_factories.py +++ b/every_election/apps/organisations/tests/test_factories.py @@ -1,10 +1,9 @@ from django.test import TestCase - from organisations.tests.factories import ( - OrganisationFactory, - OrganisationDivisionSetFactory, - OrganisationDivisionFactory, DivisionGeographyFactory, + OrganisationDivisionFactory, + OrganisationDivisionSetFactory, + OrganisationFactory, ) diff --git a/every_election/apps/organisations/tests/test_import_divisionsets_from_csv.py b/every_election/apps/organisations/tests/test_import_divisionsets_from_csv.py index 81e6b2f22..656350afe 100644 --- a/every_election/apps/organisations/tests/test_import_divisionsets_from_csv.py +++ b/every_election/apps/organisations/tests/test_import_divisionsets_from_csv.py @@ -1,9 +1,10 @@ from datetime import date + from django.test import TestCase -from organisations.models import Organisation, OrganisationDivisionSet from organisations.management.commands.import_divisionsets_from_csv import ( Command, ) +from organisations.models import Organisation, OrganisationDivisionSet class ImportDivisionSetsFromCsvTests(TestCase): diff --git a/every_election/apps/organisations/tests/test_import_lgbce.py b/every_election/apps/organisations/tests/test_import_lgbce.py index f9785e8cb..5760a090b 100644 --- a/every_election/apps/organisations/tests/test_import_lgbce.py +++ b/every_election/apps/organisations/tests/test_import_lgbce.py @@ -1,17 +1,18 @@ -from datetime import date import os import tempfile +from datetime import date from io import StringIO + from django.contrib.gis.gdal import DataSource -from django.utils.text import slugify from django.test import TestCase +from django.utils.text import slugify +from organisations.management.commands.import_lgbce import Command from organisations.models import ( DivisionGeography, Organisation, OrganisationDivision, OrganisationDivisionSet, ) -from organisations.management.commands.import_lgbce import Command class ImportLgbceTests(TestCase): @@ -87,8 +88,7 @@ def run_import_with_test_data(self, org, name_map): cmd.stderr = StringIO() cmd.handle(**args) cmd.stderr.seek(0) - error_output = cmd.stderr.read() - return error_output + return cmd.stderr.read() def test_org_not_found(self): with self.assertRaises(Organisation.DoesNotExist): @@ -165,3 +165,6 @@ def test_divisionset_has_related_geographies(self): # because the divisionset has related geographies now with self.assertRaises(Exception): self.run_import_with_test_data(self.valid_org_code, name_map) + # because the divisionset has related geographies now + with self.assertRaises(Exception): + self.run_import_with_test_data(self.valid_org_code, name_map) diff --git a/every_election/apps/organisations/tests/test_organisation_models.py b/every_election/apps/organisations/tests/test_organisation_models.py index 53f641887..b8f308c06 100644 --- a/every_election/apps/organisations/tests/test_organisation_models.py +++ b/every_election/apps/organisations/tests/test_organisation_models.py @@ -1,16 +1,16 @@ from datetime import date + from django.core.exceptions import ValidationError from django.test import TestCase +from elections.tests.factories import ElectionFactory from organisations.models import Organisation from organisations.tests.factories import ( - OrganisationFactory, - OrganisationGeographyFactory, OrganisationDivisionFactory, OrganisationDivisionSetFactory, + OrganisationFactory, + OrganisationGeographyFactory, ) -from elections.tests.factories import ElectionFactory - class TestOrganisationManager(TestCase): def setUp(self): diff --git a/every_election/apps/organisations/tests/test_update_end_dates.py b/every_election/apps/organisations/tests/test_update_end_dates.py index 0e615edae..2da1e1fd4 100644 --- a/every_election/apps/organisations/tests/test_update_end_dates.py +++ b/every_election/apps/organisations/tests/test_update_end_dates.py @@ -1,9 +1,10 @@ +import os from datetime import date from io import StringIO -import os + from django.test import TestCase -from organisations.models import Organisation, OrganisationDivisionSet from organisations.management.commands.update_end_dates import Command +from organisations.models import Organisation, OrganisationDivisionSet class UpdateEndDatesTests(TestCase): diff --git a/every_election/apps/organisations/urls.py b/every_election/apps/organisations/urls.py index e1d756ae6..e2c971846 100644 --- a/every_election/apps/organisations/urls.py +++ b/every_election/apps/organisations/urls.py @@ -1,12 +1,11 @@ from django.urls import re_path from .views import ( - SupportedOrganisationsView, OrganisationDetailView, OrganisationsFilterView, + SupportedOrganisationsView, ) - urlpatterns = [ re_path( r"^$", SupportedOrganisationsView.as_view(), name="organisations_view" diff --git a/every_election/apps/organisations/views/admin/organisation_division.py b/every_election/apps/organisations/views/admin/organisation_division.py index d87b04b03..73dfd3890 100644 --- a/every_election/apps/organisations/views/admin/organisation_division.py +++ b/every_election/apps/organisations/views/admin/organisation_division.py @@ -1,6 +1,7 @@ -from django.contrib import admin -from django import forms from datetime import datetime + +from django import forms +from django.contrib import admin from organisations.models import OrganisationDivision @@ -14,8 +15,7 @@ def lookups(self, request, model_admin): def queryset(self, request, queryset): if self.value() == "true": return queryset.filter_by_date(datetime.today()) - else: - return queryset + return queryset class TempIdFilter(admin.SimpleListFilter): @@ -28,8 +28,7 @@ def lookups(self, request, model_admin): def queryset(self, request, queryset): if self.value() == "true": return queryset.filter_with_temp_id() - else: - return queryset + return queryset class OrganisationDivisionAdminForm(forms.ModelForm): diff --git a/every_election/apps/organisations/views/admin/organisation_divisionset.py b/every_election/apps/organisations/views/admin/organisation_divisionset.py index c31f800cb..92ad0de40 100644 --- a/every_election/apps/organisations/views/admin/organisation_divisionset.py +++ b/every_election/apps/organisations/views/admin/organisation_divisionset.py @@ -1,7 +1,6 @@ -from django.contrib import admin from django import forms - -from organisations.models import OrganisationDivisionSet, OrganisationDivision +from django.contrib import admin +from organisations.models import OrganisationDivision, OrganisationDivisionSet class OrganisationDivisionSetAdminForm(forms.ModelForm): diff --git a/every_election/apps/organisations/views/admin/organisation_geography.py b/every_election/apps/organisations/views/admin/organisation_geography.py index 96660ada8..9455e5f9d 100644 --- a/every_election/apps/organisations/views/admin/organisation_geography.py +++ b/every_election/apps/organisations/views/admin/organisation_geography.py @@ -1,5 +1,5 @@ -from django.contrib import admin from django import forms +from django.contrib import admin from organisations.models import OrganisationGeography diff --git a/every_election/apps/organisations/views/public.py b/every_election/apps/organisations/views/public.py index d4dd2a969..f9bc521d7 100644 --- a/every_election/apps/organisations/views/public.py +++ b/every_election/apps/organisations/views/public.py @@ -1,10 +1,11 @@ from datetime import datetime + +from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.db.models import Prefetch, Q from django.http import Http404 -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.views.generic import ListView, TemplateView -from organisations.models import Organisation from elections.models import Election +from organisations.models import Organisation class SupportedOrganisationsView(ListView): diff --git a/every_election/apps/storage/s3wrapper.py b/every_election/apps/storage/s3wrapper.py index 26cccb30c..465755627 100644 --- a/every_election/apps/storage/s3wrapper.py +++ b/every_election/apps/storage/s3wrapper.py @@ -1,5 +1,6 @@ -import boto3 import tempfile + +import boto3 from django.conf import settings diff --git a/every_election/apps/storage/shapefile.py b/every_election/apps/storage/shapefile.py index d3461d124..1cc9f5bb0 100644 --- a/every_election/apps/storage/shapefile.py +++ b/every_election/apps/storage/shapefile.py @@ -10,8 +10,7 @@ def convert_geom_to_multipolygon(geom): if isinstance(geom, Polygon): return MultiPolygon(geom) - else: - return geom + return geom def _remove_invalid_geometries(in_features): @@ -59,11 +58,10 @@ def pre_process_layer(layer, srid): Given we mostly just want to iterate over the features, this is an OK compromise. """ - features = [f for f in layer] + features = list(layer) # then tidy it up features = _remove_invalid_geometries(features) features = _add_multipolygons(features) features = _strip_z_values(features) - features = _convert_multipolygons_to_latlong(features, srid) - return features + return _convert_multipolygons_to_latlong(features, srid) diff --git a/every_election/urls.py b/every_election/urls.py index f6def090e..6a8624dde 100644 --- a/every_election/urls.py +++ b/every_election/urls.py @@ -1,11 +1,10 @@ -from django.urls import re_path, include -from django.conf.urls.static import static +from core.views import HomeView from django.conf import settings +from django.conf.urls.static import static from django.contrib import admin +from django.urls import include, re_path from django.views.generic import TemplateView -from core.views import HomeView - handler500 = "dc_utils.urls.dc_server_error" urlpatterns = [ diff --git a/every_election/wsgi.py b/every_election/wsgi.py index ea72c3ed7..1672d7285 100644 --- a/every_election/wsgi.py +++ b/every_election/wsgi.py @@ -1,24 +1,24 @@ +import os +from os.path import abspath, dirname +from sys import path + +import dotenv +from django.core.wsgi import get_wsgi_application + """ WSGI config for every_election project. It exposes the WSGI callable as a module-level variable named ``application``. """ -import os -from os.path import abspath, dirname -from sys import path + SITE_ROOT = dirname(dirname(abspath(__file__))) path.append(SITE_ROOT) -import dotenv - dotenv.read_dotenv( os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env") ) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "every_election.settings") - -from django.core.wsgi import get_wsgi_application - application = get_wsgi_application()