diff --git a/abc.py b/abc.py index 9c03cea..e6bb770 100644 --- a/abc.py +++ b/abc.py @@ -7,7 +7,8 @@ from bs4 import BeautifulSoup import requests -soup = BeautifulSoup(requests.get('http://www.abc.net.au/news/federal-election-2013/guide/candindex/').text) +url = 'http://www.abc.net.au/news/federal-election-2013/guide/candindex/' +soup = BeautifulSoup(requests.get(url).text) parties = {} @@ -53,10 +54,13 @@ data['party'] = party # print filename - # print json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) - open('data/people/' + filename, 'w').write(json.dumps(data, sort_keys=True, - indent=4, separators=(',', ': '))) - print open('data/people/' + filename).read() + # print json.dumps(data, sort_keys=True, + # indent=4, separators=(',', ': ')) + + dpef = 'data/people/' + filename + open(dpef, 'w').write(json.dumps(data, sort_keys=True, + indent=4, separators=(',', ': '))) + print open(dpef).read() print "" for code, name in parties.items(): @@ -70,7 +74,8 @@ filename = '{}.json'.format(code.lower()) - open('data/parties/' + filename, 'w').write(json.dumps(data, sort_keys=True, - indent=4, separators=(',', ': '))) - print open('data/parties/' + filename).read() + dpaf = 'data/parties/' + filename + open(dpaf, 'w').write(json.dumps(data, sort_keys=True, + indent=4, separators=(',', ': '))) + print open(dpaf).read() print "" diff --git a/api/balloter.py b/api/balloter.py index 3596574..bb9bf7e 100644 --- a/api/balloter.py +++ b/api/balloter.py @@ -66,9 +66,11 @@ ballots = cPickle.load(open('ballots.pck')) + def disclaimer(c): c.drawString(10 * mm, PAGE_HEIGHT - 6 * mm, DISCLAIMER_TEXT) + def watermark(c): c.saveState() c.setStrokeColorRGB(0.93333, 0.93333, 0.93333) @@ -78,12 +80,14 @@ def watermark(c): c.drawString(40 * mm, 0, "belowtheline.org.au") c.restoreState() + def end_page(c): disclaimer(c) c.showPage() c.setFont(FONT, FONT_SIZE) watermark(c) + def draw_text(string, text, font, size, width, leading=None): if leading: text.setFont(font, size, leading=leading) @@ -110,6 +114,7 @@ def draw_text(string, text, font, size, width, leading=None): else: text.textLine(string) + def draw_candidate(c, number, family, given, party, i, tl, br, box_gap): number = str(number) font = pdfmetrics.getFont(FONT) @@ -120,21 +125,21 @@ def draw_candidate(c, number, family, given, party, i, tl, br, box_gap): width = font.stringWidth(number, FONT_SIZE + 1.0) c.setFont(FONT, FONT_SIZE + 1.0) c.drawCentredString(tl[0] + 1.1 * mm + BOX_SIZE / 2.0, - tl[1] - 2.3 * mm - i * box_gap - (i + 1) * BOX_SIZE + 1.5 * mm, - number) + tl[1] - 2.3 * mm - i * box_gap - (i + 1) * BOX_SIZE + 1.5 * mm, number) text = c.beginText(tl[0] + 2 * mm + BOX_SIZE, tl[1] - 3 * mm - i * box_gap - i * BOX_SIZE - 4.5) text.setFont(FONT + '-Bold', CANDIDATE_FONT_SIZE, leading=1.1 * CANDIDATE_FONT_SIZE) text.textLine(family) draw_text(given, text, FONT, CANDIDATE_FONT_SIZE, LABEL_WIDTH, - leading=CANDIDATE_FONT_SIZE) + leading=CANDIDATE_FONT_SIZE) if party: draw_text(party.upper(), text, FONT, PARTY_FONT_SIZE, LABEL_WIDTH) c.drawText(text) c.setFont(FONT, FONT_SIZE) + def generate(state_only, division, div_ticket, state, sen_ticket): container = cStringIO.StringIO() c = canvas.Canvas(container, A4R) @@ -251,12 +256,14 @@ def group_block_iterator(groups, state_only): return container.getvalue() + def setup_rollbar(environment): if 'ROLLBAR_TOKEN' not in os.environ: return rollbar.init(os.environ['ROLLBAR_TOKEN'], environment, allow_logging_basic_config=False) + @app.route('/pdf', methods=['POST']) def pdf(): try: @@ -274,8 +281,7 @@ def pdf(): request.form['state'], senate_ticket) response = make_response(pdf) response.headers['Content-Type'] = 'application/pdf' - response.headers['Content-Disposition'] = \ - 'attachment; filename=ballot.pdf' + response.headers['Content-Disposition'] = 'attachment; filename=ballot.pdf' return response except: rollbar.report_exc_info() diff --git a/api/division.py b/api/division.py index 05de175..0e20d06 100644 --- a/api/division.py +++ b/api/division.py @@ -22,6 +22,7 @@ app = Flask(__name__) + def setup_rollbar(environment): if 'ROLLBAR_TOKEN' not in os.environ: return @@ -36,6 +37,7 @@ def setup_rollbar(environment): file_handler.setLevel(logging.INFO) app.logger.addHandler(file_handler) + def crossdomain(origin=None, methods=None, headers=None, max_age=21600, attach_to_all=True, automatic_options=True): @@ -77,6 +79,7 @@ def wrapped_function(*args, **kwargs): return update_wrapper(wrapped_function, f) return decorator + @app.route('/division', methods=['GET', 'POST', 'OPTIONS']) @crossdomain(origin='*', headers=['Content-Type', 'X-Requested-With']) def division_lookup(): diff --git a/api/requirements.txt b/api/requirements.txt index d2412ac..0359a97 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -1,8 +1,8 @@ Flask==0.10.1 gunicorn==17.5 psycopg2==2.5.1 -redis==2.7.6 +redis>=2.7.6 reportlab==2.7 hiredis==0.1.1 rollbar==0.5.8 -pyrax==1.4.11 +pyrax>=1.4.11 diff --git a/api/store.py b/api/store.py index fc940ef..7459802 100644 --- a/api/store.py +++ b/api/store.py @@ -6,8 +6,7 @@ import random import string -from flask import Flask, abort, current_app, jsonify, make_response, redirect, \ - request +from flask import Flask, abort, current_app, jsonify, make_response, redirect, request import redis import rollbar @@ -18,12 +17,14 @@ app = Flask(__name__) + def setup_rollbar(environment): if 'ROLLBAR_TOKEN' not in os.environ: return rollbar.init(os.environ['ROLLBAR_TOKEN'], environment, allow_logging_basic_config=False) + def crossdomain(origin=None, methods=None, headers=None, max_age=21600, attach_to_all=True, automatic_options=True): @@ -65,6 +66,7 @@ def wrapped_function(*args, **kwargs): return update_wrapper(wrapped_function, f) return decorator + def store_at_random_id(ballot, start_length=8): r = redis.StrictRedis(host=REDIS_HOST, db=REDIS_DB) candidate = None @@ -90,6 +92,7 @@ def store(c): return candidate + @app.route('/store', methods=['POST', 'OPTIONS']) @crossdomain(origin=['*'], headers=['Content-Type', 'X-Requested-With']) def store_ballot(): @@ -140,6 +143,7 @@ def store_ballot(): rollbar.report_exc_info() raise + @app.route('/b/') @crossdomain(origin=['*'], headers=['Content-Type', 'X-Requested-With']) def redirect_ballot(ballot_id): @@ -156,6 +160,7 @@ def redirect_ballot(ballot_id): rollbar.report_exc_info() raise + @app.route('/store/', methods=['GET', 'OPTIONS']) @crossdomain(origin=['*'], headers=['Content-Type', 'X-Requested-With']) def get_ballot(ballot_id): @@ -184,4 +189,3 @@ def get_ballot(ballot_id): app.run(debug=True, port=5005) else: setup_rollbar('production') - diff --git a/candidate.py b/candidate.py index df36bb1..e624724 100644 --- a/candidate.py +++ b/candidate.py @@ -23,7 +23,8 @@ if candidate.startswith('state'): data['ballot_position'] = int(raw_input('Position : ')) - open('data/people/' + filename, 'w').write(json.dumps(data, sort_keys=True, - indent=4, separators=(',', ': '))) - print open('data/people/' + filename).read() + dpf = 'data/people/' + filename + open(dpf, 'w').write(json.dumps(data, sort_keys=True, + indent=4, separators=(',', ': '))) + print open(dpf).read() print "" diff --git a/content/about-us.md b/content/about-us.md index b8e2d8a..5bcaead 100644 --- a/content/about-us.md +++ b/content/about-us.md @@ -23,7 +23,7 @@ maintain a blog. Originally hailing from Adelaide, Michael Pearson is a mostly apolitical thirty-something web developer and systems administrator. He lives in a tree -fort in the Dandenong Ranges with his marine biologist wife Kate and their +fort in the Dandenong Ranges with his marine biologist wife, Kate, and their Rottweiler, Amos. When not preventing his yard from being overrun by bark and weeds he works for [bikeexchange.com.au](http://www.bikeexchange.com.au) in Ruby and Javascript. Michael's twitter is diff --git a/feed_candidates.py b/feed_candidates.py index eed33a1..1413266 100644 --- a/feed_candidates.py +++ b/feed_candidates.py @@ -26,20 +26,25 @@ ord(u"'"): None, } + def division_name(name): return 'division/' + name.lower().translate(ID_TRANSLATION) + def candidate_id(first, last): first = first.lower().translate(ID_TRANSLATION) last = last.lower().translate(ID_TRANSLATION) return 'people/{}-{}'.format(last, first) + def group_id(state, code): return 'group/{}-{}'.format(state.split('/')[1], code.lower()) + def jsonify(obj): return json.dumps(obj, sort_keys=True, indent=4, separators=(',', ': ')) + def inhale(preload): if not os.path.exists(DATA_DIR): os.mkdir(DATA_DIR) diff --git a/feed_gvts.py b/feed_gvts.py index 39d51aa..160a291 100644 --- a/feed_gvts.py +++ b/feed_gvts.py @@ -26,20 +26,25 @@ ord(u"'"): None, } + def division_name(name): return 'division/' + name.lower().translate(ID_TRANSLATION) + def candidate_id(first, last): first = first.lower().translate(ID_TRANSLATION) last = last.lower().translate(ID_TRANSLATION) return 'people/{}-{}'.format(last, first) + def group_id(state, code): return 'group/{}-{}'.format(state.split('/')[1], code.lower()) + def jsonify(obj): return json.dumps(obj, sort_keys=True, indent=4, separators=(',', ': ')) + def inhale(preload): if not os.path.exists(DATA_DIR): os.mkdir(DATA_DIR) diff --git a/party.py b/party.py index fa756d1..bfbcfdb 100644 --- a/party.py +++ b/party.py @@ -20,7 +20,8 @@ if website: data['website'] = website - open('data/parties/' + filename, 'w').write(json.dumps(data, sort_keys=True, - indent=4, separators=(',', ': '))) - print open('data/parties/' + filename).read() + dfp = 'data/parties/' + filename + open(dfp, 'w').write(json.dumps(data, sort_keys=True, + indent=4, separators=(',', ': '))) + print open(dfp).read() print "" diff --git a/pdfprep.py b/pdfprep.py index b986b59..9963b23 100644 --- a/pdfprep.py +++ b/pdfprep.py @@ -23,6 +23,7 @@ parties = {} divisions = {} + def sorted_candidates(candidates): return [c[:-1] for c in sorted(candidates, key=lambda x: x[3])] @@ -45,7 +46,9 @@ def sorted_candidates(candidates): continue division_id = filename[:-5] - divisions[division_id] = json.loads(open('data/division/' + filename).read()) + ddf = 'data/division/' + filename + divisions[division_id] = json.loads(open(ddf).read()) + def group_sort(a, b): a_group = a.split('-', 1)[1][:-5] @@ -62,7 +65,8 @@ def group_sort(a, b): 'candidates': [], } - groups = [f for f in os.listdir('data/groups') if f.startswith(state) and f.endswith('.json')] + groups = [f for f in os.listdir('data/groups') + if f.startswith(state) and f.endswith('.json')] groups.sort(cmp=group_sort) for filename in groups: @@ -80,14 +84,15 @@ def group_sort(a, b): 'name': group['name'], } ballot.append(ballot_group) - + candidates = [] for candidate in group['candidates']: person = people[candidate] if person.get('party', None) is not None: c = (person['last_name'], person['first_name'], - parties[person['party']]['name'], person['ballot_position']) + parties[person['party']]['name'], + person['ballot_position']) else: c = (person['last_name'], person['first_name'], None, person['ballot_position']) @@ -122,6 +127,7 @@ def group_sort(a, b): division_ballots[division].append(c) + def group_sort(a, b): a = a['label'] b = b['label'] @@ -132,7 +138,7 @@ def group_sort(a, b): return cmp(a, b) for state in ballots: - ballots[state].sort(group_sort) + ballots[state].sort(group_sort) for division, candidates in division_ballots.items(): ballots[division] = (divisions[division]['name'], diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0526f14 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +python>=2.6 +python>3.0 +requests>=2.2.1 +bs4>=4.3 +pyrax>=1.8.1 +redis>=2.9.1