<commit_before>#!/usr/bin/env python

# This isn't needed unless python_server=gevent is set.
# If we are running with gevent, then this is required.
try:
    import gevent.monkey
    gevent.monkey.patch_all()
except:
    pass

import bottle
import modules.kwlinker

from pygments import highlight
from pygments.lexers import *
from pygments.formatters import HtmlFormatter

import binascii
import ConfigParser
import difflib
import json
import Mollom
import os
import re
import redis
import socket

# Load Settings
conf = ConfigParser.SafeConfigParser({
    'cache_host': 'localhost',
    'cache_db': 0,
    'port': 80,
    'root_path': '.',
    'url': None,
    'relay_enabled': True,
    'relay_chan': None,
    'relay_admin_chan': None,
    'check_spam': True,
    'mollom_pub_key': None,
    'mollom_priv_key': None,
    'python_server': 'auto'})
conf.read('conf/settings.cfg')

app = application = bottle.Bottle()
cache = redis.Redis(host=conf.get('bottle', 'cache_host'), db=int(conf.get('bottle', 'cache_db')))

@app.route('/static/<filename:path>')
def static(filename):
    '''
    Serve static files
    '''
    return bottle.static_file(filename, root='{}/static'.format(conf.get('bottle', 'root_path')))

@app.error(500)
@app.error(404)
def errors(code):
    '''
    Handler for errors
    '''
    return bottle.jinja2_template('error.html', code=code)

@app.route('/')
def new_paste():
    '''
    Display page for new empty post
    '''
    data = {
        'name': '',
        'syntax': 'nginx',
        'private': '0'}
    dat = bottle.request.cookies.get('dat', False)
    if dat:
        data = json.loads(dat)
        data['private'] = str(str2int(data['private']))
    return bottle.jinja2_template('paste.html', data=data)

@app.route('/f/<paste_id>')
def new_fork(paste_id):
    '''
    Display page for new fork from a paste
    '''
    if not cache.exists(paste_id):
        bottle.redirect('/')

    data = json.loads(cache.get(paste_id))
    data['paste_id'] = paste_id
    data['title'] = 're: ' + data['title'][:32]
    data['private'] = str(str2int(data['private']))

    dat = bottle.request.cookies.get('dat', False)
    if dat:
        d = json.loads(dat)
        data['name'] = d['name']

    return bottle.jinja2_template('paste.html', data=data)

@app.route('/', method='POST')
def submit_paste():
    '''
    Put a new paste into the database
    '''
    r = re.compile('^[- !$%^&*()_+|~=`{}\[\]:";\'<>?,.\/a-zA-Z0-9]{1,48}$')
    paste = {
        #'code': bottle.request.POST.get('code', '').strip(),
        'code': bottle.request.POST.get('code', ''),
        'title': bottle.request.POST.get('title', '').strip(),
        'name': bottle.request.POST.get('name', '').strip(),
        'private': bottle.request.POST.get('private', '0').strip(),
        'syntax': bottle.request.POST.get('syntax', '').strip(),
        'forked_from': bottle.request.POST.get('forked_from', '').strip()}

    # Validate data
    if max(0, bottle.request.content_length) > bottle.request.MEMFILE_MAX:
        return bottle.jinja2_template('error.html', code=200, message='This request is too large to process.')
    for k in ['code', 'private', 'syntax', 'title', 'name']:
        if paste[k] == '':
            return bottle.jinja2_template('error.html', code=200, message='All fields need to be filled out.')
    for k in ['title', 'name']:
        if not r.match(paste[k]):
            return bottle.jinja2_template('error.html', code=200, message='Invalid input detected.')

    # Check post for spam
    if bottle.request.POST.get('phone', '').strip() != '':
        return bottle.jinja2_template('error.html', code=200, message='Your post triggered our spam filters!')
    if str2bool(conf.get('bottle', 'check_spam')):
        if not spam_free(paste['code']):
            return bottle.jinja2_template('error.html', code=200, message='Your post triggered our spam filters!')

    # Public pastes should have an easy to type key
    # Private pastes should have a more secure key
    id_length = 1
    if str2bool(paste['private']):
        id_length = 8

    # Pick a unique ID
    paste_id = binascii.b2a_hex(os.urandom(id_length))

    # Make sure it's actually unique or else create a new one and test again
    while cache.exists(paste_id):
        id_length += 1
        paste_id = binascii.b2a_hex(os.urandom(id_length))

    cache.set(paste_id, json.dumps(paste))
    cache.expire(paste_id, 345600)

    dat = {
      'name': str(paste['name']),
      'syntax': str(paste['syntax']),
      'private': str(paste['private'])}
    bottle.response.set_cookie('dat', json.dumps(dat))

    if str2bool(conf.get('bottle', 'relay_enabled')):
        send_irc(paste, paste_id)

    bottle.redirect('/' + paste_id)

@app.route('/<paste_id>')
def view_paste(paste_id):
    '''
    Return page with paste_id
    '''
    if not cache.exists(paste_id):
        bottle.redirect('/')

    p = json.loads(cache.get(paste_id))

    # Syntax hilighting
    try:
        lexer = get_lexer_by_name(p['syntax'], stripall=True)
    except:
        lexer = get_lexer_by_name('text', stripall=True)
    formatter = HtmlFormatter(linenos=True, cssclass="paste")
    linker = modules.kwlinker.get_linker_by_name(p['syntax'])
    if None != linker:
        lexer.add_filter(linker)
        p['code'] = highlight(p['code'], lexer, formatter)
        p['code'] = modules.kwlinker.replace_markup(p['code'])
    else:
        p['code'] = highlight(p['code'], lexer, formatter)
    p['css'] = HtmlFormatter().get_style_defs('.code')

    return bottle.jinja2_template('view.html', paste=p, pid=paste_id)

@app.route('/r/<paste_id>')
def view_raw(paste_id):
    '''
    View raw paste with paste_id
    '''
    if not cache.exists(paste_id):
        bottle.redirect('/')

    p = json.loads(cache.get(paste_id))

    return bottle.jinja2_template('raw.html', code=p['code'])

@app.route('/d/<orig>/<fork>')
def view_diff(orig, fork):
    '''
    View the diff between a paste and what it was forked from
    '''
    if not cache.exists(orig) or not cache.exists(fork):
        return bottle.jinja2_template('error.html', code=200, message='One of the pastes could not be found.')

    po = json.loads(cache.get(orig))
    pf = json.loads(cache.get(fork))
    #co = bottle.html_escape(po['code']).split()
    co = po['code'].split('\n')
    #cf = bottle.html_escape(pf['code']).split()
    cf = pf['code'].split('\n')
    lo = '' + orig + ''
    lf = '' + fork + ''

    diff = difflib.HtmlDiff().make_table(co, cf, lo, lf)
    return bottle.jinja2_template('page.html', data=diff)

@app.route('/about')
def show_about():
    '''
    Return the information page
    '''
    return bottle.jinja2_template('about.html')

def spam_free(content):
    '''
    Checks if content is spam free. Returns True if no spam is found.
    '''
    mollom_api = Mollom.MollomAPI(
        publicKey=conf.get('bottle', 'mollom_pub_key'),
        privateKey=conf.get('bottle', 'mollom_priv_key'))
    if not mollom_api.verifyKey():
        return False

    cc = mollom_api.checkContent(postBody=content)
    # cc['spam']: 1 for ham, 2 for spam, 3 for unsure;
    if cc['spam'] == 2:
        return False
    if cc['spam'] == 3:
        return False
    return True

def send_irc(paste, paste_id):
    '''
    Send notification to channels
    '''
    host = conf.get('bottle', 'relay_host')
    port = int(conf.get('bottle', 'relay_port'))

    # Build the message to send to the channel
    if paste['forked_from']:
        orig = json.loads(cache.get(paste['forked_from']))
        message = ''.join(['Paste from ', orig['name'],
            ' forked by ', paste['name'], ': [ ',
            conf.get('bottle', 'url'), paste_id, ' ] - ', paste['title']])
    else:
        message = ''.join(['Paste from ', paste['name'], ': [ ',
            conf.get('bottle', 'url'), paste_id, ' ] - ', paste['title']])

    # Get list of relay channels
    # Always admin channels, only normal channels if paste is not private
    channels = conf.get('bottle', 'relay_admin_chan')
    if not str2bool(paste['private']):
        channels = ''.join([channels, ',', conf.get('bottle', 'relay_chan')])

    # For each channel, send the relay server a message
    for channel in channels.split(','):
        nc_msg = ''.join([channel, ' ', message])
        netcat(host, port, nc_msg)

def netcat(hostname, port, content):
    '''
    Basic netcat functionality using sockets
    '''
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((hostname, port))
    s.sendall(content)
    s.shutdown(socket.SHUT_WR)
    s.close()

def str2bool(v):
    '''
    Convert string to boolean
    '''
    return v.lower() in ('yes', 'true', 't', 'y', '1', 'on')

def str2int(v):
    '''
    Convert string to boolean to integer
    '''
    return int(v.lower() in ('yes', 'true', 't', 'y', '1', 'on'))

class StripPathMiddleware(object):
    '''
    Get that leading slash out of the request
    '''
    def __init__(self, a):
        self.a = a
    def __call__(self, e, h):
        e['PATH_INFO'] = e['PATH_INFO'].rstrip('/')
        return self.a(e, h)

if __name__ == '__main__':
    bottle.run(app=StripPathMiddleware(app),
        server=conf.get('bottle', 'python_server'),
        host='0.0.0.0',
        port=conf.getint('bottle', 'port'))
<commit_msg>Finished not trimming spaces.<commit_after>#!/usr/bin/env python

# This isn't needed unless python_server=gevent is set.
# If we are running with gevent, then this is required.
try:
    import gevent.monkey
    gevent.monkey.patch_all()
except:
    pass

import bottle
import modules.kwlinker

from pygments import highlight
from pygments.lexers import *
from pygments.formatters import HtmlFormatter

import binascii
import ConfigParser
import difflib
import json
import Mollom
import os
import re
import redis
import socket

# Load Settings
conf = ConfigParser.SafeConfigParser({
    'cache_host': 'localhost',
    'cache_db': 0,
    'port': 80,
    'root_path': '.',
    'url': None,
    'relay_enabled': True,
    'relay_chan': None,
    'relay_admin_chan': None,
    'check_spam': True,
    'mollom_pub_key': None,
    'mollom_priv_key': None,
    'python_server': 'auto'})
conf.read('conf/settings.cfg')

app = application = bottle.Bottle()
cache = redis.Redis(host=conf.get('bottle', 'cache_host'), db=int(conf.get('bottle', 'cache_db')))

@app.route('/static/<filename:path>')
def static(filename):
    '''
    Serve static files
    '''
    return bottle.static_file(filename, root='{}/static'.format(conf.get('bottle', 'root_path')))

@app.error(500)
@app.error(404)
def errors(code):
    '''
    Handler for errors
    '''
    return bottle.jinja2_template('error.html', code=code)

@app.route('/')
def new_paste():
    '''
    Display page for new empty post
    '''
    data = {
        'name': '',
        'syntax': 'nginx',
        'private': '0'}
    dat = bottle.request.cookies.get('dat', False)
    if dat:
        data = json.loads(dat)
        data['private'] = str(str2int(data['private']))
    return bottle.jinja2_template('paste.html', data=data)

@app.route('/f/<paste_id>')
def new_fork(paste_id):
    '''
    Display page for new fork from a paste
    '''
    if not cache.exists(paste_id):
        bottle.redirect('/')

    data = json.loads(cache.get(paste_id))
    data['paste_id'] = paste_id
    data['title'] = 're: ' + data['title'][:32]
    data['private'] = str(str2int(data['private']))

    dat = bottle.request.cookies.get('dat', False)
    if dat:
        d = json.loads(dat)
        data['name'] = d['name']

    return bottle.jinja2_template('paste.html', data=data)

@app.route('/', method='POST')
def submit_paste():
    '''
    Put a new paste into the database
    '''
    r = re.compile('^[- !$%^&*()_+|~=`{}\[\]:";\'<>?,.\/a-zA-Z0-9]{1,48}$')
    paste = {
        #'code': bottle.request.POST.get('code', '').strip(),
        'code': bottle.request.POST.get('code', ''),
        'title': bottle.request.POST.get('title', '').strip(),
        'name': bottle.request.POST.get('name', '').strip(),
        'private': bottle.request.POST.get('private', '0').strip(),
        'syntax': bottle.request.POST.get('syntax', '').strip(),
        'forked_from': bottle.request.POST.get('forked_from', '').strip()}

    # Validate data
    if max(0, bottle.request.content_length) > bottle.request.MEMFILE_MAX:
        return bottle.jinja2_template('error.html', code=200, message='This request is too large to process.')
    for k in ['code', 'private', 'syntax', 'title', 'name']:
        if paste[k] == '':
            return bottle.jinja2_template('error.html', code=200, message='All fields need to be filled out.')
    for k in ['title', 'name']:
        if not r.match(paste[k]):
            return bottle.jinja2_template('error.html', code=200, message='Invalid input detected.')

    # Check post for spam
    if bottle.request.POST.get('phone', '').strip() != '':
        return bottle.jinja2_template('error.html', code=200, message='Your post triggered our spam filters!')
    if str2bool(conf.get('bottle', 'check_spam')):
        if not spam_free(paste['code']):
            return bottle.jinja2_template('error.html', code=200, message='Your post triggered our spam filters!')

    # Public pastes should have an easy to type key
    # Private pastes should have a more secure key
    id_length = 1
    if str2bool(paste['private']):
        id_length = 8

    # Pick a unique ID
    paste_id = binascii.b2a_hex(os.urandom(id_length))

    # Make sure it's actually unique or else create a new one and test again
    while cache.exists(paste_id):
        id_length += 1
        paste_id = binascii.b2a_hex(os.urandom(id_length))

    cache.set(paste_id, json.dumps(paste))
    cache.expire(paste_id, 345600)

    dat = {
      'name': str(paste['name']),
      'syntax': str(paste['syntax']),
      'private': str(paste['private'])}
    bottle.response.set_cookie('dat', json.dumps(dat))

    if str2bool(conf.get('bottle', 'relay_enabled')):
        send_irc(paste, paste_id)

    bottle.redirect('/' + paste_id)

@app.route('/<paste_id>')
def view_paste(paste_id):
    '''
    Return page with paste_id
    '''
    if not cache.exists(paste_id):
        bottle.redirect('/')

    p = json.loads(cache.get(paste_id))

    # Syntax hilighting
    try:
        lexer = get_lexer_by_name(p['syntax'], stripall=False)
    except:
        lexer = get_lexer_by_name('text', stripall=False)
    formatter = HtmlFormatter(linenos=True, cssclass="paste")
    linker = modules.kwlinker.get_linker_by_name(p['syntax'])
    if None != linker:
        lexer.add_filter(linker)
        p['code'] = highlight(p['code'], lexer, formatter)
        p['code'] = modules.kwlinker.replace_markup(p['code'])
    else:
        p['code'] = highlight(p['code'], lexer, formatter)
    p['css'] = HtmlFormatter().get_style_defs('.code')

    return bottle.jinja2_template('view.html', paste=p, pid=paste_id)

@app.route('/r/<paste_id>')
def view_raw(paste_id):
    '''
    View raw paste with paste_id
    '''
    if not cache.exists(paste_id):
        bottle.redirect('/')

    p = json.loads(cache.get(paste_id))

    return bottle.jinja2_template('raw.html', code=p['code'])

@app.route('/d/<orig>/<fork>')
def view_diff(orig, fork):
    '''
    View the diff between a paste and what it was forked from
    '''
    if not cache.exists(orig) or not cache.exists(fork):
        return bottle.jinja2_template('error.html', code=200, message='One of the pastes could not be found.')

    po = json.loads(cache.get(orig))
    pf = json.loads(cache.get(fork))
    #co = bottle.html_escape(po['code']).split()
    co = po['code'].split('\n')
    #cf = bottle.html_escape(pf['code']).split()
    cf = pf['code'].split('\n')
    lo = '' + orig + ''
    lf = '' + fork + ''

    diff = difflib.HtmlDiff().make_table(co, cf, lo, lf)
    return bottle.jinja2_template('page.html', data=diff)

@app.route('/about')
def show_about():
    '''
    Return the information page
    '''
    return bottle.jinja2_template('about.html')

def spam_free(content):
    '''
    Checks if content is spam free. Returns True if no spam is found.
    '''
    mollom_api = Mollom.MollomAPI(
        publicKey=conf.get('bottle', 'mollom_pub_key'),
        privateKey=conf.get('bottle', 'mollom_priv_key'))
    if not mollom_api.verifyKey():
        return False

    cc = mollom_api.checkContent(postBody=content)
    # cc['spam']: 1 for ham, 2 for spam, 3 for unsure;
    if cc['spam'] == 2:
        return False
    if cc['spam'] == 3:
        return False
    return True

def send_irc(paste, paste_id):
    '''
    Send notification to channels
    '''
    host = conf.get('bottle', 'relay_host')
    port = int(conf.get('bottle', 'relay_port'))

    # Build the message to send to the channel
    if paste['forked_from']:
        orig = json.loads(cache.get(paste['forked_from']))
        message = ''.join(['Paste from ', orig['name'],
            ' forked by ', paste['name'], ': [ ',
            conf.get('bottle', 'url'), paste_id, ' ] - ', paste['title']])
    else:
        message = ''.join(['Paste from ', paste['name'], ': [ ',
            conf.get('bottle', 'url'), paste_id, ' ] - ', paste['title']])

    # Get list of relay channels
    # Always admin channels, only normal channels if paste is not private
    channels = conf.get('bottle', 'relay_admin_chan')
    if not str2bool(paste['private']):
        channels = ''.join([channels, ',', conf.get('bottle', 'relay_chan')])

    # For each channel, send the relay server a message
    for channel in channels.split(','):
        nc_msg = ''.join([channel, ' ', message])
        netcat(host, port, nc_msg)

def netcat(hostname, port, content):
    '''
    Basic netcat functionality using sockets
    '''
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((hostname, port))
    s.sendall(content)
    s.shutdown(socket.SHUT_WR)
    s.close()

def str2bool(v):
    '''
    Convert string to boolean
    '''
    return v.lower() in ('yes', 'true', 't', 'y', '1', 'on')

def str2int(v):
    '''
    Convert string to boolean to integer
    '''
    return int(v.lower() in ('yes', 'true', 't', 'y', '1', 'on'))

class StripPathMiddleware(object):
    '''
    Get that leading slash out of the request
    '''
    def __init__(self, a):
        self.a = a
    def __call__(self, e, h):
        e['PATH_INFO'] = e['PATH_INFO'].rstrip('/')
        return self.a(e, h)

if __name__ == '__main__':
    bottle.run(app=StripPathMiddleware(app),
        server=conf.get('bottle', 'python_server'),
        host='0.0.0.0',
        port=conf.getint('bottle', 'port'))
<|endoftext|>


<commit_before>#! /usr/bin/env python
# coding: utf-8
from __future__ import unicode_literals, print_function

import datetime as dt
import time
import traceback
import sys

import MySQLdb
from slackclient import SlackClient

import config
import droppics
import gargquotes

slack_client = SlackClient(config.token)

users = {
    'U33PQTYBV': 'asmundboe',
    'U34DL838S': 'cmr',
    'U33TL3BQC': 'eirki',
    'U34HTUHN2': 'gargbot_3000',
    'U346NSERJ': 'gromsten',
    'U33SRCHB5': 'kenlee',
    'U336SL64Q': 'lbs',
    'U34FMDVTN': 'nils',
    'U34FXQLUD': 'smorten',
    'USLACKBOT': 'slackbot'
}

def handle_command(command, channel, user):
    print(dt.datetime.now())
    command = command.strip()
    print("command: %s" % command)
    if command.startswith("ping"):
        response = {"text": "GargBot 3000 is active. Beep boop beep"}

    elif command.startswith("quote"):
        try:
            user = command.split()[1]
            response = {"text": garg_quotes.quote(user)}
        except IndexError:
            response = {"text": garg_quotes.quote()}

    elif command.startswith("pic"):
        try:
            topic = command.split()[1]
            pic = garg_quotes.get_pic(topic)
        except IndexError:
            pic = garg_quotes.get_pic()
        response = {"attachments": [{"fallback":  pic, "image_url": pic}]}

    elif command.startswith("/random"):
        response = {"attachments": [{"fallback":  garg_quotes.random(), "image_url": garg_quotes.random()}]}

    elif command.startswith("vidoi"):
        response = response = {"text": garg_quotes.vidoi()}

    elif command.startswith(("hei", "hallo", "hello", "morn")):
        response = {"text": "Blëep bloöp, hallo %s!" % users.get(user, "")}

    else:
        response = {"text": ("Beep boop beep! Nôt sure whåt you mean by %s. Dette er kommandoene jeg skjønner:\n"
                             "@gargbot_3000 *pic* [lark/fe/skating] - (viser tilfedlig Larkollen/Forsterka Enhet/skate bilde)\n"
                             "@gargbot_3000 *quote* [garling] (henter tilfedlig sitat fra forumet)\n"
                             "@gargbot_3000 *vidoi* (viser tilfedlig musikkvideo fra muzakvidois tråden på forumet\n"
                             "@gargbot_3000 */random* (viser tilfedlig bilde fra \\random tråden på forumet\n"
                             % command)}

    slack_client.api_call("chat.postMessage", channel=channel, as_user=True, **response)
    print("response: %s" % response)

def parse_slack_output(slack_rtm_output):
    """
        The Slack Real Time Messaging API is an events firehose.
        this parsing function returns None unless a message is
        directed at the Bot, based on its ID.
    """
    AT_BOT = "<@%s>" % config.bot_id
    output_list = slack_rtm_output
    if output_list and len(output_list) > 0:
        for output in output_list:
            if output and 'text' in output and AT_BOT in output['text']:
                return output['text'].replace(AT_BOT, "").strip().lower(), output['channel'], output["user"]
    return None, None, None

def panic():
    text = "Error, error! Noe har gått fryktelig galt! Ææææææ. Ta kontakt med systemadministrator ummidelbart, før det er for sent. HJELP MEG. If I don't survive, tell mrs. gargbot... 'Hello'"
    slack_client.api_call("chat.postMessage", channel=channel, as_user=True, text=text)

if __name__ == "__main__":
    garg_quotes = gargquotes.GargQuotes()
    garg_quotes.connect()

    drop_pics = droppics.DropPics()
    drop_pics.connect()
    drop_pics.load_img_paths()

    if slack_client.rtm_connect():
        print("GargBot 3000 is operational!")
        try:
            while True:
                command, channel, user = parse_slack_output(slack_client.rtm_read())
                if command and channel:
                    try:
                        handle_command(command, channel, user)
                    except MySQLdb.Error:
                        garg_quotes.connect()
                        handle_command(command, channel, user)
                    except:
                        traceback.print_exc()
                        panic()
                time.sleep(1)
        except KeyboardInterrupt:
            sys.exit()
        finally:
            garg_quotes.teardown()
    else:
        print("Connection failed. Invalid Slack token or bot ID?")
<commit_msg>Refactor main loop from global scope to func<commit_after>#! /usr/bin/env python
# coding: utf-8
from __future__ import unicode_literals, print_function

import datetime as dt
import time
import traceback
import sys

import MySQLdb
from slackclient import SlackClient

import config
import droppics
import gargquotes

users = {
    'U33PQTYBV': 'asmundboe',
    'U34DL838S': 'cmr',
    'U33TL3BQC': 'eirki',
    'U34HTUHN2': 'gargbot_3000',
    'U346NSERJ': 'gromsten',
    'U33SRCHB5': 'kenlee',
    'U336SL64Q': 'lbs',
    'U34FMDVTN': 'nils',
    'U34FXQLUD': 'smorten',
    'USLACKBOT': 'slackbot'
}

def filter_slack_output(slack_rtm_output):
    """
        The Slack Real Time Messaging API is an events firehose.
        this parsing function returns None unless a message is
        directed at the Bot, based on its ID.
    """
    AT_BOT = "<@%s>" % config.bot_id
    output_list = slack_rtm_output
    if output_list and len(output_list) > 0:
        for output in output_list:
            if output and 'text' in output and AT_BOT in output['text']:
                return output['text'].replace(AT_BOT, "").strip().lower(), output['channel'], output["user"]
    return None, None, None

def command_handler_wrapper(garg_quotes, drop_pics):
    def handle_command(command, channel, user):
        print(dt.datetime.now())
        command = command.strip()
        print("command: %s" % command)
        if command.startswith("ping"):
            response = {"text": "GargBot 3000 is active. Beep boop beep"}

        elif command.startswith("quote"):
            try:
                user = command.split()[1]
                response = {"text": garg_quotes.quote(user)}
            except IndexError:
                response = {"text": garg_quotes.quote()}

        elif command.startswith("pic"):
            try:
                topic = command.split()[1]
                pic = drop_pics.get_pic(topic)
            except IndexError:
                pic = drop_pics.get_pic()
            response = {"attachments": [{"fallback":  pic, "image_url": pic}]}

        elif command.startswith("/random"):
            response = {"attachments": [{"fallback":  garg_quotes.random(), "image_url": garg_quotes.random()}]}

        elif command.startswith("vidoi"):
            response = {"text": garg_quotes.vidoi()}

        elif command.startswith(("hei", "hallo", "hello", "morn")):
            response = {"text": "Blëep bloöp, hallo %s!" % users.get(user, "")}

        else:
            response = {"text": ("Beep boop beep! Nôt sure whåt you mean by %s. Dette er kommandoene jeg skjønner:\n"
                                 "@gargbot_3000 *pic* [lark/fe/skating] - (viser tilfedlig Larkollen/Forsterka Enhet/skate bilde)\n"
                                 "@gargbot_3000 *quote* [garling] (henter tilfedlig sitat fra forumet)\n"
                                 "@gargbot_3000 *vidoi* (viser tilfedlig musikkvideo fra muzakvidois tråden på forumet\n"
                                 "@gargbot_3000 */random* (viser tilfedlig bilde fra \\random tråden på forumet\n"
                                 % command)}

        return response
    return handle_command

def panic():
    text = ("Error, error! Noe har gått fryktelig galt! Ææææææ. Ta kontakt"
            " med systemadministrator ummidelbart, før det er for sent. "
            "HJELP MEG. If I don't survive, tell mrs. gargbot... 'Hello'")
    response = {"text": text}
    return response

def send_response(slack_client, response, channel):
    print("response: %s" % response)
    slack_client.api_call("chat.postMessage", channel=channel, as_user=True, **response)

def main():
    garg_quotes = gargquotes.GargQuotes()
    garg_quotes.connect()

    drop_pics = droppics.DropPics()
    drop_pics.connect()
    drop_pics.load_img_paths()

    slack_client = SlackClient(config.token)
    connected = slack_client.rtm_connect()
    if not connected:
        raise Exception("Connection failed. Invalid Slack token or bot ID?")

    handle_command = command_handler_wrapper(garg_quotes, drop_pics)

    print("GargBot 3000 is operational!")
    try:
        while True:
            time.sleep(1)
            command, channel, user = filter_slack_output(slack_client.rtm_read())
            if not (command and channel):
                continue
            try:
                response = handle_command(command, channel, user)
            except MySQLdb.Error:
                garg_quotes.connect()
                response = handle_command(command, channel, user)
            except:
                traceback.print_exc()
                response = panic()
            send_response(slack_client, response, channel)
    except KeyboardInterrupt:
        sys.exit()
    finally:
        garg_quotes.teardown()

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before>#!/usr/local/env python

# REQ:
#	Billboard
#	flask
#	spotipy

import billboard
import datetime
import spotipy
import json

from config import WUML_SECRET

from flask import Flask
from flask import request
from flask import render_template
from spotipy import oauth2
from os import listdir
from os.path import isfile, join

app = Flask(__name__)

# def spotify_get(uri):
# 	my_user = uri.split(':')[2]
# 	my_playlist_id = uri.split(':')[4]
# 	sp_oauth = oauth2.SpotifyOAuth( WUML_ID, WUML_SECRET,scope=SCOPE,cache_path=CACHE )
# 	sp = spotipy.Spotify()
# 	data = sp.user_playlist(my_user, playlist_id=my_playlist_id)
# 	return data

# def build_database(my_dict):
# 	timeString = dto_to_string(datetime.datetime.now())
# 	print "loop starting:" + "\t" + timeString
# 	while int(timeString.split('-')[0]) >= 1952:
# 		chart = billboard.ChartData('billboard-200', date=timeString, quantize=True)
# 		update_dict(my_dict, chart, timeString)
# 		if chart.previousDate is None:
# 			print "no previous date found"
# 			timeString = dto_to_string(string_to_dto(timeString) - datetime.timedelta(days=7))
# 			print "Grabbing:" + "\t" + timeString
# 		else:
# 			timeString = chart.previousDate
# 			print "Grabbing:" + "\t" + chart.previousDate

def heal():
	current_time = datetime.date(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day)
	master_time = datetime.date(1963,8,17)
	my_dict = jload()

	print("Finding latest date in database...")

	for k in my_dict:
		if datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date() > master_time:
			master_time = datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date()
	print("Fetching data...")
	print("Latest Date:\t" + str(master_time))
	while master_time < current_time:
		chart = billboard.ChartData('billboard-200', date=dto_to_string(current_time), quantize=True)
		update_dict(my_dict, chart, dto_to_string(current_time))
		if chart.previousDate is None:
			print("No data found for " + str(chart.previousDate))
			current_time -= datetime.timedelta(days=7)
		else:
			print("Grabbing " + str(chart.previousDate))
			current_time = datetime.datetime.strptime(chart.previousDate, "%Y-%m-%d").date()
	print("Saving database...")
	jsave(my_dict)
	print("Database Saved!")

def weekly_update():
	timeString = dto_to_string(datetime.datetime.now())
	my_dict = jload()
	chart = billboard.ChartData('billboard-200', date=timeString, quantize=True)
	update_dict(my_dict, chart, timeString)
	jsave(my_dict)

def update_dict(my_dict, my_chart, timeString):
	for i in range(0, len(my_chart), 1):
		if str(my_chart[i].artist) in my_dict:
			if my_dict[my_chart[i].artist][0] > (i+1):
				my_dict[my_chart[i].artist] = [ i+1, 'http://www.billboard.com/charts/billboard-200/' + timeString ]
		else:
			my_dict[my_chart[i].artist] = [ i+1, 'http://www.billboard.com/charts/billboard-200/' + timeString ]
	return my_dict

def last_update():
	master_time = datetime.date(1963,8,17)
	my_dict = jload()
	for k in my_dict:
		if datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date() > master_time:
			master_time = datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date()
	return master_time.strftime("%B %d, %Y")

def dto_to_string(dto):
	year = dto.year
	month = zero_padding(dto.month)
	day = zero_padding(dto.day)
	my_string = str(year) + "-" + str(month) + "-" + str(day)
	return my_string

def zero_padding(num):
	if num < 10:
		return "0" + str(num)
	else:
		return str(num)

def jsave(my_dict):
	d = datetime.datetime.now()
	filename = dto_to_string(d) + '.json'
	with open(filename, 'w') as fp:
		json.dump(my_dict, fp)

def jload():
	times = list()
	files = [f for f in listdir('./') if isfile(join('./', f))]
	for f in files:
		if '.json' in f:
			times.append(f)
	times = sorted(times)
	filename = times[len(times)-1]
	with open(filename) as data_file:
		data = json.load(data_file)
	return data

def find_it(my_string):
	my_dict = jload()
	eList = list()
	cList = list()
	for i in my_dict:
		if my_string.lower() == i.lower():
			eList.append([i, my_dict[i]])
		elif my_string.lower() in i.lower():
			cList.append([i, my_dict[i]])
	return sorted(eList), sorted(cList)

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/search/')
def my_form():
    return render_template("search.html", first='true', time=last_update())

@app.route('/search/', methods=['POST'])
def my_form_post():
    text = request.form['searchBar']
    elist, clist = find_it(text)

    if len(elist) == 0 and len(clist) == 0: # No Match Found
    	return render_template('search.html', first= 'false', result='false', tested=text, time=last_update())
    if len(elist) >= 1 and len(clist) == 0: # Exact Match Found
    	return render_template('search.html', first='false', result='true', e_list=elist, tested=text, time=last_update())
    if len(elist) == 0 and len(clist) >= 1: # Partial Match Found
    	return render_template('search.html', first='false', result='true', c_list=clist, tested=text, time=last_update())
    if len(elist) >= 1 and len(clist) >= 1: # Lots of Matches Found
    	return render_template('search.html', first='false', result='true', e_list=elist, c_list=clist, tested=text, time=last_update())

@app.route('/update/', methods=['POST'])
def auto_update():
	data = request.get_json(force=True)
	if data is not None:
		app.logger.debug("JSON Recieved -- " + str(data))

		if WUML_SECRET in data["key"]:
			weekly_update()
			return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
		else:
			abort(404)
	else:
		app.logger.debug("No JSON received")
		abort(404)

@app.route('/heal/', methods=['POST'])
def auto_heal():
	data = request.get_json(force=True)
	if data is not None:
		app.logger.debug("JSON Recieved -- " + str(data))

		if WUML_SECRET in data["key"]:
			heal()
			return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
		else:
			abort(404)
	else:
		app.logger.debug("No JSON received")
		abort(404)

if __name__ == '__main__':
    app.run(debug=True, port=54321, host="0.0.0.0", threaded=True)
<commit_msg>changed defaults<commit_after>#!/usr/local/env python

# REQ:
#	Billboard
#	flask
#	spotipy

import billboard
import datetime
import spotipy
import json

from config import WUML_SECRET, MY_URL, MY_PORT

from flask import Flask
from flask import request
from flask import render_template
from spotipy import oauth2
from os import listdir
from os.path import isfile, join

app = Flask(__name__)

# def spotify_get(uri):
# 	my_user = uri.split(':')[2]
# 	my_playlist_id = uri.split(':')[4]
# 	sp_oauth = oauth2.SpotifyOAuth( WUML_ID, WUML_SECRET,scope=SCOPE,cache_path=CACHE )
# 	sp = spotipy.Spotify()
# 	data = sp.user_playlist(my_user, playlist_id=my_playlist_id)
# 	return data

# def build_database(my_dict):
# 	timeString = dto_to_string(datetime.datetime.now())
# 	print "loop starting:" + "\t" + timeString
# 	while int(timeString.split('-')[0]) >= 1952:
# 		chart = billboard.ChartData('billboard-200', date=timeString, quantize=True)
# 		update_dict(my_dict, chart, timeString)
# 		if chart.previousDate is None:
# 			print "no previous date found"
# 			timeString = dto_to_string(string_to_dto(timeString) - datetime.timedelta(days=7))
# 			print "Grabbing:" + "\t" + timeString
# 		else:
# 			timeString = chart.previousDate
# 			print "Grabbing:" + "\t" + chart.previousDate

def heal():
	current_time = datetime.date(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day)
	master_time = datetime.date(1963,8,17)
	my_dict = jload()

	print("Finding latest date in database...")

	for k in my_dict:
		if datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date() > master_time:
			master_time = datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date()
	print("Fetching data...")
	print("Latest Date:\t" + str(master_time))
	while master_time < current_time:
		chart = billboard.ChartData('billboard-200', date=dto_to_string(current_time), quantize=True)
		update_dict(my_dict, chart, dto_to_string(current_time))
		if chart.previousDate is None:
			print("No data found for " + str(chart.previousDate))
			current_time -= datetime.timedelta(days=7)
		else:
			print("Grabbing " + str(chart.previousDate))
			current_time = datetime.datetime.strptime(chart.previousDate, "%Y-%m-%d").date()
	print("Saving database...")
	jsave(my_dict)
	print("Database Saved!")

def weekly_update():
	timeString = dto_to_string(datetime.datetime.now())
	my_dict = jload()
	chart = billboard.ChartData('billboard-200', date=timeString, quantize=True)
	update_dict(my_dict, chart, timeString)
	jsave(my_dict)

def update_dict(my_dict, my_chart, timeString):
	for i in range(0, len(my_chart), 1):
		if str(my_chart[i].artist) in my_dict:
			if my_dict[my_chart[i].artist][0] > (i+1):
				my_dict[my_chart[i].artist] = [ i+1, 'http://www.billboard.com/charts/billboard-200/' + timeString ]
		else:
			my_dict[my_chart[i].artist] = [ i+1, 'http://www.billboard.com/charts/billboard-200/' + timeString ]
	return my_dict

def last_update():
	master_time = datetime.date(1963,8,17)
	my_dict = jload()
	for k in my_dict:
		if datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date() > master_time:
			master_time = datetime.datetime.strptime(my_dict[k][1].split('/')[5], "%Y-%m-%d").date()
	return master_time.strftime("%B %d, %Y")

def dto_to_string(dto):
	year = dto.year
	month = zero_padding(dto.month)
	day = zero_padding(dto.day)
	my_string = str(year) + "-" + str(month) + "-" + str(day)
	return my_string

def zero_padding(num):
	if num < 10:
		return "0" + str(num)
	else:
		return str(num)

def jsave(my_dict):
	d = datetime.datetime.now()
	filename = dto_to_string(d) + '.json'
	with open(filename, 'w') as fp:
		json.dump(my_dict, fp)

def jload():
	times = list()
	files = [f for f in listdir('./') if isfile(join('./', f))]
	for f in files:
		if '.json' in f:
			times.append(f)
	times = sorted(times)
	filename = times[len(times)-1]
	with open(filename) as data_file:
		data = json.load(data_file)
	return data

def find_it(my_string):
	my_dict = jload()
	eList = list()
	cList = list()
	for i in my_dict:
		if my_string.lower() == i.lower():
			eList.append([i, my_dict[i]])
		elif my_string.lower() in i.lower():
			cList.append([i, my_dict[i]])
	return sorted(eList), sorted(cList)

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/search/')
def my_form():
    return render_template("search.html", first='true', time=last_update())

@app.route('/search/', methods=['POST'])
def my_form_post():
    text = request.form['searchBar']
    elist, clist = find_it(text)

    if len(elist) == 0 and len(clist) == 0: # No Match Found
    	return render_template('search.html', first= 'false', result='false', tested=text, time=last_update())
    if len(elist) >= 1 and len(clist) == 0: # Exact Match Found
    	return render_template('search.html', first='false', result='true', e_list=elist, tested=text, time=last_update())
    if len(elist) == 0 and len(clist) >= 1: # Partial Match Found
    	return render_template('search.html', first='false', result='true', c_list=clist, tested=text, time=last_update())
    if len(elist) >= 1 and len(clist) >= 1: # Lots of Matches Found
    	return render_template('search.html', first='false', result='true', e_list=elist, c_list=clist, tested=text, time=last_update())

@app.route('/update/', methods=['POST'])
def auto_update():
	data = request.get_json(force=True)
	if data is not None:
		app.logger.debug("JSON Recieved -- " + str(data))

		if WUML_SECRET in data["key"]:
			weekly_update()
			return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
		else:
			abort(404)
	else:
		app.logger.debug("No JSON received")
		abort(404)

@app.route('/heal/', methods=['POST'])
def auto_heal():
	data = request.get_json(force=True)
	if data is not None:
		app.logger.debug("JSON Recieved -- " + str(data))

		if WUML_SECRET in data["key"]:
			heal()
			return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
		else:
			abort(404)
	else:
		app.logger.debug("No JSON received")
		abort(404)

if __name__ == '__main__':
    app.run(debug=True, port=MY_PORT, host=MY_URL, threaded=True)
<|endoftext|>


<commit_before>from queue import Queue
from graphs import Graph, Vertex

def bfs(g, start):
    start.setDistance(0)
    start.setPred(None)
    vertQueue = Queue()
    vertQueue.enqueue(start)
    while (vertQueue.size() > 0):
        currentVert = vertQueue.dequeue()
        for nbr in currentVert.getConnections():
            if (nbr.getColor == 'white'):
                nbr.setColor('grey')
                nbr.setDistance(currentVert.getDistance()+1)
                nbr.setPred(currentVert)
                vertQueue.enqueue(nbr)
        currentVert.setColor('black')
<commit_msg>added many comments, it may help in revision.<commit_after>from queue import Queue
from graphs import Graph, Vertex

def bfs(g, start):
    # start is the starting vertex of the graph,
    # as it's the starting point, set distance to zero
    # also predecessor to 'None' as this was the starting
    # point.
    start.setDistance(0)
    start.setPred(None)
    # initialize an empty Queue to hold the vertices.
    # enuqeue `start` in the Queue
    vertQueue = Queue()
    vertQueue.enqueue(start)
    # check if vertices Queue has any Queue items to be explored.
    # if there are any items that need to be explored we have
    # not searched far enough.
    while (vertQueue.size() > 0):
        # take out `dequeue` the first Item in the vertices Queue.
        # and assign it to  `currentVert`.
        # for loop now goes over all the connections for this vertex
        currentVert = vertQueue.dequeue()
        for nbr in currentVert.getConnections():
            # nbr is the current node in question,
            # if it was marked white, which means that it was
            # never discovered and as a flag mark it was `grey`
            if (nbr.getColor == 'white'):
                nbr.setColor('grey')
                # set distance for nbr vertex to be +1 from `currentVertex`
                nbr.setDistance(currentVert.getDistance()+1)
                # now set nbr predecessor to be current vertex
                # and then we need to put `nbr` in  vertQueue as
                # nbr needs to be explored as well for nodes.
                nbr.setPred(currentVert)
                vertQueue.enqueue(nbr)
        # when we reach here it means that currentVert connections have been completley explored.
        # and set the color to black as a marker.
        currentVert.setColor('black')
<|endoftext|>


<commit_before># coding=utf-8
import datetime
import os.path
import re
from io import BytesIO

import simplejson as json
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.utils import dateformat
from reportlab.graphics.barcode import code128
from reportlab.lib.units import inch, mm
from reportlab.pdfbase import pdfdoc
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas

import directory.models as directory
from appconf.manager import SettingManager
from directions.models import Napravleniya, Issledovaniya, TubesRegistration

PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
pdfmetrics.registerFont(
    TTFont('OpenSans', PROJECT_ROOT + '/../static/fonts/OpenSans.ttf'))
pdfmetrics.registerFont(
    TTFont('clacon', PROJECT_ROOT + '/../static/fonts/clacon.ttf'))

@login_required
def tubes(request):
    """
    Barcodes view
    :param request:
    :return:
    """
    if SettingManager.get("pdf_auto_print", "true", "b"):
        pdfdoc.PDFCatalog.OpenAction = '<</S/JavaScript/JS(this.print\({bUI:true,bSilent:false,bShrinkToFit:true}\);)>>'
    direction_id = []
    tubes_id = set()
    istubes = False
    if "napr_id" in request.GET.keys():
        direction_id = json.loads(request.GET["napr_id"])
    elif "tubes_id" in request.GET.keys():
        tubes_id = set(json.loads(request.GET["tubes_id"]))
        istubes = True

    barcode_size = [int(x) for x in request.GET.get("barcode_size", "43x25").strip().split("x")]
    barcode_type = request.GET.get("barcode_type", "std").strip()
    padding = [int(x) for x in request.GET.get("padding", "0x0x0x0").strip().split("x")]

    pw, ph = barcode_size[0], barcode_size[1]  # длина, ширина листа

    doctitle = "Штрих-коды (%s)" % (("направления " + ", ".join(str(v) for v in direction_id)) if not istubes else (
        "пробирки " + ", ".join(str(v) for v in tubes_id)))

    response = HttpResponse(content_type='application/pdf')
    response['Content-Type'] = 'application/pdf'
    symbols = (u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",
               u"abvgdeejzijklmnoprstufhzcss_y_euaABVGDEEJZIJKLMNOPRSTUFHZCSS_Y_EUA")
    response['Content-Disposition'] = str.translate('inline; filename="%s.pdf"' % doctitle,
                                                    {ord(a): ord(b) for a, b in zip(*symbols)})

    buffer = BytesIO()
    pdfdoc.PDFInfo.title = 'Barcodes'
    c = canvas.Canvas(buffer, pagesize=(pw * mm, ph * mm), bottomup=barcode_type == "std")
    c.setTitle(doctitle)
    dt = {"poli": "Поликлиника", "stat": "Стационар", "poli_stom": "Поликлиника-стом."}
    if istubes:
        direction_id = set([x.napravleniye.pk for x in Issledovaniya.objects.filter(tubes__id__in=tubes_id)])

    for d in direction_id:
        tmp2 = Napravleniya.objects.get(pk=int(d))
        tmp = Issledovaniya.objects.filter(napravleniye=tmp2).order_by("research__title")
        tubes_buffer = {}

        fresearches = set()
        fuppers = set()
        flowers = set()

        for iss in Issledovaniya.objects.filter(napravleniye=tmp2):
            for fr in iss.research.fractions_set.all():
                absor = directory.Absorption.objects.filter(fupper=fr)
                if absor.exists():
                    fuppers.add(fr.pk)
                    fresearches.add(fr.research.pk)
                    for absor_obj in absor:
                        flowers.add(absor_obj.flower.pk)
                        fresearches.add(absor_obj.flower.research.pk)

        for v in tmp:
            for val in directory.Fractions.objects.filter(research=v.research):
                vrpk = val.relation.pk
                rel = val.relation
                if val.research.pk in fresearches and val.pk in flowers:
                    absor = directory.Absorption.objects.filter(flower__pk=val.pk).first()
                    if absor.fupper.pk in fuppers:
                        vrpk = absor.fupper.relation.pk
                        rel = absor.fupper.relation

                if vrpk not in tubes_buffer.keys():
                    if not v.tubes.filter(type=rel).exists():
                        ntube = TubesRegistration(type=rel)
                        ntube.save()
                    else:
                        ntube = v.tubes.get(type=rel)
                    v.tubes.add(ntube)
                    tubes_buffer[vrpk] = {"pk": ntube.pk, "researches": set(), "title": ntube.type.tube.title}
                    if not istubes:
                        tubes_id.add(ntube.pk)
                else:
                    ntube = TubesRegistration.objects.get(pk=tubes_buffer[vrpk]["pk"])
                    v.tubes.add(ntube)

                tubes_buffer[vrpk]["researches"].add(v.research.title)
        for tube_k in tubes_buffer.keys():
            tube = tubes_buffer[tube_k]["pk"]
            if tube not in tubes_id:
                continue
            # c.setFont('OpenSans', 8)
            otd = list(tmp2.doc.podrazileniye.title.split(" "))
            fam = tmp2.client.individual.fio(short=True, dots=False)
            st = ""
            if len(otd) > 1:
                if "отделение" in otd[0].lower():
                    st = otd[1][:3] + "/о"
                else:
                    st = otd[0][:3] + "/" + otd[1][:1]
            elif len(otd) == 1:
                st = otd[0][:3]
            st = (
            st + "=>" + Issledovaniya.objects.filter(tubes__pk=tube).first().research.subgroup.podrazdeleniye.title[
                        :3]).lower()
            types = ["фиолет", "красн", "стекло", "черн", "белая", "серая", "фильтро", "чашка", "голубая", "зеленая",
                     "зелёная", "контейнер", "зонд", "п ф", "л ф", "синяя"]
            tb_t = tubes_buffer[tube_k]["title"].lower()
            pr = ""
            for s in types:
                if s in tb_t:
                    pr = s[0]
            pr = pr.upper()
            r = re.search(u"(\d+\.\d|\d+,\d+|\d+)\s(мл)", tb_t)
            if r:
                pr += r.group(1) + r.group(2)
            pr += " " + Issledovaniya.objects.filter(tubes__pk=tube).first().comment[:9]

            nm = "№" + str(d) + "," + tmp2.client.base.short_title

            for tube in [10, 100, 150, 200, 300, 400, 500, 600, 700, 1000, 2000, 3000, 5000, 10000, 20000, 30000, 50000, 80000, 100000, 150000, 180000, 200000, 250000, 400000, 500000, 800000, 1000000, 1300000, 1600000, 2000000, 5000000, 10000000, 11223344, 92223344]:
                c.setFont('clacon', 12)
                c.drawString(2 * mm, ph * mm - 3 * mm, nm)
                c.drawRightString(pw * mm - 2 * mm, ph * mm - 3 * mm, st)
                c.setFont('clacon', 18)
                if len(fam) > 14:
                    c.setFont('clacon', 18 - len(fam) * 0.7 + 12 * 0.7)
                c.drawRightString(pw * mm - 2 * mm, ph * mm - 7 * mm, fam)
                c.setFont('clacon', 12)
                c.drawString(2 * mm, mm, pr)
                c.drawRightString(pw * mm - 2 * mm, mm, str(tube))
                m = 0.0212
                if tube >= 10000:
                    m = 0.018
                if tube >= 100000:
                    m = 0.0212
                if tube >= 1000000:
                    m = 0.016
                barcode = code128.Code128(str(tube), barHeight=ph * mm - 12 * mm, barWidth=pw / 43 * inch * m)
                barcode.drawOn(c, -3 * mm, 4 * mm)

                c.showPage()
    c.save()
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response
<commit_msg>simplify<commit_after># coding=utf-8
import datetime
import os.path
import re
from io import BytesIO

import simplejson as json
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.utils import dateformat
from reportlab.graphics.barcode import code128
from reportlab.lib.units import inch, mm
from reportlab.pdfbase import pdfdoc
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas

import directory.models as directory
from appconf.manager import SettingManager
from directions.models import Napravleniya, Issledovaniya, TubesRegistration

PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
pdfmetrics.registerFont(
    TTFont('OpenSans', PROJECT_ROOT + '/../static/fonts/OpenSans.ttf'))
pdfmetrics.registerFont(
    TTFont('clacon', PROJECT_ROOT + '/../static/fonts/clacon.ttf'))

@login_required
def tubes(request):
    """
    Barcodes view
    :param request:
    :return:
    """
    if SettingManager.get("pdf_auto_print", "true", "b"):
        pdfdoc.PDFCatalog.OpenAction = '<</S/JavaScript/JS(this.print\({bUI:true,bSilent:false,bShrinkToFit:true}\);)>>'
    direction_id = []
    tubes_id = set()
    istubes = False
    if "napr_id" in request.GET.keys():
        direction_id = json.loads(request.GET["napr_id"])
    elif "tubes_id" in request.GET.keys():
        tubes_id = set(json.loads(request.GET["tubes_id"]))
        istubes = True

    barcode_size = [int(x) for x in request.GET.get("barcode_size", "43x25").strip().split("x")]
    barcode_type = request.GET.get("barcode_type", "std").strip()
    padding = [int(x) for x in request.GET.get("padding", "0x0x0x0").strip().split("x")]

    pw, ph = barcode_size[0], barcode_size[1]  # длина, ширина листа

    doctitle = "Штрих-коды (%s)" % (("направления " + ", ".join(str(v) for v in direction_id)) if not istubes else (
        "пробирки " + ", ".join(str(v) for v in tubes_id)))

    response = HttpResponse(content_type='application/pdf')
    response['Content-Type'] = 'application/pdf'
    symbols = (u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",
               u"abvgdeejzijklmnoprstufhzcss_y_euaABVGDEEJZIJKLMNOPRSTUFHZCSS_Y_EUA")
    response['Content-Disposition'] = str.translate('inline; filename="%s.pdf"' % doctitle,
                                                    {ord(a): ord(b) for a, b in zip(*symbols)})

    buffer = BytesIO()
    pdfdoc.PDFInfo.title = 'Barcodes'
    c = canvas.Canvas(buffer, pagesize=(pw * mm, ph * mm), bottomup=barcode_type == "std")
    c.setTitle(doctitle)
    dt = {"poli": "Поликлиника", "stat": "Стационар", "poli_stom": "Поликлиника-стом."}
    if istubes:
        direction_id = set([x.napravleniye.pk for x in Issledovaniya.objects.filter(tubes__id__in=tubes_id)])

    for d in direction_id:
        tmp2 = Napravleniya.objects.get(pk=int(d))
        tmp = Issledovaniya.objects.filter(napravleniye=tmp2).order_by("research__title")
        tubes_buffer = {}

        fresearches = set()
        fuppers = set()
        flowers = set()

        for iss in Issledovaniya.objects.filter(napravleniye=tmp2):
            for fr in iss.research.fractions_set.all():
                absor = directory.Absorption.objects.filter(fupper=fr)
                if absor.exists():
                    fuppers.add(fr.pk)
                    fresearches.add(fr.research.pk)
                    for absor_obj in absor:
                        flowers.add(absor_obj.flower.pk)
                        fresearches.add(absor_obj.flower.research.pk)

        for v in tmp:
            for val in directory.Fractions.objects.filter(research=v.research):
                vrpk = val.relation.pk
                rel = val.relation
                if val.research.pk in fresearches and val.pk in flowers:
                    absor = directory.Absorption.objects.filter(flower__pk=val.pk).first()
                    if absor.fupper.pk in fuppers:
                        vrpk = absor.fupper.relation.pk
                        rel = absor.fupper.relation

                if vrpk not in tubes_buffer.keys():
                    if not v.tubes.filter(type=rel).exists():
                        ntube = TubesRegistration(type=rel)
                        ntube.save()
                    else:
                        ntube = v.tubes.get(type=rel)
                    v.tubes.add(ntube)
                    tubes_buffer[vrpk] = {"pk": ntube.pk, "researches": set(), "title": ntube.type.tube.title}
                    if not istubes:
                        tubes_id.add(ntube.pk)
                else:
                    ntube = TubesRegistration.objects.get(pk=tubes_buffer[vrpk]["pk"])
                    v.tubes.add(ntube)

                tubes_buffer[vrpk]["researches"].add(v.research.title)
        for tube_k in tubes_buffer.keys():
            tube = tubes_buffer[tube_k]["pk"]
            if tube not in tubes_id:
                continue
            # c.setFont('OpenSans', 8)
            otd = list(tmp2.doc.podrazileniye.title.split(" "))
            fam = tmp2.client.individual.fio(short=True, dots=False)
            st = ""
            if len(otd) > 1:
                if "отделение" in otd[0].lower():
                    st = otd[1][:3] + "/о"
                else:
                    st = otd[0][:3] + "/" + otd[1][:1]
            elif len(otd) == 1:
                st = otd[0][:3]
            st = (
            st + "=>" + Issledovaniya.objects.filter(tubes__pk=tube).first().research.subgroup.podrazdeleniye.title[
                        :3]).lower()
            types = ["фиолет", "красн", "стекло", "черн", "белая", "серая", "фильтро", "чашка", "голубая", "зеленая",
                     "зелёная", "контейнер", "зонд", "п ф", "л ф", "синяя"]
            tb_t = tubes_buffer[tube_k]["title"].lower()
            pr = ""
            for s in types:
                if s in tb_t:
                    pr = s[0]
            pr = pr.upper()
            r = re.search(u"(\d+\.\d|\d+,\d+|\d+)\s(мл)", tb_t)
            if r:
                pr += r.group(1) + r.group(2)
            pr += " " + Issledovaniya.objects.filter(tubes__pk=tube).first().comment[:9]

            nm = "№" + str(d) + "," + tmp2.client.base.short_title

            c.setFont('clacon', 12)
            c.drawString(2 * mm, ph * mm - 3 * mm, nm)
            c.drawRightString(pw * mm - 2 * mm, ph * mm - 3 * mm, st)
            c.setFont('clacon', 18)
            if len(fam) > 14:
                c.setFont('clacon', 18 - len(fam) * 0.7 + 12 * 0.7)
            c.drawRightString(pw * mm - 2 * mm, ph * mm - 7 * mm, fam)
            c.setFont('clacon', 12)
            c.drawString(2 * mm, mm, pr)
            c.drawRightString(pw * mm - 2 * mm, mm, str(tube))
            m = 0.0212
            if tube >= 10000:
                m = 0.018
            if tube >= 100000:
                m = 0.0212
            if tube >= 1000000:
                m = 0.016
            barcode = code128.Code128(str(tube), barHeight=ph * mm - 12 * mm, barWidth=pw / 43 * inch * m)
            barcode.drawOn(c, -3 * mm, 4 * mm)

            c.showPage()
    c.save()
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response
<|endoftext|>


<commit_before>from copy import copy
from cStringIO import StringIO
import datetime
import inspect
import sys
import traceback

from django.core.management import call_command
from django.core.management.commands import loaddata
from django.db import models

import south.db
from south import exceptions
from south.db import DEFAULT_DB_ALIAS
from south.models import MigrationHistory
from south.signals import ran_migration

class Migrator(object):
    def __init__(self, verbosity=0):
        self.verbosity = int(verbosity)

    @staticmethod
    def title(target):
        raise NotImplementedError()

    def print_title(self, target):
        if self.verbosity:
            print self.title(target)

    @staticmethod
    def status(target):
        raise NotImplementedError()

    def print_status(self, migration):
        status = self.status(migration)
        if self.verbosity and status:
            print status

    @staticmethod
    def orm(migration):
        raise NotImplementedError()

    def backwards(self, migration):
        return self._wrap_direction(migration.backwards(), migration.prev_orm())

    def direction(self, migration):
        raise NotImplementedError()

    @staticmethod
    def _wrap_direction(direction, orm):
        args = inspect.getargspec(direction)
        if len(args[0]) == 1:
            # Old migration, no ORM should be passed in
            return direction
        return (lambda: direction(orm))

    @staticmethod
    def record(migration, database):
        raise NotImplementedError()

    def run_migration_error(self, migration, extra_info=''):
        return (' ! Error found during real run of migration! Aborting.\n'
                '\n'
                ' ! Since you have a database that does not support running\n'
                ' ! schema-altering statements in transactions, we have had \n'
                ' ! to leave it in an interim state between migrations.\n'
                '%s\n'
                ' ! The South developers regret this has happened, and would\n'
                ' ! like to gently persuade you to consider a slightly\n'
                ' ! easier-to-deal-with DBMS.\n') % extra_info

    def run_migration(self, migration):
        migration_function = self.direction(migration)
        south.db.db.start_transaction()
        try:
            migration_function()
            south.db.db.execute_deferred_sql()
        except:
            south.db.db.rollback_transaction()
            if not south.db.db.has_ddl_transactions:
                print self.run_migration_error(migration)
            raise
        else:
            south.db.db.commit_transaction()

    def run(self, migration):
        # Get the correct ORM.
        south.db.db.current_orm = self.orm(migration)
        # If the database doesn't support running DDL inside a transaction
        # *cough*MySQL*cough* then do a dry run first.
        if not south.db.db.has_ddl_transactions:
            dry_run = DryRunMigrator(migrator=self, ignore_fail=False)
            dry_run.run_migration(migration)
        return self.run_migration(migration)

    def done_migrate(self, migration, database):
        south.db.db.start_transaction()
        try:
            # Record us as having done this
            self.record(migration, database)
        except:
            south.db.db.rollback_transaction()
            raise
        else:
            south.db.db.commit_transaction()

    def send_ran_migration(self, migration):
        ran_migration.send(None,
                           app=migration.app_label(),
                           migration=migration,
                           method=self.__class__.__name__.lower())

    def migrate(self, migration, database):
        """
        Runs the specified migration forwards/backwards, in order.
        """
        app = migration.migrations._migrations
        migration_name = migration.name()
        self.print_status(migration)
        result = self.run(migration)
        self.done_migrate(migration, database)
        self.send_ran_migration(migration)
        return result

    def migrate_many(self, target, migrations, database):
        raise NotImplementedError()

class MigratorWrapper(object):
    def __init__(self, migrator, *args, **kwargs):
        self._migrator = copy(migrator)
        attributes = dict([(k, getattr(self, k))
                           for k in self.__class__.__dict__.iterkeys()
                           if not k.startswith('__')])
        self._migrator.__dict__.update(attributes)

    def __getattr__(self, name):
        return getattr(self._migrator, name)

class DryRunMigrator(MigratorWrapper):
    def __init__(self, ignore_fail=True, *args, **kwargs):
        super(DryRunMigrator, self).__init__(*args, **kwargs)
        self._ignore_fail = ignore_fail

    def _run_migration(self, migration):
        if migration.no_dry_run() and self.verbosity:
            print " - Migration '%s' is marked for no-dry-run." % migration
            return
        south.db.db.dry_run = True
        if self._ignore_fail:
            south.db.db.debug, old_debug = False, south.db.db.debug
        pending_creates = south.db.db.get_pending_creates()
        south.db.db.start_transaction()
        migration_function = self.direction(migration)
        try:
            try:
                migration_function()
                south.db.db.execute_deferred_sql()
            except:
                raise exceptions.FailedDryRun(migration, sys.exc_info())
        finally:
            south.db.db.rollback_transactions_dry_run()
            if self._ignore_fail:
                south.db.db.debug = old_debug
            south.db.db.clear_run_data(pending_creates)
            south.db.db.dry_run = False

    def run_migration(self, migration):
        try:
            self._run_migration(migration)
        except exceptions.FailedDryRun:
            if self._ignore_fail:
                return False
            raise

    def done_migrate(self, *args, **kwargs):
        pass

    def send_ran_migration(self, *args, **kwargs):
        pass

class FakeMigrator(MigratorWrapper):
    def run(self, migration):
        if self.verbosity:
            print '   (faked)'

    def send_ran_migration(self, *args, **kwargs):
        pass

class LoadInitialDataMigrator(MigratorWrapper):
    def load_initial_data(self, target):
        if target is None or target != target.migrations[-1]:
            return
        # Load initial data, if we ended up at target
        if self.verbosity:
            print " - Loading initial data for %s." % target.app_label()
        # Override Django's get_apps call temporarily to only load from the
        # current app
        old_get_apps = models.get_apps
        new_get_apps = lambda: [models.get_app(target.app_label())]
        models.get_apps = new_get_apps
        loaddata.get_apps = new_get_apps
        try:
            call_command('loaddata', 'initial_data', verbosity=self.verbosity)
        finally:
            models.get_apps = old_get_apps
            loaddata.get_apps = old_get_apps

    def migrate_many(self, target, migrations, database):
        migrator = self._migrator
        result = migrator.__class__.migrate_many(migrator, target, migrations, database)
        if result:
            self.load_initial_data(target)
        return True

class Forwards(Migrator):
    """
    Runs the specified migration forwards, in order.
    """
    torun = 'forwards'

    @staticmethod
    def title(target):
        if target is not None:
            return " - Migrating forwards to %s." % target.name()
        else:
            assert False, "You cannot migrate forwards to zero."

    @staticmethod
    def status(migration):
        return ' > %s' % migration

    @staticmethod
    def orm(migration):
        return migration.orm()

    def forwards(self, migration):
        return self._wrap_direction(migration.forwards(), migration.orm())

    direction = forwards

    @staticmethod
    def record(migration, database):
        # Record us as having done this
        record = MigrationHistory.for_migration(migration, database)
        record.applied = datetime.datetime.utcnow()
        if database != DEFAULT_DB_ALIAS:
            record.save(using=database)
        else:
            # Django 1.1 and below always go down this branch.
            record.save()

    def format_backwards(self, migration):
        old_debug, old_dry_run = south.db.db.debug, south.db.db.dry_run
        south.db.db.debug = south.db.db.dry_run = True
        stdout = sys.stdout
        sys.stdout = StringIO()
        try:
            try:
                self.backwards(migration)()
                return sys.stdout.getvalue()
            except:
                raise
        finally:
            south.db.db.debug, south.db.db.dry_run = old_debug, old_dry_run
            sys.stdout = stdout

    def run_migration_error(self, migration, extra_info=''):
        extra_info = ('\n'
                      '! You *might* be able to recover with:'
                      '%s'
                      '%s' %
                      (self.format_backwards(migration), extra_info))
        return super(Forwards, self).run_migration_error(migration, extra_info)

    def migrate_many(self, target, migrations, database):
        try:
            for migration in migrations:
                result = self.migrate(migration, database)
                if result is False: # The migrations errored, but nicely.
                    return False
        finally:
            # Call any pending post_syncdb signals
            south.db.db.send_pending_create_signals()
        return True

class Backwards(Migrator):
    """
    Runs the specified migration backwards, in order.
    """
    torun = 'backwards'

    @staticmethod
    def title(target):
        if target is None:
            return " - Migrating backwards to zero state."
        else:
            return " - Migrating backwards to just after %s." % target.name()

    @staticmethod
    def status(migration):
        return ' < %s' % migration

    @staticmethod
    def orm(migration):
        return migration.prev_orm()

    direction = Migrator.backwards

    @staticmethod
    def record(migration, database):
        # Record us as having not done this
        record = MigrationHistory.for_migration(migration, database)
        if record.id is not None:
            if database != DEFAULT_DB_ALIAS:
                record.delete(using=database)
            else:
                # Django 1.1 always goes down here
                record.delete()

    def migrate_many(self, target, migrations, database):
        for migration in migrations:
            self.migrate(migration, database)
        return True

<commit_msg>Fix #403: Trying to dry-run things in backwards()<commit_after>from copy import copy
from cStringIO import StringIO
import datetime
import inspect
import sys
import traceback

from django.core.management import call_command
from django.core.management.commands import loaddata
from django.db import models

import south.db
from south import exceptions
from south.db import DEFAULT_DB_ALIAS
from south.models import MigrationHistory
from south.signals import ran_migration

class Migrator(object):
    def __init__(self, verbosity=0):
        self.verbosity = int(verbosity)

    @staticmethod
    def title(target):
        raise NotImplementedError()

    def print_title(self, target):
        if self.verbosity:
            print self.title(target)

    @staticmethod
    def status(target):
        raise NotImplementedError()

    def print_status(self, migration):
        status = self.status(migration)
        if self.verbosity and status:
            print status

    @staticmethod
    def orm(migration):
        raise NotImplementedError()

    def backwards(self, migration):
        return self._wrap_direction(migration.backwards(), migration.prev_orm())

    def direction(self, migration):
        raise NotImplementedError()

    @staticmethod
    def _wrap_direction(direction, orm):
        args = inspect.getargspec(direction)
        if len(args[0]) == 1:
            # Old migration, no ORM should be passed in
            return direction
        return (lambda: direction(orm))

    @staticmethod
    def record(migration, database):
        raise NotImplementedError()

    def run_migration_error(self, migration, extra_info=''):
        return (
            ' ! Error found during real run of migration! Aborting.\n'
            '\n'
            ' ! Since you have a database that does not support running\n'
            ' ! schema-altering statements in transactions, we have had \n'
            ' ! to leave it in an interim state between migrations.\n'
            '%s\n'
            ' ! The South developers regret this has happened, and would\n'
            ' ! like to gently persuade you to consider a slightly\n'
            ' ! easier-to-deal-with DBMS.\n'
            ' ! NOTE: The error which caused the migration to fail is further up.'
        ) % extra_info

    def run_migration(self, migration):
        migration_function = self.direction(migration)
        south.db.db.start_transaction()
        try:
            migration_function()
            south.db.db.execute_deferred_sql()
        except:
            south.db.db.rollback_transaction()
            if not south.db.db.has_ddl_transactions:
                print self.run_migration_error(migration)
            raise
        else:
            south.db.db.commit_transaction()

    def run(self, migration):
        # Get the correct ORM.
        south.db.db.current_orm = self.orm(migration)
        # If the database doesn't support running DDL inside a transaction
        # *cough*MySQL*cough* then do a dry run first.
        if not south.db.db.has_ddl_transactions:
            dry_run = DryRunMigrator(migrator=self, ignore_fail=False)
            dry_run.run_migration(migration)
        return self.run_migration(migration)

    def done_migrate(self, migration, database):
        south.db.db.start_transaction()
        try:
            # Record us as having done this
            self.record(migration, database)
        except:
            south.db.db.rollback_transaction()
            raise
        else:
            south.db.db.commit_transaction()

    def send_ran_migration(self, migration):
        ran_migration.send(None,
                           app=migration.app_label(),
                           migration=migration,
                           method=self.__class__.__name__.lower())

    def migrate(self, migration, database):
        """
        Runs the specified migration forwards/backwards, in order.
        """
        app = migration.migrations._migrations
        migration_name = migration.name()
        self.print_status(migration)
        result = self.run(migration)
        self.done_migrate(migration, database)
        self.send_ran_migration(migration)
        return result

    def migrate_many(self, target, migrations, database):
        raise NotImplementedError()

class MigratorWrapper(object):
    def __init__(self, migrator, *args, **kwargs):
        self._migrator = copy(migrator)
        attributes = dict([(k, getattr(self, k))
                           for k in self.__class__.__dict__.iterkeys()
                           if not k.startswith('__')])
        self._migrator.__dict__.update(attributes)

    def __getattr__(self, name):
        return getattr(self._migrator, name)

class DryRunMigrator(MigratorWrapper):
    def __init__(self, ignore_fail=True, *args, **kwargs):
        super(DryRunMigrator, self).__init__(*args, **kwargs)
        self._ignore_fail = ignore_fail

    def _run_migration(self, migration):
        if migration.no_dry_run() and self.verbosity:
            print " - Migration '%s' is marked for no-dry-run." % migration
            return
        south.db.db.dry_run = True
        if self._ignore_fail:
            south.db.db.debug, old_debug = False, south.db.db.debug
        pending_creates = south.db.db.get_pending_creates()
        south.db.db.start_transaction()
        migration_function = self.direction(migration)
        try:
            try:
                migration_function()
                south.db.db.execute_deferred_sql()
            except:
                raise exceptions.FailedDryRun(migration, sys.exc_info())
        finally:
            south.db.db.rollback_transactions_dry_run()
            if self._ignore_fail:
                south.db.db.debug = old_debug
            south.db.db.clear_run_data(pending_creates)
            south.db.db.dry_run = False

    def run_migration(self, migration):
        try:
            self._run_migration(migration)
        except exceptions.FailedDryRun:
            if self._ignore_fail:
                return False
            raise

    def done_migrate(self, *args, **kwargs):
        pass

    def send_ran_migration(self, *args, **kwargs):
        pass

class FakeMigrator(MigratorWrapper):
    def run(self, migration):
        if self.verbosity:
            print '   (faked)'

    def send_ran_migration(self, *args, **kwargs):
        pass

class LoadInitialDataMigrator(MigratorWrapper):
    def load_initial_data(self, target):
        if target is None or target != target.migrations[-1]:
            return
        # Load initial data, if we ended up at target
        if self.verbosity:
            print " - Loading initial data for %s." % target.app_label()
        # Override Django's get_apps call temporarily to only load from the
        # current app
        old_get_apps = models.get_apps
        new_get_apps = lambda: [models.get_app(target.app_label())]
        models.get_apps = new_get_apps
        loaddata.get_apps = new_get_apps
        try:
            call_command('loaddata', 'initial_data', verbosity=self.verbosity)
        finally:
            models.get_apps = old_get_apps
            loaddata.get_apps = old_get_apps

    def migrate_many(self, target, migrations, database):
        migrator = self._migrator
        result = migrator.__class__.migrate_many(migrator, target, migrations, database)
        if result:
            self.load_initial_data(target)
        return True

class Forwards(Migrator):
    """
    Runs the specified migration forwards, in order.
    """
    torun = 'forwards'

    @staticmethod
    def title(target):
        if target is not None:
            return " - Migrating forwards to %s." % target.name()
        else:
            assert False, "You cannot migrate forwards to zero."

    @staticmethod
    def status(migration):
        return ' > %s' % migration

    @staticmethod
    def orm(migration):
        return migration.orm()

    def forwards(self, migration):
        return self._wrap_direction(migration.forwards(), migration.orm())

    direction = forwards

    @staticmethod
    def record(migration, database):
        # Record us as having done this
        record = MigrationHistory.for_migration(migration, database)
        record.applied = datetime.datetime.utcnow()
        if database != DEFAULT_DB_ALIAS:
            record.save(using=database)
        else:
            # Django 1.1 and below always go down this branch.
            record.save()

    def format_backwards(self, migration):
        if migration.no_dry_run():
            return "   (migration cannot be dry-run; cannot discover commands)"
        old_debug, old_dry_run = south.db.db.debug, south.db.db.dry_run
        south.db.db.debug = south.db.db.dry_run = True
        stdout = sys.stdout
        sys.stdout = StringIO()
        try:
            try:
                self.backwards(migration)()
                return sys.stdout.getvalue()
            except:
                raise
        finally:
            south.db.db.debug, south.db.db.dry_run = old_debug, old_dry_run
            sys.stdout = stdout

    def run_migration_error(self, migration, extra_info=''):
        extra_info = ('\n'
                      '! You *might* be able to recover with:'
                      '%s'
                      '%s' %
                      (self.format_backwards(migration), extra_info))
        return super(Forwards, self).run_migration_error(migration, extra_info)

    def migrate_many(self, target, migrations, database):
        try:
            for migration in migrations:
                result = self.migrate(migration, database)
                if result is False: # The migrations errored, but nicely.
                    return False
        finally:
            # Call any pending post_syncdb signals
            south.db.db.send_pending_create_signals()
        return True

class Backwards(Migrator):
    """
    Runs the specified migration backwards, in order.
    """
    torun = 'backwards'

    @staticmethod
    def title(target):
        if target is None:
            return " - Migrating backwards to zero state."
        else:
            return " - Migrating backwards to just after %s." % target.name()

    @staticmethod
    def status(migration):
        return ' < %s' % migration

    @staticmethod
    def orm(migration):
        return migration.prev_orm()

    direction = Migrator.backwards

    @staticmethod
    def record(migration, database):
        # Record us as having not done this
        record = MigrationHistory.for_migration(migration, database)
        if record.id is not None:
            if database != DEFAULT_DB_ALIAS:
                record.delete(using=database)
            else:
                # Django 1.1 always goes down here
                record.delete()

    def migrate_many(self, target, migrations, database):
        for migration in migrations:
            self.migrate(migration, database)
        return True

<|endoftext|>


<commit_before>#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import json

from flask import Flask
from flask import request
from flask import g
from flask import redirect
from flask import abort
from flask import render_template
from flask import flash

import os
import config
import sqlite3
import time

app = Flask(__name__)

# Load default config and override config from an environment variable
app.config.update(dict(
    DATABASE=os.path.join(app.root_path, config.DATABASE_PATH),
    DEBUG=True,
))

ALPHABET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

def base62_encode(num, alphabet=ALPHABET):
    """Encode a number in Base X

    `num`: The number to encode
    `alphabet`: The alphabet to use for encoding
    """
    if (num == 0):
        return alphabet[0]
    arr = []
    base = len(alphabet)
    while num:
        rem = num % base
        num = num // base
        arr.append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

def base62_decode(string, alphabet=ALPHABET):
    """Decode a Base X encoded string into the number

    Arguments:
    - `string`: The encoded string
    - `alphabet`: The alphabet to use for encoding
    """
    base = len(alphabet)
    strlen = len(string)
    num = 0

    idx = 0
    for char in string:
        power = (strlen - (idx + 1))
        num += alphabet.index(char) * (base ** power)
        idx += 1

    return num

def connect_db():
    """Connects to the specific database."""
    rv = sqlite3.connect(app.config['DATABASE'])
    rv.row_factory = sqlite3.Row
    return rv

def init_db():
    """Initializes the database."""
    db = get_db()
    with app.open_resource('schema/v1.sql', mode='r') as f:
        db.cursor().executescript(f.read())
    db.commit()

@app.cli.command('initdb')
def initdb_command():
    """Creates the database tables."""
    init_db()
    print('Initialized the database.')

def get_db():
    """Opens a new database connection if there is none yet for the
    current application context.
    """
    if not hasattr(g, 'sqlite_db'):
        g.sqlite_db = connect_db()
    return g.sqlite_db

def lookup_url(link_id):
    db = get_db()
    cur = db.execute('SELECT url FROM urls WHERE key = ?', (link_id,))
    link = cur.fetchall()
    if len(link) is not 1:
        return None
    else:
        return link

def save_url(url, wish=None):
    exists = None
    db = get_db()
    if wish is not None:
        exists = lookup_url(wish)
    else:
        key_exists = db.execute('SELECT key FROM urls WHERE url = ?', (url,)).fetchone()

    if exists is None:
        key = wish
    elif key_exists is not None:
        cur = db.execute('SELECT key FROM urls ORDER BY key LIMIT 1')
        last_key = cur.fetchone()
        if not last_key:
            key = base62_encode(0)
        else:
            key = base62_encode(base62_decode(last_key) + 1)
    else:
        key = key_exists

    db.execute('INSERT INTO urls (key, url) VALUES (?, ?)', (key, url))
    db.commit()

@app.teardown_appcontext
def close_db(error):
    """Closes the database again at the end of the request."""
    if hasattr(g, 'sqlite_db'):
        g.sqlite_db.close()

@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404

@app.route('/<link_id>')
def short_link(link_id):
    url = lookup_url(link_id)
    if url is None:
        abort(404)
    else:
        db = get_db()
        db.execute('INSERT INTO stats (link_id, time) VALUES(?, ?)',
                   (link_id, int(time.time()),))
        return redirect(url)

@app.route('/<link_id>+')
def link_info(link_id):
    link_url = lookup_url(link_id)
    if link_url is None:
        abort(404)

    db = get_db()
    link_stats = db.execute('SELECT time FROM stats WHERE link_id = ?',
                            (link_id,))

    return json.dumps({'Link:': link_url, 'Stats:': link_stats})

@app.route('/api/v1/short', methods=['POST'])
def api_v1_short():
    return json.dumps(request)

@app.route('/api/v1/long', methods=['POST'])
def api_v1_long():
    return json.dumps(request)

if __name__ == "__main__":
    app.run(host='localhost', port=9002)
<commit_msg>Split up line(PEP8)<commit_after>#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import json

from flask import Flask
from flask import request
from flask import g
from flask import redirect
from flask import abort
from flask import render_template
from flask import flash

import os
import config
import sqlite3
import time

app = Flask(__name__)

# Load default config and override config from an environment variable
app.config.update(dict(
    DATABASE=os.path.join(app.root_path, config.DATABASE_PATH),
    DEBUG=True,
))

ALPHABET = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

def base62_encode(num, alphabet=ALPHABET):
    """Encode a number in Base X

    `num`: The number to encode
    `alphabet`: The alphabet to use for encoding
    """
    if (num == 0):
        return alphabet[0]
    arr = []
    base = len(alphabet)
    while num:
        rem = num % base
        num = num // base
        arr.append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

def base62_decode(string, alphabet=ALPHABET):
    """Decode a Base X encoded string into the number

    Arguments:
    - `string`: The encoded string
    - `alphabet`: The alphabet to use for encoding
    """
    base = len(alphabet)
    strlen = len(string)
    num = 0

    idx = 0
    for char in string:
        power = (strlen - (idx + 1))
        num += alphabet.index(char) * (base ** power)
        idx += 1

    return num

def connect_db():
    """Connects to the specific database."""
    rv = sqlite3.connect(app.config['DATABASE'])
    rv.row_factory = sqlite3.Row
    return rv

def init_db():
    """Initializes the database."""
    db = get_db()
    with app.open_resource('schema/v1.sql', mode='r') as f:
        db.cursor().executescript(f.read())
    db.commit()

@app.cli.command('initdb')
def initdb_command():
    """Creates the database tables."""
    init_db()
    print('Initialized the database.')

def get_db():
    """Opens a new database connection if there is none yet for the
    current application context.
    """
    if not hasattr(g, 'sqlite_db'):
        g.sqlite_db = connect_db()
    return g.sqlite_db

def lookup_url(link_id):
    db = get_db()
    cur = db.execute('SELECT url FROM urls WHERE key = ?', (link_id,))
    link = cur.fetchall()
    if len(link) is not 1:
        return None
    else:
        return link

def save_url(url, wish=None):
    exists = None
    db = get_db()
    if wish is not None:
        exists = lookup_url(wish)
    else:
        cur = db.execute('SELECT key FROM urls WHERE url = ?', (url,))
        key_exists = cur.fetchone()

    if exists is None:
        key = wish
    elif key_exists is not None:
        cur = db.execute('SELECT key FROM urls ORDER BY key LIMIT 1')
        last_key = cur.fetchone()
        if not last_key:
            key = base62_encode(0)
        else:
            key = base62_encode(base62_decode(last_key) + 1)
    else:
        key = key_exists

    db.execute('INSERT INTO urls (key, url) VALUES (?, ?)', (key, url))
    db.commit()

@app.teardown_appcontext
def close_db(error):
    """Closes the database again at the end of the request."""
    if hasattr(g, 'sqlite_db'):
        g.sqlite_db.close()

@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404

@app.route('/<link_id>')
def short_link(link_id):
    url = lookup_url(link_id)
    if url is None:
        abort(404)
    else:
        db = get_db()
        db.execute('INSERT INTO stats (link_id, time) VALUES(?, ?)',
                   (link_id, int(time.time()),))
        return redirect(url)

@app.route('/<link_id>+')
def link_info(link_id):
    link_url = lookup_url(link_id)
    if link_url is None:
        abort(404)

    db = get_db()
    link_stats = db.execute('SELECT time FROM stats WHERE link_id = ?',
                            (link_id,))

    return json.dumps({'Link:': link_url, 'Stats:': link_stats})

@app.route('/api/v1/short', methods=['POST'])
def api_v1_short():
    return json.dumps(request)

@app.route('/api/v1/long', methods=['POST'])
def api_v1_long():
    return json.dumps(request)

if __name__ == "__main__":
    app.run(host='localhost', port=9002)
<|endoftext|>