summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--talersurvey/survey/amount.py74
-rw-r--r--talersurvey/survey/survey.py71
-rw-r--r--talersurvey/tests.py6
3 files changed, 78 insertions, 73 deletions
diff --git a/talersurvey/survey/amount.py b/talersurvey/survey/amount.py
index 9a6318a..46e3446 100644
--- a/talersurvey/survey/amount.py
+++ b/talersurvey/survey/amount.py
@@ -23,43 +23,46 @@
# which might need it.
class CurrencyMismatch(Exception):
- pass
+ def __init__(self, curr1, curr2):
+ super(CurrencyMismatch, self).__init__(
+ "%s vs %s" % (curr1, curr2))
class BadFormatAmount(Exception):
def __init__(self, faulty_str):
- self.faulty_str = faulty_str
+ super(BadFormatAmount, self).__init__(
+ "Bad format amount: " + faulty_str)
class Amount:
# How many "fraction" units make one "value" unit of currency
# (Taler requires 10^8). Do not change this 'constant'.
@staticmethod
- def FRACTION():
+ def _fraction():
return 10 ** 8
@staticmethod
- def MAX_VALUE():
+ def _max_value():
return (2 ** 53) - 1
def __init__(self, currency, value=0, fraction=0):
# type: (str, int, int) -> Amount
- assert(value >= 0 and fraction >= 0)
+ assert value >= 0 and fraction >= 0
self.value = value
self.fraction = fraction
self.currency = currency
self.__normalize()
- assert(self.value <= Amount.MAX_VALUE())
+ assert self.value <= Amount._max_value()
# Normalize amount
def __normalize(self):
- if self.fraction >= Amount.FRACTION():
- self.value += int(self.fraction / Amount.FRACTION())
- self.fraction = self.fraction % Amount.FRACTION()
+ if self.fraction >= Amount._fraction():
+ self.value += int(self.fraction / Amount._fraction())
+ self.fraction = self.fraction % Amount._fraction()
# Parse a string matching the format "A:B.C"
# instantiating an amount object.
@classmethod
def parse(cls, amount_str):
- exp = '^\s*([-_*A-Za-z0-9]+):([0-9]+)\.([0-9]+)\s*$'
+ exp = r'^\s*([-_*A-Za-z0-9]+):([0-9]+)\.([0-9]+)\s*$'
import re
parsed = re.search(exp, amount_str)
if not parsed:
@@ -67,7 +70,7 @@ class Amount:
value = int(parsed.group(2))
fraction = 0
for i, digit in enumerate(parsed.group(3)):
- fraction += int(int(digit) * (Amount.FRACTION() / 10 ** (i+1)))
+ fraction += int(int(digit) * (Amount._fraction() / 10 ** (i+1)))
return cls(parsed.group(1), value, fraction)
# Comare two amounts, return:
@@ -75,16 +78,16 @@ class Amount:
# 0 if a == b
# 1 if a > b
@staticmethod
- def cmp(a, b):
- if a.currency != b.currency:
- raise CurrencyMismatch()
- if a.value == b.value:
- if a.fraction < b.fraction:
+ def cmp(am1, am2):
+ if am1.currency != am2.currency:
+ raise CurrencyMismatch(am1.currency, am2.currency)
+ if am1.value == am2.value:
+ if am1.fraction < am2.fraction:
return -1
- if a.fraction > b.fraction:
+ if am1.fraction > am2.fraction:
return 1
return 0
- if a.value < b.value:
+ if am1.value < am2.value:
return -1
return 1
@@ -94,34 +97,35 @@ class Amount:
self.fraction = fraction
# Add the given amount to this one
- def add(self, a):
- if self.currency != a.currency:
- raise CurrencyMismatch()
- self.value += a.value
- self.fraction += a.fraction
+ def add(self, amount):
+ if self.currency != amount.currency:
+ raise CurrencyMismatch(self.currency, amount.currency)
+ self.value += amount.value
+ self.fraction += amount.fraction
self.__normalize()
# Subtract passed amount from this one
- def subtract(self, a):
- if self.currency != a.currency:
- raise CurrencyMismatch()
- if self.fraction < a.fraction:
- self.fraction += Amount.FRACTION()
+ def subtract(self, amount):
+ if self.currency != amount.currency:
+ raise CurrencyMismatch(self.currency, amount.currency)
+ if self.fraction < amount.fraction:
+ self.fraction += Amount._fraction()
self.value -= 1
- if self.value < a.value:
+ if self.value < amount.value:
raise ValueError('self is lesser than amount to be subtracted')
- self.value -= a.value
- self.fraction -= a.fraction
+ self.value -= amount.value
+ self.fraction -= amount.fraction
# Dump string from this amount, will put 'ndigits' numbers
# after the dot.
def stringify(self, ndigits):
assert ndigits > 0
ret = '%s:%s.' % (self.currency, str(self.value))
- f = self.fraction
- for i in range(0, ndigits):
- ret += str(int(f / (Amount.FRACTION() / 10)))
- f = (f * 10) % (Amount.FRACTION())
+ fraction = self.fraction
+ while ndigits > 0:
+ ret += str(int(fraction / (Amount._fraction() / 10)))
+ fraction = (fraction * 10) % (Amount._fraction())
+ ndigits -= 1
return ret
# Dump the Taler-compliant 'dict' amount
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index d44db73..80b07d1 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -14,53 +14,53 @@
#
# @author Marcello Stanisci
-import flask
import os
import base64
-import requests
import logging
import json
-from .amount import Amount
-from talersurvey.talerconfig import TalerConfig
from urllib.parse import urljoin
+import flask
+import requests
+from talersurvey.talerconfig import TalerConfig
+from .amount import Amount
-
-base_dir = os.path.dirname(os.path.abspath(__file__))
-app = flask.Flask(__name__, template_folder=base_dir)
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+app = flask.Flask(__name__, template_folder=BASE_DIR)
app.debug = True
app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8')
-tc = TalerConfig.from_env()
-BACKEND_URL = tc["frontends"]["backend"].value_string(required=True)
-CURRENCY = tc["taler"]["currency"].value_string(required=True)
+TC = TalerConfig.from_env()
+BACKEND_URL = TC["frontends"]["backend"].value_string(required=True)
+CURRENCY = TC["taler"]["currency"].value_string(required=True)
app.config.from_object(__name__)
-logger = logging.getLogger(__name__)
+LOGGER = logging.getLogger(__name__)
def backend_error(requests_response):
- logger.error("Backend error: status code: "
+ LOGGER.error("Backend error: status code: "
+ str(requests_response.status_code))
try:
return flask.jsonify(requests_response.json()), requests_response.status_code
except json.decoder.JSONDecodeError:
- logger.error("Backend error (NO JSON returned): status code: "
+ LOGGER.error("Backend error (NO JSON returned): status code: "
+ str(requests_response.status_code))
return flask.jsonify(dict(error="Backend died, no JSON got from it")), 502
@app.context_processor
def utility_processor():
+
def join_urlparts(*parts):
- s = ""
- i = 0
- while i < len(parts):
- n = parts[i]
- i += 1
- if s.endswith("/"):
- n = n.lstrip("/")
- elif s and not n.startswith("/"):
- n = "/" + n
- s += n
- return s
+ ret = ""
+ part = 0
+ while part < len(parts):
+ buf = parts[part]
+ part += 1
+ if ret.endswith("/"):
+ buf = buf.lstrip("/")
+ elif ret and not buf.startswith("/"):
+ buf = "/" + buf
+ ret += buf
+ return ret
def url(my_url):
return join_urlparts(flask.request.script_root, my_url)
@@ -72,11 +72,11 @@ def utility_processor():
@app.route("/tip-pickup", methods=["POST"])
def pick():
body = flask.request.get_json()
- r = requests.post(urljoin(BACKEND_URL, 'tip-pickup'), json=body)
- if 200 != r.status_code:
- return backend_error(r)
- return flask.jsonify(r.json())
-
+ resp = requests.post(urljoin(BACKEND_URL, 'tip-pickup'),
+ json=body)
+ if resp.status_code != 200:
+ return backend_error(resp)
+ return flask.jsonify(resp.json())
@app.route("/submit-survey", methods=["POST"])
def submit_survey():
@@ -84,14 +84,15 @@ def submit_survey():
amount=Amount(CURRENCY, 1).dump(),
instance="default",
justification="Payment methods survey")
- r = requests.post(urljoin(BACKEND_URL, 'tip-authorize'), json=tip_spec)
- if 200 != r.status_code:
- return backend_error(r)
+ resp = requests.post(urljoin(BACKEND_URL, 'tip-authorize'),
+ json=tip_spec)
+ if resp.status_code != 200:
+ return backend_error(resp)
response = flask.make_response(
- flask.render_template("templates/wait.html", success=True),
- 402)
- response.headers["X-Taler-Tip"] = r.json()["tip_token"]
+ flask.render_template("templates/wait.html", success=True),
+ 402)
+ response.headers["X-Taler-Tip"] = resp.json()["tip_token"]
return response
diff --git a/talersurvey/tests.py b/talersurvey/tests.py
index 56e66e4..d5845bc 100644
--- a/talersurvey/tests.py
+++ b/talersurvey/tests.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
import unittest
-from talersurvey.survey import survey
from mock import patch, MagicMock
+from talersurvey.survey import survey
from talersurvey.talerconfig import TalerConfig
TC = TalerConfig.from_env()
@@ -27,7 +27,7 @@ class SurveyTestCase(unittest.TestCase):
mocked_post.assert_called_with(
"http://backend.test.taler.net/tip-authorize",
json={
- "pickup_url": "http://localhost/tip-pickup",
+ "pickup_url": "http://localhost/tip-pickup",
"amount": {
"value": 1,
"fraction": 0,
@@ -46,7 +46,7 @@ class SurveyTestCase(unittest.TestCase):
content_type="application/json")
mocked_post.assert_called_with(
"http://backend.test.taler.net/tip-pickup",
- json={})
+ json={})
if __name__ == "__main__":
unittest.main()