Skip to content

Commit

Permalink
Merge pull request #56 from xsnippet/filter-syntax
Browse files Browse the repository at this point in the history
Add snippets filtering by syntax
  • Loading branch information
malor committed Jan 7, 2018
2 parents 6c2961f + a46799f commit 94ad81d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
43 changes: 43 additions & 0 deletions tests/resources/test_snippets.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,49 @@ async def test_get_snippets_filter_by_tag_bad_request(
}


async def test_get_snippets_filter_by_syntax(testapp, snippets, db):
await db.snippets.insert(snippets)

resp = await testapp.get(
'/snippets?syntax=python',
headers={
'Accept': 'application/json',
})
assert resp.status == 200
expected = [snippets[0]]
for snippet_db, snippet_api in zip(expected, await resp.json()):
_compare_snippets(snippet_db, snippet_api)

nonexistent = await testapp.get(
'/snippets?syntax=javascript',
headers={
'Accept': 'application/json',
})
assert nonexistent.status == 200
assert list(nonexistent.json()) == []


@pytest.mark.parametrize(
'value',
['', 'ololo'],
ids=['empty', 'non-exist']
)
async def test_get_snippets_filter_by_syntax_bad_request(
value, testapp, snippets, db, appinstance):
appinstance['conf']['snippet']['syntaxes'] = 'python\nclojure'
await db.snippets.insert(snippets)

resp = await testapp.get(
'/snippets?syntax=' + value,
headers={
'Accept': 'application/json',
})
assert resp.status == 400
assert await resp.json() == {
'message': '`syntax` - unallowed value %s.' % value
}


async def test_get_snippets_filter_by_title_and_tag(testapp, snippets, db):
await db.snippets.insert(snippets)

Expand Down
14 changes: 13 additions & 1 deletion xsnippet/api/resources/snippets.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,20 @@ async def get(self):
'tag': {
'type': 'string',
'regex': '[\w_-]+',
}
},
'syntax': {
'type': 'string',
},
})

conf = self.request.app['conf']
syntaxes = conf.getlist('snippet', 'syntaxes', fallback=None)

# If 'snippet:syntaxes' option is not empty, we need to ensure that
# only specified syntaxes are allowed.
if syntaxes:
v.schema['syntax']['allowed'] = syntaxes

if not v.validate(dict(self.request.GET)):
error = '%s.' % cerberus_errors_to_str(v.errors)
return self.make_response({'message': error}, status=400)
Expand All @@ -163,6 +174,7 @@ async def get(self):
snippets = await services.Snippet(self.db).get(
title=self.request.GET.get('title'),
tag=self.request.GET.get('tag'),
syntax=self.request.GET.get('syntax'),
# It's safe to have type cast here since those query parameters
# are guaranteed to be integer, thanks to validation above.
limit=int(self.request.GET.get('limit', 0)),
Expand Down
5 changes: 4 additions & 1 deletion xsnippet/api/services/snippet.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ async def update(self, snippet):
async def replace(self, snippet):
return await self.update(self._normalize(snippet))

async def get(self, *, title=None, tag=None, limit=100, marker=None):
async def get(self, *, title=None, tag=None, syntax=None, limit=100,
marker=None):
condition = {}

if title is not None:
condition['title'] = {'$regex': '^' + re.escape(title) + '.*'}
if tag is not None:
condition['tags'] = tag
if syntax is not None:
condition['syntax'] = syntax

if marker:
specimen = await self.db.snippets.find_one({'_id': marker})
Expand Down

0 comments on commit 94ad81d

Please sign in to comment.