Update for Transcrypt/Python 3.7

This commit is contained in:
RunasSudo 2019-01-14 17:54:31 +11:00
parent 86f01abfdd
commit cb3623fda7
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
23 changed files with 4203 additions and 82 deletions

3
.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env"]
}

3
.gitignore vendored
View File

@ -2,9 +2,10 @@
/.python-version
/htmlcov
/venv
__javascript__
__target__
__pycache__
refs
node_modules
\#*
.#*

View File

@ -1,6 +1,6 @@
#!/bin/bash
# Eos - Verifiable elections
# Copyright © 2017 RunasSudo (Yingtong Li)
# Copyright © 2017-2019 RunasSudo (Yingtong Li)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@ -20,21 +20,14 @@ FLAGS="-k -mc -o"
#for f in eos.js eos.js_tests; do
for f in eos.js_tests; do
transcrypt -b -n $FLAGS $f.py || exit 1
# Javascript identifiers cannot contain dots
perl -0777 -pi -e 's/eos.js/eosjs/g' eos/__javascript__/$f.js
# __pragma__ sometimes stops working???
perl -0777 -pi -e "s/__pragma__ \('.*?'\)//gs" eos/__javascript__/$f.js
# Transcrypt by default suppresses stack traces for some reason??
perl -0777 -pi -e 's/__except0__.__cause__ = null;//g' eos/__javascript__/$f.js
# Fix handling of properties, Transcrypt bug #407
perl -0777 -pi -e 's/var __get__ = function \(self, func, quotedFuncName\) \{/var __get__ = function (self, func, quotedFuncName) { if(typeof(func) != "function"){return func;}/g' eos/__javascript__/$f.js
perl -0777 -pi -e 's/property.call \((.*?), \g1.\g1.__impl__(.*?)\)/property.call ($1, $1.__impl__$2)/g' eos/__javascript__/$f.js
perl -0777 -pi -e 's/property.call \((.*?), \g1.\g1.__implpy_(.*?)\)/property.call ($1, $1.__impl__$2)/g' eos/__javascript__/$f.js
done
cp eos/__javascript__/eos.js_tests.js eosweb/core/static/js/eosjs.js
perl -0777 -pi -e 's/eosjs_tests/eosjs/g' eosweb/core/static/js/eosjs.js
# Transcrypt syntax errors
perl -0777 -pi -e 's/import \{, /import \{/g' __target__/eos*.js
# Add export
echo >> __target__/eos.js_tests.js
echo 'export {eos, __kwargtrans__};' >> __target__/eos.js_tests.js
# Convert to ES5
./node_modules/.bin/browserify -t babelify -r ./__target__/eos.js_tests.js:eosjs > eosweb/core/static/js/eosjs.js

View File

@ -1,5 +1,5 @@
# Eos - Verifiable elections
# Copyright © 2017 RunasSudo (Yingtong Li)
# Copyright © 2017-2019 RunasSudo (Yingtong Li)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@ -184,18 +184,21 @@ class RelatedObjectListField(Field):
return None
return EosList([EosObject.deserialise_and_unwrap(x, self.object_type) for x in value])
if is_python:
class UUIDField(Field):
def __init__(self, *args, **kwargs):
class UUIDField(Field):
def __init__(self, *args, **kwargs):
if is_python:
super().__init__(default=uuid.uuid4, *args, **kwargs)
def serialise(self, value, options=SerialiseOptions.DEFAULT):
return str(value)
def deserialise(self, value):
else:
super().__init__(*args, **kwargs)
def serialise(self, value, options=SerialiseOptions.DEFAULT):
return str(value)
def deserialise(self, value):
if is_python:
return uuid.UUID(value)
else:
UUIDField = PrimitiveField
else:
return value
class DateTimeField(Field):
def pad(self, number):
@ -359,7 +362,16 @@ class DocumentObjectType(EosObjectType):
fields = {}
if hasattr(cls, '_fields'):
fields = cls._fields.copy() if is_python else Object.create(cls._fields)
for attr in list(dir(cls)):
if is_python:
attrs = list(dir(cls))
else:
# We want the raw Javascript name for getOwnPropertyDescriptor
__pragma__('jsiter')
attrs = [x for x in cls]
__pragma__('nojsiter')
for attr in attrs:
if not is_python:
# We must skip things with getters or else they will be called here (too soon)
if Object.getOwnPropertyDescriptor(cls, attr).js_get:

View File

@ -1,5 +1,5 @@
# Eos - Verifiable elections
# Copyright © 2017 RunasSudo (Yingtong Li)
# Copyright © 2017-2019 RunasSudo (Yingtong Li)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@ -14,8 +14,23 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import eos.js
import eos.core.objects
import eos.core.bigint
import eos.core.hashing
import eos.core.tests
import eos.core.tasks
import eos.core.tasks.direct
import eos.base.election
import eos.base.workflow
import eos.psr.bitstream
import eos.psr.crypto
import eos.psr.election
import eos.psr.mixnet
import eos.psr.workflow
import eos.redditauth.election
import eos.base.tests
import eos.psr.tests

View File

@ -1,6 +1,6 @@
/*
Eos - Verifiable elections
Copyright © 2017 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -19,13 +19,15 @@
window = self; // Workaround for libraries
isLibrariesLoaded = false;
eosjs = null;
function generateEncryptedVote(election, answers, should_do_fingerprint) {
encrypted_answers = [];
for (var q_num = 0; q_num < answers.length; q_num++) {
answer_json = answers[q_num];
answer = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(answer_json, null);
encrypted_answer = eosjs.eos.psr.election.__all__.BlockEncryptedAnswer.encrypt(election.public_key, answer, election.questions.__getitem__(q_num).max_bits() + 32); // +32 bits for the length
encrypted_answers.push(eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(encrypted_answer, null));
answer = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(answer_json, null);
encrypted_answer = eosjs.eos.psr.election.BlockEncryptedAnswer.encrypt(election.public_key, answer, election.questions.__getitem__(q_num).max_bits() + 32); // +32 bits for the length
encrypted_answers.push(eosjs.eos.core.objects.EosObject.serialise_and_wrap(encrypted_answer, null));
}
postMessage({
@ -40,10 +42,11 @@ onmessage = function(msg) {
msg.data.static_base_url + "js/eosjs.js"
);
isLibrariesLoaded = true;
eosjs = require("eosjs");
}
if (msg.data.action === "generateEncryptedVote") {
msg.data.election = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(msg.data.election, null);
msg.data.election = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(msg.data.election, null);
generateEncryptedVote(msg.data.election, msg.data.answers);
} else {

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -25,7 +25,7 @@
<p>Your vote has <span class="superem">not</span> yet been cast. Please follow the instructions to continue.</p>
</div>
<p>The following is your ballot with fingerprint <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64() }}</span>, decrypted and ready for auditing.</p>
<p>The following is your ballot with fingerprint <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>, decrypted and ready for auditing.</p>
<div class="ui form">
{# For some reason nunjucks doesn't like calling this the normal way #}

View File

@ -1,6 +1,6 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -18,7 +18,7 @@
<h1>{{ election.name }}</h1>
<p><small><b>{{ election.kind|title }} fingerprint:</b> <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(election).hash_as_b64() }}</span></small></p>
<p><small><b>{{ election.kind|title }} fingerprint:</b> <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(election).hash_as_b64() }}</span></small></p>
{# Convert the template name to a numerical index for comparison #}
{% if template == 'booth/welcome.html' %}

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -20,7 +20,7 @@
{% block content %}
<div id="cast_prompt">
<p>Your vote has <span class="superem">not</span> yet been cast. Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
<p>Your vote has <span class="superem">not</span> yet been cast. Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
<div class="ui negative message">
<p>Your vote has <span class="superem">not</span> yet been cast. Please follow the instructions to continue.</p>
@ -71,7 +71,7 @@
{% block after %}
<div class="ui tiny message" style="margin-top: 3em;">
<div class="header">Information for advanced users</div>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
</div>
<script>
@ -104,8 +104,8 @@
$.ajax({
url: "{{ election_base_url }}stage_ballot",
type: "POST",
data: eosjs.eos.core.objects.__all__.EosObject.to_json({
"ballot": eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(deauditedBallot, null),
data: eosjs.eos.core.objects.EosObject.to_json({
"ballot": eosjs.eos.core.objects.EosObject.serialise_and_wrap(deauditedBallot, null),
"fingerprint": booth.fingerprint || null
}),
contentType: "application/json",
@ -167,9 +167,9 @@
dataType: "text"
})
.done(function(data) {
response = eosjs.eos.core.objects.__all__.EosObject.from_json(data);
booth.voter = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(response.voter);
booth.vote = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(response.vote);
response = eosjs.eos.core.objects.EosObject.from_json(data);
booth.voter = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(response.voter);
booth.vote = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(response.vote);
// Clear plaintexts
booth.answers = null;

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -23,7 +23,7 @@
<p>Your vote has <span class="superem">not</span> yet been cast. Please follow the instructions to continue.</p>
</div>
<p>Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>. Please retain a copy of your ballot fingerprint – you can use it to verify that your vote has been counted correctly. You may <a href="#" onclick="window.print();return false;">print this page</a> as a receipt if you wish.</p>
<p>Please make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>. Please retain a copy of your ballot fingerprint – you can use it to verify that your vote has been counted correctly. You may <a href="#" onclick="window.print();return false;">print this page</a> as a receipt if you wish.</p>
<p>To continue, copy and paste the ballot below and provide it to the election administrator.</p>
@ -41,7 +41,7 @@
{% block after %}
<div class="ui tiny message" style="margin-top: 3em;">
<div class="header">Information for advanced users</div>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
</div>
{% endblock %}

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -26,7 +26,7 @@
<div class="content">
<div class="header">Smart ballot tracker</div>
<p>This smart ballot tracker confirms that {{ voter.py_name }} cast a vote in the election {{ election.py_name }} at {{ vote.cast_at }}.</p>
<p>Ballot fingerprint: <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(vote.ballot).hash_as_b64(true) }}</span></p>
<p>Ballot fingerprint: <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(vote.ballot).hash_as_b64(true) }}</span></p>
</div>
</div>
@ -42,7 +42,7 @@
{% block after %}
<div class="ui tiny message" style="margin-top: 3em;">
<div class="header">Information for advanced users</div>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(vote.ballot).hash_as_b64() }}</span>.</p>
<p>Your full ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(vote.ballot).hash_as_b64() }}</span>.</p>
</div>
{% endblock %}

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -30,19 +30,19 @@
try {
rawAnswers = [];
for (var answer_json of booth.answers) {
rawAnswers.push(eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(answer_json, null));
rawAnswers.push(eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(answer_json, null));
}
encryptedAnswers = [];
for (var encrypted_answer_json of msg.data.encrypted_answers) {
encryptedAnswers.push(eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(encrypted_answer_json, null));
encryptedAnswers.push(eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(encrypted_answer_json, null));
}
booth.ballot = eosjs.eos.base.election.__all__.Ballot();
booth.ballot = eosjs.eos.base.election.Ballot();
booth.ballot.answers = rawAnswers;
booth.ballot.encrypted_answers = encryptedAnswers;
booth.ballot.election_id = election._id;
booth.ballot.election_hash = eosjs.eos.core.hashing.__all__.SHA256().update_obj(election).hash_as_b64();
booth.ballot.election_hash = eosjs.eos.core.hashing.SHA256().update_obj(election).hash_as_b64();
if (should_do_fingerprint) {
// String.prototype.join confuses fingerprintjs2
@ -69,7 +69,7 @@
boothWorker.postMessage({
"action": "generateEncryptedVote",
"static_base_url": "{{ static_base_url }}",
"election": eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(election, null),
"election": eosjs.eos.core.objects.EosObject.serialise_and_wrap(election, null),
"answers": booth.answers
});
} catch (err) {

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -30,7 +30,7 @@
{% include templates[selection_model_view_map[election.questions.__getitem__(loop.index0)._name]["selections_review"]] %}
{% endfor %}
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
<p>Click ‘Continue’, and you will be able to log in to cast your vote.</p>
{% endblock %}
@ -42,7 +42,7 @@
{% block after %}
<div class="ui tiny message" style="margin-top: 3em;">
<div class="header">Information for advanced users</div>
<p>Your ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
<p>Your ballot fingerprint is <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64() }}</span>.</p>
<p>If you would like to audit your ballot, <a href="#" onclick="nextTemplate(1);">click here</a></p>
</div>
{% endblock %}

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -30,7 +30,7 @@
{% include templates[selection_model_view_map[election.questions.__getitem__(loop.index0)._name]["selections_review"]] %}
{% endfor %}
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
<p>If you are happy with your selections, then make a note of your ballot fingerprint, <span class="hash">{{ eosjs.eos.core.hashing.SHA256().update_obj(ballot).hash_as_b64(true) }}</span>.</p>
<p>Click ‘Continue’, and you will be able to copy your pre-poll ballot to provide to the election administrator.</p>
{% endblock %}

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@ -1,6 +1,6 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -107,8 +107,8 @@
}
}
answer = eosjs.eos.base.election.__all__.ApprovalAnswer(eosjs.__kwargtrans__({choices: selections}));
booth.answers[booth.questionNum] = eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(answer);
answer = eosjs.eos.base.election.ApprovalAnswer(eosjs.__kwargtrans__({choices: selections}));
booth.answers[booth.questionNum] = eosjs.eos.core.objects.EosObject.serialise_and_wrap(answer);
return true;
}

View File

@ -1,6 +1,6 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -249,8 +249,8 @@
}
}
answer = eosjs.eos.base.election.__all__.PreferentialAnswer(eosjs.__kwargtrans__({choices: selections}));
booth.answers[booth.questionNum] = eosjs.eos.core.objects.__all__.EosObject.serialise_and_wrap(answer);
answer = eosjs.eos.base.election.PreferentialAnswer(eosjs.__kwargtrans__({choices: selections}));
booth.answers[booth.questionNum] = eosjs.eos.core.objects.EosObject.serialise_and_wrap(answer);
booth.q_state[booth.questionNum] = [$("#question-choices-selected .dragarea").html(), $("#question-choices-remaining .dragarea").html()]; // wew lad

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017-18 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -44,6 +44,8 @@
{% endif %}
<script>
var eosjs = require("eosjs");
var templates = {};
var election = null;
var booth = null;
@ -78,7 +80,7 @@
$.ajax({ url: "{{ url_for('election_api_json', election_id=election._id) }}", dataType: "text" })
.done(function(data) {
try {
election = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(eosjs.eos.core.objects.__all__.EosObject.from_json(data), null);
election = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(eosjs.eos.core.objects.EosObject.from_json(data), null);
boothWorker = new Worker("{{ url_for('static', filename='js/booth_worker.js') }}");
@ -117,7 +119,7 @@
})
.done(function(data) {
try {
templates[templateUrl] = nunjucks.compile(data);
templates[templateUrl] = nunjucks.compile(data, null, templateUrl);
numTemplatesLoaded += 1;
if (numTemplatesLoaded == templateUrls.length) {
// All templates loaded. Show voting booth
@ -277,7 +279,7 @@
} else {
// Cast immediately
{% if session.staged_ballot %}
booth.ballot = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(eosjs.eos.core.objects.__all__.EosObject.from_json('{{ eos.core.objects.EosObject.to_json(session.staged_ballot.ballot)|safe }}'), null);
booth.ballot = eosjs.eos.core.objects.EosObject.deserialise_and_unwrap(eosjs.eos.core.objects.EosObject.from_json('{{ eos.core.objects.EosObject.to_json(session.staged_ballot.ballot)|safe }}'), null);
{% endif %}
boothTasks.append({
activate: function(fromLeft) {

View File

@ -2,7 +2,7 @@
{#
Eos - Verifiable elections
Copyright © 2017 RunasSudo (Yingtong Li)
Copyright © 2017-2019 RunasSudo (Yingtong Li)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@ -21,6 +21,9 @@
{% block electioncontent %}
{% for question in election.questions %}
<h2>{{ loop.index }}. {{ question.prompt }}</h2>
{% if question.description %}
<p>{{ question.description | urlize }}</p>
{% endif %}
{% include eosweb.core.main.model_view_map[question.__class__]['view'] %}
{% endfor %}
{% endblock %}

4089
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,4 +13,4 @@ pymongo==3.5.1
pyRCV==0.3
pytz==2017.3
timeago==1.0.8
Transcrypt==3.6.60
Transcrypt==3.7.13

View File

@ -1 +1 @@
python-3.6.3
python-3.7.2