Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
231 lines (199 sloc) 8.53 KB
import copy
from .base import (BaseModel, SourceMixin, LinkMixin, ContactDetailMixin, OtherNameMixin,
IdentifierMixin)
from .schemas.post import schema as post_schema
from .schemas.person import schema as person_schema
from .schemas.membership import schema as membership_schema
from .schemas.organization import schema as org_schema
from ..utils import _make_pseudo_id
from pupa.exceptions import ScrapeValueError
# a copy of the org schema without sources
org_schema_no_sources = copy.deepcopy(org_schema)
org_schema_no_sources['properties'].pop('sources')
class Post(BaseModel, LinkMixin, ContactDetailMixin):
"""
A popolo-style Post
"""
_type = 'post'
_schema = post_schema
def __init__(self, *, label, role, organization_id=None, chamber=None,
division_id=None, start_date='', end_date='',
maximum_memberships=1):
super(Post, self).__init__()
self.label = label
self.role = role
self.organization_id = pseudo_organization(organization_id, chamber)
self.division_id = division_id
self.start_date = start_date
self.end_date = end_date
self.maximum_memberships = maximum_memberships
def __str__(self):
return self.label
class Membership(BaseModel, ContactDetailMixin, LinkMixin):
"""
A popolo-style Membership.
"""
_type = 'membership'
_schema = membership_schema
def __init__(self, *, person_id, organization_id, post_id=None, role='', label='',
start_date='', end_date='', on_behalf_of_id=None,
person_name=''
):
"""
Constructor for the Membership object.
We require a person ID and organization ID, as required by the
popolo spec. Additional arguments may be given, which match those
defined by popolo.
"""
super(Membership, self).__init__()
self.person_id = person_id
self.person_name = person_name
self.organization_id = organization_id
self.post_id = post_id
self.start_date = start_date
self.end_date = end_date
self.role = role
self.label = label
self.on_behalf_of_id = on_behalf_of_id
def __str__(self):
return self.person_id + ' membership in ' + self.organization_id
class Person(BaseModel, SourceMixin, ContactDetailMixin, LinkMixin, IdentifierMixin,
OtherNameMixin):
"""
Details for a Person in Popolo format.
"""
_type = 'person'
_schema = person_schema
def __init__(self, name, *, birth_date='', death_date='', biography='', summary='', image='',
gender='', national_identity='',
# specialty fields
district=None, party=None, primary_org='', role='',
start_date='', end_date='', primary_org_name=None):
super(Person, self).__init__()
self.name = name
self.birth_date = birth_date
self.death_date = death_date
self.biography = biography
self.summary = summary
self.image = image
self.gender = gender
self.national_identity = national_identity
if primary_org:
self.add_term(role, primary_org, district=district,
start_date=start_date, end_date=end_date,
org_name=primary_org_name)
if party:
self.add_party(party)
def add_membership(self, name_or_org, role='member', **kwargs):
"""
add a membership in an organization and return the membership
object in case there are more details to add
"""
if isinstance(name_or_org, Organization):
membership = Membership(person_id=self._id,
person_name=self.name,
organization_id=name_or_org._id,
role=role, **kwargs)
else:
membership = Membership(person_id=self._id,
person_name=self.name,
organization_id=_make_pseudo_id(name=name_or_org),
role=role, **kwargs)
self._related.append(membership)
return membership
def add_party(self, party, **kwargs):
membership = Membership(
person_id=self._id,
person_name=self.name,
organization_id=_make_pseudo_id(classification="party", name=party),
role='member', **kwargs)
self._related.append(membership)
def add_term(self, role, org_classification, *, district=None,
start_date='', end_date='', label='', org_name=None,
appointment=False):
if org_name:
org_id = _make_pseudo_id(classification=org_classification,
name=org_name)
else:
org_id = _make_pseudo_id(classification=org_classification)
if district:
if role:
post_id = _make_pseudo_id(label=district,
role=role,
organization__classification=org_classification)
else:
post_id = _make_pseudo_id(label=district,
organization__classification=org_classification)
elif appointment:
post_id = _make_pseudo_id(role=role,
organization__classification=org_classification)
else:
post_id = None
membership = Membership(person_id=self._id, person_name=self.name,
organization_id=org_id, post_id=post_id,
role=role, start_date=start_date, end_date=end_date, label=label)
self._related.append(membership)
return membership
def __str__(self):
return self.name
class Organization(BaseModel, SourceMixin, ContactDetailMixin, LinkMixin, IdentifierMixin,
OtherNameMixin):
"""
A single popolo-style Organization
"""
_type = 'organization'
_schema = org_schema
def __init__(self, name, *, classification='', parent_id=None,
founding_date='', dissolution_date='', image='',
chamber=None):
"""
Constructor for the Organization object.
"""
super(Organization, self).__init__()
self.name = name
self.classification = classification
self.founding_date = founding_date
self.dissolution_date = dissolution_date
self.parent_id = pseudo_organization(parent_id, chamber)
self.image = image
def __str__(self):
return self.name
def validate(self):
schema = None
# these are implicitly declared & do not require sources
if self.classification in ('party', 'legislature', 'upper', 'lower', 'executive'):
schema = org_schema_no_sources
return super(Organization, self).validate(schema=schema)
def add_post(self, label, role, **kwargs):
post = Post(label=label, role=role, organization_id=self._id, **kwargs)
self._related.append(post)
return post
def add_member(self, name_or_person, role='member', **kwargs):
if isinstance(name_or_person, Person):
membership = Membership(person_id=name_or_person._id,
person_name=name_or_person.name,
organization_id=self._id,
role=role, **kwargs)
else:
membership = Membership(person_id=_make_pseudo_id(name=name_or_person),
person_name=name_or_person,
organization_id=self._id, role=role, **kwargs)
self._related.append(membership)
return membership
def pseudo_organization(organization, classification, default=None):
""" helper for setting an appropriate ID for organizations """
if organization and classification:
raise ScrapeValueError('cannot specify both classification and organization')
elif classification:
return _make_pseudo_id(classification=classification)
elif organization:
if isinstance(organization, Organization):
return organization._id
elif isinstance(organization, str):
return organization
else:
return _make_pseudo_id(**organization)
elif default is not None:
return _make_pseudo_id(classification=default)
else:
return None