Skip to content

Commit 468ab06

Browse files
authored
feat: DFS support for test result ID, column name queries, and interactive queries (#164)
Add a `test_result_id` field to all metadata models (create, read, and modify). Add an `interactive` field to the query tables request model. Document the ability to filter tables by test result ID and column names.
1 parent c629cc5 commit 468ab06

File tree

6 files changed

+151
-14
lines changed

6 files changed

+151
-14
lines changed

nisystemlink/clients/dataframe/models/_create_table_request.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,11 @@ class CreateTableRequest(JsonModel):
1818
properties: Optional[Dict[str, str]] = None
1919
"""User-defined properties to associate with the table."""
2020

21+
test_result_id: Optional[str] = None
22+
"""The ID of the test result associated with the table. A value of ``None`` or an empty string
23+
indicates there is no associated test result. Added in version 2 of the
24+
:py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.create_tables` operation. Older
25+
versions of the service will ignore this value."""
26+
2127
workspace: Optional[str] = None
2228
"""The workspace to create the table in. Uses the default workspace when not specified."""

nisystemlink/clients/dataframe/models/_modify_table_request.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ class ColumnMetadataPatch(JsonModel):
1111

1212
properties: Dict[str, Optional[str]]
1313
"""The properties to modify. A map of key value properties containing the metadata
14-
to be added or modified. Setting a property value to ``None`` will delete the
15-
property."""
14+
to be added or modified. Set a property value to ``None`` to delete the property."""
1615

1716

1817
class ModifyTableRequest(JsonModel):
@@ -27,17 +26,23 @@ class ModifyTableRequest(JsonModel):
2726
state."""
2827

2928
name: Optional[str] = None
30-
"""The new name of the table. Setting to ``None`` will reset the name to the table's ID."""
29+
"""The new name of the table. Set to ``None`` to reset the name to the table's ID."""
30+
31+
test_result_id: Optional[str] = None
32+
"""The new test result ID associated with the table. Set to ``None`` or an empty string to
33+
remove the test result ID. Added in version 2 of the
34+
:py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.modify_metadata` operation. Older
35+
versions of the service will ignore this value."""
3136

3237
workspace: Optional[str] = None
33-
"""The new workspace for the table. Setting to ``None`` will reset to the
38+
"""The new workspace for the table. Set to ``None`` to reset to the
3439
default workspace. Changing the workspace requires permission to delete the
3540
table in its current workspace and permission to create the table in its new
3641
workspace."""
3742

3843
properties: Optional[Dict[str, Optional[str]]] = None
3944
"""The properties to modify. A map of key value properties containing the
40-
metadata to be added or modified. Setting a property value to ``None`` will
45+
metadata to be added or modified. Set a property value to ``None`` to
4146
delete the property."""
4247

4348
columns: Optional[List[ColumnMetadataPatch]] = None

nisystemlink/clients/dataframe/models/_modify_tables_request.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ class TableMetadataModification(JsonModel):
2222
name: Optional[str] = None
2323
"""The new name of the table."""
2424

25+
test_result_id: Optional[str] = None
26+
"""The new test result ID associated with the table. Set to an empty string to remove
27+
the test result ID. Added in version 2 of the
28+
:py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.modify_metadata` operation. Older
29+
versions of the service will ignore this value."""
30+
2531
workspace: Optional[str] = None
2632
"""The new workspace for the table. Changing the workspace requires
2733
permission to delete the table in its current workspace and permission to

nisystemlink/clients/dataframe/models/_query_tables_request.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class QueryTablesRequest(WithPaging):
1717
1818
Allowed properties in the filter are:
1919
20+
* ``columns``: List of columns in the table (see below; requires version 2 of the
21+
:py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.list_tables` operation)
2022
* ``createdAt``: DateTime the table was created
2123
* ``createdWithin``: TimeSpan in which the table was created
2224
* ``id``: String value uniquely identifying the table
@@ -32,8 +34,14 @@ class QueryTablesRequest(WithPaging):
3234
* ``rowCount``: Int32 number of rows in the table
3335
* ``supportsAppend``: Boolean indicating whether or not the table supports
3436
appending additional rows of data
35-
* ``workspace``: String value ID of the workspace the table belongs to
36-
* ``workspaceName``: String value name of the workspace the table belongs to
37+
* ``testResultId``: String ID of the test result associated with the table (requires version 2
38+
of the :py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.list_tables` operation)
39+
* ``workspace``: String ID of the workspace the table belongs to
40+
* ``workspaceName``: String name of the workspace the table belongs to
41+
42+
Allowed properties in the ``columns`` list are:
43+
44+
* ``name``: String name of the column (requires a ``testResultId`` filter)
3745
3846
Allowed constants in the filter are:
3947
@@ -76,3 +84,9 @@ class QueryTablesRequest(WithPaging):
7684
string. The elements in the list are sorted ascending if false and
7785
descending if true.
7886
"""
87+
88+
interactive: Optional[bool] = None
89+
"""Whether the query is being made within an interactive context, such as a web UI.
90+
Interactive queries receive faster feedback for slow queries. Added in version 2 of the
91+
:py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.list_tables` operation.
92+
Older versions of the service will ignore this value."""

nisystemlink/clients/dataframe/models/_table_metadata.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime
2-
from typing import Dict, List
2+
from typing import Dict, List, Optional
33

44
from nisystemlink.clients.core._uplink._json_model import JsonModel
55

@@ -39,5 +39,10 @@ class TableMetadata(JsonModel):
3939
supports_append: bool
4040
"""Whether the table supports appending additional rows of data."""
4141

42+
test_result_id: Optional[str] = None
43+
"""The ID of the test result associated with the table. Added in version 2 of the
44+
:py:attr:`nisystemlink.clients.dataframe.models.OperationsV1.list_tables` operation. This
45+
value will always be ``None`` when communicating with older versions of the service."""
46+
4247
workspace: str
4348
"""The workspace the table belongs to."""

tests/integration/dataframe/test_dataframe.py

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
2+
import warnings
23
from datetime import datetime, timezone
3-
from typing import List, Optional
4+
from typing import Callable, List, Optional, TypedDict
45

56
import pytest # type: ignore
67
import responses
@@ -31,6 +32,10 @@
3132
from responses import matchers
3233

3334

35+
_TestResultIdArg = TypedDict(
36+
"_TestResultIdArg", {"test_result_id": Optional[str]}, total=False
37+
)
38+
3439
int_index_column = Column(
3540
name="index", data_type=DataType.Int32, column_type=ColumnType.Index
3641
)
@@ -84,6 +89,21 @@ def test_tables(create_table):
8489
return ids
8590

8691

92+
@pytest.fixture(scope="class")
93+
def supports_test_result_id(client: DataFrameClient) -> bool:
94+
"""Fixture to determine if the server supports test result IDs."""
95+
api_info = client.api_info()
96+
result = api_info.operations.create_tables.version >= 2
97+
if not result:
98+
warnings.warn(
99+
(
100+
"The selected version of the DataFrame Service does not support test "
101+
"result IDs. Tests will not attempt to set a test result ID."
102+
)
103+
)
104+
return result
105+
106+
87107
@pytest.mark.enterprise
88108
@pytest.mark.integration
89109
class TestDataFrame:
@@ -126,6 +146,43 @@ def test__create_table__metadata_is_correct(
126146
properties={},
127147
),
128148
]
149+
assert table_metadata.test_result_id is None
150+
151+
def test__create_table__supports_test_result(
152+
self,
153+
client: DataFrameClient,
154+
create_table: Callable[[CreateTableRequest], str],
155+
supports_test_result_id: bool,
156+
):
157+
test_result_id = "Test result" if supports_test_result_id else None
158+
id = create_table(
159+
CreateTableRequest(
160+
columns=[
161+
Column(
162+
name="index",
163+
data_type=DataType.Int32,
164+
column_type=ColumnType.Index,
165+
)
166+
],
167+
name="Test table with test result ID",
168+
test_result_id=test_result_id,
169+
)
170+
)
171+
172+
table = client.get_table_metadata(id)
173+
assert table.test_result_id == test_result_id
174+
175+
page = client.list_tables(take=1, id=[id])
176+
assert len(page.tables) == 1
177+
assert page.tables[0].test_result_id == test_result_id
178+
assert page.continuation_token is None
179+
180+
page = client.query_tables(
181+
QueryTablesRequest(filter="id == @0", substitutions=[id], take=1)
182+
)
183+
assert len(page.tables) == 1
184+
assert page.tables[0].test_result_id == test_result_id
185+
assert page.continuation_token is None
129186

130187
def test__get_table__correct_timestamp(self, client: DataFrameClient, create_table):
131188
id = create_table(basic_table_model)
@@ -188,7 +245,9 @@ def test__query_tables__returns(
188245
assert len(second_page.tables) == 1
189246
assert second_page.continuation_token is None
190247

191-
def test__modify_table__returns(self, client: DataFrameClient, create_table):
248+
def test__modify_table__returns(
249+
self, client: DataFrameClient, create_table, supports_test_result_id: bool
250+
):
192251
id = create_table(basic_table_model)
193252

194253
client.modify_table(
@@ -200,12 +259,18 @@ def test__modify_table__returns(self, client: DataFrameClient, create_table):
200259
columns=[
201260
ColumnMetadataPatch(name="index", properties={"sheep": "baa"})
202261
],
262+
**self._test_result_id_if_supported(
263+
"Test result", supports_test_result_id
264+
),
203265
),
204266
)
205267
table = client.get_table_metadata(id)
206268

207269
assert table.metadata_revision == 2
208270
assert table.name == "Modified table"
271+
assert table.test_result_id == (
272+
"Test result" if supports_test_result_id else None
273+
)
209274
assert table.properties == {"cow": "moo"}
210275
assert table.columns[0].properties == {"sheep": "baa"}
211276

@@ -214,6 +279,9 @@ def test__modify_table__returns(self, client: DataFrameClient, create_table):
214279

215280
assert table.properties == {"cow": "moo", "bee": "buzz"}
216281
assert table.name == "Modified table"
282+
assert table.test_result_id == (
283+
"Test result" if supports_test_result_id else None
284+
)
217285

218286
client.modify_table(
219287
id,
@@ -222,15 +290,23 @@ def test__modify_table__returns(self, client: DataFrameClient, create_table):
222290
name=None,
223291
properties={"cow": None},
224292
columns=[ColumnMetadataPatch(name="index", properties={"sheep": None})],
293+
**self._test_result_id_if_supported(None, supports_test_result_id),
225294
),
226295
)
227296
table = client.get_table_metadata(id)
228297

229298
assert table.metadata_revision == 4
230299
assert table.name == id
300+
assert table.test_result_id is None
231301
assert table.properties == {"bee": "buzz"}
232302
assert table.columns[0].properties == {}
233303

304+
@staticmethod
305+
def _test_result_id_if_supported(
306+
test_result_id: Optional[str], supports_test_result_id: bool
307+
) -> _TestResultIdArg:
308+
return {"test_result_id": test_result_id} if supports_test_result_id else {}
309+
234310
def test__delete_table__deletes(self, client: DataFrameClient):
235311
id = client.create_table(
236312
basic_table_model
@@ -259,13 +335,16 @@ def test__delete_tables__returns_partial_success(self, client: DataFrameClient):
259335
assert len(response.error.inner_errors) == 1
260336

261337
def test__modify_tables__modifies_tables(
262-
self, client: DataFrameClient, create_table
338+
self, client: DataFrameClient, create_table, supports_test_result_id: bool
263339
):
264340
ids = [create_table(basic_table_model) for _ in range(3)]
265341

266342
updates = [
267343
TableMetadataModification(
268-
id=id, name="Modified table", properties={"duck": "quack"}
344+
id=id,
345+
name="Modified table",
346+
test_result_id="Test result" if supports_test_result_id else None,
347+
properties={"duck": "quack"},
269348
)
270349
for id in ids
271350
]
@@ -274,6 +353,9 @@ def test__modify_tables__modifies_tables(
274353

275354
for table in client.list_tables(id=ids).tables:
276355
assert table.name == "Modified table"
356+
assert table.test_result_id == (
357+
"Test result" if supports_test_result_id else None
358+
)
277359
assert table.properties == {"duck": "quack"}
278360

279361
updates = [
@@ -286,15 +368,34 @@ def test__modify_tables__modifies_tables(
286368
)
287369

288370
for table in client.list_tables(id=ids).tables:
371+
assert table.name == "Modified table"
372+
assert table.test_result_id == (
373+
"Test result" if supports_test_result_id else None
374+
)
289375
assert table.properties == {"pig": "oink"}
290376

377+
if supports_test_result_id:
378+
updates = [
379+
TableMetadataModification(id=id, test_result_id="") for id in ids
380+
]
381+
382+
assert client.modify_tables(ModifyTablesRequest(tables=updates)) is None
383+
384+
for table in client.list_tables(id=ids).tables:
385+
assert table.name == "Modified table"
386+
assert table.test_result_id is None
387+
291388
def test__modify_tables__returns_partial_success(
292-
self, client: DataFrameClient, create_table
389+
self, client: DataFrameClient, create_table, supports_test_result_id: bool
293390
):
294391
id = create_table(basic_table_model)
295392

296393
updates = [
297-
TableMetadataModification(id=id, name="Modified table")
394+
TableMetadataModification(
395+
id=id,
396+
name="Modified table",
397+
test_result_id="Test result" if supports_test_result_id else None,
398+
)
298399
for id in [id, "invalid_id"]
299400
]
300401

0 commit comments

Comments
 (0)