Skip to content

Commit

Permalink
Merge pull request #140 from jacebrowning/aliases-route
Browse files Browse the repository at this point in the history
Add aliases route
  • Loading branch information
jacebrowning committed Jan 3, 2016
2 parents 43b3bbf + 0577f6c commit 39d8422
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 7 deletions.
1 change: 1 addition & 0 deletions memegen/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,4 @@ def register_blueprints(app):
app.register_blueprint(routes.overview.blueprint)
app.register_blueprint(routes.generator.blueprint)
app.register_blueprint(routes.latest.blueprint)
app.register_blueprint(routes.aliases.blueprint)
1 change: 1 addition & 0 deletions memegen/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
from . import overview
from . import generator
from . import latest
from . import aliases
5 changes: 0 additions & 5 deletions memegen/routes/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@

from flask import current_app as app
from flask import url_for as _url_for
from webargs import fields


GITHUB_BASE = "http://github.com/jacebrowning/memegen/"
CONTRIBUTING = GITHUB_BASE + "blob/master/CONTRIBUTING.md"

OPTIONS = {
'alt': fields.Str(missing=None) # pylint: disable=no-member
}


def url_for(*args, **kwargs):
"""Unquoted version of Flask's `url_for`."""
Expand Down
32 changes: 32 additions & 0 deletions memegen/routes/aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from collections import OrderedDict

from flask import Blueprint, current_app as app
from webargs import fields, flaskparser

from ._common import url_for


blueprint = Blueprint('aliases', __name__, url_prefix="/aliases/")

FILTER = {
'name': fields.Str(missing="") # pylint: disable=no-member
}


@blueprint.route("")
@flaskparser.use_kwargs(FILTER)
def get(name):
"""Get a list of all matching aliases."""
items = OrderedDict()

for alias in sorted(app.template_service.aliases(name)):
template = app.template_service.find(alias)

data = OrderedDict()
data['styles'] = sorted(template.styles)
data['template'] = \
url_for('templates.create', key=template.key, _external=True)

items[alias] = data

return items
8 changes: 6 additions & 2 deletions memegen/routes/image.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from flask import Blueprint, redirect, send_file
from flask import current_app as app, request
from webargs import flaskparser
from webargs import fields, flaskparser
import requests

from .. import domain

from ._common import OPTIONS, url_for
from ._common import url_for

blueprint = Blueprint('image', __name__, url_prefix="/")

OPTIONS = {
'alt': fields.Str(missing=None) # pylint: disable=no-member
}


@blueprint.route("latest.jpg")
def get_latest():
Expand Down
1 change: 1 addition & 0 deletions memegen/routes/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def get():
"""Generate memes from templates."""
data = OrderedDict()
data['templates'] = url_for('templates.get', _external=True)
data['aliases'] = url_for('aliases.get', _external=True)
data['version'] = __version__
return data

Expand Down
9 changes: 9 additions & 0 deletions memegen/services/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ def find(self, key):
# Else, no match
raise self.exceptions.TemplateNotFound

def aliases(self, query=""):
"""Get all aliases with an optional name filter."""
names = []
for template in self.all():
for name in [template.key] + template.aliases:
if query in name:
names.append(name)
return names

def validate(self):
"""Ensure all template are valid and conflict-free."""
templates = self.all()
Expand Down
16 changes: 16 additions & 0 deletions memegen/test/test_services_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ def test_find_template_by_alias(self, template_service):

assert 'hello' == template.key

def test_aliases(self, template_service):
template = Template('a', aliases=['b', 'c'])
template_service.template_store.filter.return_value = [template]

aliases = template_service.aliases()

assert ['a', 'b', 'c'] == sorted(aliases)

def test_aliases_with_filter(self, template_service):
template = Template('a1', aliases=['a2', 'b1'])
template_service.template_store.filter.return_value = [template]

aliases = template_service.aliases('a')

assert ['a1', 'a2'] == sorted(aliases)

def test_validate_with_good_templates(self, template_service):
templates = [Template(key='abc',
name="The ABC Meme"),
Expand Down
35 changes: 35 additions & 0 deletions tests/test_routes_aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# pylint: disable=unused-variable,misplaced-comparison-constant,expression-not-assigned

from .conftest import load


def describe_get():

def it_returns_all_aliases(client):
response = client.get("/aliases/")

assert 200 == response.status_code
assert len(load(response)) > 200

def describe_filter():

def with_single_match(client):
response = client.get("/aliases/?name=sad-biden")

assert 200 == response.status_code
assert {
'sad-biden': {
'styles': [
'down',
'scowl',
'window',
],
'template': "http://localhost/templates/sad-biden"
}
} == load(response)

def with_many_matches(client):
response = client.get("/aliases/?name=votestakes")

assert 200 == response.status_code
assert len(load(response)) == 3
1 change: 1 addition & 0 deletions tests/test_routes_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ def test_get_root(self, client):
assert 200 == response.status_code
assert dict(
templates="http://localhost/templates/",
aliases="http://localhost/aliases/",
version="1",
) == load(response)

0 comments on commit 39d8422

Please sign in to comment.