Skip to content

Commit

Permalink
type handling improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
drkane committed Feb 2, 2024
1 parent 6de3fc6 commit 77f96bb
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 10 deletions.
64 changes: 56 additions & 8 deletions src/datasette_reconcile/reconcile.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,37 @@ async def suggest_property(self, request):
return self._response({"result": properties})

async def suggest_type(self, request):
prefix = request.args.get("prefix") # noqa: F841
prefix = request.args.get("prefix")

return self._response({"result": []})
default_type = self.config.get("type_default", [DEFAULT_TYPE])
type_field = self.config.get("type_field")
if type_field:
query_sql = """
SELECT CASE WHEN {type_field} IS NULL THEN '{default_type}' ELSE {type_field} END as type
FROM {from_clause}
GROUP BY type
""".format( # noqa: S608
type_field=escape_sqlite(type_field),
default_type=default_type[0]["id"],
from_clause=escape_sqlite(self.table),
)
types = [
{
"id": r["type"],
"name": r["type"],
}
for r in await self.db.execute(query_sql)
]
else:
types = default_type

return self._response(
{
"result": [
type_ for type_ in types if prefix.lower() in type_["id"] or prefix.lower() in type_["name"]
][:DEFAULT_LIMIT]
}
)

async def _get_properties(self):
column_descriptions = self.datasette.table_metadata(self.database, self.table).get("columns") or {}
Expand Down Expand Up @@ -182,6 +210,16 @@ async def _reconcile_queries(self, queries):
)
params["search_query"] = f"%{query['query']}%"

types = query.get("type", [])
type_field = self.config.get("type_field")
if types and type_field:
where_clauses.append(
"{type_field} in ({types})".format(
type_field=escape_sqlite(type_field),
types=",".join([f"'{t}'" for t in types]),
)
)

query_sql = """
SELECT {select_fields}
FROM {from_clause}
Expand All @@ -202,8 +240,14 @@ def _get_query_result(self, row, query):
name_match = str(name).lower().strip()
query_match = str(query["query"]).lower().strip()
type_ = self.config.get("type_default", [DEFAULT_TYPE])
if self.config.get("type_field") and self.config["type_field"] in row:
type_ = [row[self.config["type_field"]]]
type_field = self.config.get("type_field")
if type_field and type_field in dict(row):
type_ = [
{
"id": row[type_field],
"name": row[type_field],
}
]

return {
"id": str(row[self.config["id_field"]]),
Expand Down Expand Up @@ -243,10 +287,14 @@ async def _service_manifest(self, request):
"defaultTypes": self.config.get("type_default", [DEFAULT_TYPE]),
"view": {"url": view_url},
"extend": {
"propose_properties": {
"service_url": service_url,
"service_path": "/extend/propose",
},
"propose_properties": (
{
"service_url": service_url,
"service_path": "/extend/propose",
}
if self.api_version in ["0.1", "0.2"]
else True
),
"property_settings": [
{
"name": p["id"],
Expand Down
121 changes: 119 additions & 2 deletions tests/test_reconcile.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,130 @@ async def test_response_suggest_property(db_path):


@pytest.mark.asyncio
async def test_response_suggest_type(db_path):
async def test_response_suggest_type_default(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.get("http://localhost/test/dogs/-/reconcile/suggest/type?prefix=a")
response = await client.get("http://localhost/test/dogs/-/reconcile/suggest/type?prefix=obj")
assert 200 == response.status_code
data = response.json()

assert "result" in data
assert len(data["result"]) == 1
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_suggest_type_default_empty(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.get("http://localhost/test/dogs/-/reconcile/suggest/type?prefix=xxx")
assert 200 == response.status_code
data = response.json()

assert "result" in data
assert len(data["result"]) == 0
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_suggest_type_empty(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name", "type_field": "status"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.get("http://localhost/test/dogs/-/reconcile/suggest/type?prefix=xxx")
assert 200 == response.status_code
data = response.json()

assert "result" in data
assert len(data["result"]) == 0
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_suggest_type_all(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name", "type_field": "status"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.get("http://localhost/test/dogs/-/reconcile/suggest/type?prefix=dog")
assert 200 == response.status_code
data = response.json()

assert "result" in data
assert len(data["result"]) == 2
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_suggest_type_1(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name", "type_field": "status"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.get("http://localhost/test/dogs/-/reconcile/suggest/type?prefix=good")
assert 200 == response.status_code
data = response.json()

assert "result" in data
assert len(data["result"]) == 1
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_queries_post_type(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name", "type_field": "status"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.post(
"http://localhost/test/dogs/-/reconcile",
data={"queries": json.dumps({"q0": {"query": "fido", "type": ["bad dog"]}})},
)
assert 200 == response.status_code
data = response.json()
assert "q0" in data.keys()
assert len(data["q0"]["result"]) == 1
result = data["q0"]["result"][0]
assert result["id"] == "3"
assert result["name"] == "Fido"
assert result["score"] == 100
assert result["type"] == [
{
"name": "bad dog",
"id": "bad dog",
}
]
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_queries_post_type_empty(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name", "type_field": "status"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.post(
"http://localhost/test/dogs/-/reconcile",
data={"queries": json.dumps({"q0": {"query": "fido", "type": ["good dog"]}})},
)
assert 200 == response.status_code
data = response.json()
assert "q0" in data.keys()
assert len(data["q0"]["result"]) == 0
assert response.headers["Access-Control-Allow-Origin"] == "*"


@pytest.mark.asyncio
async def test_response_queries_post_type_not_given(db_path):
app = Datasette([db_path], metadata=plugin_metadata({"name_field": "name", "type_field": "status"})).app()
async with httpx.AsyncClient(app=app) as client:
response = await client.post(
"http://localhost/test/dogs/-/reconcile",
data={"queries": json.dumps({"q0": {"query": "fido"}})},
)
assert 200 == response.status_code
data = response.json()
assert "q0" in data.keys()
assert len(data["q0"]["result"]) == 1
result = data["q0"]["result"][0]
assert result["id"] == "3"
assert result["name"] == "Fido"
assert result["score"] == 100
assert result["type"] == [
{
"name": "bad dog",
"id": "bad dog",
}
]
assert response.headers["Access-Control-Allow-Origin"] == "*"

0 comments on commit 77f96bb

Please sign in to comment.