Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'master' into miles/feature/lint-docs
  • Loading branch information
jeremyjbowers committed Jul 9, 2018
2 parents b20e4be + a627c6a commit d5badfe
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 28 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -5,6 +5,7 @@ language: python
python:
- "2.7"
- "3.6"
- "pypy"

install:
- pip install -r requirements.txt
Expand Down
1 change: 1 addition & 0 deletions AUTHORS.rst
Expand Up @@ -12,3 +12,4 @@ These individuals have contributed code, tests, documentation, and troubleshooti
* Tom Giratikanon
* Ryan Pitts
* Miles Watkins
* Vanessa Qian
2 changes: 1 addition & 1 deletion Dockerfile
@@ -1,4 +1,4 @@
FROM python:3.5
FROM python:3.6
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY . /usr/src/app
Expand Down
7 changes: 4 additions & 3 deletions docs/cli.rst
Expand Up @@ -76,8 +76,9 @@ Commands and flags
--format-json Pretty print JSON when using `-o json`.
-v, --version show program's version number and exit
--results-level RESULTS_LEVEL
Specify reporting level for results
--raceids RACEIDS Specify raceids to parse
Specify reporting level for results.
--officeids OFFICEIDS Specify officeids to parse.
--raceids RACEIDS Specify raceids to parse.
--set-zero-counts Override results with zeros; omits the winner
indicator.Sets the vote, delegate, and reporting
precinct counts to zero.
Expand All @@ -88,7 +89,7 @@ Commands and flags
--batch-name BATCH_NAME
Specify a value for a `batchname` column to append to
each row.

-----------------
Command reference
-----------------
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Expand Up @@ -13,7 +13,7 @@
autodoc_member_order = 'bysource'

intersphinx_mapping = {
'python': ('http://docs.python.org/3.5', None)
'python': ('http://docs.python.org/3.6', None)
}

# Templates
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.rst
Expand Up @@ -45,7 +45,7 @@ Make sure all tests are passing in your environment by running the nose2 tests.
make test
If you have Python 2.7, 3.5, and pypy installed, run can run :code:`tox` to test in multiple environments.
If you have Python 2.7, 3.6, and pypy installed, run can run :code:`tox` to test in multiple environments.

Writing docs
============
Expand Down
7 changes: 7 additions & 0 deletions elex/api/models.py
Expand Up @@ -878,6 +878,7 @@ def __init__(self, **kwargs):
self.setzerocounts = kwargs.get('setzerocounts', False)

self.raceids = kwargs.get('raceids', [])
self.officeids = kwargs.get('officeids', None)

self.set_id_field()

Expand Down Expand Up @@ -1051,8 +1052,10 @@ def races(self):
level="ru",
test=self.testresults,
national=self.national,
officeID=self.officeids,
apiKey=self.api_key
)

race_objs = self.get_race_objects(raw_races)
races, reporting_units, candidate_reporting_units = self.get_units(
race_objs
Expand All @@ -1069,6 +1072,7 @@ def reporting_units(self):
level="ru",
test=self.testresults,
national=self.national,
officeID=self.officeids,
apiKey=self.api_key
)
race_objs = self.get_race_objects(raw_races)
Expand All @@ -1087,6 +1091,7 @@ def candidate_reporting_units(self):
level="ru",
test=self.testresults,
national=self.national,
officeID=self.officeids,
apiKey=self.api_key
)
race_objs = self.get_race_objects(raw_races)
Expand All @@ -1106,6 +1111,7 @@ def results(self):
setzerocounts=self.setzerocounts,
test=self.testresults,
national=self.national,
officeID=self.officeids,
apiKey=self.api_key
)
race_objs = self.get_race_objects(raw_races)
Expand All @@ -1124,6 +1130,7 @@ def candidates(self):
level="ru",
test=self.testresults,
national=self.national,
officeID=self.officeids,
apiKey=self.api_key
)
race_objs = self.get_race_objects(raw_races)
Expand Down
9 changes: 1 addition & 8 deletions elex/api/utils.py
Expand Up @@ -84,12 +84,7 @@ def api_request(path, **params):
`apiKey="<YOUR API KEY>`, your AP API key, or `national=True`,
for national-only results.
"""
if not params.get('apiKey', None):
if elex.API_KEY != '':
params['apiKey'] = elex.API_KEY
else:
params['apiKey'] = None

params['apiKey'] = params.get('apiKey') or elex.API_KEY
if not params['apiKey']:
raise APAPIKeyException()

Expand All @@ -98,12 +93,10 @@ def api_request(path, **params):
params = sorted(params.items()) # Sort for consistent caching

url = '{0}{1}'.format(elex.BASE_URL, path.replace('//', '/'))

response = cache.get(url, params=params)
response.raise_for_status()

write_recording(response.json())

return response


Expand Down
9 changes: 7 additions & 2 deletions elex/cli/app.py
Expand Up @@ -57,12 +57,17 @@ class Meta:
)),
(['--results-level'], dict(
action='store',
help='Specify reporting level for results',
help='Specify reporting level for results.',
default='ru'
)),
(['--officeids'], dict(
action='store',
help='Specify officeids to parse.',
default=None
)),
(['--raceids'], dict(
action='store',
help='Specify raceids to parse',
help='Specify raceids to parse.',
default=[]
)),
(['--set-zero-counts'], dict(
Expand Down
14 changes: 13 additions & 1 deletion elex/cli/hooks.py
@@ -1,6 +1,7 @@
import logging
from elex.api import Election
from elex.cli.constants import LOG_FORMAT
from elex.api import maps


def add_election_hook(app):
Expand All @@ -13,7 +14,8 @@ def add_election_hook(app):
resultslevel=app.pargs.results_level,
setzerocounts=app.pargs.set_zero_counts,
is_test=False,
raceids=[]
raceids=[],
officeids=None
)

if app.pargs.data_file:
Expand All @@ -28,6 +30,16 @@ def add_election_hook(app):
if app.pargs.raceids:
app.election.raceids = [x.strip() for x in app.pargs.raceids.split(',')]

if app.pargs.officeids:
invalid_officeids = [x for x in app.pargs.officeids.split(',') if x not in maps.OFFICE_NAMES]
if invalid_officeids:
text = '{0} is/are invalid officeID(s). Here is a list of valid officeIDs: {1}'
app.log.error(text.format(", ".join(invalid_officeids), ", ".join(maps.OFFICE_NAMES.keys())))
app.close(1)
else:
app.election.officeids = app.pargs.officeids
# kept as a comma-delimited string so officeID as a param always appears once in request url (e.g. officeID=P%2CH%2CG)


def cachecontrol_logging_hook(app):
"""
Expand Down
1 change: 1 addition & 0 deletions tests/__init__.py
Expand Up @@ -102,6 +102,7 @@ def setUp(self, **kwargs):


class NetworkTestCase(unittest.TestCase):

def api_request(self, *args, **kwargs):
response = utils.api_request(*args, **kwargs)
sleep(10)
Expand Down
36 changes: 36 additions & 0 deletions tests/test_ap_network.py
@@ -1,5 +1,6 @@
import os
import unittest
import tests

from elex.cli.app import ElexApp
from requests.exceptions import HTTPError
Expand Down Expand Up @@ -37,7 +38,42 @@ def test_nonexistent_param(self):
self.assertEqual(response.status_code, 400)


class TestRaceResultsOfficeIdParsing(NetworkTestCase):

@unittest.skipUnless(os.environ.get('AP_API_KEY', None), API_MESSAGE)
def test_officeid_number_of_races(self):
valid_officeids = self.api_request('/elections/2016-11-08/', officeID='P,H,G')
data = valid_officeids.json()
self.assertEqual(len(data['races']), 502)

@unittest.skipUnless(os.environ.get('AP_API_KEY', None), API_MESSAGE)
def test_races_with_officeids_vs_no_officeids(self):
w_officeids = self.api_request('/elections/2016-11-08/', officeID='P,H')
all_races = self.api_request('/elections/2016-11-08/')
data_w_officeids = w_officeids.json()
data_all = all_races.json()
self.assertLess(len(data_w_officeids['races']), len(data_all['races']))

raceids_filter_ph_in_all = [elem['raceID'] for elem in data_all['races'] if elem['officeID'] == 'P' or elem['officeID'] == 'H']
raceids_w_officeids = [elem['raceID'] for elem in data_w_officeids['races']]
self.assertEqual(raceids_filter_ph_in_all, raceids_w_officeids)

@unittest.skipUnless(os.environ.get('AP_API_KEY', None), API_MESSAGE)
def test_raceid_zero_with_officeid_p(self):
raceid_req = self.api_request('/elections/2016-11-08/')
officeid_req = self.api_request('/elections/2016-11-08/', officeID='P')
data_raceid = raceid_req.json()
data_officeid = officeid_req.json()

len_data_raceid_zero = sum([1 for elem in data_raceid['races'] if elem['raceID'] == '0'])
self.assertEqual(len(data_officeid['races']), len_data_raceid_zero)

len_data_officeid_zero = sum([1 for elem in data_officeid['races'] if elem['raceID'] == '0'])
self.assertEqual(len_data_officeid_zero, len_data_raceid_zero)


class ElexNetworkCacheTestCase(NetworkTestCase):

@unittest.skipUnless(os.environ.get('AP_API_KEY', None), API_MESSAGE)
def test_elex_cache_miss(self):
from elex import cache
Expand Down
14 changes: 3 additions & 11 deletions tox.ini
Expand Up @@ -4,18 +4,10 @@
# and then run "tox" from this directory.

[tox]
envlist = py27, py35, pypy
envlist = py27, py36, pypy

[testenv]
deps = -r{toxinidir}/requirements-dev.txt
whitelist_externals = make

commands = pyflakes elex
pep8 elex
pyflakes tests
pep8 tests
nose2 tests

[pep8]
# E731: Ignore the lambda def errors since they are an excusable UnicodeMixin hack
# E501: Ignore line length errors. There are long lines in docstrings that are perfectly cromulent.
ignore = E731,E501
commands = make test

0 comments on commit d5badfe

Please sign in to comment.