Skip to content

Commit

Permalink
Completed work on add column (validation etc), closes #4
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Oct 1, 2020
1 parent bd089f8 commit 3d98259
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 6 deletions.
33 changes: 28 additions & 5 deletions datasette_edit_schema/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from datasette import hookimpl
from datasette.utils.asgi import Response, NotFound, Forbidden
from datasette.utils import sqlite3
from urllib.parse import quote_plus, unquote_plus
import sqlite_utils

Expand Down Expand Up @@ -210,15 +211,37 @@ async def add_column(request, datasette, database, table, formdata):
name = formdata["name"]
type = formdata["type"]

redirect = Response.redirect(
"/-/edit-schema/{}/{}".format(quote_plus(database.name), quote_plus(table))
)

if not name:
datasette.add_message(request, "Column name is required", datasette.ERROR)
return redirect

if type.upper() not in REV_TYPES:
datasette.add_message(request, "Invalid type: {}".format(type), datasette.ERROR)
return redirect

def do_add_column(conn):
db = sqlite_utils.Database(conn)
db[table].add_column(name, type)
db[table].add_column(name, REV_TYPES[type.upper()])

await datasette.databases[database.name].execute_write_fn(do_add_column, block=True)
error = None
try:
await datasette.databases[database.name].execute_write_fn(
do_add_column, block=True
)
except sqlite3.OperationalError as e:
if "duplicate column name" in str(e):
error = "A column called '{}' already exists".format(name)
else:
error = str(e)

return Response.redirect(
"/{}/{}".format(quote_plus(database.name), quote_plus(table))
)
if error:
datasette.add_message(request, error, datasette.ERROR)

return redirect


async def rename_table(request, datasette, database, table, formdata):
Expand Down
45 changes: 44 additions & 1 deletion tests/test_edit_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async def test_delete_table(db_path):
@pytest.mark.asyncio
@pytest.mark.parametrize(
"col_type,expected_type",
[("text", str), ("integer", int), ("float", float), ("blob", bytes)],
[("text", str), ("integer", int), ("real", float), ("blob", bytes)],
)
async def test_add_column(db_path, col_type, expected_type):
ds = Datasette([db_path])
Expand All @@ -110,13 +110,56 @@ async def test_add_column(db_path, col_type, expected_type):
cookies=cookies,
)
assert 302 == response.status_code
if "ds_messages" in response.cookies:
messages = ds.unsign(response.cookies["ds_messages"], "messages")
# None of these should be errors
assert all(m[1] == Datasette.INFO for m in messages), "Got an error: {}".format(
messages
)
assert {
"name": str,
"description": str,
"new_col": expected_type,
} == table.columns_dict


@pytest.mark.asyncio
@pytest.mark.parametrize(
"name,type,expected_error",
[
("name", "text", "A column called 'name' already exists"),
("", "text", "Column name is required"),
("]]]", "integer", 'unrecognized token: "]"'),
("name", "blop", "Invalid type: blop"),
],
)
async def test_add_column_errors(db_path, name, type, expected_error):
ds = Datasette([db_path])
cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")}
async with httpx.AsyncClient(app=ds.app()) as client:
csrftoken = (
await client.get(
"http://localhost/-/edit-schema/data/creatures", cookies=cookies
)
).cookies["ds_csrftoken"]
response = await client.post(
"http://localhost/-/edit-schema/data/creatures",
data={
"add_column": "1",
"name": name,
"type": type,
"csrftoken": csrftoken,
},
allow_redirects=False,
cookies=cookies,
)
response.status_code == 302
assert response.headers["location"] == "/-/edit-schema/data/creatures"
messages = ds.unsign(response.cookies["ds_messages"], "messages")
assert len(messages) == 1
assert messages[0][0] == expected_error


@pytest.mark.asyncio
@pytest.mark.parametrize(
"post_data,expected_columns_dict,expected_order",
Expand Down

0 comments on commit 3d98259

Please sign in to comment.