Skip to content

Commit

Permalink
Work in progress with failing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Mar 30, 2018
1 parent 7365c3f commit 2f8359c
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
5 changes: 5 additions & 0 deletions datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,11 @@ async def data(self, request, name, hash, table):
if where_clauses:
where_clause = 'where {} '.format(' and '.join(where_clauses))

# Allow for custom sort order
sort = special_args.get('_sort')
if sort:
order_by = sort

if order_by:
order_by = 'order by {} '.format(order_by)

Expand Down
12 changes: 12 additions & 0 deletions datasette/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from contextlib import contextmanager
from collections import namedtuple
import base64
import hashlib
import json
Expand All @@ -12,6 +13,17 @@
import urllib


Sort = namedtuple('Sort', ['column', 'desc', 'nulls_last'])
sort_mapping = {
'_sort': Sort('_sort', False, False),
'_sort_asc': Sort('_sort', False, False),
'_sort_desc': Sort('_sort_desc', True, False),
'_sort_nulls_last': Sort('_sort_nulls_last', False, True),
'_sort_asc_nulls_last': Sort('_sort_nulls_last', False, True),
'_sort_desc_nulls_last': Sort('_sort_desc_nulls_last', True, True),
}


def compound_pks_from_path(path):
return [
urllib.parse.unquote_plus(b) for b in path.split(',')
Expand Down
37 changes: 36 additions & 1 deletion tests/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datasette.app import Datasette
import itertools
import os
import random
import sqlite3
import string
import tempfile
Expand Down Expand Up @@ -33,6 +34,25 @@ def generate_compound_rows(num):
yield a, b, c, '{}-{}-{}'.format(a, b, c)


def generate_sortable_rows(num):
rand = random.Random(42)
for a, b in itertools.islice(
itertools.product(string.ascii_lowercase, repeat=2), num
):
yield {
'pk1': a,
'pk2': b,
'content': '{}-{}'.format(a, b),
'sortable': rand.randint(-100, 100),
'sortable_with_nulls': rand.choice([
None, rand.random(), rand.random()
]),
'sortable_with_nulls_2': rand.choice([
None, rand.random(), rand.random()
]),
}


METADATA = {
'title': 'Datasette Title',
'description': 'Datasette Description',
Expand Down Expand Up @@ -69,7 +89,6 @@ def generate_compound_rows(num):
INSERT INTO compound_primary_key VALUES ('a', 'b', 'c');
CREATE TABLE compound_three_primary_keys (
pk1 varchar(30),
pk2 varchar(30),
Expand All @@ -78,6 +97,15 @@ def generate_compound_rows(num):
PRIMARY KEY (pk1, pk2, pk3)
);
CREATE TABLE sortable (
pk1 varchar(30),
pk2 varchar(30),
content text,
sortable integer,
sortable_with_nulls real,
sortable_with_nulls_2 real,
PRIMARY KEY (pk1, pk2)
);
CREATE TABLE no_primary_key (
content text,
Expand Down Expand Up @@ -134,4 +162,11 @@ def generate_compound_rows(num):
'INSERT INTO compound_three_primary_keys VALUES ("{a}", "{b}", "{c}", "{content}");'.format(
a=a, b=b, c=c, content=content
) for a, b, c, content in generate_compound_rows(1001)
]) + '\n'.join([
'''INSERT INTO sortable VALUES (
"{pk1}", "{pk2}", "{content}", {sortable},
{sortable_with_nulls}, {sortable_with_nulls_2});
'''.format(
**row
).replace('None', 'null') for row in generate_sortable_rows(201)
])
37 changes: 36 additions & 1 deletion tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .fixtures import (
app_client,
generate_compound_rows,
generate_sortable_rows,
)
import pytest

Expand All @@ -13,7 +14,7 @@ def test_homepage(app_client):
assert response.json.keys() == {'test_tables': 0}.keys()
d = response.json['test_tables']
assert d['name'] == 'test_tables'
assert d['tables_count'] == 8
assert d['tables_count'] == 9


def test_database_page(app_client):
Expand Down Expand Up @@ -99,6 +100,16 @@ def test_database_page(app_client):
'outgoing': [],
},
'label_column': None,
}, {
'columns': [
'pk1', 'pk2', 'content', 'sortable', 'sortable_with_nulls',
'sortable_with_nulls_2'
],
'name': 'sortable',
'count': 201,
'hidden': False,
'foreign_keys': {'incoming': [], 'outgoing': []},
'label_column': None,
}, {
'columns': ['pk', 'content'],
'name': 'table/with/slashes.csv',
Expand Down Expand Up @@ -247,6 +258,30 @@ def test_paginate_compound_keys_with_extra_filters(app_client):
assert expected == [f['content'] for f in fetched]


@pytest.mark.parametrize('query_string,sort_key', [
('_sort=sortable', lambda row: row['sortable']),
('_sort_desc=sortable', lambda row: -row['sortable']),
])
def test_sortable(app_client, query_string, sort_key):
path = '/test_tables/sortable.jsono?{}'.format(query_string)
fetched = []
page = 0
while path:
page += 1
assert page < 100
response = app_client.get(path, gather_request=False)
fetched.extend(response.json['rows'])
path = response.json['next_url']
assert 5 == page
expected = list(generate_sortable_rows(201))
expected.sort(key=sort_key)
assert [
r['content'] for r in expected
] == [
r['content'] for r in fetched
]


@pytest.mark.parametrize('path,expected_rows', [
('/test_tables/simple_primary_key.json?content=hello', [
['1', 'hello'],
Expand Down

0 comments on commit 2f8359c

Please sign in to comment.