diff --git a/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py b/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py index 5ff3f1490740..89e10956dedd 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/_table_client.py @@ -539,6 +539,12 @@ def list_entities( :rtype: An iterator of custom entity type. :raises: :class:`~azure.core.exceptions.HttpResponseError` """ + if "query_filter" in kwargs or "parameters" in kwargs: + raise ValueError( + "'query_filter' and 'parameters' are not supported for 'list_entities'. " + "Use 'query_entities' for server-side filtering." + ) + if select and not isinstance(select, str): select = ",".join(select) diff --git a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py index d0b32634af4d..97e2ace112dc 100644 --- a/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py +++ b/sdk/tables/azure-data-tables/azure/data/tables/aio/_table_client_async.py @@ -561,6 +561,12 @@ def list_entities( :dedent: 16 :caption: Listing all entities held within a table """ + if "query_filter" in kwargs or "parameters" in kwargs: + raise ValueError( + "'query_filter' and 'parameters' are not supported for 'list_entities'. " + "Use 'query_entities' for server-side filtering." + ) + if select and not isinstance(select, str): select = ",".join(select) diff --git a/sdk/tables/azure-data-tables/tests/test_table_client.py b/sdk/tables/azure-data-tables/tests/test_table_client.py index 46b3aa7b7e4f..2639fe0c901c 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client.py @@ -1050,3 +1050,36 @@ def test_use_development_storage(self): assert tsc._primary_endpoint == "http://127.0.0.1:10002/devstoreaccount1" assert tsc._secondary_endpoint == "http://127.0.0.1:10002/devstoreaccount1-secondary" assert not tsc._cosmos_endpoint + + def test_list_entities_rejects_query_filter(self): + """Regression test: list_entities raises ValueError for query_filter instead of leaking to transport.""" + credential = AzureNamedKeyCredential( + "fake_account", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + ) + client = TableClient("https://fake_account.table.core.windows.net", "testtable", credential=credential) + + with pytest.raises(ValueError, match="query_filter"): + client.list_entities(query_filter="PartitionKey eq 'pk001'") + client.close() + + def test_list_entities_rejects_query_filter_with_parameters(self): + """Regression test: list_entities raises ValueError when query_filter is passed with parameters.""" + credential = AzureNamedKeyCredential( + "fake_account", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + ) + client = TableClient("https://fake_account.table.core.windows.net", "testtable", credential=credential) + + with pytest.raises(ValueError, match="query_entities"): + client.list_entities(query_filter="PartitionKey eq @pk", parameters={"pk": "pk001"}) + client.close() + + def test_list_entities_rejects_parameters_without_query_filter(self): + """Regression test: list_entities raises ValueError when parameters are passed without query_filter.""" + credential = AzureNamedKeyCredential( + "fake_account", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + ) + client = TableClient("https://fake_account.table.core.windows.net", "testtable", credential=credential) + + with pytest.raises(ValueError, match="parameters"): + client.list_entities(parameters={"pk": "pk001"}) + client.close() diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_async.py b/sdk/tables/azure-data-tables/tests/test_table_client_async.py index b32e873fb5ea..54c31a6a1769 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_async.py @@ -1076,3 +1076,39 @@ def test_use_development_storage(self): assert tsc._primary_endpoint == "http://127.0.0.1:10002/devstoreaccount1" assert tsc._secondary_endpoint == "http://127.0.0.1:10002/devstoreaccount1-secondary" assert not tsc._cosmos_endpoint + + @pytest.mark.asyncio + async def test_list_entities_rejects_query_filter(self): + """Regression test: list_entities raises ValueError for query_filter instead of leaking to transport.""" + credential = AzureNamedKeyCredential( + "fake_account", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + ) + client = TableClient("https://fake_account.table.core.windows.net", "testtable", credential=credential) + + with pytest.raises(ValueError, match="query_filter"): + client.list_entities(query_filter="PartitionKey eq 'pk001'") + await client.close() + + @pytest.mark.asyncio + async def test_list_entities_rejects_query_filter_with_parameters(self): + """Regression test: list_entities raises ValueError when query_filter is passed with parameters.""" + credential = AzureNamedKeyCredential( + "fake_account", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + ) + client = TableClient("https://fake_account.table.core.windows.net", "testtable", credential=credential) + + with pytest.raises(ValueError, match="query_entities"): + client.list_entities(query_filter="PartitionKey eq @pk", parameters={"pk": "pk001"}) + await client.close() + + @pytest.mark.asyncio + async def test_list_entities_rejects_parameters_without_query_filter(self): + """Regression test: list_entities raises ValueError when parameters are passed without query_filter.""" + credential = AzureNamedKeyCredential( + "fake_account", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" + ) + client = TableClient("https://fake_account.table.core.windows.net", "testtable", credential=credential) + + with pytest.raises(ValueError, match="parameters"): + client.list_entities(parameters={"pk": "pk001"}) + await client.close()