<commit_before>###
# Copyright (c) 2002-2004, Jeremiah Fincher
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

__revision__ = "$Id$"

import supybot.fix as fix

import time

import supybot.log as log
import supybot.conf as conf
import supybot.ircdb as ircdb
import supybot.drivers as drivers
import supybot.ircmsgs as ircmsgs

from twisted.internet import reactor, error
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import ReconnectingClientFactory

class TwistedRunnerDriver(drivers.IrcDriver):
    def name(self):
        return self.__class__.__name__

    def run(self):
        try:
            reactor.iterate(conf.supybot.drivers.poll())
        except:
            drivers.log.exception('Uncaught exception outside reactor:')

class SupyIrcProtocol(LineReceiver):
    delimiter = '\n'
    MAX_LENGTH = 1024
    def __init__(self):
        self.mostRecentCall = reactor.callLater(1, self.checkIrcForMsgs)

    def lineReceived(self, line):
        start = time.time()
        msg = drivers.parseMsg(line)
        if msg is not None:
            self.irc.feedMsg(msg)

    def checkIrcForMsgs(self):
        if self.connected:
            msg = self.irc.takeMsg()
            if msg:
                self.transport.write(str(msg))
        self.mostRecentCall = reactor.callLater(1, self.checkIrcForMsgs)

    def connectionLost(self, r):
        self.mostRecentCall.cancel()
        if not r.check(error.ConnectionDone):
            drivers.log.disconnect(self.factory.currentServer, errorMsg(r))
        else:
            drivers.log.disconnect(self.factory.currentServer)
        if self.irc.zombie:
            # Let's take and take and take until our IRC is DESTROYED!
            x = 1
            while x:
                x = self.irc.takeMsg()
        else:
            self.irc.reset()

    def connectionMade(self):
        self.factory.resetDelay()
        self.irc.driver = self

    def die(self):
        drivers.log.die(self.irc)
        self.factory.continueTrying = False
        self.transport.loseConnection()

    def reconnect(self, wait=None):
        # We ignore wait here, because we handled our own waiting.
        drivers.log.reconnect(self.irc.network)
        self.transport.loseConnection()

def errorMsg(reason):
    return reason.getErrorMessage()

class SupyReconnectingFactory(ReconnectingClientFactory, drivers.ServersMixin):
    maxDelay = 300
    protocol = SupyIrcProtocol
    def __init__(self, irc):
        self.irc = irc
        drivers.ServersMixin.__init__(self, irc)
        (server, port) = self._getNextServer()
        reactor.connectTCP(server, port, self)

    def clientConnectionFailed(self, connector, r):
        drivers.log.connectError(self.currentServer, errorMsg(r))
        (connector.host, connector.port) = self._getNextServer()
        if not r.check(error.TimeoutError):
            ReconnectingClientFactory.clientConnectionFailed(self, connector,r)

    def clientConnectionLost(self, connector, r):
        (connector.host, connector.port) = self._getNextServer()
        ReconnectingClientFactory.clientConnectionLost(self, connector, r)

    def startedConnecting(self, connector):
        drivers.log.connect(self.currentServer)

    def buildProtocol(self, addr):
        protocol = ReconnectingClientFactory.buildProtocol(self, addr)
        protocol.irc = self.irc
        return protocol

Driver = SupyReconnectingFactory

try:
    ignore(poller)
except NameError:
    poller = TwistedRunnerDriver()
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
<commit_msg>Small update.<commit_after>###
# Copyright (c) 2002-2004, Jeremiah Fincher
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions, and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions, and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the author of this software nor the name of
#     contributors to this software may be used to endorse or promote products
#     derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###

__revision__ = "$Id$"

import supybot.fix as fix

import time

import supybot.log as log
import supybot.conf as conf
import supybot.ircdb as ircdb
import supybot.drivers as drivers
import supybot.ircmsgs as ircmsgs

from twisted.internet import reactor, error
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import ReconnectingClientFactory

class TwistedRunnerDriver(drivers.IrcDriver):
    def name(self):
        return self.__class__.__name__

    def run(self):
        try:
            reactor.iterate(conf.supybot.drivers.poll())
        except:
            drivers.log.exception('Uncaught exception outside reactor:')

class SupyIrcProtocol(LineReceiver):
    delimiter = '\n'
    MAX_LENGTH = 1024
    def __init__(self):
        self.mostRecentCall = reactor.callLater(1, self.checkIrcForMsgs)

    def lineReceived(self, line):
        start = time.time()
        msg = drivers.parseMsg(line)
        if msg is not None:
            self.irc.feedMsg(msg)

    def checkIrcForMsgs(self):
        if self.connected:
            msg = self.irc.takeMsg()
            if msg:
                self.transport.write(str(msg))
        self.mostRecentCall = reactor.callLater(1, self.checkIrcForMsgs)

    def connectionLost(self, r):
        self.mostRecentCall.cancel()
        if r.check(error.ConnectionDone):
            drivers.log.disconnect(self.factory.currentServer)
        else:
            drivers.log.disconnect(self.factory.currentServer, errorMsg(r))
        if self.irc.zombie:
            # Let's take and take and take until our IRC is DESTROYED!
            x = 1
            while x:
                x = self.irc.takeMsg()
        else:
            self.irc.reset()

    def connectionMade(self):
        self.factory.resetDelay()
        self.irc.driver = self

    def die(self):
        drivers.log.die(self.irc)
        self.factory.continueTrying = False
        self.transport.loseConnection()

    def reconnect(self, wait=None):
        # We ignore wait here, because we handled our own waiting.
        drivers.log.reconnect(self.irc.network)
        self.transport.loseConnection()

def errorMsg(reason):
    return reason.getErrorMessage()

class SupyReconnectingFactory(ReconnectingClientFactory, drivers.ServersMixin):
    maxDelay = 300
    protocol = SupyIrcProtocol
    def __init__(self, irc):
        self.irc = irc
        drivers.ServersMixin.__init__(self, irc)
        (server, port) = self._getNextServer()
        reactor.connectTCP(server, port, self)

    def clientConnectionFailed(self, connector, r):
        drivers.log.connectError(self.currentServer, errorMsg(r))
        (connector.host, connector.port) = self._getNextServer()
        if not r.check(error.TimeoutError):
            ReconnectingClientFactory.clientConnectionFailed(self, connector,r)

    def clientConnectionLost(self, connector, r):
        (connector.host, connector.port) = self._getNextServer()
        ReconnectingClientFactory.clientConnectionLost(self, connector, r)

    def startedConnecting(self, connector):
        drivers.log.connect(self.currentServer)

    def buildProtocol(self, addr):
        protocol = ReconnectingClientFactory.buildProtocol(self, addr)
        protocol.irc = self.irc
        return protocol

Driver = SupyReconnectingFactory

try:
    ignore(poller)
except NameError:
    poller = TwistedRunnerDriver()
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
<|endoftext|>


<commit_before>from tornado import gen
from tornado import web
from tornado import ioloop

from lib.database.users import get_user
from lib.database.showtimes import get_showtimes, get_showtime
from lib.database.reservations import get_reservations
from lib.database.reservations import remove_expired_tickets
from lib.database.showtimes import create_showtime
from lib.database.encryption import get_show_privatekey
from lib.database.encryption import get_user_keypair_from_showid
from lib.database.auth import get_user_tokens
from lib.basehandler import BaseHandler
from lib.basehandler import secured
from lib.config import CONFIG

from dateutil import parser as date_parser
from dateutil import tz
import cryptohelper

class ShowtimeKeys(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        showid = self.get_argument('showtime_id')
        shares = self.get_arguments('share')
        passphrase = self.get_argument('passphrase', None)
        if not passphrase:
            passphrase = cryptohelper.recover_passphrase(shares)
        if not (bool(shares) ^ bool(passphrase)):
            return self.error(
                400,
                'Either shares or passphrase needs to be provided'
            )
        privkey_show = yield get_show_privatekey(showid, passphrase)
        show_info = yield get_showtime(showid)
        result = {
            'showid': showid,
            'date': show_info['date'],
            'users': [],
        }
        users = yield get_user_keypair_from_showid(showid)
        for user in users:
            user_id = user['id']
            user_blob = yield get_user(user_id)
            user_privkey_pem = cryptohelper.decrypt_blob(
                privkey_show,
                user['enc_private_key']
            )
            meta = dict(showid=showid, **user_blob)
            cur_result = {
                'id': user_id,
                'meta': meta,
                'publickey': user['public_key'],
                'privatekey': user_privkey_pem,
            }
            result['users'].append(cur_result)
        return self.api_response(result)

class ShowtimeAccessTokens(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        showid = self.get_argument('showtime_id')
        shares = self.get_arguments('share')
        passphrase = self.get_argument('passphrase', None)
        if not (bool(shares) ^ bool(passphrase)):
            return self.error(
                400,
                'Either shares or passphrase needs to be provided'
            )
        if not passphrase:
            passphrase = cryptohelper.recover_passphrase(shares)
        privkey_show = yield get_show_privatekey(showid, passphrase)
        show_info = yield get_showtime(showid)
        result = {
            'showid': showid,
            'date': show_info['date'],
            'users': [],
        }
        users = yield get_user_keypair_from_showid(showid)
        for user in users:
            user_id = user['id']
            user_blob = yield get_user(user_id)
            user_privkey_pem = cryptohelper.decrypt_blob(
                privkey_show,
                user['enc_private_key']
            )
            meta = dict(showid=showid, **user_blob)
            cur_result = {
                'id': user_id,
                'meta': meta,
                'publickey': user['public_key'],
                'services': {},
            }
            user_privkey = cryptohelper.import_key(user_privkey_pem)
            access_tokens = yield get_user_tokens(user_id)
            if access_tokens is not None:
                for key, value in access_tokens.items():
                    if not isinstance(value, bytes):
                        continue
                    cur_result['services'][key] = cryptohelper.decrypt_blob(
                        user_privkey,
                        value
                    )
                result['users'].append(cur_result)
        return self.api_response(result)

@secured
class CreateShowtimeHandler(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        date_raw = self.get_argument('date')
        available_tickets = int(self.get_argument('tickets', 40))
        shitty_tickets = int(self.get_argument('shitty_tickets', 5))

        timezone = tz.gettz(CONFIG.get('timezone'))
        date = date_parser.parse(date_raw).replace(tzinfo=timezone)

        showid = yield create_showtime(date, available_tickets, shitty_tickets)
        return self.api_response({'showid': showid})

class ListShowtimesHandler(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        # inefficient databse query, figure out how to perform this query in
        # db.

        # remove all expired tickets
        yield remove_expired_tickets()

        showtimes = yield get_showtimes()
        reservations = yield get_reservations()
        showtime_map = {}  # Tuple (normal_tickets, shitty_tickets)
        for reservation in reservations:
            ticket_id = reservation["showtime_id"]
            ticketTuple = showtime_map.get(ticket_id, (0, 0))
            if reservation['is_shitty']:
                ticketTuple = (ticketTuple[0], ticketTuple[1]+1)
            else:
                ticketTuple = (ticketTuple[0]+1, ticketTuple[1])
            showtime_map[ticket_id] = ticketTuple

        result = []
        for showtime in showtimes:
            showid = showtime["id"]
            dateString = showtime["date_str"]

            if showid in showtime_map:
                available_tickets = \
                    showtime["max_normal_booking"]\
                    - showtime_map[showid][0]
                if available_tickets < 0:
                    available_tickets = 0
                available_shitty_tickets = \
                    showtime["max_shitty_booking"]\
                    - showtime_map[showid][1]
                if available_shitty_tickets < 0:
                    available_shitty_tickets = 0
            else:
                available_tickets = showtime["max_normal_booking"]
                available_shitty_tickets = showtime["max_shitty_booking"]
            result.append({
                "id": showid,
                "date": dateString,
                "available_tickets": available_tickets,
                "shitty_tickets": available_shitty_tickets
            })
        self.api_response(result)
<commit_msg>showtime shares and give shitty tickets to gulper<commit_after>from tornado import gen
from tornado import web
from tornado import ioloop

from lib.database.users import get_user
from lib.database.showtimes import get_showtimes, get_showtime
from lib.database.reservations import get_reservations
from lib.database.reservations import remove_expired_tickets
from lib.database.showtimes import create_showtime
from lib.database.encryption import get_show_privatekey
from lib.database.encryption import get_user_keypair_from_showid
from lib.database.auth import get_user_tokens
from lib.basehandler import BaseHandler
from lib.basehandler import secured
from lib.config import CONFIG

from dateutil import parser as date_parser
from dateutil import tz
import cryptohelper

class ShowtimeKeys(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        showid = self.get_argument('showtime_id')
        shares = self.get_arguments('share')
        passphrase = self.get_argument('passphrase', None)
        if not (bool(shares) ^ bool(passphrase)):
            return self.error(
                400,
                'Either shares or passphrase needs to be provided'
            )
        if not passphrase:
            passphrase = cryptohelper.recover_passphrase(shares)
        privkey_show = yield get_show_privatekey(showid, passphrase)
        show_info = yield get_showtime(showid)
        result = {
            'showid': showid,
            'date': show_info['date'],
            'users': [],
        }
        users = yield get_user_keypair_from_showid(showid)
        for user in users:
            user_id = user['id']
            user_blob = yield get_user(user_id)
            user_privkey_pem = cryptohelper.decrypt_blob(
                privkey_show,
                user['enc_private_key']
            )
            meta = dict(showid=showid, **user_blob)
            cur_result = {
                'id': user_id,
                'meta': meta,
                'publickey': user['public_key'],
                'privatekey': user_privkey_pem,
            }
            result['users'].append(cur_result)
        return self.api_response(result)

class ShowtimeAccessTokens(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        showid = self.get_argument('showtime_id')
        shares = self.get_arguments('share')
        passphrase = self.get_argument('passphrase', None)
        if not (bool(shares) ^ bool(passphrase)):
            return self.error(
                400,
                'Either shares or passphrase needs to be provided'
            )
        if not passphrase:
            passphrase = cryptohelper.recover_passphrase(shares)
        privkey_show = yield get_show_privatekey(showid, passphrase)
        show_info = yield get_showtime(showid)
        result = {
            'showid': showid,
            'date': show_info['date'],
            'users': [],
        }
        users = yield get_user_keypair_from_showid(showid)
        for user in users:
            user_id = user['id']
            user_blob = yield get_user(user_id)
            user_privkey_pem = cryptohelper.decrypt_blob(
                privkey_show,
                user['enc_private_key']
            )
            meta = dict(showid=showid, **user_blob)
            cur_result = {
                'id': user_id,
                'meta': meta,
                'publickey': user['public_key'],
                'services': {},
            }
            user_privkey = cryptohelper.import_key(user_privkey_pem)
            access_tokens = yield get_user_tokens(user_id)
            if access_tokens is not None:
                for key, value in access_tokens.items():
                    if not isinstance(value, bytes):
                        continue
                    cur_result['services'][key] = cryptohelper.decrypt_blob(
                        user_privkey,
                        value
                    )
            else:
                cur_result['services'] = {}
            result['users'].append(cur_result)
        return self.api_response(result)

@secured
class CreateShowtimeHandler(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        date_raw = self.get_argument('date')
        available_tickets = int(self.get_argument('tickets', 40))
        shitty_tickets = int(self.get_argument('shitty_tickets', 5))

        timezone = tz.gettz(CONFIG.get('timezone'))
        date = date_parser.parse(date_raw).replace(tzinfo=timezone)

        showid = yield create_showtime(date, available_tickets, shitty_tickets)
        return self.api_response({'showid': showid})

class ListShowtimesHandler(BaseHandler):
    _ioloop = ioloop.IOLoop().instance()

    @web.asynchronous
    @gen.coroutine
    def get(self):
        # inefficient databse query, figure out how to perform this query in
        # db.

        # remove all expired tickets
        yield remove_expired_tickets()

        showtimes = yield get_showtimes()
        reservations = yield get_reservations()
        showtime_map = {}  # Tuple (normal_tickets, shitty_tickets)
        for reservation in reservations:
            ticket_id = reservation["showtime_id"]
            ticketTuple = showtime_map.get(ticket_id, (0, 0))
            if reservation['is_shitty']:
                ticketTuple = (ticketTuple[0], ticketTuple[1]+1)
            else:
                ticketTuple = (ticketTuple[0]+1, ticketTuple[1])
            showtime_map[ticket_id] = ticketTuple

        result = []
        for showtime in showtimes:
            showid = showtime["id"]
            dateString = showtime["date_str"]

            if showid in showtime_map:
                available_tickets = \
                    showtime["max_normal_booking"]\
                    - showtime_map[showid][0]
                if available_tickets < 0:
                    available_tickets = 0
                available_shitty_tickets = \
                    showtime["max_shitty_booking"]\
                    - showtime_map[showid][1]
                if available_shitty_tickets < 0:
                    available_shitty_tickets = 0
            else:
                available_tickets = showtime["max_normal_booking"]
                available_shitty_tickets = showtime["max_shitty_booking"]
            result.append({
                "id": showid,
                "date": dateString,
                "available_tickets": available_tickets,
                "shitty_tickets": available_shitty_tickets
            })
        self.api_response(result)
<|endoftext|>


<commit_before>from django.utils.encoding import smart_unicode
from django.http import StreamingHttpResponse
from rest_framework import renderers
from rest_framework.response import Response
from kpi.serializers import UserSerializer
import json
import copy

class AssetJsonRenderer(renderers.JSONRenderer):
    media_type = 'application/json'
    format = 'json'

class SSJsonRenderer(renderers.JSONRenderer):
    media_type = 'application/json'
    format = 'ssjson'
    charset = 'utf-8'

    def render(self, data, media_type=None, renderer_context=None):
        # this accessing of the model might be frowned upon, but I'd prefer to avoid
        # re-building the SS structure outside of the model for now.
        return json.dumps(renderer_context['view'].get_object().to_ss_structure())

class XFormRenderer(renderers.BaseRenderer):
    media_type = 'application/xml'
    format = 'xml'
    charset = 'utf-8'

    def render(self, data, media_type=None, renderer_context=None):
        asset = renderer_context['view'].get_object()
        return asset.export.xml

class XlsRenderer(renderers.BaseRenderer):
    media_type = 'application/xls'
    format = 'xls'

    def render(self, data, media_type=None, renderer_context=None):
        '''
        Renderers cannot set headers on the response
        (https://github.com/tomchristie/django-rest-framework/issues/1041).
        "The method should return a bytestring, which will be used as the body
        of the HTTP Response"
        (http://www.django-rest-framework.org/api-guide/renderers/#custom-renderers).
        '''
        asset = renderer_context['view'].get_object()
        return asset.to_xls_io()

class EnketoPreviewLinkRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'enketopreviewlink'

    def render(self, data, media_type=None, renderer_context=None):
        raise NotImplementedError("%s not yet implemented" % (self.__class__.__name__))

<commit_msg>removing note<commit_after>from django.utils.encoding import smart_unicode
from django.http import StreamingHttpResponse
from rest_framework import renderers
from rest_framework.response import Response
from kpi.serializers import UserSerializer
import json
import copy

class AssetJsonRenderer(renderers.JSONRenderer):
    media_type = 'application/json'
    format = 'json'

class SSJsonRenderer(renderers.JSONRenderer):
    media_type = 'application/json'
    format = 'ssjson'
    charset = 'utf-8'

    def render(self, data, media_type=None, renderer_context=None):
        # this accessing of the model might be frowned upon, but I'd prefer to avoid
        # re-building the SS structure outside of the model for now.
        return json.dumps(renderer_context['view'].get_object().to_ss_structure())

class XFormRenderer(renderers.BaseRenderer):
    media_type = 'application/xml'
    format = 'xml'
    charset = 'utf-8'

    def render(self, data, media_type=None, renderer_context=None):
        asset = renderer_context['view'].get_object()
        return asset.export.xml

class XlsRenderer(renderers.BaseRenderer):
    media_type = 'application/xls'
    format = 'xls'

    def render(self, data, media_type=None, renderer_context=None):
        asset = renderer_context['view'].get_object()
        return asset.to_xls_io()

class EnketoPreviewLinkRenderer(renderers.BaseRenderer):
    media_type = 'text/plain'
    format = 'enketopreviewlink'

    def render(self, data, media_type=None, renderer_context=None):
        raise NotImplementedError("%s not yet implemented" % (self.__class__.__name__))

<|endoftext|>


<commit_before>import os
import sys
import json
import platform
import socket
import signal
import logging
import logging.config
import threading
import traceback
import multiprocessing
from time import monotonic
from typing import Tuple  # noqa

import amqp

from kuyruk import importer, signals
from kuyruk.reject import DelayedRejects
from kuyruk.heartbeat import Heartbeat
from kuyruk.exceptions import Reject, Discard, HeartbeatError

logger = logging.getLogger(__name__)

class Worker:
    """Consumes tasks from queues and runs them.

    :param app: An instance of :class:`~kuyruk.Kuyruk`
    :param args: Command line arguments

    """
    def __init__(self, app, args):
        self.kuyruk = app

        if not args.queues:
            args.queues = ['kuyruk']

        def add_host(queue):
            if queue.endswith('.localhost'):
                queue = queue.rsplit('.localhost')[0]
                return "%s.%s" % (queue, self._hostname)
            else:
                return queue

        self._hostname = socket.gethostname()
        self.queues = [add_host(q) for q in args.queues]
        self._tasks = {}  # type: Tuple[str, str]
        self.shutdown_pending = threading.Event()
        self.consuming = False
        self.current_task = None
        self.current_args = None
        self.current_kwargs = None

        self._started_at = None
        self._pid = os.getpid()

        self._logging_level = app.config.WORKER_LOGGING_LEVEL
        if args.logging_level is not None:
            self._logging_level = args.logging_level

        self._max_run_time = app.config.WORKER_MAX_RUN_TIME
        if args.max_run_time is not None:
            self._max_run_time = args.max_run_time

        self._max_load = app.config.WORKER_MAX_LOAD
        if args.max_load is not None:
            self._max_load = args.max_load
        if self._max_load == -1:
            self._max_load == multiprocessing.cpu_count()

        self._threads = []  # type: threading.Thread
        if self._max_load:
            self._threads.append(threading.Thread(target=self._watch_load))
        if self._max_run_time:
            self._threads.append(threading.Thread(target=self._shutdown_timer))

        signals.worker_init.send(self.kuyruk, worker=self)

    def run(self):
        """Runs the worker and consumes messages from RabbitMQ.
        Returns only after `shutdown()` is called.

        """
        if self._logging_level:
            logging.basicConfig(
                level=getattr(logging, self._logging_level.upper()),
                format="%(levelname).1s %(name)s.%(funcName)s:%(lineno)d - %(message)s")

        signal.signal(signal.SIGINT, self._handle_sigint)
        signal.signal(signal.SIGTERM, self._handle_sigterm)
        if platform.system() != 'Windows':
            # These features will not be available on Windows, but that is OK.
            # Read this issue for more details:
            # https://github.com/cenkalti/kuyruk/issues/54
            signal.signal(signal.SIGHUP, self._handle_sighup)
            signal.signal(signal.SIGUSR1, self._handle_sigusr1)
            signal.signal(signal.SIGUSR2, self._handle_sigusr2)

        self._started_at = os.times()[4]

        for t in self._threads:
            t.start()

        try:
            signals.worker_start.send(self.kuyruk, worker=self)
            self._consume_messages()
            signals.worker_shutdown.send(self.kuyruk, worker=self)
        finally:
            self.shutdown_pending.set()
            for t in self._threads:
                t.join()

        logger.debug("End run worker")

    def _consume_messages(self):
        with self.kuyruk.channel() as ch:
            self._rejects = DelayedRejects(ch)
            # Set prefetch count to 1. If we don't set this, RabbitMQ keeps
            # sending messages while we are already working on a message.
            ch.basic_qos(0, 1, True)

            self._declare_queues(ch)
            self._consume_queues(ch)
            logger.info('Consumer started')
            self._main_loop(ch)
            self._rejects.send_pending()

        logger.debug("End run worker")

    def _main_loop(self, ch):
        while not self.shutdown_pending.is_set():
            if self._max_load:
                self._pause_or_resume(ch)

            try:
                self._rejects.send_pending()
                ch.connection.heartbeat_tick()
                ch.connection.drain_events(timeout=1)
            except socket.timeout:
                pass
            except TimeoutError:
                pass

    def _consumer_tag(self, queue):
        return "%s:%s@%s" % (queue, self._pid, self._hostname)

    def _declare_queues(self, ch):
        for queue in self.queues:
            logger.debug("queue_declare: %s", queue)
            ch.queue_declare(queue=queue, durable=True, auto_delete=False)

    def _pause_or_resume(self, channel):
        try:
            load = self._current_load
        except AttributeError:
            should_pause = False
        else:
            should_pause = load > self._max_load

        if should_pause and self.consuming:
            logger.warning('Load is above the treshold (%.2f/%s), ' 'pausing consumer', load, self._max_load)
            self._cancel_queues(channel)
        elif not should_pause and not self.consuming:
            logger.warning('Load is below the treshold (%.2f/%s), ' 'resuming consumer', load, self._max_load)
            self._consume_queues(channel)

    def _consume_queues(self, ch):
        self.consuming = True
        for queue in self.queues:
            logger.debug("basic_consume: %s", queue)
            ch.basic_consume(queue=queue, consumer_tag=self._consumer_tag(queue), callback=self._process_message)

    def _cancel_queues(self, ch):
        self.consuming = False
        for queue in self.queues:
            logger.debug("basic_cancel: %s", queue)
            ch.basic_cancel(self._consumer_tag(queue))

    def _process_message(self, message):
        """Processes the message received from the queue."""
        if self.shutdown_pending.is_set():
            return

        try:
            description = json.loads(message.body)
        except Exception:
            message.channel.basic_reject(message.delivery_tag, requeue=False)
            logger.error("Cannot decode message. Dropping.")
        else:
            logger.info("Processing task: %r", description)
            self._process_description(message, description)

    def _process_description(self, message, description):
        try:
            task = self._import_task(description['module'], description['function'])
            args, kwargs = description['args'], description['kwargs']
        except Exception:
            logger.error('Cannot import task')
            exc_info = sys.exc_info()
            signals.worker_failure.send(self.kuyruk, description=description, exc_info=exc_info, worker=self)
            message.channel.basic_reject(message.delivery_tag, requeue=False)
        else:
            self._process_task(message, description, task, args, kwargs)

    def _import_task(self, module, function):
        if (module, function) in self._tasks:
            return self._tasks[(module, function)]

        task = importer.import_object(module, function)
        self._tasks[(module, function)] = task
        return task

    def _process_task(self, message, description, task, args, kwargs):
        queue = message.delivery_info['routing_key']
        reply_to = message.properties.get('reply_to')
        try:
            result = self._run_task(message.channel.connection, task, args, kwargs)
        except Reject:
            logger.warning('Task is rejected')
            self._rejects.push(task.reject_delay, message.delivery_tag, requeue=True)
        except Discard:
            logger.warning('Task is discarded')
            message.channel.basic_reject(message.delivery_tag, requeue=False)
            if reply_to:
                exc_info = sys.exc_info()
                self._send_reply(reply_to, message.channel, None, exc_info)
        except HeartbeatError as e:
            logger.error('Error while sending heartbeat')
            exc_info = e.exc_info
            logger.error(''.join(traceback.format_exception(*exc_info)))
            signals.worker_failure.send(
                self.kuyruk,
                description=description,
                task=task,
                args=args,
                kwargs=kwargs,
                exc_info=exc_info,
                worker=self,
                queue=queue)
            raise
        except Exception:
            logger.error('Task raised an exception')
            exc_info = sys.exc_info()
            logger.error(''.join(traceback.format_exception(*exc_info)))
            signals.worker_failure.send(
                self.kuyruk,
                description=description,
                task=task,
                args=args,
                kwargs=kwargs,
                exc_info=exc_info,
                worker=self,
                queue=queue)
            self._rejects.push(0, message.delivery_tag, requeue=False)
            if reply_to:
                self._send_reply(reply_to, message.channel, None, exc_info)
        else:
            logger.info('Task is successful')
            message.channel.basic_ack(message.delivery_tag)
            if reply_to:
                self._send_reply(reply_to, message.channel, result, None)
        finally:
            logger.debug("Task is processed")

    def _run_task(self, connection, task, args, kwargs):
        hb = Heartbeat(connection, self._on_heartbeat_error, rejects=self._rejects)
        hb.start()

        self.current_task = task
        self.current_args = args
        self.current_kwargs = kwargs
        try:
            return self._apply_task(task, args, kwargs)
        finally:
            self.current_task = None
            self.current_args = None
            self.current_kwargs = None

            hb.stop()

    def _on_heartbeat_error(self, exc_info):
        self._heartbeat_exc_info = exc_info
        os.kill(os.getpid(), signal.SIGHUP)

    @staticmethod
    def _apply_task(task, args, kwargs):
        """Logs the time spent while running the task."""
        if args is None:
            args = ()
        if kwargs is None:
            kwargs = {}

        start = monotonic()
        try:
            return task.apply(*args, **kwargs)
        finally:
            delta = monotonic() - start
            logger.info("%s finished in %i seconds." % (task.name, delta))

    def _send_reply(self, reply_to, channel, result, exc_info):
        logger.debug("Sending reply result=%r", result)

        reply = {'result': result}
        if exc_info:
            reply['exception'] = self._exc_info_dict(exc_info)

        try:
            body = json.dumps(reply)
        except Exception as e:
            logger.error('Cannot serialize result as JSON: %s', e)
            exc_info = sys.exc_info()
            reply = {'result': None, 'exception': self._exc_info_dict(exc_info)}
            body = json.dumps(reply)

        msg = amqp.Message(body=body)
        channel.basic_publish(msg, exchange="", routing_key=reply_to)

    @staticmethod
    def _exc_info_dict(exc_info):
        type_, val, tb = exc_info
        return {
            'type': '%s.%s' % (type_.__module__, str(type_.__name__)),
            'value': str(val),
            'traceback': ''.join(traceback.format_tb(tb)),
        }

    def _watch_load(self):
        """Pause consuming messages if lood goes above the allowed limit."""
        while not self.shutdown_pending.wait(1):
            self._current_load = os.getloadavg()[0]

    @property
    def uptime(self):
        if self._started_at is not None:
            return os.times()[4] - self._started_at

    def _shutdown_timer(self):
        """Counts down from MAX_WORKER_RUN_TIME. When it reaches zero sutdown
        gracefully.

        """
        remaining = self._max_run_time - self.uptime
        if not self.shutdown_pending.wait(remaining):
            logger.warning('Run time reached zero')
            self.shutdown()

    def shutdown(self):
        """Exits after the current task is finished."""
        logger.warning("Shutdown requested")
        self.shutdown_pending.set()

    def _handle_sigint(self, signum, frame):
        """Shutdown after processing current task."""
        logger.warning("Catched SIGINT")
        self.shutdown()

    def _handle_sigterm(self, signum, frame):
        """Shutdown after processing current task."""
        logger.warning("Catched SIGTERM")
        self.shutdown()

    def _handle_sighup(self, signum, frame):
        """Used internally to fail the task when connection to RabbitMQ is
        lost during the execution of the task.

        """
        logger.warning("Catched SIGHUP")
        raise HeartbeatError(self._heartbeat_exc_info)

    @staticmethod
    def _handle_sigusr1(signum, frame):
        """Print stacktrace."""
        print('=' * 70)
        print(''.join(traceback.format_stack()))
        print('-' * 70)

    def _handle_sigusr2(self, signum, frame):
        """Drop current task."""
        logger.warning("Catched SIGUSR2")
        if self.current_task:
            logger.warning("Dropping current task...")
            raise Discard

    def drop_task(self):
        os.kill(os.getpid(), signal.SIGUSR2)
<commit_msg>remove duplicate log<commit_after>import os
import sys
import json
import platform
import socket
import signal
import logging
import logging.config
import threading
import traceback
import multiprocessing
from time import monotonic
from typing import Tuple  # noqa

import amqp

from kuyruk import importer, signals
from kuyruk.reject import DelayedRejects
from kuyruk.heartbeat import Heartbeat
from kuyruk.exceptions import Reject, Discard, HeartbeatError

logger = logging.getLogger(__name__)

class Worker:
    """Consumes tasks from queues and runs them.

    :param app: An instance of :class:`~kuyruk.Kuyruk`
    :param args: Command line arguments

    """
    def __init__(self, app, args):
        self.kuyruk = app

        if not args.queues:
            args.queues = ['kuyruk']

        def add_host(queue):
            if queue.endswith('.localhost'):
                queue = queue.rsplit('.localhost')[0]
                return "%s.%s" % (queue, self._hostname)
            else:
                return queue

        self._hostname = socket.gethostname()
        self.queues = [add_host(q) for q in args.queues]
        self._tasks = {}  # type: Tuple[str, str]
        self.shutdown_pending = threading.Event()
        self.consuming = False
        self.current_task = None
        self.current_args = None
        self.current_kwargs = None

        self._started_at = None
        self._pid = os.getpid()

        self._logging_level = app.config.WORKER_LOGGING_LEVEL
        if args.logging_level is not None:
            self._logging_level = args.logging_level

        self._max_run_time = app.config.WORKER_MAX_RUN_TIME
        if args.max_run_time is not None:
            self._max_run_time = args.max_run_time

        self._max_load = app.config.WORKER_MAX_LOAD
        if args.max_load is not None:
            self._max_load = args.max_load
        if self._max_load == -1:
            self._max_load == multiprocessing.cpu_count()

        self._threads = []  # type: threading.Thread
        if self._max_load:
            self._threads.append(threading.Thread(target=self._watch_load))
        if self._max_run_time:
            self._threads.append(threading.Thread(target=self._shutdown_timer))

        signals.worker_init.send(self.kuyruk, worker=self)

    def run(self):
        """Runs the worker and consumes messages from RabbitMQ.
        Returns only after `shutdown()` is called.

        """
        if self._logging_level:
            logging.basicConfig(
                level=getattr(logging, self._logging_level.upper()),
                format="%(levelname).1s %(name)s.%(funcName)s:%(lineno)d - %(message)s")

        signal.signal(signal.SIGINT, self._handle_sigint)
        signal.signal(signal.SIGTERM, self._handle_sigterm)
        if platform.system() != 'Windows':
            # These features will not be available on Windows, but that is OK.
            # Read this issue for more details:
            # https://github.com/cenkalti/kuyruk/issues/54
            signal.signal(signal.SIGHUP, self._handle_sighup)
            signal.signal(signal.SIGUSR1, self._handle_sigusr1)
            signal.signal(signal.SIGUSR2, self._handle_sigusr2)

        self._started_at = os.times()[4]

        for t in self._threads:
            t.start()

        try:
            signals.worker_start.send(self.kuyruk, worker=self)
            self._consume_messages()
            signals.worker_shutdown.send(self.kuyruk, worker=self)
        finally:
            self.shutdown_pending.set()
            for t in self._threads:
                t.join()

        logger.debug("End run worker")

    def _consume_messages(self):
        with self.kuyruk.channel() as ch:
            self._rejects = DelayedRejects(ch)
            # Set prefetch count to 1. If we don't set this, RabbitMQ keeps
            # sending messages while we are already working on a message.
            ch.basic_qos(0, 1, True)

            self._declare_queues(ch)
            self._consume_queues(ch)
            logger.info('Consumer started')
            self._main_loop(ch)
            self._rejects.send_pending()

    def _main_loop(self, ch):
        while not self.shutdown_pending.is_set():
            if self._max_load:
                self._pause_or_resume(ch)

            try:
                self._rejects.send_pending()
                ch.connection.heartbeat_tick()
                ch.connection.drain_events(timeout=1)
            except socket.timeout:
                pass
            except TimeoutError:
                pass

    def _consumer_tag(self, queue):
        return "%s:%s@%s" % (queue, self._pid, self._hostname)

    def _declare_queues(self, ch):
        for queue in self.queues:
            logger.debug("queue_declare: %s", queue)
            ch.queue_declare(queue=queue, durable=True, auto_delete=False)

    def _pause_or_resume(self, channel):
        try:
            load = self._current_load
        except AttributeError:
            should_pause = False
        else:
            should_pause = load > self._max_load

        if should_pause and self.consuming:
            logger.warning('Load is above the treshold (%.2f/%s), ' 'pausing consumer', load, self._max_load)
            self._cancel_queues(channel)
        elif not should_pause and not self.consuming:
            logger.warning('Load is below the treshold (%.2f/%s), ' 'resuming consumer', load, self._max_load)
            self._consume_queues(channel)

    def _consume_queues(self, ch):
        self.consuming = True
        for queue in self.queues:
            logger.debug("basic_consume: %s", queue)
            ch.basic_consume(queue=queue, consumer_tag=self._consumer_tag(queue), callback=self._process_message)

    def _cancel_queues(self, ch):
        self.consuming = False
        for queue in self.queues:
            logger.debug("basic_cancel: %s", queue)
            ch.basic_cancel(self._consumer_tag(queue))

    def _process_message(self, message):
        """Processes the message received from the queue."""
        if self.shutdown_pending.is_set():
            return

        try:
            description = json.loads(message.body)
        except Exception:
            message.channel.basic_reject(message.delivery_tag, requeue=False)
            logger.error("Cannot decode message. Dropping.")
        else:
            logger.info("Processing task: %r", description)
            self._process_description(message, description)

    def _process_description(self, message, description):
        try:
            task = self._import_task(description['module'], description['function'])
            args, kwargs = description['args'], description['kwargs']
        except Exception:
            logger.error('Cannot import task')
            exc_info = sys.exc_info()
            signals.worker_failure.send(self.kuyruk, description=description, exc_info=exc_info, worker=self)
            message.channel.basic_reject(message.delivery_tag, requeue=False)
        else:
            self._process_task(message, description, task, args, kwargs)

    def _import_task(self, module, function):
        if (module, function) in self._tasks:
            return self._tasks[(module, function)]

        task = importer.import_object(module, function)
        self._tasks[(module, function)] = task
        return task

    def _process_task(self, message, description, task, args, kwargs):
        queue = message.delivery_info['routing_key']
        reply_to = message.properties.get('reply_to')
        try:
            result = self._run_task(message.channel.connection, task, args, kwargs)
        except Reject:
            logger.warning('Task is rejected')
            self._rejects.push(task.reject_delay, message.delivery_tag, requeue=True)
        except Discard:
            logger.warning('Task is discarded')
            message.channel.basic_reject(message.delivery_tag, requeue=False)
            if reply_to:
                exc_info = sys.exc_info()
                self._send_reply(reply_to, message.channel, None, exc_info)
        except HeartbeatError as e:
            logger.error('Error while sending heartbeat')
            exc_info = e.exc_info
            logger.error(''.join(traceback.format_exception(*exc_info)))
            signals.worker_failure.send(
                self.kuyruk,
                description=description,
                task=task,
                args=args,
                kwargs=kwargs,
                exc_info=exc_info,
                worker=self,
                queue=queue)
            raise
        except Exception:
            logger.error('Task raised an exception')
            exc_info = sys.exc_info()
            logger.error(''.join(traceback.format_exception(*exc_info)))
            signals.worker_failure.send(
                self.kuyruk,
                description=description,
                task=task,
                args=args,
                kwargs=kwargs,
                exc_info=exc_info,
                worker=self,
                queue=queue)
            self._rejects.push(0, message.delivery_tag, requeue=False)
            if reply_to:
                self._send_reply(reply_to, message.channel, None, exc_info)
        else:
            logger.info('Task is successful')
            message.channel.basic_ack(message.delivery_tag)
            if reply_to:
                self._send_reply(reply_to, message.channel, result, None)
        finally:
            logger.debug("Task is processed")

    def _run_task(self, connection, task, args, kwargs):
        hb = Heartbeat(connection, self._on_heartbeat_error, rejects=self._rejects)
        hb.start()

        self.current_task = task
        self.current_args = args
        self.current_kwargs = kwargs
        try:
            return self._apply_task(task, args, kwargs)
        finally:
            self.current_task = None
            self.current_args = None
            self.current_kwargs = None

            hb.stop()

    def _on_heartbeat_error(self, exc_info):
        self._heartbeat_exc_info = exc_info
        os.kill(os.getpid(), signal.SIGHUP)

    @staticmethod
    def _apply_task(task, args, kwargs):
        """Logs the time spent while running the task."""
        if args is None:
            args = ()
        if kwargs is None:
            kwargs = {}

        start = monotonic()
        try:
            return task.apply(*args, **kwargs)
        finally:
            delta = monotonic() - start
            logger.info("%s finished in %i seconds." % (task.name, delta))

    def _send_reply(self, reply_to, channel, result, exc_info):
        logger.debug("Sending reply result=%r", result)

        reply = {'result': result}
        if exc_info:
            reply['exception'] = self._exc_info_dict(exc_info)

        try:
            body = json.dumps(reply)
        except Exception as e:
            logger.error('Cannot serialize result as JSON: %s', e)
            exc_info = sys.exc_info()
            reply = {'result': None, 'exception': self._exc_info_dict(exc_info)}
            body = json.dumps(reply)

        msg = amqp.Message(body=body)
        channel.basic_publish(msg, exchange="", routing_key=reply_to)

    @staticmethod
    def _exc_info_dict(exc_info):
        type_, val, tb = exc_info
        return {
            'type': '%s.%s' % (type_.__module__, str(type_.__name__)),
            'value': str(val),
            'traceback': ''.join(traceback.format_tb(tb)),
        }

    def _watch_load(self):
        """Pause consuming messages if lood goes above the allowed limit."""
        while not self.shutdown_pending.wait(1):
            self._current_load = os.getloadavg()[0]

    @property
    def uptime(self):
        if self._started_at is not None:
            return os.times()[4] - self._started_at

    def _shutdown_timer(self):
        """Counts down from MAX_WORKER_RUN_TIME. When it reaches zero sutdown
        gracefully.

        """
        remaining = self._max_run_time - self.uptime
        if not self.shutdown_pending.wait(remaining):
            logger.warning('Run time reached zero')
            self.shutdown()

    def shutdown(self):
        """Exits after the current task is finished."""
        logger.warning("Shutdown requested")
        self.shutdown_pending.set()

    def _handle_sigint(self, signum, frame):
        """Shutdown after processing current task."""
        logger.warning("Catched SIGINT")
        self.shutdown()

    def _handle_sigterm(self, signum, frame):
        """Shutdown after processing current task."""
        logger.warning("Catched SIGTERM")
        self.shutdown()

    def _handle_sighup(self, signum, frame):
        """Used internally to fail the task when connection to RabbitMQ is
        lost during the execution of the task.

        """
        logger.warning("Catched SIGHUP")
        raise HeartbeatError(self._heartbeat_exc_info)

    @staticmethod
    def _handle_sigusr1(signum, frame):
        """Print stacktrace."""
        print('=' * 70)
        print(''.join(traceback.format_stack()))
        print('-' * 70)

    def _handle_sigusr2(self, signum, frame):
        """Drop current task."""
        logger.warning("Catched SIGUSR2")
        if self.current_task:
            logger.warning("Dropping current task...")
            raise Discard

    def drop_task(self):
        os.kill(os.getpid(), signal.SIGUSR2)
<|endoftext|>


<commit_before>from flask import Flask, render_template, request
import json

# pyMongodb wrapper
from kyzr_db import dbEditor
kyzr = dbEditor()

# Setup flask
app = Flask(__name__)

# Main homepage
# TODO: Add login ability and other inputs
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/class_notes')
def notes():
    return render_template('class_notes.html')

# Map page
# TODO: Merge with homepage (?)
#       Call map data from database
#       Have input from phone ID
#@app.route('/maps/<coords>')
@app.route('/maps', methods=['GET', 'POST'])
def maps():
    coords = []
    center = [0,0]
    zoom = 3
    torchID = ''
    error = False
    dist = ''
    username = ''
    num_tran = ''

    if(request.method=="POST"):
        if("id" in request.form.keys()):
            torchID = request.form["id"]

            if(torchID):
                user = kyzr.find_user(torchID)
                if(user is not None):
                    coords = user['locs']
                else:
                    error = True
            #else:
            #    return render_template('error.html')
    if coords:
        lats = [ coords[j][0] for j in xrange(len(coords))]
        lons = [ coords[j][1] for j in xrange(len(coords))]
        center = [ float(sum(i)/len(i)) for i in (lats, lons) ]
        zoom = max( [ max(lats) - min(lats), max(lons)-min(lons)])
        for i in xrange(0,15,2):
            if zoom < 0.005:
                zoom = 15-i
                break
            zoom = zoom/7.0
        stats = kyzr.compute_stats(torchID)
        dist = stats["DISTANCE"]
        username = stats["TORCH"]
        num_tran = stats["NUMTRANSACTION"]

    return render_template('maps.html',
           coords=json.dumps(coords),
           center=json.dumps(center),
           zoom=json.dumps(zoom),
           torchID=torchID,
           dist=json.dumps(dist),
           torch_held=json.dumps(username),
           num_tran=json.dumps(num_tran),
           error=error)
#   return render_template('debug.html',
#           coords=json.dumps(coords),
#           center=json.dumps(center),
#           zoom=json.dumps(zoom))

@app.route('/verify', methods=['GET', 'POST'])
def verify():

    if request.method=="POST":
        if ("search_id" in request.form.keys()):
            if( ' ' in request.form["search_id"]):
                return "Username cannot contain spaces."

            user = kyzr.find_user(request.form["search_id"])

            if(user is None):
                return "False"
            return "User already exists."
    return "Invalid Search"

@app.route('/newuser', methods=['GET', 'POST'])
def newuser():

    if request.method=="POST":
        print request.form.keys()
        if("pid" in request.form.keys() and
            "username" in request.form.keys() and
            "lat" in request.form.keys() and
            "lng" in request.form.keys()):

            pid = request.form["pid"]
            username = request.form["username"]
            lat = float(request.form["lat"])
            lng = float(request.form["lng"])
            if ' ' in username:
                return "False"

            user = kyzr.verify_user(pid, username)

            if(user is None):
                kyzr.add_user(pid, username, lat, lng)
                return "True"
            else:
                return "False"
    return "Invalid Search"

# Next two functions are for database
# adding/receiving for the android phones
@app.route('/dbadd', methods=['GET','POST'])
def dbadd():

    if request.method=="POST":
        if("lat" in request.form.keys() and "lng" in request.form.keys() and
            "id1" in request.form.keys() and "id2" in request.form.keys()):

            for key in request.form.keys():
                if key == "lat":
                    try:
                        lat = float(request.form[key])
                    except:
                        return "Request Failed: latitude was not a float"
                elif key == "lng":
                    try:
                        lng = float(request.form[key])
                    except:
                        return "Request Failed: longitude was not a float"
                elif key == "id1":
                    phone1_id = request.form[key]
                elif key == "id2":
                    phone2_id = request.form[key]

            kyzr.swap_torch(phone1_id, phone2_id, lat, lng)

            return "Success"
    return "Request method failed."

@app.route('/stats', methods=['GET', 'POST'])
def stats():

    if request.method=="POST":
        if ("phone_id" in request.form.keys()):
            phone_id = request.form["phone_id"]

            #stats = sc.compute_stats(user)
            stats = kyzr.compute_stats(phone_id)

            return json.dumps(stats)

    return "Request failed."

@app.route('/currtorch', methods=['GET', 'POST'])
def currtorch():

    if request.method=="POST":
        if ("phone_id" in request.form.keys()):
            phone_id = request.form["phone_id"]
            user = kyzr.find_user(phone_id)
            if user is not None:
                torch = user['torch']
                torchowner = kyzr.find_user(torch)
                return torchowner['username']

    return "Cannot find username."

if __name__ == "__main__":
    app.run()
<commit_msg>No more uppercase letters!<commit_after>from flask import Flask, render_template, request
import json

# pyMongodb wrapper
from kyzr_db import dbEditor
kyzr = dbEditor()

# Setup flask
app = Flask(__name__)

# Main homepage
# TODO: Add login ability and other inputs
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/class_notes')
def notes():
    return render_template('class_notes.html')

# Map page
# TODO: Merge with homepage (?)
#       Call map data from database
#       Have input from phone ID
#@app.route('/maps/<coords>')
@app.route('/maps', methods=['GET', 'POST'])
def maps():
    coords = []
    center = [0,0]
    zoom = 3
    torchID = ''
    error = False
    dist = ''
    username = ''
    num_tran = ''

    if(request.method=="POST"):
        if("id" in request.form.keys()):
            torchID = request.form["id"]

            if(torchID):
                user = kyzr.find_user(torchID)
                if(user is not None):
                    coords = user['locs']
                else:
                    error = True
            #else:
            #    return render_template('error.html')
    if coords:
        lats = [ coords[j][0] for j in xrange(len(coords))]
        lons = [ coords[j][1] for j in xrange(len(coords))]
        center = [ float(sum(i)/len(i)) for i in (lats, lons) ]
        zoom = max( [ max(lats) - min(lats), max(lons)-min(lons)])
        for i in xrange(0,15,2):
            if zoom < 0.005:
                zoom = 15-i
                break
            zoom = zoom/7.0
        stats = kyzr.compute_stats(torchID)
        dist = stats["DISTANCE"]
        username = stats["TORCH"]
        num_tran = stats["NUMTRANSACTION"]

    return render_template('maps.html',
           coords=json.dumps(coords),
           center=json.dumps(center),
           zoom=json.dumps(zoom),
           torchID=torchID,
           dist=json.dumps(dist),
           torch_held=json.dumps(username),
           num_tran=json.dumps(num_tran),
           error=error)
#   return render_template('debug.html',
#           coords=json.dumps(coords),
#           center=json.dumps(center),
#           zoom=json.dumps(zoom))

@app.route('/verify', methods=['GET', 'POST'])
def verify():

    if request.method=="POST":
        if ("search_id" in request.form.keys()):
            if( ' ' in request.form["search_id"]):
                return "Username cannot contain spaces."

            user = kyzr.find_user(request.form["search_id"])

            if(user is None):
                return "False"
            return "User already exists."
    return "Invalid Search"

@app.route('/newuser', methods=['GET', 'POST'])
def newuser():

    if request.method=="POST":
        print request.form.keys()
        if("pid" in request.form.keys() and
            "username" in request.form.keys() and
            "lat" in request.form.keys() and
            "lng" in request.form.keys()):

            pid = request.form["pid"]
            username = request.form["username"].lower()
            lat = float(request.form["lat"])
            lng = float(request.form["lng"])
            if ' ' in username:
                return "False"

            user = kyzr.verify_user(pid, username)

            if(user is None):
                kyzr.add_user(pid, username, lat, lng)
                return "True"
            else:
                return "False"
    return "Invalid Search"

# Next two functions are for database
# adding/receiving for the android phones
@app.route('/dbadd', methods=['GET','POST'])
def dbadd():

    if request.method=="POST":
        if("lat" in request.form.keys() and "lng" in request.form.keys() and
            "id1" in request.form.keys() and "id2" in request.form.keys()):

            for key in request.form.keys():
                if key == "lat":
                    try:
                        lat = float(request.form[key])
                    except:
                        return "Request Failed: latitude was not a float"
                elif key == "lng":
                    try:
                        lng = float(request.form[key])
                    except:
                        return "Request Failed: longitude was not a float"
                elif key == "id1":
                    phone1_id = request.form[key]
                elif key == "id2":
                    phone2_id = request.form[key]

            kyzr.swap_torch(phone1_id, phone2_id, lat, lng)

            return "Success"
    return "Request method failed."

@app.route('/stats', methods=['GET', 'POST'])
def stats():

    if request.method=="POST":
        if ("phone_id" in request.form.keys()):
            phone_id = request.form["phone_id"]

            #stats = sc.compute_stats(user)
            stats = kyzr.compute_stats(phone_id)

            return json.dumps(stats)

    return "Request failed."

@app.route('/currtorch', methods=['GET', 'POST'])
def currtorch():

    if request.method=="POST":
        if ("phone_id" in request.form.keys()):
            phone_id = request.form["phone_id"]
            user = kyzr.find_user(phone_id)
            if user is not None:
                torch = user['torch']
                torchowner = kyzr.find_user(torch)
                return torchowner['username']

    return "Cannot find username."

if __name__ == "__main__":
    app.run()
<|endoftext|>


<commit_before># -*- coding: latin-1 -*-
import os
import sys
from flask import Flask, render_template, request

current_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(current_dir, '..'))

from wm_metrics import fdc
from wm_metrics import wmfr_photography
from wm_metrics import commons_cat_metrics
from wm_metrics import category_induced
from wm_metrics import mw_util

app = Flask(__name__)

@app.route("/")
def index():
    return render_template('index.html')

@app.route("/fdc")
def fdc_report_page():
    return render_template('fdc-report.html')

@app.route("/category-induced")
def category_induced_page():
    return render_template('category-induced.html')

@app.route("/fdc/submit", methods=["POST"])
def compute_fdc_report():
    category = request.form['category']
    fdc_year = int(request.form['year'])
    round_num = int(request.form['round'])
    nb_uploaders_on = 'indicator-uploaders' in request.form
    nb_files_on = 'indicator-files' in request.form
    nb_labels_on = 'indicator-highlighted' in request.form
    pct_labels_on = 'indicator-highlighted_percentage' in request.form

    fdc_round = fdc.Round(fdc_year-1, fdc_year, round_num)
    results = 'Nothing'
    try:
        results = wmfr_photography.make_example_report(fdc_round, category,
                        nb_files_on=nb_files_on,
                        nb_labels_on=nb_labels_on,
                        nb_uploaders_on=nb_uploaders_on,
                        pct_labels_on=pct_labels_on)

    except wmfr_photography.WMmetricsException, e:
        message = 'Something went wrong in Wm_metrics: ' + e.message
        return render_template('error.html', message=message)
    try:
        return render_template('fdc-report-results.html',
                               category=category,
                               fdc_round=fdc_round,
                               contents=results.decode('utf-8'))
    except UnicodeDecodeError, e:
        return render_template('error.html', message='Unicode error')
    except Exception, e:
        return render_template('error.html', message=e)

@app.route("/category-induced/submit", methods=["POST"])
def compute_category_induced():
    category = mw_util.str2cat(request.form['category'])
    try:
        ci = category_induced.CategoryInduced(category)
        ci.categories = ci.list_category()
        first_images = [ci.first_image(x) for x in ci.categories]
        first_images.sort()
        images_count = len(first_images)
        images = [x.decode('utf-8')[5:].replace(" ", "_")  for x in ci.list_images()]
        images_count = len(images)
        result = [first_images[x][0] for x in range(len(first_images)) if (len(first_images[x][1]) > 0 and first_images[x][1][0] in images)]
        result.sort()
        results_count = len(result)
        categories_traversed_count = len(first_images)
        contents = '\n'.join(result)
        return render_template('category-induced-result.html',
                               category=category,
                               images_count = images_count,
                               categories_count = categories_count,
                               results_count = results_count,
                               contents=contents)
    except Exception, e:
        return render_template('error.html', message=e)

@app.errorhandler(404)
def page_not_found(error):
    message = "Page does not exist."
    return render_template('error.html', message=message), 404

if __name__ == "__main__":
    app.run(debug=True)
<commit_msg>App: Variable reference bug<commit_after># -*- coding: latin-1 -*-
import os
import sys
from flask import Flask, render_template, request

current_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(current_dir, '..'))

from wm_metrics import fdc
from wm_metrics import wmfr_photography
from wm_metrics import commons_cat_metrics
from wm_metrics import category_induced
from wm_metrics import mw_util

app = Flask(__name__)

@app.route("/")
def index():
    return render_template('index.html')

@app.route("/fdc")
def fdc_report_page():
    return render_template('fdc-report.html')

@app.route("/category-induced")
def category_induced_page():
    return render_template('category-induced.html')

@app.route("/fdc/submit", methods=["POST"])
def compute_fdc_report():
    category = request.form['category']
    fdc_year = int(request.form['year'])
    round_num = int(request.form['round'])
    nb_uploaders_on = 'indicator-uploaders' in request.form
    nb_files_on = 'indicator-files' in request.form
    nb_labels_on = 'indicator-highlighted' in request.form
    pct_labels_on = 'indicator-highlighted_percentage' in request.form

    fdc_round = fdc.Round(fdc_year-1, fdc_year, round_num)
    results = 'Nothing'
    try:
        results = wmfr_photography.make_example_report(fdc_round, category,
                        nb_files_on=nb_files_on,
                        nb_labels_on=nb_labels_on,
                        nb_uploaders_on=nb_uploaders_on,
                        pct_labels_on=pct_labels_on)

    except wmfr_photography.WMmetricsException, e:
        message = 'Something went wrong in Wm_metrics: ' + e.message
        return render_template('error.html', message=message)
    try:
        return render_template('fdc-report-results.html',
                               category=category,
                               fdc_round=fdc_round,
                               contents=results.decode('utf-8'))
    except UnicodeDecodeError, e:
        return render_template('error.html', message='Unicode error')
    except Exception, e:
        return render_template('error.html', message=e)

@app.route("/category-induced/submit", methods=["POST"])
def compute_category_induced():
    category = mw_util.str2cat(request.form['category'])
    try:
        ci = category_induced.CategoryInduced(category)
        ci.categories = ci.list_category()
        first_images = [ci.first_image(x) for x in ci.categories]
        first_images.sort()
        categories_count = len(first_images)
        images = [x.decode('utf-8')[5:].replace(" ", "_")  for x in ci.list_images()]
        images_count = len(images)
        result = [first_images[x][0] for x in range(len(first_images)) if (len(first_images[x][1]) > 0 and first_images[x][1][0] in images)]
        result.sort()
        results_count = len(result)
        categories_traversed_count = len(first_images)
        contents = '\n'.join(result)
        return render_template('category-induced-result.html',
                               category=category,
                               images_count = images_count,
                               categories_count = categories_count,
                               results_count = results_count,
                               contents=contents)
    except Exception, e:
        return render_template('error.html', message=e)

@app.errorhandler(404)
def page_not_found(error):
    message = "Page does not exist."
    return render_template('error.html', message=message), 404

if __name__ == "__main__":
    app.run(debug=True)
<|endoftext|>


<commit_before>#!/usr/bin/env python2
# coding=UTF-8

"""
This script allows for a user to control the laser and PSU.

This script will grab the UID from an NFC tag, verify that the UID is granted
access to the laser, then let the user actually do so.
"""

####---- Imports ----####
from __future__ import print_function

import binascii
import time

import Adafruit_GPIO as GPIO
import Adafruit_PN532 as PN532

####---- Variables ----####
# BCM pins for various functions
## SPI
spi = dict(cs=8, mosi=10, miso=9, sclk=11)
## Relays and other outputs
out_pins = dict(laser=20, psu=21, grbl=27)

####---- Generic Functions ----####
def initialize_nfc_reader(CS=spi['cs'], MOSI=spi['mosi'], MISO=spi['miso'], SCLK=spi['sclk']):
    """Take in pin assignments, return class instance and firmware version"""

    reader = PN532.PN532(cs=CS, mosi=MOSI, miso=MISO, sclk=SCLK)
    success = False
    while not success:
        try:
            reader.begin()
            success = True
        except RuntimeError:
            print("Failed to detect reader. Check pin assignments and connections.")
            time.sleep(2)

    # Make sure reader is functioning
    ic, version, revision, support = reader.get_firmware_version()
    if (version is None) or (revision is None):
        print("Something went wrong")

    # Configure reader to accept Mifare cards (and all cards, really)
    configured = False
    while not configured:
        try:
            reader.SAM_configuration()
            configured = True
        except RuntimeError:
            print("Something went wrong during configuration.")
            time.sleep(2)

    return reader, "{}.{}.{}".format(version, revision, support)

def get_uid_block(reader):
    """Takes a reader object and returns the UID of a tag, stopping script until UID is returned"""
    uid = None
    while uid is None:
        uid = reader.read_passive_target()
        time.sleep(0.5) # Prevent script from taking too much CPU time
    return uid

def get_uid_noblock(reader):
    """Takes a reader object and returns the UID of a tag, even if it's None"""
    return reader.read_passive_target()

def _dummy_verify_uid(uid):
    """Takes a UID, verifies that it matches a dummy value, and returns True/False

    This is just a way of being able to check the other functions without
    having to implement the API calls yet (esp. since the API doesn't even
    exist yet)"""
    if uid is not None:
        return True
    else:
        return False

def verify_uid(uid):
    """Takes a UID, returns True/False depending on user permission"""

    return _dummy_verify_uid(uid) # No API to use yet for users

def gpio_setup():
    """Set up GPIO for use, returns Adafruit_GPIO class instance."""
    board = GPIO.get_platform_gpio()
    for item,pin in out_pins.iteritems():
        print("Setting pin {} to OUT".format(pin))
        try:
            board.setup(pin,GPIO.OUT)
        except:
            print("Something went wrong with setting up '{}' ({})".format(item,pin))

####---- Test print() ----####
#reader, version = initialize_nfc_reader()
#print("{}\n{}".format(reader, version))

#print(get_uid_noblock(reader))

#for uid in [None, True, False, 1234567, "user id str", binascii.unhexlify("deadbeef")]:
#    print("{}: {}".format(str(uid), verify_uid(uid)))

gpio_setup()
<commit_msg>Actually return the GPIO class instance<commit_after>#!/usr/bin/env python2
# coding=UTF-8

"""
This script allows for a user to control the laser and PSU.

This script will grab the UID from an NFC tag, verify that the UID is granted
access to the laser, then let the user actually do so.
"""

####---- Imports ----####
from __future__ import print_function

import binascii
import time

import Adafruit_GPIO as GPIO
import Adafruit_PN532 as PN532

####---- Variables ----####
# BCM pins for various functions
## SPI
spi = dict(cs=8, mosi=10, miso=9, sclk=11)
## Relays and other outputs
out_pins = dict(laser=20, psu=21, grbl=27)

####---- Generic Functions ----####
def initialize_nfc_reader(CS=spi['cs'], MOSI=spi['mosi'], MISO=spi['miso'], SCLK=spi['sclk']):
    """Take in pin assignments, return class instance and firmware version"""

    reader = PN532.PN532(cs=CS, mosi=MOSI, miso=MISO, sclk=SCLK)
    success = False
    while not success:
        try:
            reader.begin()
            success = True
        except RuntimeError:
            print("Failed to detect reader. Check pin assignments and connections.")
            time.sleep(2)

    # Make sure reader is functioning
    ic, version, revision, support = reader.get_firmware_version()
    if (version is None) or (revision is None):
        print("Something went wrong")

    # Configure reader to accept Mifare cards (and all cards, really)
    configured = False
    while not configured:
        try:
            reader.SAM_configuration()
            configured = True
        except RuntimeError:
            print("Something went wrong during configuration.")
            time.sleep(2)

    return reader, "{}.{}.{}".format(version, revision, support)

def get_uid_block(reader):
    """Takes a reader object and returns the UID of a tag, stopping script until UID is returned"""
    uid = None
    while uid is None:
        uid = reader.read_passive_target()
        time.sleep(0.5) # Prevent script from taking too much CPU time
    return uid

def get_uid_noblock(reader):
    """Takes a reader object and returns the UID of a tag, even if it's None"""
    return reader.read_passive_target()

def _dummy_verify_uid(uid):
    """Takes a UID, verifies that it matches a dummy value, and returns True/False

    This is just a way of being able to check the other functions without
    having to implement the API calls yet (esp. since the API doesn't even
    exist yet)"""
    if uid is not None:
        return True
    else:
        return False

def verify_uid(uid):
    """Takes a UID, returns True/False depending on user permission"""

    return _dummy_verify_uid(uid) # No API to use yet for users

def gpio_setup():
    """Set up GPIO for use, returns Adafruit_GPIO class instance."""
    board = GPIO.get_platform_gpio()
    for item,pin in out_pins.iteritems():
        print("Setting pin {} to OUT".format(pin))
        try:
            board.setup(pin,GPIO.OUT)
        except:
            print("Something went wrong with setting up '{}' ({})".format(item,pin))
    return board

####---- Test print() ----####
#reader, version = initialize_nfc_reader()
#print("{}\n{}".format(reader, version))

#print(get_uid_noblock(reader))

#for uid in [None, True, False, 1234567, "user id str", binascii.unhexlify("deadbeef")]:
#    print("{}: {}".format(str(uid), verify_uid(uid)))

board = gpio_setup()
print(board)
<|endoftext|>


<commit_before>import serial

class LCDInterface():

    def __init__(self, operation_mode="hardware"):
        self.operation_mode = operation_mode
        self.lcdCom = serial.Serial
            (
             port="/dev/serial0",
             baudrate=9600,
             parity=serial.PARITY_NONE,
             stopbits=serial.STOPBITS_ONE,
             bytesize=serial.EIGHTBITS,
             timeout=1
            )

    def display(self, first_line, second_line):
        if (self.operation_mode=="hardware"):
            print("To hardware: {}".format(first_line))
            print("To hardware: {}".format(second_line))
        else:
            print(first_line)
            print(second_line)

    def clear():
        self.lcdCom.write(b"\xFE\x01")
        self.lcdCom.write(bytes("                ", "ASCII"))
        self.lcdCom.write(bytes("                ", "ASCII"))

    def dPrint():
        self.lcdCom.write(b"\xFE\x01")
        self.lcdCom.write(bytes("Line 1", "ASCII"))
        self.lcdCom.write(bytes("Line 2", "ASCII"))

    def close():
        self.lcdCom.close()
<commit_msg>fixed lcd test<commit_after>import serial

class LCDInterface():

    def __init__(self, operation_mode="hardware"):

        if (self.operation_mode == "hardware"):
            self.lcdCom = serial.Serial
                (
                port="/dev/serial0",
                baudrate=9600,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS,
                timeout=1
                )

    def display(self, first_line, second_line):
        if len(first_line) > 16:
            raise ValueError("First line of text can not be more than 16 characters")
        if len(second_line) > 16:
            raise ValueError("Second line of text can not be more than 16 characters")

        if (self.operation_mode=="hardware"):
            self.lcdCom.write(b"\xFE\x01")
            self.lcdCom.write(bytes(first_line, "ASCII"))
            self.lcdCom.write(bytes(second_line, "ASCII"))
        else:
            print(first_line)
            print(second_line)

    def clear(self):
        if (self.operation_mode == "hardware"):
            self.lcdCom.write(b"\xFE\x01")
            self.lcdCom.write(bytes("                ", "ASCII"))
            self.lcdCom.write(bytes("                ", "ASCII"))

    def close(self):
        if (self.operation_mode == "hardware"):
            self.lcdCom.close()
<|endoftext|>


<commit_before>from coroutine import Coroutine
import inspect
import smtplib
import socket
import types
import time
import sys

EXCEPTION = "EXCEPTION"
CRITICAL = "CRITICAL"
ERROR = "ERROR"
WARNING = "WARNING"
INFO = "INFO"
ALL = [EXCEPTION, CRITICAL, ERROR, WARNING, INFO]

class Lggr():
	""" Simplified logging. Dispatches messages to any type of
		logging function you want to write, all it has to support
		is send() and close(). """
	def __init__(self):
		self.config = {
				EXCEPTION: set(),
				CRITICAL: set(),
				ERROR: set(),
				WARNING: set(),
				INFO: set()
			}
		self.history = []
		self.enabled = True

	def disable(self):
		""" Turn off logging. """
		self.enabled = False

	def enable(self):
		""" Turn on logging. Enabled by default. """
		self.enabled = True

	def close(self):
		for level in ALL:
			self.clear(level)

	def add(self, levels, logger):
		""" Given a list of logging levels, add a logger
			instance to each. """
		for lvl in levels:
			self.config[lvl].add(logger)

	def remove(self, level, logger):
		""" Given a level, remove a given logger function
			if it is a member of that level, closing the logger
			function either way."""
		self.config[level].discard(logger)
		logger.close()

	def clear(self, level):
		""" Remove all logger functions from a given level. """
		for item in self.config[level]:
			item.close()
		self.config[level].clear()

	def log(self, levels, fmt, *args, **kwargs):
		""" Send a log message to all of the logging functions
			for each level in a given list, as well as adding the
			message to this logger instance's history. """
		if not self.enabled:
			return # Fail silently so that logging can easily be removed

		message = fmt.format(*args, **kwargs)

		for lvl_name in levels:
			self.history.append((time.time(), lvl_name, message))
			log_funcs = self.config[lvl_name]
			for lf in log_funcs.copy(): # so that we can edit the original while iterating
				try:
					lf.send(message)
				except StopIteration: # already closed
					self.remove(lvl_name, lf)
					self.info("Logging function {} in level {} stopped.", lf, lvl_name)

	def critical(self, msg, *args, **kwargs):
		""" Log a message with CRITICAL level """
		self.log([CRITICAL], msg, *args, **kwargs)

	def error(self, msg, *args, **kwargs):
		""" Log a message with ERROR level """
		self.log([ERROR], msg, *args, **kwargs)

	def warning(self, msg, *args, **kwargs):
		""" Log a message with WARNING level """
		self.log([WARNING], msg, *args, **kwargs)

	def info(self, msg, *args, **kwargs):
		""" Log a message with INFO level """
		self.log([INFO], msg, *args, **kwargs)
	def all(self, msg, *args, **kwargs):
		""" Log a message at all levels """
		self.log(ALL, msg, *args, **kwargs)

@Coroutine
def Printer(open_file=sys.stdout, closing=False):
	""" Prints items with a timestamp. """
	message = "({0}): {1}\n"
	try:
		while True:
			item = (yield)
			open_file.write(message.format(time.asctime(), item))
	except GeneratorExit:
		if closing:
			try: open_file.close()
			except: pass

def StderrPrinter():
	""" Prints items to stderr. """
	return Printer(open_file=sys.stderr, closing=False)

def FilePrinter(filename, mode='a', closing=True):
	""" Opens the given file and returns a printer to it. """
	f = open(filename, mode)
	return Printer(f, closing)

@Coroutine
def SocketWriter(host, port, af=socket.AF_INET, st=socket.SOCK_STREAM):
	""" Writes messages to a socket/host. """
	message = "({0}): {1}"
	s = socket.socket(af, st)
	s.connect(host, port)
	try:
		while True:
			item = (yield)
			s.send(message.format(time.asctime(), item))
	except GeneratorExit:
		s.close()

@Coroutine
def Emailer(recipients, sender=None):
	""" Sends messages as emails to the given list
		of recipients. """
	hostname = socket.gethostname()
	sender = "lggr@{}".format(hostname)
	smtp = smtplib.SMTP('localhost')
	try:
		while True:
			item = (yield)
			try:
				smtp.sendmail(sender, recipients, item)
			except smtplib.SMTPExcpetion:
				pass
	except GeneratorExit:
		smtp.quit()
<commit_msg>Stops ignoring sender addresses passed to Emailer<commit_after>from coroutine import Coroutine
import inspect
import smtplib
import socket
import types
import time
import sys

EXCEPTION = "EXCEPTION"
CRITICAL = "CRITICAL"
ERROR = "ERROR"
WARNING = "WARNING"
INFO = "INFO"
ALL = [EXCEPTION, CRITICAL, ERROR, WARNING, INFO]

class Lggr():
	""" Simplified logging. Dispatches messages to any type of
		logging function you want to write, all it has to support
		is send() and close(). """
	def __init__(self):
		self.config = {
				EXCEPTION: set(),
				CRITICAL: set(),
				ERROR: set(),
				WARNING: set(),
				INFO: set()
			}
		self.history = []
		self.enabled = True

	def disable(self):
		""" Turn off logging. """
		self.enabled = False

	def enable(self):
		""" Turn on logging. Enabled by default. """
		self.enabled = True

	def close(self):
		for level in ALL:
			self.clear(level)

	def add(self, levels, logger):
		""" Given a list of logging levels, add a logger
			instance to each. """
		for lvl in levels:
			self.config[lvl].add(logger)

	def remove(self, level, logger):
		""" Given a level, remove a given logger function
			if it is a member of that level, closing the logger
			function either way."""
		self.config[level].discard(logger)
		logger.close()

	def clear(self, level):
		""" Remove all logger functions from a given level. """
		for item in self.config[level]:
			item.close()
		self.config[level].clear()

	def log(self, levels, fmt, *args, **kwargs):
		""" Send a log message to all of the logging functions
			for each level in a given list, as well as adding the
			message to this logger instance's history. """
		if not self.enabled:
			return # Fail silently so that logging can easily be removed

		message = fmt.format(*args, **kwargs)

		for lvl_name in levels:
			self.history.append((time.time(), lvl_name, message))
			log_funcs = self.config[lvl_name]
			for lf in log_funcs.copy(): # so that we can edit the original while iterating
				try:
					lf.send(message)
				except StopIteration: # already closed
					self.remove(lvl_name, lf)
					self.info("Logging function {} in level {} stopped.", lf, lvl_name)

	def critical(self, msg, *args, **kwargs):
		""" Log a message with CRITICAL level """
		self.log([CRITICAL], msg, *args, **kwargs)

	def error(self, msg, *args, **kwargs):
		""" Log a message with ERROR level """
		self.log([ERROR], msg, *args, **kwargs)

	def warning(self, msg, *args, **kwargs):
		""" Log a message with WARNING level """
		self.log([WARNING], msg, *args, **kwargs)

	def info(self, msg, *args, **kwargs):
		""" Log a message with INFO level """
		self.log([INFO], msg, *args, **kwargs)
	def all(self, msg, *args, **kwargs):
		""" Log a message at all levels """
		self.log(ALL, msg, *args, **kwargs)

@Coroutine
def Printer(open_file=sys.stdout, closing=False):
	""" Prints items with a timestamp. """
	message = "({0}): {1}\n"
	try:
		while True:
			item = (yield)
			open_file.write(message.format(time.asctime(), item))
	except GeneratorExit:
		if closing:
			try: open_file.close()
			except: pass

def StderrPrinter():
	""" Prints items to stderr. """
	return Printer(open_file=sys.stderr, closing=False)

def FilePrinter(filename, mode='a', closing=True):
	""" Opens the given file and returns a printer to it. """
	f = open(filename, mode)
	return Printer(f, closing)

@Coroutine
def SocketWriter(host, port, af=socket.AF_INET, st=socket.SOCK_STREAM):
	""" Writes messages to a socket/host. """
	message = "({0}): {1}"
	s = socket.socket(af, st)
	s.connect(host, port)
	try:
		while True:
			item = (yield)
			s.send(message.format(time.asctime(), item))
	except GeneratorExit:
		s.close()

@Coroutine
def Emailer(recipients, sender=None):
	""" Sends messages as emails to the given list
		of recipients. """
	hostname = socket.gethostname()
	if not sender:
		sender = "lggr@{}".format(hostname)
	smtp = smtplib.SMTP('localhost')
	try:
		while True:
			item = (yield)
			try:
				smtp.sendmail(sender, recipients, item)
			except smtplib.SMTPExcpetion:
				pass
	except GeneratorExit:
		smtp.quit()
<|endoftext|>