From 88f2bc9cba9d2f3057813f8e0b4bc029ddcee117 Mon Sep 17 00:00:00 2001 From: Faakhir Zahid <110815427+Faakhir30@users.noreply.github.com> Date: Wed, 22 Jan 2025 08:01:56 +0500 Subject: [PATCH] add query param to search registry records. (#1861) * add query param to search registry records. * refactor serializer. * format using black. * use tmp registry isntead of seperate serializer class. * udpate http resp files * update docs. * update docs. * version added * Update docs/source/endpoints/registry.md * Apply suggestions from code review --------- Co-authored-by: Steve Piercy Co-authored-by: David Glick --- docs/source/endpoints/registry.md | 19 +++++++ news/1861.feature | 1 + src/plone/restapi/services/registry/get.py | 13 ++++- .../registry_get_list_filtered.req | 3 + .../registry_get_list_filtered.resp | 57 +++++++++++++++++++ src/plone/restapi/tests/test_documentation.py | 4 ++ src/plone/restapi/tests/test_registry.py | 9 +++ 7 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 news/1861.feature create mode 100644 src/plone/restapi/tests/http-examples/registry_get_list_filtered.req create mode 100644 src/plone/restapi/tests/http-examples/registry_get_list_filtered.resp diff --git a/docs/source/endpoints/registry.md b/docs/source/endpoints/registry.md index 57fb9f3426..1a5e0a9c7f 100644 --- a/docs/source/endpoints/registry.md +++ b/docs/source/endpoints/registry.md @@ -52,6 +52,25 @@ Example response: :language: http ``` +## Filter list of registry records + +```{versionadded} plone.restapi 9.10.0 +``` + +You can filter a list of registry records and batch the results. +To do so, append a query string to the listing endpoint with a `q` parameter and its value set to the prefix of the desired record name. +See {doc}`../usage/batching` for details of how to work with batched results. + +```{eval-rst} +.. http:example:: curl httpie python-requests + :request: ../../../src/plone/restapi/tests/http-examples/registry_get_list_filtered.req +``` + +Example response: + +```{literalinclude} ../../../src/plone/restapi/tests/http-examples/registry_get_list_filtered.resp +:language: http +``` ## Updating registry records diff --git a/news/1861.feature b/news/1861.feature new file mode 100644 index 0000000000..5e3538d612 --- /dev/null +++ b/news/1861.feature @@ -0,0 +1 @@ +In the `@registry` endpoint, added support for filtering the list of registry records. @Faakhir30 \ No newline at end of file diff --git a/src/plone/restapi/services/registry/get.py b/src/plone/restapi/services/registry/get.py index b75ecc07a4..689d712da3 100644 --- a/src/plone/restapi/services/registry/get.py +++ b/src/plone/restapi/services/registry/get.py @@ -1,3 +1,4 @@ +from plone.registry import Registry from plone.registry.interfaces import IRegistry from plone.restapi.interfaces import ISerializeToJson from plone.restapi.serializer.converters import json_compatible @@ -35,5 +36,15 @@ def reply(self): value = registry[self._get_record_name] return json_compatible(value) else: # batched listing - serializer = getMultiAdapter((registry, self.request), ISerializeToJson) + if q := self.request.form.get("q"): + + tmp_registry = Registry() + for key in registry.records.keys(): + if key.startswith(q): + tmp_registry.records[key] = registry.records[key] + registry = tmp_registry + serializer = getMultiAdapter( + (registry, self.request), + ISerializeToJson, + ) return serializer() diff --git a/src/plone/restapi/tests/http-examples/registry_get_list_filtered.req b/src/plone/restapi/tests/http-examples/registry_get_list_filtered.req new file mode 100644 index 0000000000..f9cfd8b3c8 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/registry_get_list_filtered.req @@ -0,0 +1,3 @@ +GET /plone/@registry?q=Products.CMFPlone HTTP/1.1 +Accept: application/json +Authorization: Basic YWRtaW46c2VjcmV0 diff --git a/src/plone/restapi/tests/http-examples/registry_get_list_filtered.resp b/src/plone/restapi/tests/http-examples/registry_get_list_filtered.resp new file mode 100644 index 0000000000..8962fb5d70 --- /dev/null +++ b/src/plone/restapi/tests/http-examples/registry_get_list_filtered.resp @@ -0,0 +1,57 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "@id": "http://localhost:55001/plone/@registry?q=Products.CMFPlone", + "items": [ + { + "name": "Products.CMFPlone.i18nl10n.override_dateformat.Enabled", + "schema": { + "properties": { + "description": "Override the translation machinery", + "factory": "Yes/No", + "title": "Enabled", + "type": "boolean" + } + }, + "value": false + }, + { + "name": "Products.CMFPlone.i18nl10n.override_dateformat.date_format_long", + "schema": { + "properties": { + "description": "Default value: %Y-%m-%d %H:%M (2038-01-19 03:14)", + "factory": "Text line (String)", + "title": "old ZMI property: localLongTimeFormat", + "type": "string" + } + }, + "value": "%Y-%m-%d %H:%M" + }, + { + "name": "Products.CMFPlone.i18nl10n.override_dateformat.date_format_short", + "schema": { + "properties": { + "description": "Default value: %Y-%m-%d (2038-01-19)", + "factory": "Text line (String)", + "title": "old ZMI property: localTimeFormat", + "type": "string" + } + }, + "value": "%Y-%m-%d" + }, + { + "name": "Products.CMFPlone.i18nl10n.override_dateformat.time_format", + "schema": { + "properties": { + "description": "Default value: %H:%M (03:14)", + "factory": "Text line (String)", + "title": "old ZMI property: localTimeOnlyFormat", + "type": "string" + } + }, + "value": "%H:%M" + } + ], + "items_total": 4 +} diff --git a/src/plone/restapi/tests/test_documentation.py b/src/plone/restapi/tests/test_documentation.py index 574873ce6e..916f654b2a 100644 --- a/src/plone/restapi/tests/test_documentation.py +++ b/src/plone/restapi/tests/test_documentation.py @@ -549,6 +549,10 @@ def test_documentation_registry_get_list(self): response = self.api_session.get("/@registry") save_request_and_response_for_docs("registry_get_list", response) + def test_documentation_registry_get_list_filtered(self): + response = self.api_session.get("/@registry?q=Products.CMFPlone") + save_request_and_response_for_docs("registry_get_list_filtered", response) + def test_documentation_types(self): response = self.api_session.get("/@types") save_request_and_response_for_docs("types", response) diff --git a/src/plone/restapi/tests/test_registry.py b/src/plone/restapi/tests/test_registry.py index 61a266b644..069ca363cb 100644 --- a/src/plone/restapi/tests/test_registry.py +++ b/src/plone/restapi/tests/test_registry.py @@ -107,3 +107,12 @@ def test_get_listing(self): self.assertIn("items", response) self.assertIn("batching", response) self.assertIn("next", response["batching"]) + + def test_get_filtered_listing(self): + response = self.api_session.get("/@registry?q=foo.bar1") + self.assertEqual(response.status_code, 200) + response = response.json() + # 10 records from foo.bar10 to foo.bar19 and 1 record foo.bar1 + self.assertEqual(len(response["items"]), 11) + self.assertEqual(response["items"][0]["name"], "foo.bar1") + self.assertEqual(response["items"][0]["value"], "Lorem Ipsum")