Source code for parsons.google.google_civic

from parsons.utilities import check_env
import requests
from parsons.etl import Table

URI = "https://www.googleapis.com/civicinfo/v2/"


[docs]class GoogleCivic(object): """ `Args:` api_key : str A valid Google api key. Not required if ``GOOGLE_CIVIC_API_KEY`` env variable set. `Returns:` class """ def __init__(self, api_key=None): self.api_key = check_env.check("GOOGLE_CIVIC_API_KEY", api_key) self.uri = URI def request(self, url, args=None): # Internal request method if not args: args = {} args["key"] = self.api_key r = requests.get(url, params=args) return r.json()
[docs] def get_elections(self): """ Get a collection of information about elections and voter information. `Returns:` Parsons Table See :ref:`parsons-table` for output options. """ url = self.uri + "elections" return Table((self.request(url))["elections"])
def _get_voter_info(self, election_id, address): # Internal method to call voter info end point. Portions of this are # parsed for other methods. url = self.uri + "voterinfo" args = {"address": address, "electionId": election_id} return self.request(url, args=args)
[docs] def get_polling_location(self, election_id, address): """ Get polling location information for a given address. `Args:` election_id: int A valid election id. Election ids can be found by running the :meth:`get_elections` method. address: str A valid US address in a single string. `Returns:` Parsons Table See :ref:`parsons-table` for output options. """ r = self._get_voter_info(election_id, address) return r["pollingLocations"]
[docs] def get_polling_locations(self, election_id, table, address_field="address"): """ Get polling location information for a table of addresses. `Args:` election_id: int A valid election id. Election ids can be found by running the :meth:`get_elections` method. address: str A valid US address in a single string. address_field: str The name of the column where the address is stored. `Returns:` Parsons Table See :ref:`parsons-table` for output options. """ polling_locations = [] # Iterate through the rows of the table for row in table: loc = self.get_polling_location(election_id, row[address_field]) # Insert original passed address loc[0]["passed_address"] = row[address_field] # Add to list of lists polling_locations.append(loc[0]) # Unpack values tbl = Table(polling_locations) tbl.unpack_dict("address", prepend_value="polling") tbl.unpack_list("sources", replace=True) tbl.unpack_dict("sources_0", prepend_value="source") tbl.rename_column("polling_line1", "polling_address") # Resort columns tbl.move_column("pollingHours", len(tbl.columns)) tbl.move_column("notes", len(tbl.columns)) tbl.move_column("polling_locationName", 1) tbl.move_column("polling_address", 2) return tbl
[docs] def get_representative_info_by_address( self, address: str, include_offices=True, levels=None, roles=None ): """ Get representative information for a given address. This method returns the raw JSON response from the Google Civic API. It is a complex response that is not easily parsed into a table. Here is the information on how to parse the response: https://developers.google.com/civic-information/docs/v2/representatives/representativeInfoByAddress `Args:` address: str A valid US address in a single string. include_offices: bool Whether to return information about offices and officials. If false, only the top-level district information will be returned. (Default: True) levels: list of str A list of office levels to filter by. Only offices that serve at least one of these levels will be returned. Divisions that don't contain a matching office will not be returned. Acceptable values are: "administrativeArea1" "administrativeArea2" "country" "international" "locality" "regional" "special" "subLocality1" "subLocality2" roles: list of str A list of office roles to filter by. Only offices fulfilling one of these roles will be returned. Divisions that don't contain a matching office will not be returned. Acceptable values are: "deputyHeadOfGovernment" "executiveCouncil" "governmentOfficer" "headOfGovernment" "headOfState" "highestCourtJudge" "judge" "legislatorLowerBody" "legislatorUpperBody" "schoolBoard" "specialPurposeOfficer" `Returns:` Parsons Table See :ref:`parsons-table` for output options. """ if levels is not None and not isinstance(levels, list): raise ValueError("levels must be a list of strings") if roles is not None and not isinstance(roles, list): raise ValueError("roles must be a list of strings") if address is None or not isinstance(address, str): raise ValueError("address must be a string") url = self.uri + "representatives" args = { "address": address, "includeOffices": include_offices, "levels": levels, "roles": roles, } response = self.request(url, args=args) # Raise an error if the address was invalid if "error" in response: raise ValueError(response["error"]["message"]) return response