gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-blog] branch master updated: mostly linted


From: gnunet
Subject: [GNUnet-SVN] [taler-blog] branch master updated: mostly linted
Date: Tue, 05 Dec 2017 20:50:28 +0100

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

marcello pushed a commit to branch master
in repository blog.

The following commit(s) were added to refs/heads/master by this push:
     new c7a1a78  mostly linted
c7a1a78 is described below

commit c7a1a78c049eb224ff303c56784b77c0b8c04b6b
Author: Marcello Stanisci <address@hidden>
AuthorDate: Tue Dec 5 20:50:11 2017 +0100

    mostly linted
---
 talerblog/blog/blog.py    | 158 +++++++++++++-------------
 talerblog/blog/content.py |  36 +++---
 talerblog/helpers.py      |  59 +++++-----
 talerblog/talerconfig.py  | 277 +++++++++++++++++++++++++---------------------
 talerblog/tests.py        |  26 ++---
 5 files changed, 288 insertions(+), 268 deletions(-)

diff --git a/talerblog/blog/blog.py b/talerblog/blog/blog.py
index c42e9d4..101a968 100644
--- a/talerblog/blog/blog.py
+++ b/talerblog/blog/blog.py
@@ -20,37 +20,32 @@
 Implement URL handlers and payment logic for the blog merchant.
 """
 
-import flask
-from urllib.parse import urljoin, urlencode, quote, parse_qsl
-import requests
+from urllib.parse import urljoin, quote, parse_qsl
 import logging
 import os
 import base64
-import random
-import time
-import json
-import datetime
-from pprint import pprint
+import requests
+import flask
 from talerblog.talerconfig import TalerConfig
-from talerblog.helpers import (make_url,
-        expect_parameter, join_urlparts, get_query_string,
-        backend_error)
-from talerblog.blog.content import (articles,
-get_article_file, get_image_file)
+from talerblog.helpers import (make_url, \
+    expect_parameter, join_urlparts, \
+    get_query_string, backend_error)
+from talerblog.blog.content import (ARTICLES, \
+    get_article_file, get_image_file)
 
-logger = logging.getLogger(__name__)
+LOGGER = logging.getLogger(__name__)
 
-base_dir = os.path.dirname(os.path.abspath(__file__))
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
 
-app = flask.Flask(__name__, template_folder=base_dir)
+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()
+TC = TalerConfig.from_env()
 
-BACKEND_URL = tc["frontends"]["backend"].value_string(required=True)
-CURRENCY = tc["taler"]["currency"].value_string(required=True)
-INSTANCE = tc["blog"]["instance"].value_string(required=True)
+BACKEND_URL = TC["frontends"]["backend"].value_string(required=True)
+CURRENCY = TC["taler"]["currency"].value_string(required=True)
+INSTANCE = TC["blog"]["instance"].value_string(required=True)
 ARTICLE_AMOUNT = dict(value=1, fraction=0, currency=CURRENCY)
 
 app.config.from_object(__name__)
@@ -69,7 +64,7 @@ def utility_processor():
 def index():
     return flask.render_template("templates/index.html",
                                  merchant_currency=CURRENCY,
-                                 articles=articles.values())
+                                 articles=ARTICLES.values())
 
 
 @app.route("/javascript")
@@ -85,17 +80,17 @@ def refund():
         article_name = flask.request.form.get("article_name")
         if not article_name:
             return flask.jsonify(dict(error="No article_name found in form")), 
400
-        logger.info("Looking for %s to refund" % article_name)
+        LOGGER.info("Looking for %s to refund" % article_name)
         order_id = payed_articles.get(article_name)
         if not order_id:
             return flask.jsonify(dict(error="Aborting refund: article not 
payed")), 401
-        r = requests.post(urljoin(BACKEND_URL, "refund"),
-                          json=dict(order_id=order_id,
-                                    refund=dict(value=1, fraction=0, 
currency=CURRENCY),
-                                    reason="Demo reimbursement",
-                                    instance=INSTANCE))
-        if 200 != r.status_code:
-            return backend_error(r)
+        resp = requests.post(urljoin(BACKEND_URL, "refund"),
+                             json=dict(order_id=order_id,
+                                       refund=dict(value=1, fraction=0, 
currency=CURRENCY),
+                                       reason="Demo reimbursement",
+                                       instance=INSTANCE))
+        if resp.status_code != 200:
+            return backend_error(resp)
         payed_articles[article_name] = "__refunded"
         response = flask.make_response()
         response.headers["X-Taler-Refund-Url"] = make_url("/refund", 
("order_id", order_id))
@@ -104,13 +99,13 @@ def refund():
     else:
         order_id = expect_parameter("order_id", False)
         if not order_id:
-            logger.error("Missing parameter 'order_id'")
+            LOGGER.error("Missing parameter 'order_id'")
             return flask.jsonify(dict(error="Missing parameter 'order_id'")), 
400
-        r = requests.get(urljoin(BACKEND_URL, "refund"), 
params=dict(order_id=order_id,
-                                                                     
instance=INSTANCE))
-        if 200 != r.status_code:
-            return backend_error(r)
-        return flask.jsonify(r.json()), r.status_code
+        resp = requests.get(urljoin(BACKEND_URL, "refund"),
+                            params=dict(order_id=order_id, instance=INSTANCE))
+        if resp.status_code != 200:
+            return backend_error(resp)
+        return flask.jsonify(resp.json()), resp.status_code
 
 
 @app.route("/generate-contract", methods=["GET"])
@@ -140,10 +135,11 @@ def generate_contract():
         ),
         extra=dict(article_name=article_name),
     )
-    r = requests.post(urljoin(BACKEND_URL, "proposal"), json=dict(order=order))
-    if r.status_code != 200:
-        return backend_error(r)
-    proposal_resp = r.json()
+    resp = requests.post(urljoin(BACKEND_URL, "proposal"),
+                         json=dict(order=order))
+    if resp.status_code != 200:
+        return backend_error(resp)
+    proposal_resp = resp.json()
     return flask.jsonify(**proposal_resp)
 
 
@@ -155,34 +151,35 @@ def cc_payment(name):
 
 @app.route("/essay/<name>")
 @app.route("/essay/<name>/data/<data>")
-def article(name, data=None):
-    logger.info("processing %s" % name)
+def article(namex, data=None):
+    LOGGER.info("processing %s" % namex)
     payed_articles = flask.session.get("payed_articles", {})
 
-    if payed_articles.get(name, "") == "__refunded":
-        return flask.render_template("templates/article_refunded.html", 
article_name=name)
+    if payed_articles.get(namex, "") == "__refunded":
+        return flask.render_template("templates/article_refunded.html", 
article_name=namex)
 
-    if name in payed_articles:
-        article = articles[name]
-        if article is None:
+    if namex in payed_articles:
+        articlex = ARTICLES[namex]
+        if articlex is None:
             flask.abort(500)
         if data is not None:
-            if data in article.extra_files:
+            if data in articlex.extra_files:
                 return flask.send_file(get_image_file(data))
-            else:
-                return "permission denied", 400
+            return "permission denied", 400
         return flask.render_template("templates/article_frame.html",
-                                     article_file=get_article_file(article),
-                                     article_name=name)
+                                     article_file=get_article_file(articlex),
+                                     article_name=namex)
 
-    contract_url = make_url("/generate-contract", ("article_name",name))
-    response = 
flask.make_response(flask.render_template("templates/fallback.html"), 402)
+    contract_url = make_url("/generate-contract",
+                            ("article_name", namex))
+    response = flask.make_response(
+        flask.render_template("templates/fallback.html"), 402)
     response.headers["X-Taler-Contract-Url"] = contract_url
     response.headers["X-Taler-Contract-Query"] = "fulfillment_url"
     # Useless (?) header, as X-Taler-Contract-Url takes always (?) precedence
     # over X-Offer-Url.  This one might only be useful if the contract 
retrieval
     # goes wrong.
-    response.headers["X-Taler-Offer-Url"] = make_url("/essay/" + quote(name))
+    response.headers["X-Taler-Offer-Url"] = make_url("/essay/" + quote(namex))
     return response
 
 
@@ -190,36 +187,41 @@ def article(name, data=None):
 def pay():
     deposit_permission = flask.request.get_json()
     if deposit_permission is None:
-        e = flask.jsonify(error="no json in body"),
-        return e, 400
-    r = requests.post(urljoin(BACKEND_URL, "pay"), json=deposit_permission)
-    if 200 != r.status_code:
-        return backend_error(r)
-    proposal_data = r.json()["contract_terms"]
+        return flask.jsonify(error="no json in body"), 400
+    resp = requests.post(urljoin(BACKEND_URL, "pay"),
+                         json=deposit_permission)
+    if resp.status_code != 200:
+        return backend_error(resp)
+    proposal_data = resp.json()["contract_terms"]
     article_name = proposal_data["extra"]["article_name"]
     payed_articles = flask.session["payed_articles"] = 
flask.session.get("payed_articles", {})
-    if len(r.json()["refund_permissions"]) != 0:
+
+    try:
+        resp.json()["refund_permissions"].pop()
         # we had some refunds on the article purchase already!
-        logger.info("Article %s was refunded, before /pay" % article_name)
+        LOGGER.info("Article %s was refunded, before /pay" % article_name)
         payed_articles[article_name] = "__refunded"
-        return flask.jsonify(r.json()), 200
+        return flask.jsonify(resp.json()), 200
+    except IndexError:
+        pass
+
     if not deposit_permission["order_id"]:
-        logger.error("order_id missing from deposit_permission!")
+        LOGGER.error("order_id missing from deposit_permission!")
         return flask.jsonify(dict(error="internal error: ask for refund!")), 
500
     if article_name not in payed_articles:
-        logger.info("Article %s goes in state" % article_name)
+        LOGGER.info("Article %s goes in state" % article_name)
         payed_articles[article_name] = deposit_permission["order_id"]
-    return flask.jsonify(r.json()), 200
+    return flask.jsonify(resp.json()), 200
 
 
 @app.route("/history")
 def history():
     qs = get_query_string().decode("utf-8")
     url = urljoin(BACKEND_URL, "history")
-    r = requests.get(url, params=dict(parse_qsl(qs)))
-    if 200 != r.status_code:
-        return backend_error(r)
-    return flask.jsonify(r.json()), r.status_code
+    resp = requests.get(url, params=dict(parse_qsl(qs)))
+    if resp.status_code != 200:
+        return backend_error(resp)
+    return flask.jsonify(resp.json()), resp.status_code
 
 
 @app.route("/backoffice")
@@ -232,17 +234,17 @@ def track():
 def track_transfer():
     qs = get_query_string().decode("utf-8")
     url = urljoin(BACKEND_URL, "track/transfer")
-    r = requests.get(url, params=dict(parse_qsl(qs)))
-    if 200 != r.status_code:
-        return backend_error(r)
-    return flask.jsonify(r.json()), r.status_code
+    resp = requests.get(url, params=dict(parse_qsl(qs)))
+    if resp.status_code != 200:
+        return backend_error(resp)
+    return flask.jsonify(resp.json()), resp.status_code
 
 
 @app.route("/track/order")
 def track_order():
     qs = get_query_string().decode("utf-8")
     url = urljoin(BACKEND_URL, "track/transaction")
-    r = requests.get(url, params=dict(parse_qsl(qs)))
-    if 200 != r.status_code:
-        return backend_error(r)
-    return flask.jsonify(r.json()), r.status_code
+    resp = requests.get(url, params=dict(parse_qsl(qs)))
+    if resp.status_code != 200:
+        return backend_error(resp)
+    return flask.jsonify(resp.json()), resp.status_code
diff --git a/talerblog/blog/content.py b/talerblog/blog/content.py
index 42ecf18..3202a50 100644
--- a/talerblog/blog/content.py
+++ b/talerblog/blog/content.py
@@ -18,33 +18,32 @@
 Define content and associated metadata that is served on the blog.
 """
 
-from collections import OrderedDict
-from bs4 import BeautifulSoup
-from pkg_resources import resource_stream, resource_filename
-from collections import namedtuple
+from collections import OrderedDict, namedtuple
 import logging
 import os
 import re
+from bs4 import BeautifulSoup
+from pkg_resources import resource_stream, resource_filename
 
-logger = logging.getLogger(__name__)
+LOGGER = logging.getLogger(__name__)
 
 Article = namedtuple("Article", "slug title teaser main_file extra_files")
 
-articles = OrderedDict()
+ARTICLES = OrderedDict()
 
 
-def add_article(slug, title, teaser, main_file, extra_files=[]):
-    articles[slug] = Article(slug, title, teaser, main_file, extra_files)
+def add_article(slug, title, teaser, main_file, extra_files):
+    ARTICLES[slug] = Article(slug, title, teaser, main_file, extra_files)
 
 
 def get_image_file(image):
-    f = resource_filename("talerblog", os.path.join("blog/data/", image)) 
-    return os.path.abspath(f)
+    filex = resource_filename("talerblog", os.path.join("blog/data/", image))
+    return os.path.abspath(filex)
 
 
 def get_article_file(article):
-    f = resource_filename("talerblog", article.main_file)
-    return os.path.basename(f)
+    filex = resource_filename("talerblog", article.main_file)
+    return os.path.basename(filex)
 
 
 def add_from_html(resource_name, teaser_paragraph=0, title=None):
@@ -56,29 +55,30 @@ def add_from_html(resource_name, teaser_paragraph=0, 
title=None):
     if title is None:
         title_el = soup.find("h1", attrs={"class":["chapter", "unnumbered"]})
         if title_el is None:
-            logger.warn("Can't extract title from '%s'", resource_name)
+            LOGGER.warning("Can't extract title from '%s'", resource_name)
             title = resource_name
         else:
             title = title_el.get_text().strip()
     slug = title.replace(" ", "_")
     paragraphs = soup.find_all("p")
-    
+
     teaser = soup.find("p", attrs={"id":["teaser"]})
     if teaser is None:
         teaser = str(paragraphs[teaser_paragraph])
-    p = re.compile("^/essay/[^/]+/data/[^/]+$")
+    re_proc = re.compile("^/essay/[^/]+/data/[^/]+$")
     imgs = soup.find_all("img")
     extra_files = []
     for img in imgs:
         # We require that any image whose access is regulated is src'd
         # as "<slug>/data/img.png". We also need to check if the <slug>
         # component actually matches the article's slug
-        if p.match(img['src']):
+        if re_proc.match(img['src']):
             if img['src'].split(os.sep)[2] == slug:
-                logger.info("extra file for %s is %s" % (slug, 
os.path.basename(img['src'])))
+                LOGGER.info("extra file for %s is %s" % (slug, 
os.path.basename(img['src'])))
                 extra_files.append(os.path.basename(img['src']))
             else:
-                logger.warning("Image src and slug don't match: '%s' != '%s'" 
% (img['src'].split(os.sep)[2], slug))
+                LOGGER.warning("Image src and slug don't match: '%s' != '%s'" \
+                               % (img['src'].split(os.sep)[2], slug))
     add_article(slug, title, teaser, resource_name, extra_files)
 
 
diff --git a/talerblog/helpers.py b/talerblog/helpers.py
index 257192d..614e463 100644
--- a/talerblog/helpers.py
+++ b/talerblog/helpers.py
@@ -15,22 +15,18 @@
 #  @author Florian Dold
 #  @author Marcello Stanisci
 
-from flask import request, jsonify, make_response, current_app, render_template
-import flask
 from urllib.parse import urljoin, urlencode
 import logging
-import requests
-import re
-import datetime
 import json
+import flask
 from .talerconfig import TalerConfig
 
-logger = logging.getLogger(__name__)
+LOGGER = logging.getLogger(__name__)
 
-tc = TalerConfig.from_env()
-BACKEND_URL = tc["frontends"]["backend"].value_string(required=True)
-NDIGITS = tc["frontends"]["NDIGITS"].value_int()
-CURRENCY = tc["taler"]["CURRENCY"].value_string()
+TC = TalerConfig.from_env()
+BACKEND_URL = TC["frontends"]["backend"].value_string(required=True)
+NDIGITS = TC["frontends"]["NDIGITS"].value_int()
+CURRENCY = TC["taler"]["CURRENCY"].value_string()
 
 FRACTION_BASE = 1e8
 
@@ -40,29 +36,30 @@ if not NDIGITS:
 class MissingParameterException(Exception):
     def __init__(self, param):
         self.param = param
+        super().__init__()
 
 def amount_to_float(amount):
     return amount['value'] + (float(amount['fraction']) / float(FRACTION_BASE))
 
 
-def amount_from_float(x):
-    value = int(x)
-    fraction = int((x - value) * FRACTION_BASE)
+def amount_from_float(floatx):
+    value = int(floatx)
+    fraction = int((floatx - value) * FRACTION_BASE)
     return dict(currency=CURRENCY, value=value, fraction=fraction)
 
 
 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 make_url(page, *query_params):
@@ -72,10 +69,10 @@ def make_url(page, *query_params):
     """
     query = urlencode(query_params)
     if page.startswith("/"):
-        root = request.url_root
+        root = flask.request.url_root
         page = page.lstrip("/")
     else:
-        root = request.base_url
+        root = flask.request.base_url
     url = urljoin(root, "%s?%s" % (page, query))
     # urlencode is overly eager with quoting, the wallet right now
     # needs some characters unquoted.
@@ -83,22 +80,22 @@ def make_url(page, *query_params):
 
 
 def expect_parameter(name, alt=None):
-    value = request.args.get(name, None)
+    value = flask.request.args.get(name, None)
     if value is None and alt is None:
-        logger.error("Missing parameter '%s' from '%s'." % (name, 
request.args))
+        LOGGER.error("Missing parameter '%s' from '%s'." % (name, 
flask.request.args))
         raise MissingParameterException(name)
     return value if value else alt
 
 
 def get_query_string():
-    return request.query_string
+    return flask.request.query_string
 
 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
diff --git a/talerblog/talerconfig.py b/talerblog/talerconfig.py
index ba4dfbb..a7ca065 100644
--- a/talerblog/talerconfig.py
+++ b/talerblog/talerconfig.py
@@ -18,23 +18,22 @@
 Parse GNUnet-style configurations in pure Python
 """
 
-# FIXME: make sure that autovivification of config entries
-# does not leave garbage behind (use weakrefs!)
-
 import logging
 import collections
 import os
 import weakref
+import sys
+import re
 
-logger = logging.getLogger(__name__)
+LOGGER = logging.getLogger(__name__)
 
 __all__ = ["TalerConfig"]
 
-taler_datadir = None
+TALER_DATADIR = None
 try:
     # not clear if this is a good idea ...
-    from talerpaths import taler_datadir as t
-    taler_datadir = t
+    from talerpaths import TALER_DATADIR as t
+    TALER_DATADIR = t
 except ImportError:
     pass
 
@@ -45,7 +44,7 @@ class ExpansionSyntaxError(Exception):
     pass
 
 
-def expand(s, getter):
+def expand(var, getter):
     """
     Do shell-style parameter expansion.
     Supported syntax:
@@ -56,18 +55,18 @@ def expand(s, getter):
     pos = 0
     result = ""
     while pos != -1:
-        start = s.find("$", pos)
+        start = var.find("$", pos)
         if start == -1:
             break
-        if s[start:].startswith("${"):
+        if var[start:].startswith("${"):
             balance = 1
             end = start + 2
-            while balance > 0 and end < len(s):
-                balance += {"{": 1, "}": -1}.get(s[end], 0)
+            while balance > 0 and end < len(var):
+                balance += {"{": 1, "}": -1}.get(var[end], 0)
                 end += 1
             if balance != 0:
                 raise ExpansionSyntaxError("unbalanced parentheses")
-            piece = s[start+2:end-1]
+            piece = var[start+2:end-1]
             if piece.find(":-") > 0:
                 varname, alt = piece.split(":-", 1)
                 replace = getter(varname)
@@ -77,20 +76,20 @@ def expand(s, getter):
                 varname = piece
                 replace = getter(varname)
                 if replace is None:
-                    replace = s[start:end]
+                    replace = var[start:end]
         else:
             end = start + 2
-            while end < len(s) and s[start+1:end+1].isalnum():
+            while end < len(var) and var[start+1:end+1].isalnum():
                 end += 1
-            varname = s[start+1:end]
+            varname = var[start+1:end]
             replace = getter(varname)
             if replace is None:
-                replace = s[start:end]
+                replace = var[start:end]
         result = result + replace
         pos = end
 
 
-    return result + s[pos:]
+    return result + var[pos:]
 
 
 class OptionDict(collections.defaultdict):
@@ -99,79 +98,81 @@ class OptionDict(collections.defaultdict):
         self.section_name = section_name
         super().__init__()
     def __missing__(self, key):
-        e = Entry(self.config(), self.section_name, key)
-        self[key] = e
-        return e
-    def __getitem__(self, slice):
-        return super().__getitem__(slice.lower())
-    def __setitem__(self, slice, value):
-        super().__setitem__(slice.lower(), value)
+        entry = Entry(self.config(), self.section_name, key)
+        self[key] = entry
+        return entry
+    def __getitem__(self, chunk):
+        return super().__getitem__(chunk.lower())
+    def __setitem__(self, chunk, value):
+        super().__setitem__(chunk.lower(), value)
 
 
 class SectionDict(collections.defaultdict):
-    def __init__(self):
-        super().__init__()
     def __missing__(self, key):
-        v = OptionDict(self, key)
-        self[key] = v
-        return v
-    def __getitem__(self, slice):
-        return super().__getitem__(slice.lower())
-    def __setitem__(self, slice, value):
-        super().__setitem__(slice.lower(), value)
+        value = OptionDict(self, key)
+        self[key] = value
+        return value
+    def __getitem__(self, chunk):
+        return super().__getitem__(chunk.lower())
+    def __setitem__(self, chunk, value):
+        super().__setitem__(chunk.lower(), value)
 
 
 class Entry:
-    def __init__(self, config, section, option, value=None, filename=None, 
lineno=None):
-        self.value = value
-        self.filename = filename
-        self.lineno = lineno
+    def __init__(self, config, section, option, **kwargs):
+        self.value = kwargs.get("value")
+        self.filename = kwargs.get("filename")
+        self.lineno = kwargs.get("lineno")
         self.section = section
         self.option = option
         self.config = weakref.ref(config)
 
     def __repr__(self):
-        return "<Entry section=%s, option=%s, value=%s>" % (self.section, 
self.option, repr(self.value),)
+        return "<Entry section=%s, option=%s, value=%s>" \
+               % (self.section, self.option, repr(self.value),)
 
     def __str__(self):
         return self.value
 
-    def value_string(self, default=None, warn=False, required=False):
+    def value_string(self, default=None, required=False, warn=False):
         if required and self.value is None:
-            raise ConfigurationError("Missing required option '%s' in section 
'%s'" % (self.option.upper(), self.section.upper()))
+            raise ConfigurationError("Missing required option '%s' in section 
'%s'" \
+                                     % (self.option.upper(), 
self.section.upper()))
         if self.value is None:
             if warn:
                 if default is not None:
-                    logger.warn("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.warn("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
 
-    def value_int(self, default=None, warn=False, required=False):
-        v = self.value_string(default, warn, required)
-        if v is None:
+    def value_int(self, default=None, required=False, warn=False):
+        value = self.value_string(default, warn, required)
+        if value is None:
             return None
         try:
-            return int(v)
+            return int(value)
         except ValueError:
-            raise ConfigurationError("Expected number for option '%s' in 
section '%s'" % (self.option.upper(), self.section.upper()))
+            raise ConfigurationError("Expected number for option '%s' in 
section '%s'" \
+                                     % (self.option.upper(), 
self.section.upper()))
 
     def _getsubst(self, key):
-        x = self.config()["paths"][key].value
-        if x is not None:
-            return x
-        x = os.environ.get(key)
-        if x is not None:
-            return x
+        value = self.config()["paths"][key].value
+        if value is not None:
+            return value
+        value = os.environ.get(key)
+        if value is not None:
+            return value
         return None
 
-    def value_filename(self, default=None, warn=False, required=False):
-        v = self.value_string(default, warn, required)
-        if v is None:
+    def value_filename(self, default=None, required=False, warn=False):
+        value = self.value_string(default, required, warn)
+        if value is None:
             return None
-        return expand(v, lambda x: self._getsubst(x))
+        return expand(value, self._getsubst)
 
     def location(self):
         if self.filename is None or self.lineno is None:
@@ -190,6 +191,8 @@ class TalerConfig:
         """
         self.sections = SectionDict()
 
+    # defaults != config file: the first is the 'base'
+    # whereas the second overrides things from the first.
     @staticmethod
     def from_file(filename=None, load_defaults=True):
         cfg = TalerConfig()
@@ -204,14 +207,17 @@ class TalerConfig:
         cfg.load_file(filename)
         return cfg
 
-    def value_string(self, section, option, default=None, required=None, 
warn=False):
-        return self.sections[section][option].value_string(default, required, 
warn)
+    def value_string(self, section, option, **kwargs):
+        return self.sections[section][option].value_string(
+            kwargs.get("default"), kwargs.get("required"), kwargs.get("warn"))
 
-    def value_filename(self, section, option, default=None, required=None, 
warn=False):
-        return self.sections[section][option].value_filename(default, 
required, warn)
+    def value_filename(self, section, option, **kwargs):
+        return self.sections[section][option].value_filename(
+            kwargs.get("default"), kwargs.get("required"), kwargs.get("warn"))
 
-    def value_int(self, section, option, default=None, required=None, 
warn=False):
-        return self.sections[section][option].value_int(default, required, 
warn)
+    def value_int(self, section, option, **kwargs):
+        return self.sections[section][option].value_int(
+            kwargs.get("default"), kwargs.get("required"), kwargs.get("warn"))
 
     def load_defaults(self):
         base_dir = os.environ.get("TALER_BASE_CONFIG")
@@ -220,12 +226,15 @@ class TalerConfig:
             return
         prefix = os.environ.get("TALER_PREFIX")
         if prefix:
+            tmp = os.path.split(os.path.normpath(prefix))
+            if re.match("lib", tmp[1]):
+                prefix = tmp[0]
             self.load_dir(os.path.join(prefix, "share/taler/config.d"))
             return
-        if taler_datadir:
-            self.load_dir(os.path.join(taler_datadir, "share/taler/config.d"))
+        if TALER_DATADIR:
+            self.load_dir(os.path.join(TALER_DATADIR, "share/taler/config.d"))
             return
-        logger.warn("no base directory found")
+        LOGGER.warning("no base directory found")
 
     @staticmethod
     def from_env(*args, **kwargs):
@@ -240,7 +249,7 @@ class TalerConfig:
         try:
             files = os.listdir(dirname)
         except FileNotFoundError:
-            logger.warn("can't read config directory '%s'", dirname)
+            LOGGER.warning("can't read config directory '%s'", dirname)
             return
         for file in files:
             if not file.endswith(".conf"):
@@ -249,73 +258,85 @@ class TalerConfig:
 
     def load_file(self, filename):
         sections = self.sections
-        with open(filename, "r") as file:
-            lineno = 0
-            current_section = None
-            for line in file:
-                lineno += 1
-                line = line.strip()
-                if len(line) == 0:
-                    # empty line
-                    continue
-                if line.startswith("#"):
-                    # comment
-                    continue
-                if line.startswith("["):
-                    if not line.endswith("]"):
-                        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))
-                    continue
-                kv = line.split("=", 1)
-                if len(kv) != 2:
-                    logger.error("invalid option in line %s: %s", lineno, 
repr(line))
-                key = kv[0].strip()
-                value = kv[1].strip()
-                if value.startswith('"'):
-                    value = value[1:]
-                    if not value.endswith('"'):
-                        logger.error("mismatched quotes in line %s: %s", 
lineno, repr(line))
-                    else:
-                        value = value[:-1]
-                e = Entry(self.sections, current_section, key, value, 
filename, lineno)
-                sections[current_section][key] = e
+        try:
+            with open(filename, "r") as file:
+                lineno = 0
+                current_section = None
+                for line in file:
+                    lineno += 1
+                    line = line.strip()
+                    if line == "":
+                        # empty line
+                        continue
+                    if line.startswith("#"):
+                        # comment
+                        continue
+                    if line.startswith("["):
+                        if not line.endswith("]"):
+                            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))
+                        continue
+                    pair = line.split("=", 1)
+                    if len(pair) != 2:
+                        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))
+                        else:
+                            value = value[:-1]
+                    entry = Entry(self.sections, current_section, key,
+                                  value=value, filename=filename, 
lineno=lineno)
+                    sections[current_section][key] = entry
+        except FileNotFoundError:
+            LOGGER.error("Configuration file (%s) not found", filename)
+            sys.exit(3)
 
 
     def dump(self):
-        for section_name, section in self.sections.items():
-            print("[%s]" % (section.section_name,))
-            for option_name, e in section.items():
-                print("%s = %s # %s" % (e.option, e.value, e.location()))
-
-    def __getitem__(self, slice):
-        if isinstance(slice, str):
-            return self.sections[slice]
+        for kv_section in self.sections.items():
+            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()))
+
+    def __getitem__(self, chunk):
+        if isinstance(chunk, str):
+            return self.sections[chunk]
         raise TypeError("index must be string")
 
 
 if __name__ == "__main__":
-    import sys
     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')
-    args = parser.parse_args()
-
-    tc = TalerConfig.from_file(args.config)
-
-    if args.section is not None and args.option is not None:
-        if args.expand_filename:
-            x = tc.value_filename(args.section, args.option)
+    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')
+    ARGS = PARSER.parse_args()
+
+    TC = TalerConfig.from_file(ARGS.config)
+
+    if ARGS.section is not None and ARGS.option is not None:
+        if ARGS.expand_filename:
+            X = TC.value_filename(ARGS.section, ARGS.option)
         else:
-            x = tc.value_string(args.section, args.option)
-        if x is not None:
-            print(x)
+            X = TC.value_string(ARGS.section, ARGS.option)
+        if X is not None:
+            print(X)
     else:
-        tc.dump()
+        TC.dump()
diff --git a/talerblog/tests.py b/talerblog/tests.py
index 36d27c5..dc720cf 100644
--- a/talerblog/tests.py
+++ b/talerblog/tests.py
@@ -5,8 +5,8 @@ from mock import patch, MagicMock
 from talerblog.blog import blog
 from talerblog.talerconfig import TalerConfig
 
-tc = TalerConfig.from_env()
-CURRENCY = tc["taler"]["currency"].value_string(required=True)
+TC = TalerConfig.from_env()
+CURRENCY = TC["taler"]["currency"].value_string(required=True)
 
 class BlogTestCase(unittest.TestCase):
     def setUp(self):
@@ -14,12 +14,12 @@ class BlogTestCase(unittest.TestCase):
         self.app = blog.app.test_client()
 
     @patch("requests.post")
-    def test_proposal_creation(self, mocked_post): 
+    def test_proposal_creation(self, mocked_post):
         ret_post = MagicMock()
         ret_post.status_code = 200
         ret_post.json.return_value = {}
         mocked_post.return_value = ret_post
-        self.app.get("/generate-contract?nonce=55&article_name=Check_Me") 
+        self.app.get("/generate-contract?nonce=55&article_name=Check_Me")
         mocked_post.assert_called_with(
             "http://backend.test.taler.net/proposal";,
             json={
@@ -35,21 +35,21 @@ class BlogTestCase(unittest.TestCase):
                         "fraction": 0,
                         "currency": CURRENCY},
                     "products": [{
-                            "description": "Essay: Check Me",
-                            "quantity": 1,
-                            "product_id": 0,
-                            "price": {
-                                "value": 1,
-                                "fraction": 0,
-                                "currency": CURRENCY}}],
+                        "description": "Essay: Check Me",
+                        "quantity": 1,
+                        "product_id": 0,
+                        "price": {
+                            "value": 1,
+                            "fraction": 0,
+                            "currency": CURRENCY}}],
                     "fulfillment_url": "http://localhost/essay/Check_Me";,
                     "pay_url": "http://localhost/pay";,
                     "merchant": {
-                        "instance": 
tc["blog"]["instance"].value_string(required=True),
+                        "instance": 
TC["blog"]["instance"].value_string(required=True),
                         "address": "nowhere",
                         "name": "Kudos Inc.",
                         "jurisdiction": "none"},
                     "extra": {"article_name": "Check_Me"}}})
 
-if "__main__" == __name__:
+if __name__ == "__main__":
     unittest.main()

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



reply via email to

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