<commit_before>from . import app
from . import rec_systems
from flask import request
from flask.ext.restful import reqparse
from datetime import datetime

@app.route('/')
def index():
    return 'Welcome!'

view_arg_parser = reqparse.RequestParser()
view_arg_parser.add_argument('api_key', type=str, required=True)
view_arg_parser.add_argument('community_id', type=str)
view_arg_parser.add_argument('query_string', type=str, required=True)
view_arg_parser.add_argument('record_id', type=str, required=True)
view_arg_parser.add_argument('session_id', type=str, required=True)
view_arg_parser.add_argument('timestamp', type=int, required=True)

@app.route('/api/view', methods=['GET'])
def view():
    args = view_arg_parser.parse_args(request)

    api_key = args['api_key']
    community_id = args['community_id']
    if not community_id:
        community_id = app.config['DEFAULT_COMMUNITY']
    query_string = args['query_string']
    record_id = args['record_id']
    session_id = args['session_id']
    t_stamp = datetime.fromtimestamp(
        args['timestamp']
    ).strftime('%Y-%m-%d %H:%M:%S')

    if community_id not in rec_systems:
        return 'No Community called: {}'.format(community_id)
    rec = rec_systems[community_id]
    rec.register_hit(
        query_string=query_string, record_id=record_id,
        t_stamp=t_stamp, session_id=session_id)

    return 'Complete'

simq_arg_parser = reqparse.RequestParser()
simq_arg_parser.add_argument('api_key', type=str, required=True)
simq_arg_parser.add_argument('community_id', type=str)
simq_arg_parser.add_argument('query_string', type=str, required=True)

@app.route('/api/similar_queries', methods=['GET'])
def similar_queries():
    '''Returns a list of queries which are similar to the target query'''
    args = simq_arg_parser.parse_args(request)

    api_key = args['api_key']
    community_id = args['community_id']
    query_string = args['query_string']

sreq_arg_parser = reqparse.RequestParser()
sreq_arg_parser.add_argument('api_key', type=str, required=True)
sreq_arg_parser.add_argument('community_id', type=str)
sreq_arg_parser.add_argument('query_string', type=str, required=True)

@app.route('/api/search_recommendation', methods=['GET'])
def search_recommendation():
    '''Recommends search results other users from the same community where
    interested in when using a similar query'''
    args = sreq_arg_parser.parse_args(request)

    api_key = args['api_key']
    community_id = args['community_id']
    query_string = args['query_string']
<commit_msg>handling default community<commit_after>from . import app
from . import rec_systems
from flask import request
from flask.ext.restful import reqparse
from datetime import datetime

@app.route('/')
def index():
    return 'Welcome!'

view_arg_parser = reqparse.RequestParser()
view_arg_parser.add_argument('api_key', type=str, required=True)
view_arg_parser.add_argument(
    'community_id', type=str, default=app.config['DEFAULT_COMMUNITY'])
view_arg_parser.add_argument('query_string', type=str, required=True)
view_arg_parser.add_argument('record_id', type=str, required=True)
view_arg_parser.add_argument('session_id', type=str, required=True)
view_arg_parser.add_argument('timestamp', type=int, required=True)

@app.route('/api/view', methods=['GET'])
def view():
    args = view_arg_parser.parse_args(request)

    api_key = args['api_key']
    community_id = args['community_id']
    query_string = args['query_string']
    record_id = args['record_id']
    session_id = args['session_id']
    t_stamp = datetime.fromtimestamp(
        args['timestamp']
    ).strftime('%Y-%m-%d %H:%M:%S')

    if community_id not in rec_systems:
        return 'No Community called: {}'.format(community_id)
    rec = rec_systems[community_id]
    rec.register_hit(
        query_string=query_string, record_id=record_id,
        t_stamp=t_stamp, session_id=session_id)

    return 'Complete'

simq_arg_parser = reqparse.RequestParser()
simq_arg_parser.add_argument('api_key', type=str, required=True)
simq_arg_parser.add_argument(
    'community_id', type=str, default=app.config['DEFAULT_COMMUNITY'])
simq_arg_parser.add_argument('query_string', type=str, required=True)

@app.route('/api/similar_queries', methods=['GET'])
def similar_queries():
    '''Returns a list of queries which are similar to the target query'''
    args = simq_arg_parser.parse_args(request)

    api_key = args['api_key']
    community_id = args['community_id']
    query_string = args['query_string']

sreq_arg_parser = reqparse.RequestParser()
sreq_arg_parser.add_argument('api_key', type=str, required=True)
sreq_arg_parser.add_argument(
    'community_id', type=str, default=app.config['DEFAULT_COMMUNITY'])
sreq_arg_parser.add_argument('query_string', type=str, required=True)

@app.route('/api/search_recommendation', methods=['GET'])
def search_recommendation():
    '''Recommends search results other users from the same community where
    interested in when using a similar query'''
    args = sreq_arg_parser.parse_args(request)

    api_key = args['api_key']
    community_id = args['community_id']
    query_string = args['query_string']
<|endoftext|>


<commit_before>from lxml import etree
import abc
import re
import requests

import gensim.models as models
import gensim.models.phrases as phrases
import gensim.models.word2vec as word2vec

class Rewriter(object):
  """
  Abstract class around a query rewriter, which takes a given term and
  rewrites it to a set of semantically related terms. This, hopefully,
  helps search engines return more, and more useful, results.
  """
  # make it an abstract class
  __metaclass__ = abc.ABCMeta

  def rewrite(self, term):
    """
    Rewrites a term to a list of new terms to search with. Abstract base!

    :param str term: a string to rewrite
    :return: a list of semantically related strings, including ``term``
    :rtype: list(str)
    """
    raise NotImplementedError("Subclasses must implement!")

class ControlRewriter(Rewriter):
  """
  A rewriter that's basically a no-op. Just returns the term you give it.
  This is mostly useful for testing purposes.
  """

  def rewrite(self, term):
    """
    Rewrites a term to a list containing just itself. This is the degenerate case
    of query rewriting - the original term isn't actually rewritten at all.

    ``rewrite(x) == [x]`` for all x.

    :param str term: a string to rewrite
    :return: a list containing just ``term``
    :rtype: list(str)
    """
    return [term]

class WikipediaRewriter(Rewriter):
  """
  A class to rewrite queries using Wikipedia's category api.
  """

  WIKI_BASE = 'https://en.wikipedia.org/w/api.php?format=xml&action=query&prop=categories&titles='

  def clean_category(self, x):
    return x.replace('Category:', '')

  def rewrite(self, term):
    """
    Given a base term, returns a list of related terms based on the Wikipedia
    category API.
    """
    api = self.WIKI_BASE + term
    r = requests.get(api)
    tree = etree.fromstring(r.text)

    # TODO join this and the below
    wikipedia_results = [self.clean_category(
        x.get('title')) for x in tree.findall('.//cl')]

    # Words that identify a need to drop the category
    dropwords = ['articles', 'wikipedia', 'accuracy', 'articles', 'statements',
                 'magic', 'pages', 'authors', 'editors', 'appearances', 'redirects', 'cs1']
    dropwords.append(term)
    wikipedia_results = [w.split('Category:')[-1].lower()
                         for w in wikipedia_results if not any(d in w.lower() for d in dropwords)]

    # append the original term just for completeness
    raw_results = wikipedia_results + [term]
    # convert to unicode for consistency w/ other rewriters
    # TODO this doesn't work
    return raw_results
    # return [unicode(rr) for rr in raw_results]

class Word2VecRewriter(Rewriter):
  """
  A class to rewrite queries using Word2Vec trained on a user-provided
  corpus.
  """

  # TODO use kwargs or something to make creating this less insane
  # http://stackoverflow.com/questions/1098549/proper-way-to-use-kwargs-in-python#1098556
  def __init__(self, model_path, create=False, corpus=None, bigrams=True):
    """
    Initializes the rewriter, given a particular word2vec corpus.
    A good example corpus is the Text8Corpus or the Brown corpus.
    You only need the corpus if you are recreating the model from scratch.

    If create is True, this generates a new Word2Vec
    model (which takes a really long time to build.) If False, this loads
    an existing model we already saved.

    :param model_path {string}: where to store the model files. This file
        needn't exist, but its parent folder should.
    :param create {bool}: True to create a new Word2Vec model, False to
        use the one stored at `model_path`.
    :param corpus {Iterable}: only needed if `create=True`. Defines a corpus
        for Word2Vec to learn from.
    :param bigrams {bool}: only needed if `create=True`. If True, takes some
        more time to build a model that supports bigrams (e.g. `new_york`).
        Otherwise, it'll only support one-word searches. `bigram=True` makes
        this slower but more complete.
    """

    self.model_path = model_path

    # TODO: add logic around defaulting to creating or not

    if create:
      # generate a new Word2Vec model... takes a while!
      # TODO optimize parameters

      transformed_corpus = None
      if bigrams:
        # TODO save the phraser somewhere... but that requires
        # even more arguments.
        # the Phrases class lets you generate bigrams, but the
        # Phraser class is a more compact version of the same
        # TODO making the phrases takes forever, making the phraser
        # takes forever, turning it into a list takes forever... this
        # is really annoying. is there any way to speed it up?
        bigram_generator = phrases.Phraser(phrases.Phrases(corpus))
        # weird bug where the bigram generator won't work unless
        # it's turned into a list first. if you try to do it straight,
        # it'll give you total gibberish. FIXME
        bigram_corpus = list(bigram_generator[corpus])
        transformed_corpus = bigram_corpus
      else:
        # no bigrams, same old corpus
        transformed_corpus = corpus

      self.model = word2vec.Word2Vec(transformed_corpus, workers=8)
      self.model.save(self.model_path)
    else:
      self.model = word2vec.Word2Vec.load(self.model_path)

  def rewrite(self, term):
    # try using the model to rewrite the term
    results = []
    try:
      # preprocess the term so it's more palatable to word2vec
      encoded_term = self.encode_term(term)
      # most_similar returns an array of tuples, each representing a term/phrase
      # that is close to the original
      # TODO consider choosing fewer results! or have a higher bar on how
      # related they need to be
      raw_results = self.model.similar_by_word(encoded_term, topn=10)

      # extract just the name, which is index 0
      # and decode all the results we get from word2vec
      results = [self.decode_term(r[0]) for r in raw_results]
    except KeyError as k:
      # the word wasn't found in the model... must be too niche.
      # no results then
      results = []

    # finally, tack on the original term to the results for completeness
    return results + [term.decode("utf8")]

  def encode_term(self, term):
    """
    Converts a search term like `Hadrian's Wall` to `hadrians_wall`, which
    plays better with word2vec.
    """
    # remove anything that isn't alphanumeric or space
    alphanum_pattern = re.compile(r'[^\w\d\s]')
    cleaned = alphanum_pattern.sub('', term)
    # sub out spaces for underscores
    space_pattern = re.compile(' ')
    cleaned = space_pattern.sub('_', cleaned)
    # finally lowercase it all
    # TODO replace numbers with words (mp3 => mp_three)
    return cleaned.lower()

  def decode_term(self, encoded):
    """
    Converts an encoded search term into something more human readable,
    like `hadrians_wall` to `hadrians wall`.
    """
    # not much we can do besides replace underscores with spaces
    underscore_pattern = re.compile('_')
    return underscore_pattern.sub(' ', encoded)
<commit_msg>tweaks to docing<commit_after>from lxml import etree
import abc
import re
import requests

import gensim.models as models
import gensim.models.phrases as phrases
import gensim.models.word2vec as word2vec

class Rewriter(object):
  """
  Abstract class around a query rewriter, which takes a given term and
  rewrites it to a set of semantically related terms. This, hopefully,
  helps search engines return more, and more useful, results.
  """
  # make it an abstract class
  __metaclass__ = abc.ABCMeta

  def rewrite(self, term):
    """
    Rewrites a term to a list of new terms to search with. Abstract base!

    :param str term: a string to rewrite
    :return: a list of semantically related strings, including ``term``
    :rtype: list(str)
    """
    raise NotImplementedError("Subclasses must implement!")

class ControlRewriter(Rewriter):
  """
  A rewriter that's basically a no-op. Just returns the term you give it.
  This is mostly useful for testing purposes.
  """

  def rewrite(self, term):
    """
    Rewrites a term to a list containing just itself. This is the degenerate case
    of query rewriting - the original term isn't actually rewritten at all.

    ``rewrite(x) == [x]`` for all x.

    :param str term: a string to rewrite
    :return: a list containing just ``term``
    :rtype: list(str)
    """
    return [term]

class WikipediaRewriter(Rewriter):
  """
  A class to rewrite queries using Wikipedia's Category API.
  """

  WIKI_BASE = 'https://en.wikipedia.org/w/api.php?format=xml&action=query&prop=categories&titles='

  def clean_category(self, x):
    return x.replace('Category:', '')

  def rewrite(self, term):
    """
    Given a base term, returns a list of related terms based on the Wikipedia
    category API.

    For example, visit your favorite Wikipedia page and look for the list of
    Categories at the very bottom of the page.

    :param str term: a string to rewrite
    :return: a list of semantically related strings, including ``term``
    :rtype: list(str)
    """
    api = self.WIKI_BASE + term
    r = requests.get(api)
    tree = etree.fromstring(r.text)

    # TODO join this and the below
    wikipedia_results = [self.clean_category(
        x.get('title')) for x in tree.findall('.//cl')]

    # Words that identify a need to drop the category
    dropwords = ['articles', 'wikipedia', 'accuracy', 'articles', 'statements',
                 'magic', 'pages', 'authors', 'editors', 'appearances', 'redirects', 'cs1']
    dropwords.append(term)
    wikipedia_results = [w.split('Category:')[-1].lower()
                         for w in wikipedia_results if not any(d in w.lower() for d in dropwords)]

    # append the original term just for completeness
    raw_results = wikipedia_results + [term]
    # convert to unicode for consistency w/ other rewriters
    # TODO this doesn't work
    return raw_results
    # return [unicode(rr) for rr in raw_results]

class Word2VecRewriter(Rewriter):
  """
  A class to rewrite queries using Word2Vec, an NLP package that finds
  semantically related words and phrases to inputted words and phrases.
  Word2Vec must be trained on a user-provided dataset before it is used.
  """

  # TODO use kwargs or something to make creating this less insane
  # http://stackoverflow.com/questions/1098549/proper-way-to-use-kwargs-in-python#1098556
  def __init__(self, model_path, create=False, corpus=None, bigrams=True):
    """
    Initializes the rewriter, given a particular Word2Vec corpus.
    A good example corpus is the Wikipedia Text8Corpus.
    You only need the corpus if you are recreating the model from scratch.

    If ``create == True``, this generates a new Word2Vec
    model (which takes a really long time to build.) If ``False``, this loads
    an existing model we already saved.

    :param str model_path: where to store the model files. This file
        needn't exist, but its parent folder should.
    :param bool create: True to create a new Word2Vec model, False to
        use the one stored at ``model_path``.
    :param Iterable corpus: only needed if ``create=True``. Defines a corpus
        for Word2Vec to learn from.
    :param bool bigrams: only needed if ``create=True``. If True, takes some
        more time to build a model that supports bigrams (e.g. ```new_york``).
        Otherwise, it'll only support one-word searches. ``bigram=True`` makes
        this slower but more complete.
    """

    self.model_path = model_path

    # TODO: add logic around defaulting to creating or not

    if create:
      # generate a new Word2Vec model... takes a while!
      # TODO optimize parameters

      transformed_corpus = None
      if bigrams:
        # TODO save the phraser somewhere... but that requires
        # even more arguments.
        # the Phrases class lets you generate bigrams, but the
        # Phraser class is a more compact version of the same
        # TODO making the phrases takes forever, making the phraser
        # takes forever, turning it into a list takes forever... this
        # is really annoying. is there any way to speed it up?
        bigram_generator = phrases.Phraser(phrases.Phrases(corpus))
        # weird bug where the bigram generator won't work unless
        # it's turned into a list first. if you try to do it straight,
        # it'll give you total gibberish. FIXME
        bigram_corpus = list(bigram_generator[corpus])
        transformed_corpus = bigram_corpus
      else:
        # no bigrams, same old corpus
        transformed_corpus = corpus

      self.model = word2vec.Word2Vec(transformed_corpus, workers=8)
      self.model.save(self.model_path)
    else:
      self.model = word2vec.Word2Vec.load(self.model_path)

  def rewrite(self, term):
    # try using the model to rewrite the term
    results = []
    try:
      # preprocess the term so it's more palatable to word2vec
      encoded_term = self.encode_term(term)
      # most_similar returns an array of tuples, each representing a term/phrase
      # that is close to the original
      # TODO consider choosing fewer results! or have a higher bar on how
      # related they need to be
      raw_results = self.model.similar_by_word(encoded_term, topn=10)

      # extract just the name, which is index 0
      # and decode all the results we get from word2vec
      results = [self.decode_term(r[0]) for r in raw_results]
    except KeyError as k:
      # the word wasn't found in the model... must be too niche.
      # no results then
      results = []

    # finally, tack on the original term to the results for completeness
    return results + [term.decode("utf8")]

  def encode_term(self, term):
    """
    Converts a search term like `Hadrian's Wall` to `hadrians_wall`, which
    plays better with word2vec.
    """
    # remove anything that isn't alphanumeric or space
    alphanum_pattern = re.compile(r'[^\w\d\s]')
    cleaned = alphanum_pattern.sub('', term)
    # sub out spaces for underscores
    space_pattern = re.compile(' ')
    cleaned = space_pattern.sub('_', cleaned)
    # finally lowercase it all
    # TODO replace numbers with words (mp3 => mp_three)
    return cleaned.lower()

  def decode_term(self, encoded):
    """
    Converts an encoded search term into something more human readable,
    like `hadrians_wall` to `hadrians wall`.
    """
    # not much we can do besides replace underscores with spaces
    underscore_pattern = re.compile('_')
    return underscore_pattern.sub(' ', encoded)
<|endoftext|>


<commit_before>## The goal of this module is to eventually be to MIDI players what
## 'webbrowser' is to Web browsers.
##
## Personally, I only need it to work on OS X so patches accepted for other
## operating systems.

import sys
import tempfile
import subprocess

from sebastian.midi import write_midi

def play(tracks):
    f = tempfile.NamedTemporaryFile(suffix=".mid", delete=False)
    s = write_midi.SMF(tracks)
    s.write(f)
    f.close()
    if sys.platform == "darwin":
        subprocess.call(["open", f.name])
    elif sys.platform == "linux2":
        subprocess.call(["timidity", f.name])
    else:
        print "Only OS X supported at the moment. Patches accepted!"
<commit_msg>Added support for passing `program` to play(). Added constants for default programs<commit_after>## The goal of this module is to eventually be to MIDI players what
## 'webbrowser' is to Web browsers.

import sys
import tempfile
import subprocess

from sebastian.midi import write_midi

OPEN = 'open'
TIMIDITY = 'timidity'

def play(tracks, program=''):
    f = tempfile.NamedTemporaryFile(suffix=".mid", delete=False)
    s = write_midi.SMF(tracks)
    s.write(f)
    f.close()
    if not program:
        if sys.platform == "darwin":
            program = OPEN
        elif sys.platform == "linux2":
            program = TIMIDITY
    if program:
        subprocess.call([program, f.name])
    else:
        print 'A suitable program for your platform is unknown'
<|endoftext|>


<commit_before>import logging
# from botanio import botan
# import json
import os

import pkg_resources
import requests
import youtube_dl
from plumbum import local
from requests.exceptions import Timeout, RequestException, SSLError

bin_path = os.getenv('BIN_PATH', '')
scdl_bin = local[os.path.join(bin_path, 'scdl')]
bandcamp_dl_bin = local[os.path.join(bin_path, 'bandcamp-dl')]
youtube_dl_bin = local[os.path.join(bin_path, 'youtube-dl')]

BOTAN_TRACK_URL = 'https://api.botan.io/track'
BOTAN_SHORTENER_URL = 'https://api.botan.io/s/'

logger = logging.getLogger(__name__)

def get_response_text(file_name):
    # https://stackoverflow.com/a/20885799/2490759
    path = '/'.join(('texts', file_name))
    return pkg_resources.resource_string(__name__, path).decode("UTF-8")

def md_italic(text):
    return "".join(["_", text, "_"])

def youtube_dl_func(url, ydl_opts, queue=None):
    ydl = youtube_dl.YoutubeDL(ydl_opts)
    try:
        ydl.download([url])
    except Exception as exc:
        ydl_status = 1, str(exc)
        # ydl_status = exc  #TODO: pass and re-raise original Exception
    else:
        ydl_status = 0, "OK"
    if queue:
        queue.put(ydl_status)
    else:
        return ydl_status

def botan_track(token, message, event_name):
    try:
        # uid = message.chat_id
        uid = message.from_user.id
    except AttributeError:
        logger.warning('No chat_id in message')
        return False
    num_retries = 2
    ssl_verify = True
    for i in range(num_retries):
        try:
            r = requests.post(
                BOTAN_TRACK_URL,
                params={"token": token, "uid": uid, "name": event_name},
                json=message.to_dict(),
                verify=ssl_verify,
            )
            return r.json()
        except Timeout:
            logger.exception("botan_track timeout")
        except SSLError:
            ssl_verify = False
        except (Exception, RequestException, ValueError):
            # catastrophic error
            logger.exception("botan_track catastrophic error")
    return False
<commit_msg>🙀astrophic error<commit_after>import logging
# from botanio import botan
# import json
import os

import pkg_resources
import requests
import youtube_dl
from plumbum import local
from requests.exceptions import Timeout, RequestException, SSLError

bin_path = os.getenv('BIN_PATH', '')
scdl_bin = local[os.path.join(bin_path, 'scdl')]
bandcamp_dl_bin = local[os.path.join(bin_path, 'bandcamp-dl')]
youtube_dl_bin = local[os.path.join(bin_path, 'youtube-dl')]

BOTAN_TRACK_URL = 'https://api.botan.io/track'
BOTAN_SHORTENER_URL = 'https://api.botan.io/s/'

logger = logging.getLogger(__name__)

def get_response_text(file_name):
    # https://stackoverflow.com/a/20885799/2490759
    path = '/'.join(('texts', file_name))
    return pkg_resources.resource_string(__name__, path).decode("UTF-8")

def md_italic(text):
    return "".join(["_", text, "_"])

def youtube_dl_func(url, ydl_opts, queue=None):
    ydl = youtube_dl.YoutubeDL(ydl_opts)
    try:
        ydl.download([url])
    except Exception as exc:
        ydl_status = 1, str(exc)
        # ydl_status = exc  #TODO: pass and re-raise original Exception
    else:
        ydl_status = 0, "OK"
    if queue:
        queue.put(ydl_status)
    else:
        return ydl_status

def botan_track(token, message, event_name):
    try:
        # uid = message.chat_id
        uid = message.from_user.id
    except AttributeError:
        logger.warning('No chat_id in message')
        return False
    num_retries = 2
    ssl_verify = True
    for i in range(num_retries):
        try:
            r = requests.post(
                BOTAN_TRACK_URL,
                params={"token": token, "uid": uid, "name": event_name},
                json=message.to_dict(),
                verify=ssl_verify,
            )
            return r.json()
        except Timeout:
            logger.exception("botan_track timeout")
        except SSLError:
            ssl_verify = False
        except (Exception, RequestException, ValueError):
            # catastrophic error
            logger.exception("botan_track 🙀astrophic error")
    return False
<|endoftext|>


<commit_before>import datetime
from flask import Blueprint, redirect, request, render_template, url_for
from flask_login import current_user, login_required
from app import app
from app.forms import CreatePostForm
from app.models import Page, Post

mod = Blueprint('general', __name__)

def url_for_other_page(page):
    args = request.view_args.copy()
    args['page'] = page
    return url_for(request.endpoint, **args)
app.jinja_env.globals['url_for_other_page'] = url_for_other_page

@mod.route('/<page>/new-post/', methods=['GET', 'POST'])
@login_required
def new_post(page):
    page_obj = Page.get(Page.name == page)
    form = CreatePostForm(request.form)
    if form.validate_on_submit():
        post = Post.create(title=form.title.data,
                           content=form.content.data,
                           published=form.published.data,
                           timestamp=datetime.datetime.now(),
                           author=current_user.id,
                           page=page_obj.id)
        return redirect(post.slug)

    return render_template('edit-post.html', page=page_obj, form=form)

@mod.route('/<slug>/')
def view_post(slug):
    post = Post.get(Post.slug == slug)
    return render_template('view-post.html',
                           post=post)

@mod.route('/<slug>/edit/', methods=['GET', 'POST'])
@login_required
def edit_post(slug):
    post = Post.get(Post.slug == slug)
    form = CreatePostForm(request.form, post)

    if form.validate_on_submit():
        post.title = form.title.data
        post.content = form.content.data
        post.published = form.published.data
        post.save()
        return redirect(post.slug)

    return render_template('edit-post.html',
                           page=None,
                           form=form)
<commit_msg>return 404 if url doesn't match at slug<commit_after>import datetime
from flask import Blueprint, redirect, request, render_template, url_for
from flask_login import current_user, login_required
from playhouse.flask_utils import get_object_or_404
from app import app
from app.forms import CreatePostForm
from app.models import Page, Post

mod = Blueprint('general', __name__)

def url_for_other_page(page):
    args = request.view_args.copy()
    args['page'] = page
    return url_for(request.endpoint, **args)
app.jinja_env.globals['url_for_other_page'] = url_for_other_page

@mod.route('/<page>/new-post/', methods=['GET', 'POST'])
@login_required
def new_post(page):
    page_obj = Page.get(Page.name == page)
    form = CreatePostForm(request.form)
    if form.validate_on_submit():
        post = Post.create(title=form.title.data,
                           content=form.content.data,
                           published=form.published.data,
                           timestamp=datetime.datetime.now(),
                           author=current_user.id,
                           page=page_obj.id)
        return redirect(post.slug)

    return render_template('edit-post.html', page=page_obj, form=form)

@mod.route('/<slug>/')
def view_post(slug):
    post = get_object_or_404(Post, Post.slug == slug)
    return render_template('view-post.html',
                           post=post)

@mod.route('/<slug>/edit/', methods=['GET', 'POST'])
@login_required
def edit_post(slug):
    post = get_object_or_404(Post, Post.slug == slug)
    form = CreatePostForm(request.form, post)

    if form.validate_on_submit():
        post.title = form.title.data
        post.content = form.content.data
        post.published = form.published.data
        post.save()
        return redirect(post.slug)

    return render_template('edit-post.html',
                           page=None,
                           form=form)
<|endoftext|>


<commit_before>import logging
import os
import shutil
import tempfile
from pathlib import Path
from subprocess import PIPE, CalledProcessError, run as subprocess_run  # nosec
from uuid import UUID, uuid5

import docker

from ._config import Config
from .exceptions import TaskCatException

LOG = logging.getLogger(__name__)

class LambdaBuild:
    NULL_UUID = UUID("{00000000-0000-0000-0000-000000000000}")

    def __init__(self, config: Config, project_root: Path):
        self._docker = docker.from_env()
        self._config = config
        self._project_root = Path(project_root).expanduser().resolve()
        self._lambda_source_path = (
            self._project_root / config.config.project.lambda_source_path
        ).resolve()
        self._lambda_zip_path = (
            self._project_root / config.config.project.lambda_zip_path
        ).resolve()
        self._build_lambdas(self._lambda_source_path, self._lambda_zip_path)
        self._build_submodules()

    def _build_submodules(self):
        if not self._config.config.project.build_submodules:
            return
        rel_source = self._lambda_source_path.relative_to(self._project_root)
        rel_zip = self._lambda_zip_path.relative_to(self._project_root)
        self._recurse(self._project_root, rel_source, rel_zip)

    def _recurse(self, base_path, rel_source, rel_zip):
        submodules_path = Path(base_path) / "submodules"
        if not submodules_path.is_dir():
            return
        for submodule in submodules_path.iterdir():
            source_path = submodule / rel_source
            if not source_path.is_dir():
                continue
            output_path = submodule / rel_zip
            self._build_lambdas(source_path, output_path)
            self._recurse(submodule, rel_source, rel_zip)

    def _build_lambdas(self, parent_path: Path, output_path):
        if not parent_path.is_dir():
            return
        for path in parent_path.iterdir():
            (output_path / path.stem).mkdir(parents=True, exist_ok=True)
            if (path / "Dockerfile").is_file():
                tag = f"taskcat-build-{uuid5(self.NULL_UUID, str(path)).hex}"
                LOG.info(
                    f"Packaging lambda source from {path} using docker image {tag}"
                )
                self._docker_build(path, tag)
                self._docker_extract(tag, output_path / path.stem)
            elif (path / "requirements.txt").is_file():
                LOG.info(f"Packaging python lambda source from {path} using pip")
                self._pip_build(path, output_path / path.stem)
            else:
                LOG.info(
                    f"Packaging lambda source from {path} without building "
                    f"dependencies"
                )
                self._zip_dir(path, output_path / path.stem)

    @staticmethod
    def _make_pip_command(base_path):
        return [
            "pip",
            "install",
            "--no-cache-dir",
            "--no-color",
            "--disable-pip-version-check",
            "--upgrade",
            "--requirement",
            str(base_path / "requirements.txt"),
            "--target",
            str(base_path),
        ]

    @classmethod
    def _pip_build(cls, base_path, output_path):
        tmp_path = Path(tempfile.mkdtemp())
        try:
            build_path = tmp_path / "build"
            shutil.copytree(base_path, build_path)
            command = cls._make_pip_command(build_path)
            LOG.debug("command is '%s'", command)

            LOG.info("Starting pip build.")
            try:
                completed_proc = subprocess_run(  # nosec
                    command, cwd=build_path, check=True, stdout=PIPE, stderr=PIPE
                )
            except (FileNotFoundError, CalledProcessError) as e:
                raise TaskCatException("pip build failed") from e
            LOG.debug("--- pip stdout:\n%s", completed_proc.stdout)
            LOG.debug("--- pip stderr:\n%s", completed_proc.stderr)
            cls._zip_dir(build_path, output_path)
            shutil.rmtree(tmp_path, ignore_errors=True)
        except Exception as e:  # pylint: disable=broad-except
            shutil.rmtree(tmp_path, ignore_errors=True)
            raise e

    @staticmethod
    def _zip_dir(build_path, output_path):
        zip_path = output_path / "lambda.zip"
        if zip_path.is_file():
            zip_path.unlink()
        shutil.make_archive(output_path / "lambda", "zip", build_path)

    @staticmethod
    def _clean_build_log(line):
        if "stream" in line:
            line = line["stream"]
        elif "aux" in line:
            line = line["aux"]
        return str(line).strip()

    def _docker_build(self, path, tag):
        _, logs = self._docker.images.build(path=str(path), tag=tag)
        build_logs = []
        for line in logs:
            line = self._clean_build_log(line)
            if line:
                build_logs.append(line)
        LOG.debug("docker build logs: \n{}".format("\n".join(build_logs)))

    def _docker_extract(self, tag, package_path):
        volumes = {str(package_path): {"bind": "/output", "mode": "rw"}}
        logs = self._docker.containers.run(
            image=tag, auto_remove=True, volumes=volumes, user=os.getuid()
        )
        LOG.debug("docker run logs: \n{}".format(logs.decode("utf-8").strip()))
<commit_msg>fix docker in docker builds<commit_after>import logging
import os
import shutil
import tarfile
import tempfile
from pathlib import Path
from subprocess import PIPE, CalledProcessError, run as subprocess_run  # nosec
from uuid import UUID, uuid5

import docker

from ._config import Config
from .exceptions import TaskCatException

LOG = logging.getLogger(__name__)

class LambdaBuild:
    NULL_UUID = UUID("{00000000-0000-0000-0000-000000000000}")

    def __init__(self, config: Config, project_root: Path):
        self._docker = docker.from_env()
        self._config = config
        self._project_root = Path(project_root).expanduser().resolve()
        self._lambda_source_path = (
            self._project_root / config.config.project.lambda_source_path
        ).resolve()
        self._lambda_zip_path = (
            self._project_root / config.config.project.lambda_zip_path
        ).resolve()
        self._build_lambdas(self._lambda_source_path, self._lambda_zip_path)
        self._build_submodules()

    def _build_submodules(self):
        if not self._config.config.project.build_submodules:
            return
        rel_source = self._lambda_source_path.relative_to(self._project_root)
        rel_zip = self._lambda_zip_path.relative_to(self._project_root)
        self._recurse(self._project_root, rel_source, rel_zip)

    def _recurse(self, base_path, rel_source, rel_zip):
        submodules_path = Path(base_path) / "submodules"
        if not submodules_path.is_dir():
            return
        for submodule in submodules_path.iterdir():
            source_path = submodule / rel_source
            if not source_path.is_dir():
                continue
            output_path = submodule / rel_zip
            self._build_lambdas(source_path, output_path)
            self._recurse(submodule, rel_source, rel_zip)

    def _build_lambdas(self, parent_path: Path, output_path):
        if not parent_path.is_dir():
            return
        for path in parent_path.iterdir():
            if (path / "Dockerfile").is_file():
                tag = f"taskcat-build-{uuid5(self.NULL_UUID, str(path)).hex}"
                LOG.info(
                    f"Packaging lambda source from {path} using docker image {tag}"
                )
                self._docker_build(path, tag)
                self._docker_extract(tag, output_path / path.stem)
            elif (path / "requirements.txt").is_file():
                LOG.info(f"Packaging python lambda source from {path} using pip")
                self._pip_build(path, output_path / path.stem)
            else:
                LOG.info(
                    f"Packaging lambda source from {path} without building "
                    f"dependencies"
                )
                self._zip_dir(path, output_path / path.stem)

    @staticmethod
    def _make_pip_command(base_path):
        return [
            "pip",
            "install",
            "--no-cache-dir",
            "--no-color",
            "--disable-pip-version-check",
            "--upgrade",
            "--requirement",
            str(base_path / "requirements.txt"),
            "--target",
            str(base_path),
        ]

    @classmethod
    def _pip_build(cls, base_path, output_path):
        tmp_path = Path(tempfile.mkdtemp())
        try:
            build_path = tmp_path / "build"
            shutil.copytree(base_path, build_path)
            command = cls._make_pip_command(build_path)
            LOG.debug("command is '%s'", command)

            LOG.info("Starting pip build.")
            try:
                completed_proc = subprocess_run(  # nosec
                    command, cwd=build_path, check=True, stdout=PIPE, stderr=PIPE
                )
            except (FileNotFoundError, CalledProcessError) as e:
                raise TaskCatException("pip build failed") from e
            LOG.debug("--- pip stdout:\n%s", completed_proc.stdout)
            LOG.debug("--- pip stderr:\n%s", completed_proc.stderr)
            cls._zip_dir(build_path, output_path)
            shutil.rmtree(tmp_path, ignore_errors=True)
        except Exception as e:  # pylint: disable=broad-except
            shutil.rmtree(tmp_path, ignore_errors=True)
            raise e

    @staticmethod
    def _zip_dir(build_path, output_path):
        output_path.mkdir(parents=True, exist_ok=True)
        zip_path = output_path / "lambda.zip"
        if zip_path.is_file():
            zip_path.unlink()
        shutil.make_archive(output_path / "lambda", "zip", build_path)

    @staticmethod
    def _clean_build_log(line):
        if "stream" in line:
            line = line["stream"]
        elif "aux" in line:
            line = line["aux"]
        return str(line).strip()

    def _docker_build(self, path, tag):
        _, logs = self._docker.images.build(path=str(path), tag=tag)
        build_logs = []
        for line in logs:
            line = self._clean_build_log(line)
            if line:
                build_logs.append(line)
        LOG.debug("docker build logs: \n{}".format("\n".join(build_logs)))

    def _docker_extract(self, tag, package_path):
        container = self._docker.containers.run(image=tag, detach=True)
        exit_code = container.wait()["StatusCode"]
        logs = container.logs()
        LOG.debug("docker run logs: \n{}".format(logs.decode("utf-8").strip()))
        if exit_code != 0:
            raise TaskCatException("docker build failed")
        arc, _ = container.get_archive("/output/")
        container.remove()
        with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
            for chunk in arc:
                tmpfile.write(chunk)
        with tarfile.open(tmpfile.name) as tar:
            for member in tar.getmembers():
                if member.name.startswith("output/"):
                    member.name = member.name[len("output/") :]
                    tar.extract(member)
            tar.extractall(path=str(package_path))
        os.unlink(tmpfile.name)
<|endoftext|>


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

import gzip
import peewee as pw

db = pw.SqliteDatabase('test.sqlite')

class BaseModel(pw.Model):
    class Meta:
        database = db

class Taxa(BaseModel):
    """table Taxa. Each row is a taxon.

    Fields:
    primary -- the primary key
    ncbi_taxid -- the TaxID of the taxon (from nodes.dmp)
    parent_taxid -- the TaxID of the parent taxon (from nodes.dmp)
    tax_name -- the scientific name of the taxon (from names.dmp)
    lineage_level -- the level of lineage of the taxon (from nodes.dmp)
    """
    primary = pw.PrimaryKeyField()
    ncbi_taxid = pw.IntegerField(null=False)
    parent_taxid = pw.ForeignKeyField(rel_model=pw.Model)
    tax_name = pw.CharField()
    lineage_level = pw.CharField()

class Sequence(BaseModel):
    """table Sequence. Each row is a sequence. Each sequence has a taxon_id.

    Fields:
    primary -- the primary key
    taxid -- reference to a taxon in the table Taxa.
    accession -- the accession number of the sequence.
    version -- the version of the sequence.
    gi -- (deprecated) the GI number of the sequence.
    db_type -- the database where the sequence is from.
    """
    primary = pw.PrimaryKeyField()
    taxid = pw.ForeignKeyField(Taxa, to_field='ncbi_taxid')
    accession = pw.CharField(null=False)
    version = pw.IntegerField(null=False)
    # gi = pw.CharField()
    # db_type = pw.CharField(null=False)

def create_db(db):
    """Create the database."""
    db.connect()
    db.create_table(Taxa)
    db.create_table(Sequence)

def parse_taxdump(nodes_file, names_file):
    """Parse the nodes.dmp and names.dmp files (from taxdump.tgz) and insert
    taxons in the Taxa table.

    Arguments:
    nodes_file -- the nodes.dmp file
    names_file -- the names.dmp file
    """
    # parse nodes.dmp
    nodes_data = list()
    with open(nodes_file, 'r') as f:
        for line in f:
            line_list = line.split('|')
            data_dict = {
                'ncbi_taxid': line_list[0].strip('\t'),
                'parent_taxid': line_list[1].strip('\t'),
                'tax_name': '',
                'lineage_level': line_list[2].strip('\t')
                }
            nodes_data.append(data_dict)
    print('parsed nodes')

    # parse names.dmp
    names_data = list()
    with open(names_file, 'r') as f:
        for line in f:
            if 'scientific name' in line:
                line_list = line.split('|')
                data_dict = {
                    'ncbi_taxid': line_list[0].strip('\t'),
                    'tax_name': line_list[1].strip('\t')
                    }
                names_data.append(data_dict)
    print('parsed names')

    # merge the two dictionaries
    taxa_info_list = list()
    taxa_info = {}
    for nodes, names in zip(nodes_data, names_data):
        taxa_info = {**nodes, **names}  # PEP 448, requires python 3.5
        taxa_info_list.append(taxa_info)
    print('merge successful')

    # insert in database
    with db.atomic():
        for i in range(0, len(taxa_info_list), 500):
            Taxa.insert_many(taxa_info_list[i:i+500]).execute()
    print('Taxa: completed')

def parse_accession2taxid(acc2taxid):
    """Parse the accession2taxid files.

    Arguments:
    acc2taxid -- input file (gzipped)
    """
    with db.atomic():
        with gzip.open(acc2taxid, 'rb') as f:
            f.readline()  # discard the header
            for line in f:
                line_list = line.decode().rstrip('\n').split('\t')
                data_dict = {
                    'accession': line_list[0],
                    'version': line_list[1].split('.')[1],
                    'taxid': line_list[2]
                    # 'gi': line_list[3],
                    # 'db_type': 'gss'
                }
                Sequence.create(**data_dict)
    print('%s added to database' % (acc2taxid))

def main():
    create_db(db)
    parse_taxdump('nodes.dmp', 'names.dmp')
    parse_accession2taxid('nucl_est.accession2taxid.gz')
    parse_accession2taxid('nucl_gb.accession2taxid.gz')
    parse_accession2taxid('nucl_gss.accession2taxid.gz')
    parse_accession2taxid('nucl_wgs.accession2taxid.gz')
    parse_accession2taxid('prot.accession2taxid.gz')

if __name__ == '__main__':
    main()
<commit_msg>testing prot_acc parsing<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import gzip
import peewee as pw

db = pw.SqliteDatabase('test.sqlite')

class BaseModel(pw.Model):
    class Meta:
        database = db

class Taxa(BaseModel):
    """table Taxa. Each row is a taxon.

    Fields:
    primary -- the primary key
    ncbi_taxid -- the TaxID of the taxon (from nodes.dmp)
    parent_taxid -- the TaxID of the parent taxon (from nodes.dmp)
    tax_name -- the scientific name of the taxon (from names.dmp)
    lineage_level -- the level of lineage of the taxon (from nodes.dmp)
    """
    primary = pw.PrimaryKeyField()
    ncbi_taxid = pw.IntegerField(null=False)
    parent_taxid = pw.ForeignKeyField(rel_model=pw.Model)
    tax_name = pw.CharField()
    lineage_level = pw.CharField()

class Sequence(BaseModel):
    """table Sequence. Each row is a sequence. Each sequence has a taxon_id.

    Fields:
    primary -- the primary key
    taxid -- reference to a taxon in the table Taxa.
    accession -- the accession number of the sequence.
    version -- the version of the sequence.
    gi -- (deprecated) the GI number of the sequence.
    db_type -- the database where the sequence is from.
    """
    primary = pw.PrimaryKeyField()
    taxid = pw.ForeignKeyField(Taxa, to_field='ncbi_taxid')
    accession = pw.CharField(null=False)
    version = pw.IntegerField(null=False)
    # gi = pw.CharField()
    # db_type = pw.CharField(null=False)

def create_db(db):
    """Create the database."""
    db.connect()
    db.create_table(Taxa)
    db.create_table(Sequence)

def parse_taxdump(nodes_file, names_file):
    """Parse the nodes.dmp and names.dmp files (from taxdump.tgz) and insert
    taxons in the Taxa table.

    Arguments:
    nodes_file -- the nodes.dmp file
    names_file -- the names.dmp file
    """
    # parse nodes.dmp
    nodes_data = list()
    with open(nodes_file, 'r') as f:
        for line in f:
            line_list = line.split('|')
            data_dict = {
                'ncbi_taxid': line_list[0].strip('\t'),
                'parent_taxid': line_list[1].strip('\t'),
                'tax_name': '',
                'lineage_level': line_list[2].strip('\t')
                }
            nodes_data.append(data_dict)
    print('parsed nodes')

    # parse names.dmp
    names_data = list()
    with open(names_file, 'r') as f:
        for line in f:
            if 'scientific name' in line:
                line_list = line.split('|')
                data_dict = {
                    'ncbi_taxid': line_list[0].strip('\t'),
                    'tax_name': line_list[1].strip('\t')
                    }
                names_data.append(data_dict)
    print('parsed names')

    # merge the two dictionaries
    taxa_info_list = list()
    taxa_info = {}
    for nodes, names in zip(nodes_data, names_data):
        taxa_info = {**nodes, **names}  # PEP 448, requires python 3.5
        taxa_info_list.append(taxa_info)
    print('merge successful')

    # insert in database
    with db.atomic():
        for i in range(0, len(taxa_info_list), 500):
            Taxa.insert_many(taxa_info_list[i:i+500]).execute()
    print('Taxa: completed')

def parse_accession2taxid(acc2taxid):
    """Parse the accession2taxid files.

    Arguments:
    acc2taxid -- input file (gzipped)
    """
    with db.atomic():
        with gzip.open(acc2taxid, 'rb') as f:
            f.readline()  # discard the header
            for line in f:
                line_list = line.decode().rstrip('\n').split('\t')
                print(line_list)
                data_dict = {
                    'accession': line_list[0],
                    'version': line_list[1].split('.')[1],
                    'taxid': line_list[2]
                    # 'gi': line_list[3],
                    # 'db_type': 'gss'
                }
                Sequence.create(**data_dict)
    print('%s added to database' % (acc2taxid))

def main():
    create_db(db)
    parse_taxdump('nodes.dmp', 'names.dmp')
    # parse_accession2taxid('nucl_est.accession2taxid.gz')
    # parse_accession2taxid('nucl_gb.accession2taxid.gz')
    # parse_accession2taxid('nucl_gss.accession2taxid.gz')
    # parse_accession2taxid('nucl_wgs.accession2taxid.gz')
    parse_accession2taxid('prot.accession2taxid.gz')

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


<commit_before>import os
import sys
import logging
import importlib
from flask import Flask, request, jsonify

from .options import load_config
from .server import TAXIIServer
from .middleware import TAXIIMiddleware, service_wrapper, attach_error_handlers
from .persistence.sql import SQLDB
from .persistence import DataStorage

config = load_config('default_config.ini', 'TAXII_SERVER_CONFIG')
logging_level = logging.getLevelName(config.logging_level)

app = Flask(__name__)
app.wsgi_app = TAXIIMiddleware(app.wsgi_app)

#app.debug = (logging_level == logging.DEBUG)
#if not app.debug:
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging_level)
app.logger.addHandler(stream_handler)

root_logger = logging.getLogger('taxii_server')
root_logger.addHandler(logging.StreamHandler(sys.stdout))

db = SQLDB(config.db_connection)
db.create_all_tables()

server = TAXIIServer(
    config = config,
    storage = DataStorage(db=db)
)

for path, service in server.path_to_service.items():
    app.add_url_rule(
        path,
        service.uid + "_view",
        view_func = service_wrapper(service),
        methods = ['POST']
    )

attach_error_handlers(app)

for hooks_module in config.storage_hooks:
    importlib.import_module(hooks_module)

<commit_msg>testing logging config<commit_after>import os
import sys
import logging
import importlib
from flask import Flask, request, jsonify

from .options import load_config
from .server import TAXIIServer
from .middleware import TAXIIMiddleware, service_wrapper, attach_error_handlers
from .persistence.sql import SQLDB
from .persistence import DataStorage

config = load_config('default_config.ini', 'TAXII_SERVER_CONFIG')
logging_level = logging.getLevelName(config.logging_level)

app = Flask(__name__)
app.wsgi_app = TAXIIMiddleware(app.wsgi_app)

formatter = logging.Formatter('%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s')

stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
app.logger.addHandler(stream_handler)
app.logger.setLevel(logging_level)

root_logger = logging.getLogger('taxii_server')
root_logger.setFormatter(formatter)
root_logger.addHandler(logging.StreamHandler())
root_logger.setLevel(logging_level)

db = SQLDB(config.db_connection)
db.create_all_tables()

server = TAXIIServer(
    config = config,
    storage = DataStorage(db=db)
)

for path, service in server.path_to_service.items():
    app.add_url_rule(
        path,
        service.uid + "_view",
        view_func = service_wrapper(service),
        methods = ['POST']
    )

attach_error_handlers(app)

for hooks_module in config.storage_hooks:
    importlib.import_module(hooks_module)

<|endoftext|>


<commit_before>from setuptools import setup
execfile('setup.py') #,

# FIXME: GV: This is probably not necessary, but I am keeping it here,
#            just in case we lost useful information.
#
#         {'additional_params' :
#         {'namespace_packages' : ['mpl_toolkits']}})

#from os.path import join
#import sys
#from setuptools import setup, Extension
#
#from neuroimaging import packages, __version__, __doc__, ENTHOUGHT_TRAITS_DEF
#
#def main(packages):
#
#    packages = ['']+list(packages)
#    ext_modules = [Extension('data_io.formats.minc._mincutils',
#      [join(*('neuroimaging/data_io/formats/minc/_mincutils.c'.split('/')))],
#      extra_link_args=["-lminc"],
#      include_dirs=get_numpy_include_dirs())]
#
#    package_dir = {'': '.'}
#
#    if not ENTHOUGHT_TRAITS_DEF:
#        ext_modules += [Extension('utils.enthought.traits.ctraits',
#          [join(*('neuroimaging/utils/enthought/traits/ctraits.c'.split('/')))])]
#        package_dir['neuroimaging.utils.enthought'] = \
#          join(*('neuroimaging/utils/enthought/'.split('/')))
#
#    setup( name = 'neuroimaging',
#           version = __version__,
#           description = 'This is a neuroimaging python package',
#           author = 'Various',
#           author_email = 'nipy-devel@neuroimaging.scipy.org',
#           ext_package = 'neuroimaging',
#           packages=packages,
#           ext_modules=ext_modules,
#           package_dir = package_dir,
#           url = 'http://neuroimaging.scipy.org',
#           long_description = __doc__)
#

if __name__ == "__main__":
    main(packages)
<commit_msg>Remove setup_egg.py.  Handle egg support when core is more functional.<commit_after><|endoftext|>


<commit_before>import ldap
import urllib2

from flask import flash, url_for, redirect, request
from application import app, mandrill, db
from application.models import WHMCSclients, Badges, BadgesHistory
from flask.ext.login import current_user, AnonymousUserMixin
from bs4 import BeautifulSoup
from datetime import datetime

class AnonymousUser(AnonymousUserMixin):
    """ AnonymousUser definition
    """
    def __init__(self):
        self.id = None
        self.first_name = None
        self.last_name = None
        self.email = None
        self.username = None
        self.admin = False

class AdminOnlyMixin(object):
    """ For overriding admin-only views.
    """
    def is_accessible(self):
        return current_user.is_authenticated() and current_user.is_admin()

        def _handle_view(self, name, **kwargs):
            if not self.is_accessible():
                if current_user.is_authenticated():
                    flash('Access Denied', 'error')
                    return redirect(url_for('admin.index'))
                else:
                    flash('Please log in to access this page.', 'error')
                    return redirect(url_for('login.index', next=request.url))

class BadgeUpdateException(Exception):
    """ Custom exception class for when change_badge_status fails
    """
    pass

def change_badge_status(status=None, whmcs_user_id=None, badge=None):
    """ Makes an API call to the web service attached to the access controller.
    """
    api_url = app.config['API_URL']

    # determine add or remove based on status_map
    status_map = {'Active': 'add', 'Deactivated': 'remove', 'Lost': 'remove'}
    try:
        add_or_remove = status_map[status]
    except KeyError:
        return dict(error="Status required. Must be: " + ", ".join(status_map.keys()))

    try:
        float(whmcs_user_id)
    except ValueError, TypeError:
        return dict(error="Invalid WHMCS user ID. Must be a number.")

    user = WHMCSclients.query.get(whmcs_user_id)
    if not user:
        return dict(error="Could not find that User ID in WHMCS.")

    # do not allow badge activation if too many badges are already active
    if ((user.deactivated_badges > user.active_products_and_addons) and (status == "Active")):
        return dict(error="User has too many deactivated badges. "
                          "Some of the badges need to be marked as 'Lost'.")

    # Send activation/deactivation request to a webservice:
    # https://raw.githubusercontent.com/pawl/Chinese-RFID-Access-Control-Library/master/examples/webserver.py
    responses = []
    if badge:
        # single badge update
        responses.append(urllib2.urlopen(api_url + add_or_remove + '&badge=' + str(badge)))
    else:
        # find all of the user's badges and reactivate them
        badges = Badges.query.filter(db.and_(Badges.whmcs_user_id == whmcs_user_id,
                                             Badges.status == "Deactivated")).all()
        if badges:
            for record in badges:
                responses.append(urllib2.urlopen(api_url + add_or_remove + '&badge=%s' % record.badge))
        else:
            return dict(error="No badges found.")

    errors = []
    messages = []
    for response in responses:
        html = response.read()
        if response.getcode() == 200:
            if html == "User Added Successfully":
                subject = "DMS Badge Activated"
                message = "%s's badge has been activated." % (user.full_name,)
                send_email(subject, message, user, email_admins=False)

                # record activation in log
                record = BadgesHistory(whmcs_user_id, current_user.email, str(badge), status, datetime.now())
                db.session.add(record)
                db.session.commit()

                messages.append(html)
            elif html == "User Removed Successfully":
                # record deactivation in log
                record = BadgesHistory(whmcs_user_id, current_user.email, str(badge), status, datetime.now())
                db.session.add(record)
                db.session.commit()

                messages.append(html)
            else:
                errors.append("Unexpected Response: %s" % (html,))
        else:
            errors.append("Status Code: %s Response" % (response.getcode(),))

    if messages and errors:
        return dict(message=", ".join(messages), error=", ".join(errors))
    elif messages and not errors:
        return dict(message=", ".join(messages))
    else:
        return dict(error=", ".join(errors))

def verify_waiver_signed(firstname=None, lastname=None, email=None):
    """ Make API call to Smartwaiver and see if we have a waiver on file
    """

    # Unfortunately Smartwaiver doesn't allow querying by email for firstname too
    xml_response = urllib2.urlopen(
        'https://www.smartwaiver.com/api/v3/?rest_request=%s&'
        'rest_request_lastname=%s&' % (
            app.config['SMARTWAIVER_KEY'], lastname
        )
    )
    soup = BeautifulSoup(xml_response.read())

    firstname_match, lastname_match, email_match = (None, None, None)

    for participant in soup.participants:
        p_firstname = participant.find('firstname')
        p_lastname = participant.find('lastname')
        p_email = participant.find('primary_email')

        # E-mail in Smartwaiver is not required, so it can be None
        if (p_firstname and p_lastname and p_email and firstname and lastname and email):
            firstname_match = (p_firstname.text.strip().lower() == firstname.strip().lower())
            lastname_match = (p_lastname.text.strip().lower() == lastname.strip().lower())
            email_match = (p_email.text.strip().lower() == email.strip().lower())

        if (firstname_match and lastname_match and email_match):
            break
        else:
            firstname_match, lastname_match, email_match = (None, None, None)

    return (firstname_match and lastname_match and email_match)

def send_email(subject, message, user, email_admins=True):
    ''' Params:
        `user`: WHMCSclients model record
        `subject`: email subject
        `message`: email body contents
        `email_admins`: prevents spam to admins
    '''

    html_template = '''
        <html>
            <head>
                <title>%s</title>
            </head>
            <body>
                %s
            </body>
        </html>
    '''
    html = html_template % (subject, message)

    # prevent duplicate emails if owner is activator
    if (current_user.email == user.email):
        email_addresses = []
    else:
        email_addresses = [{'email': user.email}]

    # don't sent email to admins unless it's a pending request
    if email_admins:
        email_addresses = email_addresses + [{'email': app.config['ADMIN_EMAIL']}]

    if email_addresses:
        mandrill.send_email(
            from_email=app.config['ADMIN_EMAIL'],
            subject=subject,
            to=email_addresses,
            html=html
        )
<commit_msg>fix issue with no badges found error<commit_after>import ldap
import urllib2

from flask import flash, url_for, redirect, request
from application import app, mandrill, db
from application.models import WHMCSclients, Badges, BadgesHistory
from flask.ext.login import current_user, AnonymousUserMixin
from bs4 import BeautifulSoup
from datetime import datetime

class AnonymousUser(AnonymousUserMixin):
    """ AnonymousUser definition
    """
    def __init__(self):
        self.id = None
        self.first_name = None
        self.last_name = None
        self.email = None
        self.username = None
        self.admin = False

class AdminOnlyMixin(object):
    """ For overriding admin-only views.
    """
    def is_accessible(self):
        return current_user.is_authenticated() and current_user.is_admin()

        def _handle_view(self, name, **kwargs):
            if not self.is_accessible():
                if current_user.is_authenticated():
                    flash('Access Denied', 'error')
                    return redirect(url_for('admin.index'))
                else:
                    flash('Please log in to access this page.', 'error')
                    return redirect(url_for('login.index', next=request.url))

class BadgeUpdateException(Exception):
    """ Custom exception class for when change_badge_status fails
    """
    pass

def change_badge_status(status=None, whmcs_user_id=None, badge=None):
    """ Makes an API call to the web service attached to the access controller.
    """
    api_url = app.config['API_URL']

    # determine add or remove based on status_map
    status_map = {'Active': 'add', 'Deactivated': 'remove', 'Lost': 'remove'}
    try:
        add_or_remove = status_map[status]
    except KeyError:
        return dict(error="Status required. Must be: " + ", ".join(status_map.keys()))

    try:
        float(whmcs_user_id)
    except ValueError, TypeError:
        return dict(error="Invalid WHMCS user ID. Must be a number.")

    user = WHMCSclients.query.get(whmcs_user_id)
    if not user:
        return dict(error="Could not find that User ID in WHMCS.")

    # do not allow badge activation if too many badges are already active
    if ((status == "Active") and (user.deactivated_badges > user.active_products_and_addons)):
        return dict(error="User has too many deactivated badges. "
                          "Some of the badges need to be marked as 'Lost'.")

    # Send activation/deactivation request to a webservice:
    # https://raw.githubusercontent.com/pawl/Chinese-RFID-Access-Control-Library/master/examples/webserver.py
    responses = []
    if badge:
        # single badge update
        responses.append(urllib2.urlopen(api_url + add_or_remove + '&badge=' + str(badge)))
    else:
        # find all of the user's badges
        # TODO: change status in database
        if (status == "Active"):
            badges = Badges.query.filter(db.and_(Badges.whmcs_user_id == whmcs_user_id,
                                                 Badges.status == "Deactivated")).all()
        elif (status == "Deactivated"):
            badges = Badges.query.filter(db.and_(Badges.whmcs_user_id == whmcs_user_id,
                                                 Badges.status == "Active")).all()

        if badges:
            for record in badges:
                responses.append(urllib2.urlopen(api_url + add_or_remove + '&badge=%s' % record.badge))
        else:
            return dict(error="No badges found.")

    errors = []
    messages = []
    for response in responses:
        html = response.read()
        if response.getcode() == 200:
            if html == "User Added Successfully":
                subject = "DMS Badge Activated"
                message = "%s's badge has been activated." % (user.full_name,)
                send_email(subject, message, user, email_admins=False)

                # record activation in log
                record = BadgesHistory(whmcs_user_id, current_user.email, str(badge), status, datetime.now())
                db.session.add(record)
                db.session.commit()

                messages.append(html)
            elif html == "User Removed Successfully":
                # record deactivation in log
                record = BadgesHistory(whmcs_user_id, current_user.email, str(badge), status, datetime.now())
                db.session.add(record)
                db.session.commit()

                messages.append(html)
            else:
                errors.append("Unexpected Response: %s" % (html,))
        else:
            errors.append("Status Code: %s Response" % (response.getcode(),))

    if messages and errors:
        return dict(message=", ".join(messages), error=", ".join(errors))
    elif messages and not errors:
        return dict(message=", ".join(messages))
    else:
        return dict(error=", ".join(errors))

def verify_waiver_signed(firstname=None, lastname=None, email=None):
    """ Make API call to Smartwaiver and see if we have a waiver on file
    """

    # Unfortunately Smartwaiver doesn't allow querying by email for firstname too
    xml_response = urllib2.urlopen(
        'https://www.smartwaiver.com/api/v3/?rest_request=%s&'
        'rest_request_lastname=%s&' % (
            app.config['SMARTWAIVER_KEY'], lastname
        )
    )
    soup = BeautifulSoup(xml_response.read())

    firstname_match, lastname_match, email_match = (None, None, None)

    for participant in soup.participants:
        p_firstname = participant.find('firstname')
        p_lastname = participant.find('lastname')
        p_email = participant.find('primary_email')

        # E-mail in Smartwaiver is not required, so it can be None
        if (p_firstname and p_lastname and p_email and firstname and lastname and email):
            firstname_match = (p_firstname.text.strip().lower() == firstname.strip().lower())
            lastname_match = (p_lastname.text.strip().lower() == lastname.strip().lower())
            email_match = (p_email.text.strip().lower() == email.strip().lower())

        if (firstname_match and lastname_match and email_match):
            break
        else:
            firstname_match, lastname_match, email_match = (None, None, None)

    return (firstname_match and lastname_match and email_match)

def send_email(subject, message, user, email_admins=True):
    ''' Params:
        `user`: WHMCSclients model record
        `subject`: email subject
        `message`: email body contents
        `email_admins`: prevents spam to admins
    '''

    html_template = '''
        <html>
            <head>
                <title>%s</title>
            </head>
            <body>
                %s
            </body>
        </html>
    '''
    html = html_template % (subject, message)

    # prevent duplicate emails if owner is activator
    if (current_user.email == user.email):
        email_addresses = []
    else:
        email_addresses = [{'email': user.email}]

    # don't sent email to admins unless it's a pending request
    if email_admins:
        email_addresses = email_addresses + [{'email': app.config['ADMIN_EMAIL']}]

    if email_addresses:
        mandrill.send_email(
            from_email=app.config['ADMIN_EMAIL'],
            subject=subject,
            to=email_addresses,
            html=html
        )
<|endoftext|>


<commit_before>from mopidy.models import Track

class BaseCurrentPlaylistControllerTest(object):
    uris = []
    backend_class = None

    def setUp(self):
        self.backend = self.backend_class()

    def test_add(self):
        playlist = self.backend.current_playlist

        for uri in self.uris:
            playlist.add(uri)
            self.assertEqual(uri, playlist.tracks[-1].uri)

    def test_add_at_position(self):
        playlist = self.backend.current_playlist

        for uri in self.uris:
            playlist.add(uri, 0)
            self.assertEqual(uri, playlist.tracks[0].uri)

        # FIXME test other placements

class BasePlaybackControllerTest(object):
    backend_class = None

    def setUp(self):
        self.backend = self.backend_class()

    def test_play(self):
        playback = self.backend.playback

        self.assertEqual(playback.state, playback.STOPPED)

        playback.play()

        self.assertEqual(playback.state, playback.PLAYING)
<commit_msg>Add test for next<commit_after>from mopidy.models import Track

class BaseCurrentPlaylistControllerTest(object):
    uris = []
    backend_class = None

    def setUp(self):
        self.backend = self.backend_class()

    def test_add(self):
        playlist = self.backend.current_playlist

        for uri in self.uris:
            playlist.add(uri)
            self.assertEqual(uri, playlist.tracks[-1].uri)

    def test_add_at_position(self):
        playlist = self.backend.current_playlist

        for uri in self.uris:
            playlist.add(uri, 0)
            self.assertEqual(uri, playlist.tracks[0].uri)

        # FIXME test other placements

class BasePlaybackControllerTest(object):
    backend_class = None

    def setUp(self):
        self.backend = self.backend_class()

    def test_play(self):
        playback = self.backend.playback

        self.assertEqual(playback.state, playback.STOPPED)

        playback.play()

        self.assertEqual(playback.state, playback.PLAYING)

    def test_next(self):
        playback = self.backend.playback

        current_song = playback.playlist_position

        playback.next()

        self.assertEqual(playback.playlist_position, current_song+1)
<|endoftext|>


<commit_before>import os
import argparse

from structlog import get_logger

from . import Client

def main():
    """
    Usage:
        1. To get a new certificate:
        CLOUDFLARE_EMAIL=example@example.com \
        CLOUDFLARE_DNS_ZONE_ID=some-zone \
        CLOUDFLARE_API_KEY=api-key \
        sewer \
        --dns cloudflare \
        --domains example.com \
        --action run

        2. To renew a certificate:
        CLOUDFLARE_EMAIL=example@example.com \
        CLOUDFLARE_DNS_ZONE_ID=some-zone \
        CLOUDFLARE_API_KEY=api-key \
        sewer \
        --account_key /path/to/your/account.key \
        --dns cloudflare \
        --domains example.com \
        --action renew
    """
    # TODO: enable people to specify the location where they want certificate and keys to be stored.
    # currently, we store them in the directory from which sewer is ran
    parser = argparse.ArgumentParser(
        prog='sewer', description="Sewer is a Let's Encrypt(ACME) client.")
    parser.add_argument(
        "--account_key",
        type=argparse.FileType('r'),
        required=False,
        help="The path to your letsencrypt/acme account key.")
    parser.add_argument(
        "--dns",
        type=str,
        required=True,
        choices=['cloudflare'],
        help="The name of the dns provider that you want to use.")
    parser.add_argument(
        "--domains",
        type=str,
        required=True,
        help="The domain/subdomain name for which \
        you want to get/renew certificate for.")
    parser.add_argument(
        "--bundle_name",
        type=str,
        required=False,
        help="The name to use for certificate \
        certificate key and account key. Default is value of domains.")
    parser.add_argument(
        "--endpoint",
        type=str,
        required=False,
        default='production',
        choices=['production', 'staging'],
        help="Whether to use letsencrypt/acme production/live endpoints \
        or staging endpoints. production endpoints are used by default.")
    parser.add_argument(
        "--action",
        type=str,
        required=True,
        choices=['run', 'renew'],
        help="The action that you want to perform. \
        Either run (get a new certificate) or renew (renew a certificate).")

    args = parser.parse_args()
    logger = get_logger(__name__)

    dns_provider = args.dns
    domains = args.domains
    action = args.action
    account_key = args.account_key
    bundle_name = args.bundle_name
    endpoint = args.endpoint

    if account_key:
        account_key = account_key.read()
    if bundle_name:
        file_name = bundle_name
    else:
        file_name = '{0}'.format(domains)
    if endpoint == 'staging':
        # TODO: move this to a config.py file.
        # the cli and the client would both read this urls from that config file
        GET_NONCE_URL = "https://acme-staging.api.letsencrypt.org/directory",
        ACME_CERTIFICATE_AUTHORITY_URL = "https://acme-staging.api.letsencrypt.org"
    else:
        GET_NONCE_URL = "https://acme-v01.api.letsencrypt.org/directory",
        ACME_CERTIFICATE_AUTHORITY_URL = "https://acme-v01.api.letsencrypt.org",

    if dns_provider == 'cloudflare':
        from . import CloudFlareDns
        try:
            CLOUDFLARE_EMAIL = os.environ['CLOUDFLARE_EMAIL']
            CLOUDFLARE_API_KEY = os.environ['CLOUDFLARE_API_KEY']
            CLOUDFLARE_DNS_ZONE_ID = os.environ['CLOUDFLARE_DNS_ZONE_ID']

            dns_class = CloudFlareDns(
                CLOUDFLARE_DNS_ZONE_ID=CLOUDFLARE_DNS_ZONE_ID,
                CLOUDFLARE_EMAIL=CLOUDFLARE_EMAIL,
                CLOUDFLARE_API_KEY=CLOUDFLARE_API_KEY)
            logger.info(
                'chosen_dns_provider',
                message='Using {0} as dns provider.'.format(dns_provider))
        except KeyError as e:
            logger.info("ERROR:: Please supply {0} as an environment variable.".
                        format(str(e)))
    else:
        raise ValueError(
            'The dns provider {0} is not recognised.'.format(dns_provider))

    client = Client(
        domain_name=domains,
        dns_class=dns_class,
        account_key=account_key,
        GET_NONCE_URL=GET_NONCE_URL,
        ACME_CERTIFICATE_AUTHORITY_URL=ACME_CERTIFICATE_AUTHORITY_URL)
    certificate_key = client.certificate_key
    account_key = client.account_key

    # write out account_key in current directory
    with open('{0}.account.key'.format(file_name), 'w') as account_file:
        account_file.write(account_key)
    logger.info(
        "write_account_key",
        message='account key succesfully written to current directory.')

    if action == 'renew':
        message = 'Certificate Succesfully renewed. The certificate, certificate key and account key have been saved in the current directory'
        certificate = client.renew()
    else:
        message = 'Certificate Succesfully issued. The certificate, certificate key and account key have been saved in the current directory'
        certificate = client.cert()

    # write out certificate and certificate key in current directory
    with open('{0}.crt'.format(file_name), 'w') as certificate_file:
        certificate_file.write(certificate)
    with open('{0}.key'.format(file_name), 'w') as certificate_key_file:
        certificate_key_file.write(certificate_key)

    logger.info("the_end", message=message)
<commit_msg>fix tuple typo<commit_after>import os
import argparse

from structlog import get_logger

from . import Client

def main():
    """
    Usage:
        1. To get a new certificate:
        CLOUDFLARE_EMAIL=example@example.com \
        CLOUDFLARE_DNS_ZONE_ID=some-zone \
        CLOUDFLARE_API_KEY=api-key \
        sewer \
        --dns cloudflare \
        --domains example.com \
        --action run

        2. To renew a certificate:
        CLOUDFLARE_EMAIL=example@example.com \
        CLOUDFLARE_DNS_ZONE_ID=some-zone \
        CLOUDFLARE_API_KEY=api-key \
        sewer \
        --account_key /path/to/your/account.key \
        --dns cloudflare \
        --domains example.com \
        --action renew
    """
    # TODO: enable people to specify the location where they want certificate and keys to be stored.
    # currently, we store them in the directory from which sewer is ran
    parser = argparse.ArgumentParser(
        prog='sewer', description="Sewer is a Let's Encrypt(ACME) client.")
    parser.add_argument(
        "--account_key",
        type=argparse.FileType('r'),
        required=False,
        help="The path to your letsencrypt/acme account key.")
    parser.add_argument(
        "--dns",
        type=str,
        required=True,
        choices=['cloudflare'],
        help="The name of the dns provider that you want to use.")
    parser.add_argument(
        "--domains",
        type=str,
        required=True,
        help="The domain/subdomain name for which \
        you want to get/renew certificate for.")
    parser.add_argument(
        "--bundle_name",
        type=str,
        required=False,
        help="The name to use for certificate \
        certificate key and account key. Default is value of domains.")
    parser.add_argument(
        "--endpoint",
        type=str,
        required=False,
        default='production',
        choices=['production', 'staging'],
        help="Whether to use letsencrypt/acme production/live endpoints \
        or staging endpoints. production endpoints are used by default.")
    parser.add_argument(
        "--action",
        type=str,
        required=True,
        choices=['run', 'renew'],
        help="The action that you want to perform. \
        Either run (get a new certificate) or renew (renew a certificate).")

    args = parser.parse_args()
    logger = get_logger(__name__)

    dns_provider = args.dns
    domains = args.domains
    action = args.action
    account_key = args.account_key
    bundle_name = args.bundle_name
    endpoint = args.endpoint

    if account_key:
        account_key = account_key.read()
    if bundle_name:
        file_name = bundle_name
    else:
        file_name = '{0}'.format(domains)
    if endpoint == 'staging':
        # TODO: move this to a config.py file.
        # the cli and the client would both read this urls from that config file
        GET_NONCE_URL = "https://acme-staging.api.letsencrypt.org/directory",
        ACME_CERTIFICATE_AUTHORITY_URL = "https://acme-staging.api.letsencrypt.org"
    else:
        GET_NONCE_URL = "https://acme-v01.api.letsencrypt.org/directory",
        ACME_CERTIFICATE_AUTHORITY_URL = "https://acme-v01.api.letsencrypt.org"

    if dns_provider == 'cloudflare':
        from . import CloudFlareDns
        try:
            CLOUDFLARE_EMAIL = os.environ['CLOUDFLARE_EMAIL']
            CLOUDFLARE_API_KEY = os.environ['CLOUDFLARE_API_KEY']
            CLOUDFLARE_DNS_ZONE_ID = os.environ['CLOUDFLARE_DNS_ZONE_ID']

            dns_class = CloudFlareDns(
                CLOUDFLARE_DNS_ZONE_ID=CLOUDFLARE_DNS_ZONE_ID,
                CLOUDFLARE_EMAIL=CLOUDFLARE_EMAIL,
                CLOUDFLARE_API_KEY=CLOUDFLARE_API_KEY)
            logger.info(
                'chosen_dns_provider',
                message='Using {0} as dns provider.'.format(dns_provider))
        except KeyError as e:
            logger.info("ERROR:: Please supply {0} as an environment variable.".
                        format(str(e)))
    else:
        raise ValueError(
            'The dns provider {0} is not recognised.'.format(dns_provider))

    client = Client(
        domain_name=domains,
        dns_class=dns_class,
        account_key=account_key,
        GET_NONCE_URL=GET_NONCE_URL,
        ACME_CERTIFICATE_AUTHORITY_URL=ACME_CERTIFICATE_AUTHORITY_URL)
    certificate_key = client.certificate_key
    account_key = client.account_key

    # write out account_key in current directory
    with open('{0}.account.key'.format(file_name), 'w') as account_file:
        account_file.write(account_key)
    logger.info(
        "write_account_key",
        message='account key succesfully written to current directory.')

    if action == 'renew':
        message = 'Certificate Succesfully renewed. The certificate, certificate key and account key have been saved in the current directory'
        certificate = client.renew()
    else:
        message = 'Certificate Succesfully issued. The certificate, certificate key and account key have been saved in the current directory'
        certificate = client.cert()

    # write out certificate and certificate key in current directory
    with open('{0}.crt'.format(file_name), 'w') as certificate_file:
        certificate_file.write(certificate)
    with open('{0}.key'.format(file_name), 'w') as certificate_key_file:
        certificate_key_file.write(certificate_key)

    logger.info("the_end", message=message)
<|endoftext|>


<commit_before>from flask import render_template, request, make_response, Markup
from application import app
from .registry import registers
from thingstance.representations import representations as _representations

# TBD: register url should be constructed from the register object ..
def register_filter(register):
    result = ('%s' % (register, register))
    return Markup(result)

# TBD: should be a register of filters for a Field/Datatype ..
@app.template_filter('datatype')
def datatype_filter(value, fieldname):
    if fieldname == "register":
        return register_filter(value)
    elif fieldname == "hash":
        return Markup('%s' % (value, value))
    return value

# TBD: push this into thingstance.representations ..
representations = {}
for representation in _representations:
    module = __import__('thingstance.representations.' + representation,
                        globals(),
                        locals(),
                        ['content_type'])
    if module.content_type:
        representations[representation] = module

def subdomain(request):
    import os
    if 'REGISTER' in os.environ:
        return os.environ['REGISTER'] # temp workround for heroku named apps
    else:
        return request.headers['Host'].split('.')[0]

def represent_thing(thing, suffix):
    text = getattr(thing, suffix)
    resp = make_response(text, 200)
    resp.headers['Content-Type'] = representations[suffix].content_type
    return resp

@app.route("/hash/<hash>")
def thing_by_hash(hash):
    return thing_by_hash_suffix(hash, "html")

@app.route("/hash/<hash>.<suffix>")
def thing_by_hash_suffix(hash, suffix="html"):
    register = None
    try:
        register = registers[subdomain(request)]
        thing = register._store.get(hash)
        if thing:
            if suffix == "html":
                return render_template("thing.html",
                                       register=register.primitive,
                                       representations=representations,
                                       hash=hash,
                                       thing=thing.primitive)

            if suffix in representations:
                return represent_thing(thing, suffix)
    except KeyError:
        pass

    return render_template('404.html', register=register), 404

@app.route("/")
def things():
    return find_things("Thing", query={})

@app.route("/name/<name>")
def find_latest_thing_by_name(name):
    return find_latest_thing(query={"name": name})

def find_latest_thing(query={}, suffix="html"):
    register = registers[subdomain(request)]
    meta, things = register._store.find(query)
    thing = things[0]  # egregious hack to find latest ..
    return thing_by_hash_suffix(thing.hash, "html")

def find_things(tag, query={}, suffix="html"):
    register = None
    try:
        register = registers[subdomain(request)]
        meta, things = register._store.find(query)
        things_list = [[thing.hash, thing.primitive] for thing in things]
        thing_keys = []
        if things_list:
            thing_keys = [field for field in things_list[0][1]]
            thing_keys.remove('register')
            thing_keys.remove('name')
            thing_keys.sort()
        if suffix == "html":
            return render_template("things.html",
                                   register=register.primitive,
                                   representations=representations,
                                   meta=meta,
                                   things_list=things_list,
                                   thing_keys=thing_keys)

    except KeyError:
        pass

    return render_template('404.html', register=register), 404
<commit_msg>Stack trace on missing fields<commit_after>from flask import render_template, request, make_response, Markup
from application import app
from .registry import registers
from thingstance.representations import representations as _representations

# TBD: register url should be constructed from the register object ..
def register_filter(register):
    result = ('%s' % (register, register))
    return Markup(result)

# TBD: should be a register of filters for a Field/Datatype ..
@app.template_filter('datatype')
def datatype_filter(value, fieldname):
    if fieldname == "register":
        return register_filter(value)
    elif fieldname == "hash":
        return Markup('%s' % (value, value))
    return value

# TBD: push this into thingstance.representations ..
representations = {}
for representation in _representations:
    module = __import__('thingstance.representations.' + representation,
                        globals(),
                        locals(),
                        ['content_type'])
    if module.content_type:
        representations[representation] = module

def subdomain(request):
    import os
    if 'REGISTER' in os.environ:
        return os.environ['REGISTER'] # temp workround for heroku named apps
    else:
        return request.headers['Host'].split('.')[0]

def represent_thing(thing, suffix):
    text = getattr(thing, suffix)
    resp = make_response(text, 200)
    resp.headers['Content-Type'] = representations[suffix].content_type
    return resp

@app.route("/hash/<hash>")
def thing_by_hash(hash):
    return thing_by_hash_suffix(hash, "html")

@app.route("/hash/<hash>.<suffix>")
def thing_by_hash_suffix(hash, suffix="html"):
    register = None
    try:
        register = registers[subdomain(request)]
        thing = register._store.get(hash)
        if thing:
            if suffix == "html":
                return render_template("thing.html",
                                       register=register.primitive,
                                       representations=representations,
                                       hash=hash,
                                       thing=thing.primitive)

            if suffix in representations:
                return represent_thing(thing, suffix)
    except KeyError:
        pass

    return render_template('404.html', register=register), 404

@app.route("/")
def things():
    return find_things("Thing", query={})

@app.route("/name/<name>")
def find_latest_thing_by_name(name):
    return find_latest_thing(query={"name": name})

def find_latest_thing(query={}, suffix="html"):
    register = registers[subdomain(request)]
    meta, things = register._store.find(query)
    thing = things[0]  # egregious hack to find latest ..
    return thing_by_hash_suffix(thing.hash, "html")

def find_things(tag, query={}, suffix="html"):
    register = None
    try:
        register = registers[subdomain(request)]
        meta, things = register._store.find(query)
        things_list = [[thing.hash, thing.primitive] for thing in things]
        thing_keys = []
        if things_list:
            thing_keys = [field for field in things_list[0][1]]
            if 'register' in thing_keys:
                thing_keys.remove('register')
            if 'name' in thing_keys:
                thing_keys.remove('name')
            thing_keys.sort()
        if suffix == "html":
            return render_template("things.html",
                                   register=register.primitive,
                                   representations=representations,
                                   meta=meta,
                                   things_list=things_list,
                                   thing_keys=thing_keys)

    except KeyError:
        pass

    return render_template('404.html', register=register), 404
<|endoftext|>


<commit_before>"""
sentry.utils
~~~~~~~~~~~~

:copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from django.http import HttpRequest
from django.utils.encoding import force_unicode

class _Missing(object):
    def __repr__(self):
        return 'no value'

    def __reduce__(self):
        return '_missing'

_missing = _Missing()

class cached_property(object):
    # This is borrowed from werkzeug : http://bytebucket.org/mitsuhiko/werkzeug-main
    """A decorator that converts a function into a lazy property.  The
    function wrapped is called the first time to retrieve the result
    and then that calculated result is used the next time you access
    the value::

        class Foo(object):

            @cached_property
            def foo(self):
                # calculate something important here
                return 42

    The class has to have a `__dict__` in order for this property to
    work.

    .. versionchanged:: 0.6
       the `writeable` attribute and parameter was deprecated.  If a
       cached property is writeable or not has to be documented now.
       For performance reasons the implementation does not honor the
       writeable setting and will always make the property writeable.
    """

    # implementation detail: this property is implemented as non-data
    # descriptor.  non-data descriptors are only invoked if there is
    # no entry with the same name in the instance's __dict__.
    # this allows us to completely get rid of the access function call
    # overhead.  If one choses to invoke __get__ by hand the property
    # will still work as expected because the lookup logic is replicated
    # in __get__ for manual invocation.

    def __init__(self, func, name=None, doc=None, writeable=False):
        if writeable:
            from warnings import warn
            warn(DeprecationWarning('the writeable argument to the '
                                    'cached property is a noop since 0.6 '
                                    'because the property is writeable '
                                    'by default for performance reasons'))

        self.__name__ = name or func.__name__
        self.__module__ = func.__module__
        self.__doc__ = doc or func.__doc__
        self.func = func

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        value = obj.__dict__.get(self.__name__, _missing)
        if value is _missing:
            value = self.func(obj)
            obj.__dict__[self.__name__] = value
        return value

class MockDjangoRequest(HttpRequest):
    GET = {}
    POST = {}
    META = {}
    COOKIES = {}
    FILES = {}
    raw_post_data = ''
    url = ''
    path = '/'
    plugins = []

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        from pprint import pformat

        # Since this is called as part of error handling, we need to be very
        # robust against potentially malformed input.
        try:
            get = pformat(self.GET)
        except:
            get = '<could not parse>'
        try:
            post = pformat(self.POST)
        except:
            post = '<could not parse>'
        try:
            cookies = pformat(self.COOKIES)
        except:
            cookies = '<could not parse>'
        try:
            meta = pformat(self.META)
        except:
            meta = '<could not parse>'
        return '<Request\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
            (get, post, cookies, meta)

    def build_absolute_uri(self):
        return self.url

def to_unicode(value):
    try:
        value = unicode(force_unicode(value))
    except (UnicodeEncodeError, UnicodeDecodeError):
        value = '(Error decoding value)'
    except Exception:  # in some cases we get a different exception
        try:
            value = str(repr(type(value)))
        except Exception:
            value = '(Error decoding value)'
    return value

def is_float(var):
    try:
        float(var)
    except ValueError:
        return False
    return True
<commit_msg>Remove writeable argument from cached_property<commit_after>"""
sentry.utils
~~~~~~~~~~~~

:copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from django.http import HttpRequest
from django.utils.encoding import force_unicode

class _Missing(object):
    def __repr__(self):
        return 'no value'

    def __reduce__(self):
        return '_missing'

_missing = _Missing()

class cached_property(object):
    # This is borrowed from werkzeug : http://bytebucket.org/mitsuhiko/werkzeug-main
    """A decorator that converts a function into a lazy property.  The
    function wrapped is called the first time to retrieve the result
    and then that calculated result is used the next time you access
    the value::

        class Foo(object):

            @cached_property
            def foo(self):
                # calculate something important here
                return 42

    The class has to have a `__dict__` in order for this property to
    work.
    """

    # implementation detail: this property is implemented as non-data
    # descriptor.  non-data descriptors are only invoked if there is
    # no entry with the same name in the instance's __dict__.
    # this allows us to completely get rid of the access function call
    # overhead.  If one choses to invoke __get__ by hand the property
    # will still work as expected because the lookup logic is replicated
    # in __get__ for manual invocation.

    def __init__(self, func, name=None, doc=None):
        self.__name__ = name or func.__name__
        self.__module__ = func.__module__
        self.__doc__ = doc or func.__doc__
        self.func = func

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        value = obj.__dict__.get(self.__name__, _missing)
        if value is _missing:
            value = self.func(obj)
            obj.__dict__[self.__name__] = value
        return value

class MockDjangoRequest(HttpRequest):
    GET = {}
    POST = {}
    META = {}
    COOKIES = {}
    FILES = {}
    raw_post_data = ''
    url = ''
    path = '/'
    plugins = []

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        from pprint import pformat

        # Since this is called as part of error handling, we need to be very
        # robust against potentially malformed input.
        try:
            get = pformat(self.GET)
        except:
            get = '<could not parse>'
        try:
            post = pformat(self.POST)
        except:
            post = '<could not parse>'
        try:
            cookies = pformat(self.COOKIES)
        except:
            cookies = '<could not parse>'
        try:
            meta = pformat(self.META)
        except:
            meta = '<could not parse>'
        return '<Request\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
            (get, post, cookies, meta)

    def build_absolute_uri(self):
        return self.url

def to_unicode(value):
    try:
        value = unicode(force_unicode(value))
    except (UnicodeEncodeError, UnicodeDecodeError):
        value = '(Error decoding value)'
    except Exception:  # in some cases we get a different exception
        try:
            value = str(repr(type(value)))
        except Exception:
            value = '(Error decoding value)'
    return value

def is_float(var):
    try:
        float(var)
    except ValueError:
        return False
    return True
<|endoftext|>


<commit_before>from django.conf.urls.defaults import patterns, url, include
from django.conf import settings

import userena.views as userena_views

import views

urlpatterns = patterns('django.views.generic.simple',
    (r'^$', 'redirect_to', {'url': 'dashboard'}),
)

urlpatterns += patterns('',

    url(r'^profile/avatar$', views.avatar_set, name='avatar'),

    url(r'dashboard/$', views.dashboard, name='dashboard'),

    url(r'^signup/$', views.signup, name='userena_signup'),
    url(r'^signin/$', userena_views.signin, name='userena_signin'),

    url(r'^signout/$', views.logout, name='userena_signout'),

    url(r'^(?P<username>[-\w]+)/$', views.detail, name='userena_profile_detail'),
    url(r'^(?P<username>[-\w]+)/edit/$', views.edit, name='userena_profile_edit'),
    url(r'^(?P<username>\w+)/password/complete/$', views.password_change_complete, name='userena_password_change_complete'),

)
<commit_msg>fix regexp<commit_after>from django.conf.urls.defaults import patterns, url, include
from django.conf import settings

import userena.views as userena_views

import views

urlpatterns = patterns('django.views.generic.simple',
    (r'^$', 'redirect_to', {'url': 'dashboard'}),
)

urlpatterns += patterns('',

    url(r'^profile/avatar$', views.avatar_set, name='avatar'),

    url(r'dashboard/$', views.dashboard, name='dashboard'),

    url(r'^signup/$', views.signup, name='userena_signup'),
    url(r'^signin/$', userena_views.signin, name='userena_signin'),

    url(r'^signout/$', views.logout, name='userena_signout'),

    url(r'^(?P<username>[-\w]+)/$', views.detail, name='userena_profile_detail'),
    url(r'^(?P<username>[-\w]+)/edit/$', views.edit, name='userena_profile_edit'),
    url(r'^(?P<username>[-\w]+)/password/complete/$', views.password_change_complete, name='userena_password_change_complete'),

)
<|endoftext|>