gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-survey] branch stable updated (ac0b8a1 -> 90d2bb4)


From: gnunet
Subject: [GNUnet-SVN] [taler-survey] branch stable updated (ac0b8a1 -> 90d2bb4)
Date: Thu, 18 Jan 2018 18:48:22 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a change to branch stable
in repository survey.

 discard ac0b8a1  use new tipping API, fix various little things

This update removed existing revisions from the reference, leaving the
reference pointing at a previous point in the repository history.

 * -- * -- N   refs/heads/stable (90d2bb4)
            \
             O -- O -- O   (ac0b8a1)

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

No new revisions were added by this update.

Summary of changes:
 talersurvey/survey/amount.py            | 135 ++++++++++++++++++++++++++++++++
 talersurvey/survey/survey.py            |  66 ++++++++--------
 talersurvey/survey/templates/base.html  |  10 +--
 talersurvey/survey/templates/index.html |   2 +-
 4 files changed, 175 insertions(+), 38 deletions(-)
 create mode 100644 talersurvey/survey/amount.py

diff --git a/talersurvey/survey/amount.py b/talersurvey/survey/amount.py
new file mode 100644
index 0000000..46e3446
--- /dev/null
+++ b/talersurvey/survey/amount.py
@@ -0,0 +1,135 @@
+#  This file is part of TALER
+#  (C) 2017 TALER SYSTEMS
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+#
+#  @author Marcello Stanisci
+#  @version 0.1
+#  @repository https://git.taler.net/copylib.git/
+#  This code is "copylib", it is versioned under the Git repository
+#  mentioned above, and it is meant to be manually copied into any project
+#  which might need it.
+
+class CurrencyMismatch(Exception):
+    def __init__(self, curr1, curr2):
+        super(CurrencyMismatch, self).__init__(
+            "%s vs %s" % (curr1, curr2))
+
+class BadFormatAmount(Exception):
+    def __init__(self, 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():
+        return 10 ** 8
+
+    @staticmethod
+    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
+        self.value = value
+        self.fraction = fraction
+        self.currency = currency
+        self.__normalize()
+        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()
+
+    # Parse a string matching the format "A:B.C"
+    # instantiating an amount object.
+    @classmethod
+    def parse(cls, amount_str):
+        exp = r'^\s*([-_*A-Za-z0-9]+):([0-9]+)\.([0-9]+)\s*$'
+        import re
+        parsed = re.search(exp, amount_str)
+        if not parsed:
+            raise BadFormatAmount(amount_str)
+        value = int(parsed.group(2))
+        fraction = 0
+        for i, digit in enumerate(parsed.group(3)):
+            fraction += int(int(digit) * (Amount._fraction() / 10 ** (i+1)))
+        return cls(parsed.group(1), value, fraction)
+
+    # Comare two amounts, return:
+    # -1 if a < b
+    # 0 if a == b
+    # 1 if a > b
+    @staticmethod
+    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 am1.fraction > am2.fraction:
+                return 1
+            return 0
+        if am1.value < am2.value:
+            return -1
+        return 1
+
+    def set(self, currency, value=0, fraction=0):
+        self.currency = currency
+        self.value = value
+        self.fraction = fraction
+
+    # Add the given amount to this one
+    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, 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 < amount.value:
+            raise ValueError('self is lesser than amount to be subtracted')
+        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))
+        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
+    def dump(self):
+        return dict(value=self.value,
+                    fraction=self.fraction,
+                    currency=self.currency)
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index d068f66..6c2f4c8 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -48,53 +48,55 @@ def backend_error(requests_response):
 
 @app.context_processor
 def utility_processor():
+
+    def join_urlparts(*parts):
+        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)
     def env(name, default=None):
         return os.environ.get(name, default)
     return dict(url=url, env=env)
 
 
-def err_abort(abort_status_code, **params):
-    t = flask.render_template("templates/error.html", **params)
-    flask.abort(flask.make_response(t, abort_status_code))
-
-
-def backend_post(endpoint, json):
-    try:
-        resp = requests.post(urljoin(BACKEND_URL, endpoint), json=json)
-    except requests.ConnectionError:
-        err_abort(500, message="Could not establish connection to backend")
-    try:
-        response_json = resp.json()
-    except ValueError:
-        err_abort(500, message="Could not parse response from backend",
-                  status_code=resp.status_code)
address@hidden("/tip-pickup", methods=["POST"])
+def pick():
+    request_body = flask.request.get_json()
+    resp = requests.post(urljoin(BACKEND_URL, "tip-pickup"),
+                         json=request_body)
     if resp.status_code != 200:
-        err_abort(500, message="Backend returned error status",
-                  json=response_json, status_code=resp.status_code)
-    return response_json
-
-
address@hidden(Exception)
-def internal_error(e):
-    return flask.render_template("templates/error.html",
-                                 message="Internal error",
-                                 stack=traceback.format_exc())
-
+        return backend_error(resp)
+    response_body = resp.json()
+    return flask.jsonify(response_body)
 
 @app.route("/submit-survey", methods=["POST"])
 def submit_survey():
     tip_spec = dict(pickup_url=urljoin(flask.request.base_url, "/tip-pickup"),
-                    amount=CURRENCY + ":1.0",
+                    amount=Amount(CURRENCY, 1).dump(),
                     next_url=os.environ.get("TALER_ENV_URL_INTRO", 
"https://taler.net/";),
                     instance="default",
                     justification="Payment methods survey")
-    resp = backend_post("tip-authorize", tip_spec)
+    resp = requests.post(urljoin(BACKEND_URL, "tip-authorize"),
+                         json=tip_spec)
+    if resp.status_code != 200:
+        return backend_error(resp)
 
-    if resp.get("tip_redirect_url"):
-        flask.redirect(resp["tip_redirect_url"]
+    response = flask.make_response(
+        flask.render_template("templates/wait.html", success=True),
+        402)
+    response.headers["X-Taler-Tip"] = resp.json()["tip_token"]
 
-    err_abort(500, message="Tipping failed, unexpected backend response",
-              json=resp)
+    return response
 
 
 @app.route("/", methods=["GET"])
diff --git a/talersurvey/survey/templates/base.html 
b/talersurvey/survey/templates/base.html
index 879a24d..3826797 100644
--- a/talersurvey/survey/templates/base.html
+++ b/talersurvey/survey/templates/base.html
@@ -18,10 +18,10 @@
 <html>
 <head>
   <title>Taler Survey Demo</title>
-  <link rel="stylesheet" type="text/css" href="{{ url_for('static', 
filename='web-common/pure.css') }}" />
-  <link rel="stylesheet" type="text/css" href="{{ url_for('static', 
filename='web-common/demo.css') }}" />
-  <script src="{{ url_for('static', filename='web-common/taler-wallet-lib.js') 
}}" type="application/javascript"></script>
-  <script src="{{ url_for('static', filename='static/web-common/lang.js') }}" 
type="application/javascript"></script>
+  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/pure.css') }}" />
+  <link rel="stylesheet" type="text/css" href="{{ 
url('/static/web-common/demo.css') }}" />
+  <script src="{{ url("/static/web-common/taler-wallet-lib.js") }}" 
type="application/javascript"></script>
+  <script src="{{ url("/static/web-common/lang.js") }}" 
type="application/javascript"></script>
   {% block styles %}{% endblock %}
   {% block scripts %}{% endblock %}
 </head>
@@ -41,7 +41,7 @@
   </div>
 
   <section id="main" class="content">
-    <a href="{{ url_for('index') }}">
+    <a href="{{ url("/") }}">
       <div id="logo">
         <svg height="100" width="100">
           <circle cx="50" cy="50" r="40" stroke="darkcyan" stroke-width="6" 
fill="white" />
diff --git a/talersurvey/survey/templates/index.html 
b/talersurvey/survey/templates/index.html
index f40c235..1799abd 100644
--- a/talersurvey/survey/templates/index.html
+++ b/talersurvey/survey/templates/index.html
@@ -8,7 +8,7 @@
     </p>
   </div>
   <div>
-    <form action="{{ url_for('submit_survey') }}" method="post" 
class="pure-form pure-form-stacked">
+    <form action="{{ url('/submit-survey') }}" method="post" class="pure-form 
pure-form-stacked">
       <legend>What do you prefer?</legend>
       <fieldset>
       <label for="option-taler">

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]