From 4f1f0cf04268918406cc3afc99bf1b60df320f8d Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Tue, 5 Dec 2017 19:40:26 +1030 Subject: [PATCH] Improve dealing with Transcrypt's funky aliases Transcrypt issue 414 --- build_js.sh | 3 -- eos/core/objects/__init__.py | 40 +++++++++++++------ eos/core/tests.py | 6 +-- eosweb/core/static/nunjucks/booth/base.html | 2 +- .../core/static/nunjucks/booth/complete.html | 2 +- .../core/static/nunjucks/booth/welcome.html | 2 +- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/build_js.sh b/build_js.sh index 54f80d8..c92b9db 100755 --- a/build_js.sh +++ b/build_js.sh @@ -30,9 +30,6 @@ for f in eos.js_tests; do # Transcrypt by default suppresses stack traces for some reason?? perl -0777 -pi -e 's/__except0__.__cause__ = null;//g' eos/__javascript__/$f.js - # Disable handling of special attributes - perl -0777 -pi -e 's/var __specialattrib__ = function \(attrib\) \{/var __specialattrib__ = function (attrib) { return false;/g' eos/__javascript__/$f.js - # Fix handling of properties, Transcrypt bug #407 perl -077 -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 diff --git a/eos/core/objects/__init__.py b/eos/core/objects/__init__.py index 16a8f4a..053c0b9 100644 --- a/eos/core/objects/__init__.py +++ b/eos/core/objects/__init__.py @@ -297,7 +297,17 @@ class DocumentObjectType(EosObjectType): val = getattr(cls, attr) if isinstance(val, Field): val._instance = (cls, name) - fields[attr] = val + + # Transcrypt does funky things with aliases, which are usually helpful, but not here + if not is_python and attr.startswith('py_'): + real_attr = attr[3:] + else: + real_attr = attr + + val.real_name = real_attr # The JSON/Python name + val.internal_name = attr # The name that gets passed in as kwargs in Javascript + + fields[real_attr] = val delattr(cls, attr) cls._fields = fields @@ -316,7 +326,9 @@ class DocumentObjectType(EosObjectType): return property(field_getter, field_setter) for attr, val in fields.items(): - setattr(cls, attr, make_property(attr, val)) + setattr(cls, val.real_name, make_property(val.real_name, val)) + #if val.real_name != val.internal_name: + # setattr(cls, val.internal_name, make_property(val.real_name, val)) else: # Handled at instance level pass @@ -348,24 +360,29 @@ class DocumentObject(EosObject, metaclass=DocumentObjectType): if not value._inited: value.post_init() return (field_getter, field_setter) - prop = make_property(attr, val) + prop = make_property(val.real_name, val) # TNYI: No support for property() - Object.defineProperty(self, attr, { + Object.defineProperty(self, val.real_name, { 'get': prop[0], 'set': prop[1] }) + if val.real_name != val.internal_name: + # Allow reference as e.g. both obj.py_name (from Python code) and obj.name (from JS templates) + Object.defineProperty(self, val.internal_name, { + 'get': prop[0], + 'set': prop[1] + }) - if attr in kwargs: - setattr(self, attr, kwargs[attr]) + if val.internal_name in kwargs: + setattr(self, val.real_name, kwargs[val.internal_name]) else: default = val.default if default is not None and callable(default): default = default() - setattr(self, attr, default) + setattr(self, val.real_name, default) - # TNYI: Strange things happen with py_ attributes def serialise(self, for_hash=False, should_protect=False): - return {(attr[3:] if attr.startswith('py_') else attr): val.serialise(getattr(self, attr), for_hash, should_protect) for attr, val in self._fields.items() if ((val.is_hashed or not for_hash) and (not should_protect or not val.is_protected))} + return {val.real_name: val.serialise(getattr(self, val.real_name), for_hash, should_protect) for attr, val in self._fields.items() if ((val.is_hashed or not for_hash) and (not should_protect or not val.is_protected))} @classmethod def deserialise(cls, value): @@ -374,9 +391,8 @@ class DocumentObject(EosObject, metaclass=DocumentObjectType): attrs = {} for attr, val in cls._fields.items(): - json_attr = attr[3:] if attr.startswith('py_') else attr - if json_attr in value: - attrs[attr] = val.deserialise(value[json_attr]) + if attr in value: + attrs[val.internal_name] = val.deserialise(value[val.real_name]) return cls(**attrs) class TopLevelObject(DocumentObject): diff --git a/eos/core/tests.py b/eos/core/tests.py index b44dd2b..93b623d 100644 --- a/eos/core/tests.py +++ b/eos/core/tests.py @@ -73,7 +73,7 @@ class ObjectTestCase(EosTestCase): def setUpClass(cls): class Person(TopLevelObject): name = StringField() - address = StringField(default=None) + address = StringField(default='Default address') def say_hi(self): return 'Hello! My name is ' + self.name @@ -81,10 +81,10 @@ class ObjectTestCase(EosTestCase): def test_basic(self): person1 = self.Person(name='John', address='Address 1') - person2 = self.Person(name='James', address='Address 2') + person2 = self.Person(name='James') self.assertEqual(person1.address, 'Address 1') - self.assertEqual(person2.address, 'Address 2') + self.assertEqual(person2.address, 'Default address') self.assertEqual(person1.say_hi(), 'Hello! My name is John') self.assertEqual(person2.say_hi(), 'Hello! My name is James') diff --git a/eosweb/core/static/nunjucks/booth/base.html b/eosweb/core/static/nunjucks/booth/base.html index 6ca84ce..225f96b 100644 --- a/eosweb/core/static/nunjucks/booth/base.html +++ b/eosweb/core/static/nunjucks/booth/base.html @@ -16,7 +16,7 @@ along with this program. If not, see . #} -

{{ election.py_name }}

+

{{ election.name }}

{{ election.kind|title }} fingerprint: {{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(election).hash_as_b64() }}

diff --git a/eosweb/core/static/nunjucks/booth/complete.html b/eosweb/core/static/nunjucks/booth/complete.html index 6450212..0cb5f36 100644 --- a/eosweb/core/static/nunjucks/booth/complete.html +++ b/eosweb/core/static/nunjucks/booth/complete.html @@ -23,7 +23,7 @@
Smart ballot tracker
-

This smart ballot tracker confirms that {{ voter.py_name }} cast a vote in the election {{ election.py_name }} at {{ vote.cast_at }}.

+

This smart ballot tracker confirms that {{ voter.name }} cast a vote in the election {{ election.py_name }} at {{ vote.cast_at }}.

Ballot fingerprint: {{ eosjs.eos.core.hashing.__all__.SHA256().update_obj(vote.ballot).hash_as_b64() }}

diff --git a/eosweb/core/static/nunjucks/booth/welcome.html b/eosweb/core/static/nunjucks/booth/welcome.html index 88cf184..3eec202 100644 --- a/eosweb/core/static/nunjucks/booth/welcome.html +++ b/eosweb/core/static/nunjucks/booth/welcome.html @@ -19,7 +19,7 @@ #} {% block content %} -

Welcome to the {{ election.py_name }} voting booth.

+

Welcome to the {{ election.name }} voting booth.

Follow the on-screen directions to prepare and cast your ballot in this {{ election.kind }}. The bar above will show your progress. Please note that your ballot will not be cast until you complete the final ‘Cast ballot’ stage and receive a ‘smart ballot tracker’.

If at any point you wish to return to a previous screen, click the ‘Back’ button below.

If you wish, you may disconnect your internet connection now while preparing your ballot, however you must re-connect your internet connection before logging in to cast your ballot.