Commit 82a3b1dc authored by Nicolas Joyard's avatar Nicolas Joyard

Fix rep import tests (using natural keys)

parent cf3db8a5
import pytest
import os import os
import copy
from django.core.serializers.json import Deserializer
from representatives.models import Representative from representatives.models import Representative
from representatives.tests.base import TestBase
from representatives.contrib.francedata import import_representatives from representatives.contrib.francedata import import_representatives
@pytest.mark.django_db class FranceDataRepresentativesTest(TestBase):
def test_francedata_import_representatives(): def test_francedata_import_representatives(self):
inputjson = os.path.join(os.path.dirname(__file__), inputjson = os.path.join(os.path.dirname(__file__),
'representatives_input.json') 'representatives_input.json')
expected = os.path.join(os.path.dirname(__file__), expected = os.path.join(os.path.dirname(__file__),
'representatives_expected.json') 'representatives_expected.json')
# Disable django auto fields
exclude = ('id', '_state', 'created', 'updated', 'fingerprint')
with open(inputjson, 'r') as f: with open(inputjson, 'r') as f:
import_representatives.main(f) import_representatives.main(f)
missing = [] self.assertObjectsFromFixture(expected)
with open(expected, 'r') as f:
for obj in Deserializer(f.read()):
compare = copy.copy(obj.object.__dict__)
for field in exclude:
if field in compare:
compare.pop(field)
try:
type(obj.object).objects.get(**compare)
except:
missing.append(compare)
assert len(missing) is 0
assert Representative.objects.count() == 2 assert Representative.objects.count() == 2
import pytest
import os import os
import copy
from django.core.serializers.json import Deserializer
from representatives.models import Representative from representatives.models import Representative
from representatives.tests.base import TestBase
from representatives.contrib.parltrack import import_representatives from representatives.contrib.parltrack import import_representatives
@pytest.mark.django_db class ParltracRepresentativesTest(TestBase):
def test_parltrack_import_representatives(): def test_parltrack_import_representatives(self):
fixture = os.path.join(os.path.dirname(__file__), fixture = os.path.join(os.path.dirname(__file__),
'representatives_fixture.json') 'representatives_fixture.json')
expected = os.path.join(os.path.dirname(__file__), expected = os.path.join(os.path.dirname(__file__),
'representatives_expected.json') 'representatives_expected.json')
# Disable django auto fields
exclude = ('id', '_state', 'created', 'updated', 'fingerprint')
with open(fixture, 'r') as f: with open(fixture, 'r') as f:
import_representatives.main(f) import_representatives.main(f)
missing = [] self.assertObjectsFromFixture(expected)
with open(expected, 'r') as f:
for obj in Deserializer(f.read()):
compare = copy.copy(obj.object.__dict__)
for field in exclude:
if field in compare:
compare.pop(field)
try:
type(obj.object).objects.get(**compare)
except:
missing.append(compare)
assert len(missing) is 0
assert Representative.objects.count() == 2 assert Representative.objects.count() == 2
...@@ -20,19 +20,36 @@ class TimeStampedModel(models.Model): ...@@ -20,19 +20,36 @@ class TimeStampedModel(models.Model):
abstract = True abstract = True
class CountryManager(models.Manager):
def get_by_natural_key(self, code):
return self.get(code=code)
class Country(models.Model): class Country(models.Model):
objects = CountryManager()
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
code = models.CharField(max_length=2, unique=True) code = models.CharField(max_length=2, unique=True)
def __unicode__(self): def __unicode__(self):
return u'{} [{}]'.format(self.name, self.code) return u'{} [{}]'.format(self.name, self.code)
def natural_key(self):
return (self.code,)
class RepresentativeManager(models.Manager):
def get_by_natural_key(self, slug):
return self.get(slug=slug)
class Representative(TimeStampedModel): class Representative(TimeStampedModel):
""" """
Base model for representatives Base model for representatives
""" """
objects = RepresentativeManager()
slug = models.SlugField(max_length=100, unique=True) slug = models.SlugField(max_length=100, unique=True)
first_name = models.CharField(max_length=255, blank=True, default='') first_name = models.CharField(max_length=255, blank=True, default='')
last_name = models.CharField(max_length=255, blank=True, default='') last_name = models.CharField(max_length=255, blank=True, default='')
...@@ -52,6 +69,9 @@ class Representative(TimeStampedModel): ...@@ -52,6 +69,9 @@ class Representative(TimeStampedModel):
def __unicode__(self): def __unicode__(self):
return smart_unicode(self.full_name) return smart_unicode(self.full_name)
def natural_key(self):
return (self.slug,)
def gender_as_str(self): def gender_as_str(self):
genders = {0: 'N/A', 1: 'F', 2: 'M'} genders = {0: 'N/A', 1: 'F', 2: 'M'}
return genders[self.gender] return genders[self.gender]
...@@ -79,7 +99,15 @@ class WebSite(Contact): ...@@ -79,7 +99,15 @@ class WebSite(Contact):
kind = models.CharField(max_length=255, blank=True, default='') kind = models.CharField(max_length=255, blank=True, default='')
class AddressManager(models.Manager):
def get_by_natural_key(self, name, kind, representative_slug):
representative = Representative.objects.get(slug=representative_slug)
return self.get(name=name, kind=kind, representative=representative)
class Address(Contact): class Address(Contact):
objects = AddressManager()
country = models.ForeignKey(Country) country = models.ForeignKey(Country)
city = models.CharField(max_length=255, blank=True, default='') city = models.CharField(max_length=255, blank=True, default='')
street = models.CharField(max_length=255, blank=True, default='') street = models.CharField(max_length=255, blank=True, default='')
...@@ -91,6 +119,10 @@ class Address(Contact): ...@@ -91,6 +119,10 @@ class Address(Contact):
name = models.CharField(max_length=255, blank=True, default='') name = models.CharField(max_length=255, blank=True, default='')
location = models.CharField(max_length=255, blank=True, default='') location = models.CharField(max_length=255, blank=True, default='')
def natural_key(self):
representative_nk = self.representative.natural_key()
return (self.name, self.kind) + representative_nk
class Phone(Contact): class Phone(Contact):
number = models.CharField(max_length=255, blank=True, default='') number = models.CharField(max_length=255, blank=True, default='')
...@@ -98,10 +130,17 @@ class Phone(Contact): ...@@ -98,10 +130,17 @@ class Phone(Contact):
address = models.ForeignKey(Address, null=True, related_name='phones') address = models.ForeignKey(Address, null=True, related_name='phones')
class ChamberManager(models.Manager):
def get_by_natural_key(self, abbreviation):
return self.get(abbreviation=abbreviation)
class Chamber(models.Model): class Chamber(models.Model):
""" """
A representative chamber A representative chamber
""" """
objects = ChamberManager()
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
country = models.ForeignKey('Country', null=True, related_name='chambers') country = models.ForeignKey('Country', null=True, related_name='chambers')
abbreviation = models.CharField(max_length=10, blank=True, default='', abbreviation = models.CharField(max_length=10, blank=True, default='',
...@@ -110,11 +149,26 @@ class Chamber(models.Model): ...@@ -110,11 +149,26 @@ class Chamber(models.Model):
def __unicode__(self): def __unicode__(self):
return u'{} [{}]'.format(self.name, self.abbreviation) return u'{} [{}]'.format(self.name, self.abbreviation)
def natural_key(self):
return (self.abbreviation,)
class GroupManager(models.Manager):
def get_by_natural_key(self, name, kind, chamber_nk):
if chamber_nk:
chamber = Chamber.objects.get_by_natural_key(chamber_nk)
else:
chamber = None
return self.get(name=name, kind=kind, chamber=chamber)
class Group(TimeStampedModel): class Group(TimeStampedModel):
""" """
An entity represented by a representative through a mandate An entity represented by a representative through a mandate
""" """
objects = GroupManager()
name = models.CharField(max_length=511, db_index=True) name = models.CharField(max_length=511, db_index=True)
abbreviation = models.CharField(max_length=10, blank=True, default='', abbreviation = models.CharField(max_length=10, blank=True, default='',
db_index=True) db_index=True)
...@@ -128,14 +182,30 @@ class Group(TimeStampedModel): ...@@ -128,14 +182,30 @@ class Group(TimeStampedModel):
def __unicode__(self): def __unicode__(self):
return unicode(self.name) return unicode(self.name)
def natural_key(self):
chamber_nk = self.chamber.natural_key() if self.chamber else (None,)
return (self.name, self.kind) + chamber_nk
class Meta: class Meta:
ordering = ('name',) ordering = ('name',)
class ConstituencyManager(models.Manager):
def get_by_natural_key(self, name, country_nk):
if country_nk:
country = Country.objects.get_by_natural_key(country_nk)
else:
country = None
return self.get(name=name, country=country)
class Constituency(TimeStampedModel): class Constituency(TimeStampedModel):
""" """
An authority for which a representative has a mandate An authority for which a representative has a mandate
""" """
objects = ConstituencyManager()
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
country = models.ForeignKey('Country', null=True, blank=True, country = models.ForeignKey('Country', null=True, blank=True,
related_name='constituencies') related_name='constituencies')
...@@ -147,6 +217,10 @@ class Constituency(TimeStampedModel): ...@@ -147,6 +217,10 @@ class Constituency(TimeStampedModel):
def __unicode__(self): def __unicode__(self):
return unicode(self.name) return unicode(self.name)
def natural_key(self):
country_nk = self.country.natural_key() if self.country else (None,)
return (self.name,) + country_nk
class MandateManager(models.Manager): class MandateManager(models.Manager):
""" This satisfies repr(Mandate) """ """ This satisfies repr(Mandate) """
...@@ -158,8 +232,18 @@ class MandateManager(models.Manager): ...@@ -158,8 +232,18 @@ class MandateManager(models.Manager):
'constituency') 'constituency')
class Mandate(TimeStampedModel): class MandateManager(models.Manager):
def get_by_natural_key(self, begin_date, end_date, representative_slug,
group_name, group_kind, group_chamber_nk):
representative = Representative.objects.get_by_natural_key(
representative_slug)
group = Group.objects.get_by_natural_key(group_name, group_kind,
group_chamber_nk)
return self.get(begin_date=begin_date, end_date=end_date,
representative=representative, group=group)
class Mandate(TimeStampedModel):
objects = MandateManager() objects = MandateManager()
group = models.ForeignKey(Group, null=True, related_name='mandates') group = models.ForeignKey(Group, null=True, related_name='mandates')
...@@ -190,5 +274,13 @@ class Mandate(TimeStampedModel): ...@@ -190,5 +274,13 @@ class Mandate(TimeStampedModel):
constituency=self.constituency, constituency=self.constituency,
group=self.group) group=self.group)
def natural_key(self):
rep_nk = self.representative.natural_key() \
if self.representative else (None,)
group_nk = self.group.natural_key() \
if self.group else (None, None, None)
return (self.begin_date, self.end_date) + rep_nk + group_nk
class Meta: class Meta:
ordering = ('-end_date',) ordering = ('-end_date',)
import copy
import logging
import re
from django import test
from django.core.serializers.json import Deserializer
class TestBase(test.TestCase):
logger = logging.getLogger('representatives')
_exclude = ('id', '_state', 'created', 'updated', 'fingerprint')
_exclude_re = (re.compile(r'^_.*_cache$'),)
def assertObjectsFromFixture(self, fixture):
missing = []
with open(fixture, 'r') as f:
for obj in Deserializer(f.read()):
compare = copy.copy(obj.object.__dict__)
for field in self._exclude:
if field in compare:
compare.pop(field)
for re in self._exclude_re:
for field in compare.keys():
if re.match(field):
compare.pop(field)
try:
type(obj.object).objects.get(**compare)
except:
self.logger.warn(
'MISSING %s\n %s' % (type(obj.object), compare))
missing.append(compare)
assert len(missing) is 0
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment