From 7c898b3153c22a03d39bcb9e649c8d130ea1b92e Mon Sep 17 00:00:00 2001
From: Marcello Stanisci
Date: Mon, 27 May 2019 18:42:07 +0200
Subject: upgrade/fix config logic
---
talersurvey/talerconfig.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
(limited to 'talersurvey')
diff --git a/talersurvey/talerconfig.py b/talersurvey/talerconfig.py
index 69d06a8..4a44c97 100644
--- a/talersurvey/talerconfig.py
+++ b/talersurvey/talerconfig.py
@@ -344,6 +344,7 @@ class TalerConfig:
filename = os.path.join(xdg, "taler.conf")
else:
filename = os.path.expanduser("~/.config/taler.conf")
+ print("Loading default config: (%s)" % filename)
if load_defaults:
cfg.load_defaults()
cfg.load_file(os.path.expanduser(filename))
@@ -496,7 +497,8 @@ class TalerConfig:
value=value, filename=filename, lineno=lineno)
sections[current_section][key] = entry
except FileNotFoundError:
- LOGGER.error("Configuration file (%s) not found", filename)
+ # not logging here, as this interests the final user mostly.
+ print("Configuration file (%s) not found" % filename)
sys.exit(3)
##
--
cgit v1.2.3
From 141e949fa9f09e5f54acdfa90f609895236a8ac0 Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Thu, 29 Aug 2019 23:08:26 +0200
Subject: make pretty
---
.style.yapf | 5 ++
bin/taler-merchant-survey | 48 ++++++++++---------
setup.py | 58 +++++++++++-----------
talersurvey/survey/survey.py | 102 ++++++++++++++++++++++++++-------------
talersurvey/talerconfig.py | 112 ++++++++++++++++++++++++++++++-------------
talersurvey/tests.py | 1 +
6 files changed, 210 insertions(+), 116 deletions(-)
create mode 100644 .style.yapf
(limited to 'talersurvey')
diff --git a/.style.yapf b/.style.yapf
new file mode 100644
index 0000000..3b39780
--- /dev/null
+++ b/.style.yapf
@@ -0,0 +1,5 @@
+[style]
+based_on_style = pep8
+coalesce_brackets=True
+column_limit=80
+dedent_closing_brackets=True
diff --git a/bin/taler-merchant-survey b/bin/taler-merchant-survey
index 418cd78..2da6fde 100755
--- a/bin/taler-merchant-survey
+++ b/bin/taler-merchant-survey
@@ -28,7 +28,6 @@ import site
import logging
from talersurvey.talerconfig import TalerConfig
-
LOGGER = logging.getLogger(__name__)
# No perfect match to our logging format, but good enough ...
UWSGI_LOGFMT = "%(ltime) %(proto) %(method) %(uri) %(proto) => %(status)"
@@ -43,13 +42,11 @@ def handle_serve_http(args):
port = args.port
if port is None:
port = TC["survey"]["http_port"].value_int(required=True)
- spec = ":%d" % (port,)
- os.execlp("uwsgi", "uwsgi",
- "--master",
- "--die-on-term",
- "--log-format", UWSGI_LOGFMT,
- "--http", spec,
- "--module", "talersurvey")
+ spec = ":%d" % (port, )
+ os.execlp(
+ "uwsgi", "uwsgi", "--master", "--die-on-term", "--log-format",
+ UWSGI_LOGFMT, "--http", spec, "--module", "talersurvey"
+ )
##
@@ -60,22 +57,22 @@ def handle_serve_http(args):
#
# @param command line options.
def handle_serve_uwsgi(args):
- del args # pacify PEP checkers
- serve_uwsgi = TC["survey"]["uwsgi_serve"].value_string(required=True).lower()
- params = ["uwsgi", "uwsgi",
- "--master",
- "--die-on-term",
- "--log-format", UWSGI_LOGFMT,
- "--module", "talersurvey"]
+ del args # pacify PEP checkers
+ serve_uwsgi = TC["survey"]["uwsgi_serve"].value_string(required=True
+ ).lower()
+ params = [
+ "uwsgi", "uwsgi", "--master", "--die-on-term", "--log-format",
+ UWSGI_LOGFMT, "--module", "talersurvey"
+ ]
if serve_uwsgi == "tcp":
port = TC["survey"]["uwsgi_port"].value_int(required=True)
- spec = ":%d" % (port,)
+ spec = ":%d" % (port, )
params.extend(["--socket", spec])
elif serve_uwsgi == "unix":
spec = TC["survey"]["uwsgi_unixpath"].value_filename(required=True)
mode = TC["survey"]["uwsgi_unixpath_mode"].value_filename(required=True)
params.extend(["--socket", spec])
- params.extend(["--chmod-socket="+mode])
+ params.extend(["--chmod-socket=" + mode])
os.makedirs(os.path.dirname(spec), exist_ok=True)
logging.info("launching uwsgi with argv %s", params[1:])
os.execlp(*params)
@@ -84,14 +81,21 @@ def handle_serve_uwsgi(args):
## @cond
PARSER = argparse.ArgumentParser()
PARSER.set_defaults(func=None)
-PARSER.add_argument('--config', '-c',
- help="configuration file to use",
- metavar="CONFIG", type=str,
- dest="config", default=None)
+PARSER.add_argument(
+ '--config',
+ '-c',
+ help="configuration file to use",
+ metavar="CONFIG",
+ type=str,
+ dest="config",
+ default=None
+)
SUB = PARSER.add_subparsers()
P = SUB.add_parser('serve-http', help="Serve over HTTP")
-P.add_argument("--port", "-p", dest="port", type=int, default=None, metavar="PORT")
+P.add_argument(
+ "--port", "-p", dest="port", type=int, default=None, metavar="PORT"
+)
P.set_defaults(func=handle_serve_http)
P = SUB.add_parser('serve-uwsgi', help="Serve over UWSGI")
diff --git a/setup.py b/setup.py
index cf6f1ca..fa132d6 100755
--- a/setup.py
+++ b/setup.py
@@ -1,30 +1,32 @@
from setuptools import setup, find_packages
-setup(name='talersurvey',
- version='0.6.0pre1',
- description='Example survey site for GNU Taler',
- url='git://taler.net/survey',
- author='Marcello Stanisci',
- author_email='stanisci.m@gmail.com',
- license='GPL',
- packages=find_packages(),
- install_requires=["Flask>=0.10", "jsmin"],
- test_suite="nose.collector",
- tests_require=["mock", "nose", "requests", "uwsgi"],
- package_data={
- '':[
- "survey/templates/*.html",
- "survey/static/favicon.ico",
- "survey/static/*.svg",
- "survey/static/*.css",
- "survey/static/*.js",
- "survey/static/*.js.tar.gz",
- "survey/static/web-common/*.png",
- "survey/static/web-common/*.css",
- "survey/static/web-common/*.js",
- "survey/static/web-common/*.js.tar.gz",
- "survey/static/web-common/*.html",
- ]
- },
- scripts=['./bin/taler-merchant-survey'],
- zip_safe=False)
+setup(
+ name='talersurvey',
+ version='0.6.0pre1',
+ description='Example survey site for GNU Taler',
+ url='git://taler.net/survey',
+ author='Marcello Stanisci',
+ author_email='stanisci.m@gmail.com',
+ license='GPL',
+ packages=find_packages(),
+ install_requires=["Flask>=0.10", "jsmin"],
+ test_suite="nose.collector",
+ tests_require=["mock", "nose", "requests", "uwsgi"],
+ package_data={
+ '': [
+ "survey/templates/*.html",
+ "survey/static/favicon.ico",
+ "survey/static/*.svg",
+ "survey/static/*.css",
+ "survey/static/*.js",
+ "survey/static/*.js.tar.gz",
+ "survey/static/web-common/*.png",
+ "survey/static/web-common/*.css",
+ "survey/static/web-common/*.js",
+ "survey/static/web-common/*.js.tar.gz",
+ "survey/static/web-common/*.html",
+ ]
+ },
+ scripts=['./bin/taler-merchant-survey'],
+ zip_safe=False
+)
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index 79d0f16..1c6b8aa 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -48,14 +48,21 @@ LOGGER = logging.getLogger(__name__)
# the merchant backend.
# @return a flask-native response object.
def backend_error(requests_response):
- LOGGER.error("Backend error: status code: "
- + str(requests_response.status_code))
+ LOGGER.error(
+ "Backend error: status code: " + str(requests_response.status_code)
+ )
try:
- return flask.jsonify(requests_response.json()), requests_response.status_code
+ return flask.jsonify(
+ requests_response.json()
+ ), requests_response.status_code
except json.decoder.JSONDecodeError:
- 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
+ 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
##
@@ -66,14 +73,15 @@ def backend_error(requests_response):
def utility_processor():
def env(name, default=None):
return os.environ.get(name, default)
+
def prettydate(talerdate):
- parsed_time = re.search(r"/Date\(([0-9]+)\)/", talerdate)
- if not parsed_time:
- return "malformed date given"
- parsed_time = int(parsed_time.group(1))
- timestamp = datetime.datetime.fromtimestamp(parsed_time)
- # returns the YYYY-MM-DD date format.
- return timestamp.strftime("%Y-%b-%d")
+ parsed_time = re.search(r"/Date\(([0-9]+)\)/", talerdate)
+ if not parsed_time:
+ return "malformed date given"
+ parsed_time = int(parsed_time.group(1))
+ timestamp = datetime.datetime.fromtimestamp(parsed_time)
+ # returns the YYYY-MM-DD date format.
+ return timestamp.strftime("%Y-%b-%d")
return dict(env=env, prettydate=prettydate)
@@ -99,17 +107,26 @@ def err_abort(abort_status_code, **params):
def backend_post(endpoint, json):
headers = {"Authorization": "ApiKey " + APIKEY}
try:
- resp = requests.post(urljoin(BACKEND_URL, endpoint), json=json, headers=headers)
+ resp = requests.post(
+ urljoin(BACKEND_URL, endpoint), json=json, headers=headers
+ )
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)
+ err_abort(
+ 500,
+ message="Could not parse response from backend",
+ status_code=resp.status_code
+ )
if resp.status_code != 200:
- err_abort(500, message="Backend returned error status",
- json=response_json, status_code=resp.status_code)
+ err_abort(
+ 500,
+ message="Backend returned error status",
+ json=response_json,
+ status_code=resp.status_code
+ )
return response_json
@@ -123,7 +140,9 @@ def backend_post(endpoint, json):
def backend_get(endpoint, params):
headers = {"Authorization": "ApiKey " + APIKEY}
try:
- resp = requests.get(urljoin(BACKEND_URL, endpoint), params=params, headers=headers)
+ resp = requests.get(
+ urljoin(BACKEND_URL, endpoint), params=params, headers=headers
+ )
except requests.ConnectionError:
err_abort(500, message="Could not establish connection to backend")
try:
@@ -131,8 +150,12 @@ def backend_get(endpoint, params):
except ValueError:
err_abort(500, message="Could not parse response from backend")
if resp.status_code != 200:
- err_abort(500, message="Backend returned error status",
- json=response_json, status_code=resp.status_code)
+ err_abort(
+ 500,
+ message="Backend returned error status",
+ json=response_json,
+ status_code=resp.status_code
+ )
return response_json
@@ -144,9 +167,11 @@ def backend_get(endpoint, params):
# (and execution stack!).
@app.errorhandler(Exception)
def internal_error(e):
- return flask.render_template("templates/error.html",
- message="Internal error",
- stack=traceback.format_exc())
+ return flask.render_template(
+ "templates/error.html",
+ message="Internal error",
+ stack=traceback.format_exc()
+ )
##
@@ -156,8 +181,12 @@ def internal_error(e):
@app.route("/favicon.ico")
def favicon():
print("will look into: " + os.path.join(app.root_path, 'static'))
- return flask.send_from_directory(os.path.join(app.root_path, 'static'),
- "favicon.ico", mimetype="image/vnd.microsoft.ico")
+ return flask.send_from_directory(
+ os.path.join(app.root_path, 'static'),
+ "favicon.ico",
+ mimetype="image/vnd.microsoft.ico"
+ )
+
##
# Give information about the tip reserve status.
@@ -169,6 +198,7 @@ def survey_stats():
stats = backend_get("tip-query", dict(instance="default"))
return flask.render_template("templates/survey_stats.html", stats=stats)
+
##
# Tell the backend to 'authorize' a tip; this means that
# the backend will allocate a certain amount to be later
@@ -179,17 +209,21 @@ def survey_stats():
# otherwise.
@app.route("/submit-survey", methods=["POST"])
def submit_survey():
- tip_spec = dict(amount=CURRENCY + ":1.0",
- next_url=os.environ.get("TALER_ENV_URL_INTRO", "https://taler.net/"),
- instance="default",
- justification="Payment methods survey")
+ tip_spec = dict(
+ amount=CURRENCY + ":1.0",
+ 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)
if resp.get("tip_redirect_url"):
return flask.redirect(resp["tip_redirect_url"])
- err_abort(500, message="Tipping failed, unexpected backend response",
- json=resp)
+ err_abort(
+ 500, message="Tipping failed, unexpected backend response", json=resp
+ )
+
##
# Serve the main index page.
@@ -197,4 +231,6 @@ def submit_survey():
# @return response object of the index page.
@app.route("/", methods=["GET"])
def index():
- return flask.render_template("templates/index.html", merchant_currency=CURRENCY)
+ return flask.render_template(
+ "templates/index.html", merchant_currency=CURRENCY
+ )
diff --git a/talersurvey/talerconfig.py b/talersurvey/talerconfig.py
index 4a44c97..1a33294 100644
--- a/talersurvey/talerconfig.py
+++ b/talersurvey/talerconfig.py
@@ -38,17 +38,20 @@ try:
except ImportError:
pass
+
##
# Exception class for a any configuration error.
class ConfigurationError(Exception):
pass
+
##
# Exception class for malformed strings having with parameter
# expansion.
class ExpansionSyntaxError(Exception):
pass
+
##
# Do shell-style parameter expansion.
# Supported syntax:
@@ -80,7 +83,7 @@ def expand(var: str, getter: Callable[[str], str]) -> str:
end += 1
if balance != 0:
raise ExpansionSyntaxError("unbalanced parentheses")
- piece = var[start+2:end-1]
+ piece = var[start + 2:end - 1]
if piece.find(":-") > 0:
varname, alt = piece.split(":-", 1)
replace = getter(varname)
@@ -93,9 +96,9 @@ def expand(var: str, getter: Callable[[str], str]) -> str:
replace = var[start:end]
else:
end = start + 2
- while end < len(var) and var[start+1:end+1].isalnum():
+ while end < len(var) and var[start + 1:end + 1].isalnum():
end += 1
- varname = var[start+1:end]
+ varname = var[start + 1:end]
replace = getter(varname)
if replace is None:
replace = var[start:end]
@@ -104,6 +107,7 @@ def expand(var: str, getter: Callable[[str], str]) -> str:
return result + var[pos:]
+
##
# A configuration entry.
class Entry:
@@ -164,11 +168,16 @@ class Entry:
if self.value is None:
if warn:
if default is not None:
- LOGGER.warning("Configuration is missing option '%s' in section '%s',\
- falling back to '%s'", self.option, self.section, default)
+ LOGGER.warning(
+ "Configuration is missing option '%s' in section '%s',\
+ falling back to '%s'", self.option,
+ self.section, default
+ )
else:
- LOGGER.warning("Configuration ** is missing option '%s' in section '%s'",
- self.option.upper(), self.section.upper())
+ LOGGER.warning(
+ "Configuration ** is missing option '%s' in section '%s'",
+ self.option.upper(), self.section.upper()
+ )
return default
return self.value
@@ -190,6 +199,7 @@ class Entry:
except ValueError:
raise ConfigurationError("Expected number for option '%s' in section '%s'" \
% (self.option.upper(), self.section.upper()))
+
##
# Fetch value to substitute to expansion variables.
#
@@ -231,6 +241,7 @@ class Entry:
return ""
return "%s:%s" % (self.filename, self.lineno)
+
##
# Represent a section by inheriting from 'defaultdict'.
class OptionDict(collections.defaultdict):
@@ -280,6 +291,7 @@ class OptionDict(collections.defaultdict):
def __setitem__(self, chunk: str, value: Entry) -> None:
super().__setitem__(chunk.lower(), value)
+
##
# Collection of all the (@a OptionDict) sections.
class SectionDict(collections.defaultdict):
@@ -313,6 +325,7 @@ class SectionDict(collections.defaultdict):
def __setitem__(self, chunk: str, value: OptionDict) -> None:
super().__setitem__(chunk.lower(), value)
+
##
# One loaded taler configuration, including base configuration
# files and included files.
@@ -323,7 +336,7 @@ class TalerConfig:
#
# @param self the object itself.
def __init__(self) -> None:
- self.sections = SectionDict() # just plain dict
+ self.sections = SectionDict() # just plain dict
##
# Load a configuration file, instantiating a config object.
@@ -362,7 +375,8 @@ class TalerConfig:
# a error occurs).
def value_string(self, section, option, **kwargs) -> str:
return self.sections[section][option].value_string(
- kwargs.get("default"), kwargs.get("required"), kwargs.get("warn"))
+ kwargs.get("default"), kwargs.get("required"), kwargs.get("warn")
+ )
##
# Get a value from the config that should be a filename.
@@ -377,7 +391,8 @@ class TalerConfig:
# a error occurs).
def value_filename(self, section, option, **kwargs) -> str:
return self.sections[section][option].value_filename(
- kwargs.get("default"), kwargs.get("required"), kwargs.get("warn"))
+ kwargs.get("default"), kwargs.get("required"), kwargs.get("warn")
+ )
##
# Get a integer value from the config.
@@ -391,7 +406,8 @@ class TalerConfig:
# a error occurs).
def value_int(self, section, option, **kwargs) -> int:
return self.sections[section][option].value_int(
- kwargs.get("default"), kwargs.get("required"), kwargs.get("warn"))
+ kwargs.get("default"), kwargs.get("required"), kwargs.get("warn")
+ )
##
# Load default values from canonical locations.
@@ -465,36 +481,59 @@ class TalerConfig:
if line.startswith("@INLINE@"):
pair = line.split()
if 2 != len(pair):
- LOGGER.error("invalid inlined config filename given ('%s')" % line)
- continue
+ LOGGER.error(
+ "invalid inlined config filename given ('%s')" %
+ line
+ )
+ continue
if pair[1].startswith("/"):
self.load_file(pair[1])
else:
- self.load_file(os.path.join(os.path.dirname(filename), pair[1]))
+ self.load_file(
+ os.path.join(
+ os.path.dirname(filename), pair[1]
+ )
+ )
continue
if line.startswith("["):
if not line.endswith("]"):
- LOGGER.error("invalid section header in line %s: %s",
- lineno, repr(line))
+ LOGGER.error(
+ "invalid section header in line %s: %s", lineno,
+ repr(line)
+ )
section_name = line.strip("[]").strip().strip('"')
current_section = section_name
continue
if current_section is None:
- LOGGER.error("option outside of section in line %s: %s", lineno, repr(line))
+ LOGGER.error(
+ "option outside of section in line %s: %s", lineno,
+ repr(line)
+ )
continue
pair = line.split("=", 1)
if len(pair) != 2:
- LOGGER.error("invalid option in line %s: %s", lineno, repr(line))
+ LOGGER.error(
+ "invalid option in line %s: %s", lineno, repr(line)
+ )
key = pair[0].strip()
value = pair[1].strip()
if value.startswith('"'):
value = value[1:]
if not value.endswith('"'):
- LOGGER.error("mismatched quotes in line %s: %s", lineno, repr(line))
+ LOGGER.error(
+ "mismatched quotes in line %s: %s", lineno,
+ repr(line)
+ )
else:
value = value[:-1]
- entry = Entry(self.sections, current_section, key,
- value=value, filename=filename, lineno=lineno)
+ entry = Entry(
+ self.sections,
+ current_section,
+ key,
+ value=value,
+ filename=filename,
+ lineno=lineno
+ )
sections[current_section][key] = entry
except FileNotFoundError:
# not logging here, as this interests the final user mostly.
@@ -503,23 +542,22 @@ class TalerConfig:
##
# Dump the textual representation of a config object.
- #
+ #
# Format:
- #
+ #
# [section]
# option = value # FIXME (what is location?)
#
# @param self the object itself, that will be dumped.
def dump(self) -> None:
for kv_section in self.sections.items():
- print("[%s]" % (kv_section[1].section_name,))
+ print("[%s]" % (kv_section[1].section_name, ))
for kv_option in kv_section[1].items():
print("%s = %s # %s" % \
(kv_option[1].option,
kv_option[1].value,
kv_option[1].location()))
-
##
# Return a whole section from this object.
#
@@ -538,14 +576,22 @@ if __name__ == "__main__":
import argparse
PARSER = argparse.ArgumentParser()
- PARSER.add_argument("--section", "-s", dest="section",
- default=None, metavar="SECTION")
- PARSER.add_argument("--option", "-o", dest="option",
- default=None, metavar="OPTION")
- PARSER.add_argument("--config", "-c", dest="config",
- default=None, metavar="FILE")
- PARSER.add_argument("--filename", "-f", dest="expand_filename",
- default=False, action='store_true')
+ PARSER.add_argument(
+ "--section", "-s", dest="section", default=None, metavar="SECTION"
+ )
+ PARSER.add_argument(
+ "--option", "-o", dest="option", default=None, metavar="OPTION"
+ )
+ PARSER.add_argument(
+ "--config", "-c", dest="config", default=None, metavar="FILE"
+ )
+ PARSER.add_argument(
+ "--filename",
+ "-f",
+ dest="expand_filename",
+ default=False,
+ action='store_true'
+ )
ARGS = PARSER.parse_args()
TC = TalerConfig.from_file(ARGS.config)
diff --git a/talersurvey/tests.py b/talersurvey/tests.py
index d25da48..d13e2f1 100644
--- a/talersurvey/tests.py
+++ b/talersurvey/tests.py
@@ -35,5 +35,6 @@ class SurveyTestCase(unittest.TestCase):
survey.app.testing = True
self.app = survey.app.test_client()
+
if __name__ == "__main__":
unittest.main()
--
cgit v1.2.3
From 095aa94e9adfaf1c60260839782c741b40b10e8f Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:13:23 +0200
Subject: mobile tipping
---
talersurvey/survey/survey.py | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
(limited to 'talersurvey')
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index 1c6b8aa..e64de96 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -199,6 +199,12 @@ def survey_stats():
return flask.render_template("templates/survey_stats.html", stats=stats)
+def get_qrcode_svg(data):
+ factory = qrcode.image.svg.SvgImage
+ img = qrcode.make(data, image_factory=factory)
+ return lxml.etree.tostring(img.get_image()).decode("utf-8")
+
+
##
# Tell the backend to 'authorize' a tip; this means that
# the backend will allocate a certain amount to be later
@@ -215,10 +221,18 @@ def submit_survey():
instance="default",
justification="Payment methods survey"
)
- resp = backend_post("tip-authorize", tip_spec)
-
- if resp.get("tip_redirect_url"):
- return flask.redirect(resp["tip_redirect_url"])
+ backend_resp = backend_post("tip-authorize", tip_spec)
+
+ taler_tip_uri = backend_resp.get("taler_tip_uri")
+ if taler_tip_uri:
+ qrcode_svg = get_qrcode_svg(taler_tip_uri)
+ content = flask.render_tempate(
+ "templates/show_tip.html",
+ qrcode_svg=qrcode_svg,
+ taler_tip_uri=taler_tip_uri,
+ )
+ headers = {"Taler", taler_tip_uri}
+ return flask.Response(content, status=402, headers)
err_abort(
500, message="Tipping failed, unexpected backend response", json=resp
--
cgit v1.2.3
From 2840396446ccc913e7cc7f6f813eddf8888e9463 Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:13:44 +0200
Subject: qr code template
---
talersurvey/survey/templates/show_tip.html | 35 ++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 talersurvey/survey/templates/show_tip.html
(limited to 'talersurvey')
diff --git a/talersurvey/survey/templates/show_tip.html b/talersurvey/survey/templates/show_tip.html
new file mode 100644
index 0000000..1c6317a
--- /dev/null
+++ b/talersurvey/survey/templates/show_tip.html
@@ -0,0 +1,35 @@
+{% extends "templates/base.html" %}
+
+
+{% block meta %}
+
+{% endblock meta %}
+
+{% block main %}
+
+Tip Offered
+
+
+
+ Looks like your browser doesn't support GNU Taler payments. You can try
+ installing a wallet browser extension.
+
+
+
+
+
+
+ You can use this QR code to receive a tip with your mobile wallet:
+
+
+ {{ qrcode_svg | safe }}
+
+
+ Click this link to open your system's Taler wallet if it exists.
+
+
+
+
+{% endblock main %}
--
cgit v1.2.3
From 2f09f9049d1dca01dfe7c49fadf75c6eff321808 Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:14:30 +0200
Subject: deps and imports
---
setup.py | 2 +-
talersurvey/survey/survey.py | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
(limited to 'talersurvey')
diff --git a/setup.py b/setup.py
index fa132d6..01425ac 100755
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@ setup(
packages=find_packages(),
install_requires=["Flask>=0.10", "jsmin"],
test_suite="nose.collector",
- tests_require=["mock", "nose", "requests", "uwsgi"],
+ tests_require=["mock", "nose", "requests", "uwsgi", "qrcode", "lxml"],
package_data={
'': [
"survey/templates/*.html",
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index e64de96..076aa93 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -26,6 +26,9 @@ from urllib.parse import urljoin
import flask
import requests
import traceback
+import qrcode
+import qrcode.image.svg
+import lxml.etree
from ..talerconfig import TalerConfig
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
--
cgit v1.2.3
From 991e4c08cb5a5cb89557743e707041f97d55107f Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:15:28 +0200
Subject: set headers correctly
---
talersurvey/survey/survey.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'talersurvey')
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index 076aa93..7ac4efa 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -235,7 +235,7 @@ def submit_survey():
taler_tip_uri=taler_tip_uri,
)
headers = {"Taler", taler_tip_uri}
- return flask.Response(content, status=402, headers)
+ return flask.Response(content, status=402, headers=headers)
err_abort(
500, message="Tipping failed, unexpected backend response", json=resp
--
cgit v1.2.3
From 894c77695f9eca57390825b5894e3796b57454b0 Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:18:12 +0200
Subject: typo
---
talersurvey/survey/survey.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'talersurvey')
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index 7ac4efa..76e2dbb 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -229,7 +229,7 @@ def submit_survey():
taler_tip_uri = backend_resp.get("taler_tip_uri")
if taler_tip_uri:
qrcode_svg = get_qrcode_svg(taler_tip_uri)
- content = flask.render_tempate(
+ content = flask.render_template(
"templates/show_tip.html",
qrcode_svg=qrcode_svg,
taler_tip_uri=taler_tip_uri,
--
cgit v1.2.3
From 6caf873159bc7482771dc65e8f0bed28c89a65ef Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:19:03 +0200
Subject: typo
---
talersurvey/survey/survey.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'talersurvey')
diff --git a/talersurvey/survey/survey.py b/talersurvey/survey/survey.py
index 76e2dbb..14e2258 100644
--- a/talersurvey/survey/survey.py
+++ b/talersurvey/survey/survey.py
@@ -205,7 +205,7 @@ def survey_stats():
def get_qrcode_svg(data):
factory = qrcode.image.svg.SvgImage
img = qrcode.make(data, image_factory=factory)
- return lxml.etree.tostring(img.get_image()).decode("utf-8")
+ return lxml.etree.tostring(img.get_image()).decode("utf-8")
##
@@ -234,7 +234,7 @@ def submit_survey():
qrcode_svg=qrcode_svg,
taler_tip_uri=taler_tip_uri,
)
- headers = {"Taler", taler_tip_uri}
+ headers = {"Taler": taler_tip_uri}
return flask.Response(content, status=402, headers=headers)
err_abort(
--
cgit v1.2.3
From 18ab3d0f84c42de7a6e7ca29448020945fb05f62 Mon Sep 17 00:00:00 2001
From: Florian Dold
Date: Fri, 30 Aug 2019 14:20:01 +0200
Subject: no more wallet detection
---
talersurvey/survey/templates/index.html | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
(limited to 'talersurvey')
diff --git a/talersurvey/survey/templates/index.html b/talersurvey/survey/templates/index.html
index ffd8f61..e58e669 100644
--- a/talersurvey/survey/templates/index.html
+++ b/talersurvey/survey/templates/index.html
@@ -7,11 +7,7 @@
and get a nice tip - via your Taler wallet - from this shop! (survey stats)
-
-
The survey is not possible without the wallet;
- please install one!
-
-