From 527b349fbe6f7b9a630788e39b7af9aa718535c2 Mon Sep 17 00:00:00 2001 From: Martin Zimmermann Date: Sun, 27 Oct 2013 13:40:15 +0100 Subject: [PATCH] use python's logging module --- isso/__init__.py | 25 +++++++++++++--------- isso/colors.py | 48 ------------------------------------------- isso/core.py | 22 ++++++++++++++++---- isso/utils/http.py | 8 ++++---- isso/views/comment.py | 11 ++++++++++ 5 files changed, 48 insertions(+), 66 deletions(-) delete mode 100644 isso/colors.py diff --git a/isso/__init__.py b/isso/__init__.py index 82f4cba..e8253ce 100644 --- a/isso/__init__.py +++ b/isso/__init__.py @@ -33,6 +33,7 @@ dist = pkg_resources.get_distribution("isso") import sys import os import socket +import logging from os.path import dirname, join from argparse import ArgumentParser @@ -57,10 +58,18 @@ from werkzeug.contrib.fixers import ProxyFix from jinja2 import Environment, FileSystemLoader -from isso import db, migrate, views, wsgi, colors +from isso import db, migrate, views, wsgi from isso.core import ThreadedMixin, uWSGIMixin, Config +from isso.utils import parse from isso.views import comment, admin +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s %(levelname)s: %(message)s") + +logger = logging.getLogger("isso") + + rules = Map([ Rule('/new', methods=['POST'], endpoint=views.comment.new), @@ -144,17 +153,13 @@ def make_app(conf=None): isso = App(conf) - if not conf.get("general", "host").startswith(("http://", "https://")): - raise SystemExit("error: host must start with http:// or https://") - try: - print(" * connecting to HTTP server", end=" ") - rv = urlparse.urlparse(conf.get("general", "host")) - host = (rv.netloc + ':443') if rv.scheme == 'https' else rv.netloc - httplib.HTTPConnection(host, timeout=5).request('GET', rv.path) - print("[%s]" % colors.green("ok")) + host, port, ssl = parse.host(conf.get("general", "host")) + con = httplib.HTTPSConnection if ssl else httplib.HTTPConnection + con(host, port, timeout=5).request('GET', '/') + logger.info("connected to HTTP server") except (httplib.HTTPException, socket.error): - print("[%s]" % colors.red("failed")) + logger.warn("unable to connect to HTTP server") app = ProxyFix(wsgi.SubURI(SharedDataMiddleware(isso.wsgi_app, { '/static': join(dirname(__file__), 'static/'), diff --git a/isso/colors.py b/isso/colors.py deleted file mode 100644 index dc5785e..0000000 --- a/isso/colors.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- encoding: utf-8 -*- - -# from isso import compat -from isso.compat import text_type as str, string_types - - -# @compat.implements_to_string -class ANSIString(object): - - style = 0 - color = 30 - - def __init__(self, obj, style=None, color=None): - - if isinstance(obj, ANSIString): - if style is None: - style = obj.style - if color is None: - color = obj.color - obj = obj.obj - elif not isinstance(obj, string_types): - obj = str(obj) - - self.obj = obj - if style: - self.style = style - if color: - self.color = color - - def __str__(self): - return '\033[%i;%im' % (self.style, self.color) + self.obj + '\033[0m' - - def __add__(self, other): - return str.__add__(str(self), other) - - def __radd__(self, other): - return other + str(self) - - def encode(self, encoding): - return str(self).encode(encoding) - - -normal, bold, underline = [lambda obj, x=x: ANSIString(obj, style=x) - for x in (0, 1, 4)] - -black, red, green, yellow, blue, \ -magenta, cyan, white = [lambda obj, y=y: ANSIString(obj, color=y) - for y in range(30, 38)] diff --git a/isso/core.py b/isso/core.py index a354db8..f4721a8 100644 --- a/isso/core.py +++ b/isso/core.py @@ -7,6 +7,7 @@ import os import time import binascii import threading +import logging import socket import smtplib @@ -25,9 +26,11 @@ if PY2K: else: import _thread as thread -from isso import notify, colors +from isso import notify from isso.utils import parse +logger = logging.getLogger("isso") + class IssoParser(ConfigParser): @@ -71,23 +74,34 @@ class Config: @classmethod def load(cls, configfile): + # return set of (section, option) + setify = lambda cp: set((section, option) for section in cp.sections() + for option in cp.options(section)) + rv = IssoParser(allow_no_value=True) rv.read_file(io.StringIO(u'\n'.join(Config.default))) + a = setify(rv) + if configfile: rv.read(configfile) + diff = setify(rv).difference(a) + + if diff: + for item in diff: + logger.warn("no such option: [%s] %s", *item) + return rv def SMTP(conf): try: - print(" * connecting to SMTP server", end=" ") mailer = notify.SMTPMailer(conf) - print("[%s]" % colors.green("ok")) + logger.info("connected to SMTP server") except (socket.error, smtplib.SMTPException): - print("[%s]" % colors.red("failed")) + logger.warn("unable to connect to SMTP server") mailer = notify.NullMailer() return mailer diff --git a/isso/utils/http.py b/isso/utils/http.py index 647db7b..15cdb86 100644 --- a/isso/utils/http.py +++ b/isso/utils/http.py @@ -16,8 +16,8 @@ from isso.utils import parse def urlexists(host, path): - host, port = parse.host(host) - http = httplib.HTTPSConnection if port == 443 else httplib.HTTPConnection + host, port, ssl = parse.host(host) + http = httplib.HTTPSConnection if ssl else httplib.HTTPConnection with closing(http(host, port, timeout=3)) as con: try: @@ -31,8 +31,8 @@ def heading(host, path): """Connect to `host`, GET path and start from #isso-thread to search for a possible heading (h1). Returns `None` if nothing found.""" - host, port = parse.host(host) - http = httplib.HTTPSConnection if port == 443 else httplib.HTTPConnection + host, port, ssl = parse.host(host) + http = httplib.HTTPSConnection if ssl else httplib.HTTPConnection with closing(http(host, port, timeout=15)) as con: con.request('GET', path) diff --git a/isso/views/comment.py b/isso/views/comment.py index 202212c..d80bb62 100644 --- a/isso/views/comment.py +++ b/isso/views/comment.py @@ -6,6 +6,7 @@ import time import hashlib import logging import sqlite3 +import logging from itsdangerous import SignatureExpired, BadSignature @@ -18,6 +19,8 @@ from isso import utils, notify, db from isso.utils import http from isso.crypto import pbkdf2 +logger = logging.getLogger("isso") + FIELDS = set(['id', 'parent', 'text', 'author', 'website', 'email', 'mode', 'created', 'modified', 'likes', 'dislikes', 'hash']) @@ -74,6 +77,7 @@ def new(app, environ, request, uri): with app.lock: if uri not in app.db.threads: app.db.threads.new(uri, http.heading(app.conf.get('general', 'host'), uri)) + logger.info('new thread: %s -> %s', uri, app.db.threads[uri].title) title = app.db.threads[uri].title try: @@ -107,6 +111,9 @@ def new(app, environ, request, uri): for key in set(rv.keys()) - FIELDS: rv.pop(key) + # success! + logger.info('comment created: %s', json.dumps(rv)) + resp = Response(json.dumps(rv), 202 if rv["mode"] == 2 else 201, content_type='application/json') resp.set_cookie(str(rv["id"]), app.sign([rv["id"], checksum]), max_age=app.conf.getint('general', 'max-age')) @@ -163,6 +170,8 @@ def single(app, environ, request, id): for key in set(rv.keys()) - FIELDS: rv.pop(key) + logger.info('comment %i edited: %s', id, json.dumps(rv)) + checksum = hashlib.md5(rv["text"].encode('utf-8')).hexdigest() rv["text"] = app.markdown(rv["text"]) @@ -177,6 +186,8 @@ def single(app, environ, request, id): for key in set(rv.keys()) - FIELDS: rv.pop(key) + logger.info('comment %i deleted', id) + resp = Response(json.dumps(rv), 200, content_type='application/json') resp.delete_cookie(str(id), path='/') return resp