# -*- coding: utf-8 -*-
"""
"""
import os
import markdown2
from flask import (Blueprint,
                   request,
                   render_template,
                   flash, g,
                   session,
                   redirect,
                   url_for,
                   abort,
                   Markup)
from werkzeug import check_password_hash, generate_password_hash
from logzero import logger
from base import db, app
from base import search as search_module  # don't override function name
from base.users.forms import RegisterForm, LoginForm
from base.users.models import User
from base.threads.models import Thread, Publication
from base.subreddits.models import Subreddit
from base.users.decorators import requires_login
from base.utils.user_utils import get_school
from base.subreddits.forms import subreddit_subs, sub_form
from base.utils.email import send_email
from base.utils.misc import random_string, validate_sort_type

mod = Blueprint('frontends', __name__, url_prefix='')


@mod.before_request
def before_request():
    g.user = None
    if session.get('user_id'):
        g.user = User.query.get(session['user_id'])


def home_subreddit():
    logger.info(g.user)
    if g.get('user'):
        subreddit_subs = g.user.subreddit_subs.get('subs')
        subs = Thread.query.order_by(db.desc(Thread.hotness), db.desc(Thread.hotness)) \
                           .filter(Subreddit.name.in_(subreddit_subs))
    else:
        subs = Thread.query.order_by(db.desc(Thread.hotness), db.desc(Thread.hotness))
    return subs


def get_subreddits():
    """
    Fetch user subreddits otherwise fetch a list of defaults
    """
    if g.get('user'):
        subreddit_subs = g.user.subreddit_subs.get('subs')
        subreddits = Subreddit.query.filter(Subreddit.name.in_(subreddit_subs))
    else:
        # Default set of subreddits
        subreddits = Subreddit.query.all()
    return subreddits


def process_thread_paginator(trending=False, rs=None, subreddit=None, sort_type='hot'):
    """
    abstracted because many sources pull from a thread listing
    source (subreddit permalink, homepage, etc)
    """
    threads_per_page = 15
    cur_page = request.args.get('page') or 1
    cur_page = int(cur_page)
    thread_paginator = None

    # if we are passing in a resultset, that means we are just looking to
    # quickly paginate some arbitrary data, no sorting
    if rs:
        thread_paginator = rs.paginate(cur_page,
                                       per_page=threads_per_page,
                                       error_out=True)
        return thread_paginator

    # sexy line of code :)
    base_query = subreddit.threads if subreddit else Thread.query

    # Filter by user subs
    logger.info(g.user)
    if g.user:
        subreddit_subs = g.user.subreddit_subs.get('subs')
        base_query = base_query.join(Subreddit).filter(Subreddit.name.in_(subreddit_subs))

    # Sorting
    if sort_type == 'hot':
        base_query = base_query.order_by(db.desc(Thread.hotness))
    elif sort_type == 'top':
        base_query = base_query.order_by(db.desc(Thread.votes))
    elif sort_type == 'comments':
        base_query = base_query.order_by(db.desc(Thread.n_comments))
    elif sort_type == 'new':
        base_query = base_query.order_by(db.desc(Thread.created_on))
    elif sort_type == 'publication_date':
        base_query = base_query.join(Publication).order_by(db.desc(Publication.pub_date))

    thread_paginator = base_query.paginate(cur_page, per_page=threads_per_page, error_out=True)

    return thread_paginator


@mod.route('/')
def home(sort_type='hot'):
    """
    If not trending we order by creation date
    """
    atom_url = url_for('subreddits.atom_feed', subreddit_name='frontpage', _external=True)
    trending = True if request.path.endswith('trending') else False
    page_title = "Trending" if trending else "Frontpage"
    thread_paginator = process_thread_paginator(trending=trending)

    return render_template('home.html',
                           atom_url=atom_url,
                           page_title=page_title,
                           cur_subreddit=home_subreddit(),
                           thread_paginator=thread_paginator)


@mod.route('/.atom')
@mod.route('/.xml')
@mod.route('/.rss')
def atom_redirect():
    return redirect(url_for("subreddits.atom_feed", subreddit_name="frontpage"))


@mod.route('/h/<string:page>')
def render_markdown(page):
    page_md = f"base/markdown/{page}.md"
    if not os.path.exists(page_md):
        abort(404)
    with open(page_md, 'r') as f:
        content = f.read()
        md = markdown2.markdown(content,
                                extras = ['fenced-code-blocks',
                                          'nofollow',
                                          'target-blank-links',
                                          'toc',
                                          'tables',
                                          'footnotes',
                                          'metadata',
                                          'markdown-in-html'])
    return render_template('markdown.html',
                           page=md,
                           **md.metadata)


@mod.route('/search/', methods=['GET'])
def search():
    """
    Allows users to search threads and comments
    """
    query = request.args.get('query')
    page_title=f"Search results for '{query}'"
    rs = search_module.search(query, orderby='creation', search_title=True,
            search_text=True)

    thread_paginator = process_thread_paginator(rs=rs)
    #rs = rs.all()
    num_searches = rs.count()
    subreddits = get_subreddits()

    return render_template('home.html',
                            page_title=page_title,
                            cur_subreddit=home_subreddit(),
                            thread_paginator=thread_paginator,
                            num_searches=num_searches)


@mod.route('/login/', methods=['GET', 'POST'])
def login():
    """
    We had to do some extra work to route the user back to
    his or her original place before logging in
    """
    if g.user:
        return redirect(url_for('frontends.home'))

    next = ''
    if request.method == 'GET':
        if 'next' in request.args:
            next = request.args['next']

    form = LoginForm(request.form)
    # make sure data is valid, but doesn't validate password is right
    if form.validate_on_submit():
        # continue where we left off if so
        user = User.query.filter_by(email=form.email.data).first()
        # we use werzeug to validate user's password
        if user and check_password_hash(user.password, form.password.data):
            # the session can't be modified as it's signed,
            # it's a safe place to store the user id
            session['user_id'] = user.id

            if 'next' in request.form and request.form['next']:
                return redirect(request.form['next'])
            return redirect(url_for('frontends.home'))

        flash('Wrong email or password', 'danger')
    return render_template("login.html", form=form, next=next)


@mod.route('/logout/', methods=['GET', 'POST'])
@requires_login
def logout():
    session.pop('user_id', None)
    return redirect(url_for('frontends.home'))


@mod.route('/confirm-email/<string:token>')
def confirm_email(token):
    """
        Confirm user email
    """
    user = User.query.filter_by(email_token=token).first()
    if user.email_token == token:
        user.email_verified = True
    db.session.commit()
    flash("Thank you for confirming your email! You can now submit and comment.", 'success')
    return redirect(url_for('frontends.home'))


@mod.route('/register/', methods=['GET', 'POST'])
def register():
    """
        Registration page
    """
    if g.user:
        # If the user is logged in send them home
        return redirect(url_for('frontends.home'))

    next = ''
    if request.method == 'GET':
        if 'next' in request.args:
            next = request.args['next']

    form = RegisterForm(request.form)
    if form.validate_on_submit():
        # create an user instance not yet stored in the database
        user = User(username=form.username.data,
                    email=form.email.data, \
                    password=generate_password_hash(form.password.data),
                    university=get_school(form.email.data),
                    email_token=random_string())
        # Insert the record in our database and commit it
        db.session.add(user)
        email_confirm_link = url_for('frontends.confirm_email', token = user.email_token)
        email_response = send_email("Confirm upvote.pub email",
                                    """Please visit the link below to confirm your email:\n\n{}{}""".format(request.url_root.strip("/"), email_confirm_link),
                                    user.email)
        # Log the user in, as he now has an id
        db.session.commit()
        session['user_id'] = user.id
        flash('Thanks for signing up! Please confirm your email by following the link sent in the confirmation email.', 'success')
        if 'next' in request.form and request.form['next']:
            return redirect(request.form['next'])
        return redirect(url_for('frontends.home'))

    return render_template("register.html", form=form, next=next)


@mod.route('/subs/', methods=['GET', 'POST'])
def view_all():
    """
    """
    subreddit_list = Subreddit.query.all()
    form = None
    if g.user:
        if request.form:
            form = subreddit_subs(request.form)
            if form.validate_on_submit():
                form_subs = form.data.get('subs')
                form_subs = list(set([x['sub_name'] for x in form_subs if x['value']]))
                g.user.subreddit_subs = {'subs': form_subs}
                flash("Updated Subs", 'success')
                db.session.commit()
        else:
            form = subreddit_subs()
            for subreddit in subreddit_list:
                sform = sub_form()
                sform.sub_name = subreddit.name
                sform.sub_group = subreddit.group
                if g.user:
                    sform.value=subreddit.name in g.user.subreddit_subs['subs']
                form.subs.append_entry(sform)


    return render_template('subreddits/subs.html',
                           cur_subreddit=None,
                           page_title='subs',
                           form=form,
                           subreddit_list=subreddit_list)

[((957, 1004), 'flask.Blueprint', 'Blueprint', (['"""frontends"""', '__name__'], {'url_prefix': '""""""'}), "('frontends', __name__, url_prefix='')\n", (966, 1004), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1074, 1096), 'flask.session.get', 'session.get', (['"""user_id"""'], {}), "('user_id')\n", (1085, 1096), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1178, 1197), 'logzero.logger.info', 'logger.info', (['g.user'], {}), '(g.user)\n', (1189, 1197), False, 'from logzero import logger\n'), ((1205, 1218), 'flask.g.get', 'g.get', (['"""user"""'], {}), "('user')\n", (1210, 1218), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1660, 1673), 'flask.g.get', 'g.get', (['"""user"""'], {}), "('user')\n", (1665, 1673), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((2738, 2757), 'logzero.logger.info', 'logger.info', (['g.user'], {}), '(g.user)\n', (2749, 2757), False, 'from logzero import logger\n'), ((3705, 3780), 'flask.url_for', 'url_for', (['"""subreddits.atom_feed"""'], {'subreddit_name': '"""frontpage"""', '_external': '(True)'}), "('subreddits.atom_feed', subreddit_name='frontpage', _external=True)\n", (3712, 3780), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((5120, 5176), 'flask.render_template', 'render_template', (['"""markdown.html"""'], {'page': 'md'}), "('markdown.html', page=md, **md.metadata)\n", (5135, 5176), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((5363, 5388), 'flask.request.args.get', 'request.args.get', (['"""query"""'], {}), "('query')\n", (5379, 5388), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((5445, 5533), 'base.search.search', 'search_module.search', (['query'], {'orderby': '"""creation"""', 'search_title': '(True)', 'search_text': '(True)'}), "(query, orderby='creation', search_title=True,\n    search_text=True)\n", (5465, 5533), True, 'from base import search as search_module\n'), ((6336, 6359), 'base.users.forms.LoginForm', 'LoginForm', (['request.form'], {}), '(request.form)\n', (6345, 6359), False, 'from base.users.forms import RegisterForm, LoginForm\n'), ((7094, 7145), 'flask.render_template', 'render_template', (['"""login.html"""'], {'form': 'form', 'next': 'next'}), "('login.html', form=form, next=next)\n", (7109, 7145), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((7230, 7258), 'flask.session.pop', 'session.pop', (['"""user_id"""', 'None'], {}), "('user_id', None)\n", (7241, 7258), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((7553, 7572), 'base.db.session.commit', 'db.session.commit', ([], {}), '()\n', (7570, 7572), False, 'from base import db, app\n'), ((7577, 7669), 'flask.flash', 'flash', (['"""Thank you for confirming your email! You can now submit and comment."""', '"""success"""'], {}), "('Thank you for confirming your email! You can now submit and comment.',\n    'success')\n", (7582, 7669), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((8073, 8099), 'base.users.forms.RegisterForm', 'RegisterForm', (['request.form'], {}), '(request.form)\n', (8085, 8099), False, 'from base.users.forms import RegisterForm, LoginForm\n'), ((9338, 9392), 'flask.render_template', 'render_template', (['"""register.html"""'], {'form': 'form', 'next': 'next'}), "('register.html', form=form, next=next)\n", (9353, 9392), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((9494, 9515), 'base.subreddits.models.Subreddit.query.all', 'Subreddit.query.all', ([], {}), '()\n', (9513, 9515), False, 'from base.subreddits.models import Subreddit\n'), ((10339, 10464), 'flask.render_template', 'render_template', (['"""subreddits/subs.html"""'], {'cur_subreddit': 'None', 'page_title': '"""subs"""', 'form': 'form', 'subreddit_list': 'subreddit_list'}), "('subreddits/subs.html', cur_subreddit=None, page_title=\n    'subs', form=form, subreddit_list=subreddit_list)\n", (10354, 10464), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1115, 1149), 'base.users.models.User.query.get', 'User.query.get', (["session['user_id']"], {}), "(session['user_id'])\n", (1129, 1149), False, 'from base.users.models import User\n'), ((1245, 1278), 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', (['"""subs"""'], {}), "('subs')\n", (1270, 1278), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1700, 1733), 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', (['"""subs"""'], {}), "('subs')\n", (1725, 1733), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1881, 1902), 'base.subreddits.models.Subreddit.query.all', 'Subreddit.query.all', ([], {}), '()\n', (1900, 1902), False, 'from base.subreddits.models import Subreddit\n'), ((2183, 2207), 'flask.request.args.get', 'request.args.get', (['"""page"""'], {}), "('page')\n", (2199, 2207), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((2798, 2831), 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', (['"""subs"""'], {}), "('subs')\n", (2823, 2831), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((3804, 3837), 'flask.request.path.endswith', 'request.path.endswith', (['"""trending"""'], {}), "('trending')\n", (3825, 3837), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((4335, 4394), 'flask.url_for', 'url_for', (['"""subreddits.atom_feed"""'], {'subreddit_name': '"""frontpage"""'}), "('subreddits.atom_feed', subreddit_name='frontpage')\n", (4342, 4394), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((4508, 4531), 'os.path.exists', 'os.path.exists', (['page_md'], {}), '(page_md)\n', (4522, 4531), False, 'import os\n'), ((4541, 4551), 'flask.abort', 'abort', (['(404)'], {}), '(404)\n', (4546, 4551), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((4626, 4788), 'markdown2.markdown', 'markdown2.markdown', (['content'], {'extras': "['fenced-code-blocks', 'nofollow', 'target-blank-links', 'toc', 'tables',\n    'footnotes', 'metadata', 'markdown-in-html']"}), "(content, extras=['fenced-code-blocks', 'nofollow',\n    'target-blank-links', 'toc', 'tables', 'footnotes', 'metadata',\n    'markdown-in-html'])\n", (4644, 4788), False, 'import markdown2\n'), ((7040, 7082), 'flask.flash', 'flash', (['"""Wrong email or password"""', '"""danger"""'], {}), "('Wrong email or password', 'danger')\n", (7045, 7082), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((7279, 7304), 'flask.url_for', 'url_for', (['"""frontends.home"""'], {}), "('frontends.home')\n", (7286, 7304), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((7686, 7711), 'flask.url_for', 'url_for', (['"""frontends.home"""'], {}), "('frontends.home')\n", (7693, 7711), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((8541, 8561), 'base.db.session.add', 'db.session.add', (['user'], {}), '(user)\n', (8555, 8561), False, 'from base import db, app\n'), ((8591, 8649), 'flask.url_for', 'url_for', (['"""frontends.confirm_email"""'], {'token': 'user.email_token'}), "('frontends.confirm_email', token=user.email_token)\n", (8598, 8649), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((8977, 8996), 'base.db.session.commit', 'db.session.commit', ([], {}), '()\n', (8994, 8996), False, 'from base import db, app\n'), ((9042, 9174), 'flask.flash', 'flash', (['"""Thanks for signing up! Please confirm your email by following the link sent in the confirmation email."""', '"""success"""'], {}), "(\n    'Thanks for signing up! Please confirm your email by following the link sent in the confirmation email.'\n    , 'success')\n", (9047, 9174), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((1403, 1437), 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', (['subreddit_subs'], {}), '(subreddit_subs)\n', (1421, 1437), False, 'from base.subreddits.models import Subreddit\n'), ((1486, 1509), 'base.db.desc', 'db.desc', (['Thread.hotness'], {}), '(Thread.hotness)\n', (1493, 1509), False, 'from base import db, app\n'), ((1511, 1534), 'base.db.desc', 'db.desc', (['Thread.hotness'], {}), '(Thread.hotness)\n', (1518, 1534), False, 'from base import db, app\n'), ((1778, 1812), 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', (['subreddit_subs'], {}), '(subreddit_subs)\n', (1796, 1812), False, 'from base.subreddits.models import Subreddit\n'), ((2887, 2921), 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', (['subreddit_subs'], {}), '(subreddit_subs)\n', (2905, 2921), False, 'from base.subreddits.models import Subreddit\n'), ((3006, 3029), 'base.db.desc', 'db.desc', (['Thread.hotness'], {}), '(Thread.hotness)\n', (3013, 3029), False, 'from base import db, app\n'), ((6175, 6200), 'flask.url_for', 'url_for', (['"""frontends.home"""'], {}), "('frontends.home')\n", (6182, 6200), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((6647, 6701), 'werkzeug.check_password_hash', 'check_password_hash', (['user.password', 'form.password.data'], {}), '(user.password, form.password.data)\n', (6666, 6701), False, 'from werkzeug import check_password_hash, generate_password_hash\n'), ((7432, 7471), 'base.users.models.User.query.filter_by', 'User.query.filter_by', ([], {'email_token': 'token'}), '(email_token=token)\n', (7452, 7471), False, 'from base.users.models import User\n'), ((7912, 7937), 'flask.url_for', 'url_for', (['"""frontends.home"""'], {}), "('frontends.home')\n", (7919, 7937), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((9244, 9274), 'flask.redirect', 'redirect', (["request.form['next']"], {}), "(request.form['next'])\n", (9252, 9274), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((9299, 9324), 'flask.url_for', 'url_for', (['"""frontends.home"""'], {}), "('frontends.home')\n", (9306, 9324), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((9591, 9619), 'base.subreddits.forms.subreddit_subs', 'subreddit_subs', (['request.form'], {}), '(request.form)\n', (9605, 9619), False, 'from base.subreddits.forms import subreddit_subs, sub_form\n'), ((9978, 9994), 'base.subreddits.forms.subreddit_subs', 'subreddit_subs', ([], {}), '()\n', (9992, 9994), False, 'from base.subreddits.forms import subreddit_subs, sub_form\n'), ((3101, 3122), 'base.db.desc', 'db.desc', (['Thread.votes'], {}), '(Thread.votes)\n', (3108, 3122), False, 'from base import db, app\n'), ((6522, 6565), 'base.users.models.User.query.filter_by', 'User.query.filter_by', ([], {'email': 'form.email.data'}), '(email=form.email.data)\n', (6542, 6565), False, 'from base.users.models import User\n'), ((6945, 6975), 'flask.redirect', 'redirect', (["request.form['next']"], {}), "(request.form['next'])\n", (6953, 6975), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((7004, 7029), 'flask.url_for', 'url_for', (['"""frontends.home"""'], {}), "('frontends.home')\n", (7011, 7029), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((8322, 8364), 'werkzeug.generate_password_hash', 'generate_password_hash', (['form.password.data'], {}), '(form.password.data)\n', (8344, 8364), False, 'from werkzeug import check_password_hash, generate_password_hash\n'), ((8397, 8424), 'base.utils.user_utils.get_school', 'get_school', (['form.email.data'], {}), '(form.email.data)\n', (8407, 8424), False, 'from base.utils.user_utils import get_school\n'), ((8458, 8473), 'base.utils.misc.random_string', 'random_string', ([], {}), '()\n', (8471, 8473), False, 'from base.utils.misc import random_string, validate_sort_type\n'), ((8824, 8851), 'flask.request.url_root.strip', 'request.url_root.strip', (['"""/"""'], {}), "('/')\n", (8846, 8851), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((9876, 9908), 'flask.flash', 'flash', (['"""Updated Subs"""', '"""success"""'], {}), "('Updated Subs', 'success')\n", (9881, 9908), False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((9925, 9944), 'base.db.session.commit', 'db.session.commit', ([], {}), '()\n', (9942, 9944), False, 'from base import db, app\n'), ((10064, 10074), 'base.subreddits.forms.sub_form', 'sub_form', ([], {}), '()\n', (10072, 10074), False, 'from base.subreddits.forms import subreddit_subs, sub_form\n'), ((1316, 1339), 'base.db.desc', 'db.desc', (['Thread.hotness'], {}), '(Thread.hotness)\n', (1323, 1339), False, 'from base import db, app\n'), ((1341, 1364), 'base.db.desc', 'db.desc', (['Thread.hotness'], {}), '(Thread.hotness)\n', (1348, 1364), False, 'from base import db, app\n'), ((3199, 3225), 'base.db.desc', 'db.desc', (['Thread.n_comments'], {}), '(Thread.n_comments)\n', (3206, 3225), False, 'from base import db, app\n'), ((3297, 3323), 'base.db.desc', 'db.desc', (['Thread.created_on'], {}), '(Thread.created_on)\n', (3304, 3323), False, 'from base import db, app\n'), ((3426, 3455), 'base.db.desc', 'db.desc', (['Publication.pub_date'], {}), '(Publication.pub_date)\n', (3433, 3455), False, 'from base import db, app\n')]