Skip to content

Commit c60a0ef

Browse files
committed
[#3688] Add objecttypes client
1 parent 745cbbe commit c60a0ef

File tree

7 files changed

+236
-5
lines changed

7 files changed

+236
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
from .objects import ObjectsClient, ObjecttypesClient
1+
from .objects import ObjectsClient
2+
from .objecttypes import ObjecttypesClient
23

34
__all__ = ["ObjectsClient", "ObjecttypesClient"]

src/openforms/contrib/objects_api/clients/objects.py

-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,3 @@ def create_object(self, object_data: dict) -> dict:
99
response.raise_for_status()
1010

1111
return response.json()
12-
13-
14-
class ObjecttypesClient(NLXClient):
15-
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import Any
2+
from uuid import UUID
3+
4+
from zgw_consumers.nlx import NLXClient
5+
6+
from openforms.utils.api_clients import PaginatedResponseData, pagination_helper
7+
8+
9+
class ObjecttypesClient(NLXClient):
10+
11+
def _get_paginated(
12+
self,
13+
endpoint: str,
14+
page: int | None = None,
15+
page_size: int | None = None,
16+
query_params: dict[Any, Any] | None = None,
17+
):
18+
query_params = query_params or {}
19+
if page is None and page_size is None:
20+
response = self.get(endpoint, params=query_params)
21+
response.raise_for_status()
22+
data: PaginatedResponseData[dict[str, Any]] = response.json()
23+
all_data = pagination_helper(self, data)
24+
return list(all_data)
25+
26+
if page is not None:
27+
query_params["page"] = page
28+
if page_size is not None:
29+
query_params["pageSize"] = page_size
30+
31+
response = self.get(endpoint, params=query_params)
32+
response.raise_for_status()
33+
return response.json()["results"]
34+
35+
def list_objecttypes(
36+
self,
37+
page: int | None = None,
38+
page_size: int | None = None,
39+
) -> list[dict[str, Any]]:
40+
return self._get_paginated(
41+
"objecttypes",
42+
page=page,
43+
page_size=page_size,
44+
)
45+
46+
def list_objecttype_versions(
47+
self,
48+
objecttype_uuid: str | UUID,
49+
page: int | None = None,
50+
page_size: int | None = None,
51+
) -> list[dict[str, Any]]:
52+
return self._get_paginated(
53+
f"objecttypes/{objecttype_uuid}/versions", page=page, page_size=page_size
54+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate, br
9+
Authorization:
10+
- Token 171be5abaf41e7856b423ad513df1ef8f867ff48
11+
Connection:
12+
- keep-alive
13+
User-Agent:
14+
- python-requests/2.31.0
15+
method: GET
16+
uri: http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions
17+
response:
18+
body:
19+
string: '{"count":3,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3","version":3,"objectType":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","status":"draft","jsonSchema":{"$id":"https://example.com/person.schema.json","type":"object","title":"Person","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"age":{"type":"integer","minimum":18,"description":"Age
20+
in years which must be equal to or greater than 18."},"country":{"type":"string","description":"The
21+
person''s current country."},"lastName":{"type":"string","description":"The
22+
person''s last name."},"firstName":{"type":"string","description":"The person''s
23+
first name."}}},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","publishedAt":"2024-02-08"},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2","version":2,"objectType":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","status":"published","jsonSchema":{"$id":"https://example.com/person.schema.json","type":"object","title":"Person","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"age":{"type":"integer","minimum":18,"description":"Age
24+
in years which must be equal to or greater than 18."},"lastName":{"type":"string","description":"The
25+
person''s last name."},"firstName":{"type":"string","description":"The person''s
26+
first name."}}},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","publishedAt":"2024-02-08"},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","version":1,"objectType":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","status":"published","jsonSchema":{"$id":"https://example.com/person.schema.json","type":"object","title":"Person","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"age":{"type":"integer","minimum":0,"description":"Age
27+
in years which must be equal to or greater than zero."},"lastName":{"type":"string","description":"The
28+
person''s last name."},"firstName":{"type":"string","description":"The person''s
29+
first name."}}},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","publishedAt":"2024-02-08"}]}'
30+
headers:
31+
Allow:
32+
- GET, POST, HEAD, OPTIONS
33+
Content-Length:
34+
- '2282'
35+
Content-Type:
36+
- application/json
37+
Referrer-Policy:
38+
- same-origin
39+
X-Content-Type-Options:
40+
- nosniff
41+
X-Frame-Options:
42+
- DENY
43+
status:
44+
code: 200
45+
message: OK
46+
version: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate, br
9+
Authorization:
10+
- Token 171be5abaf41e7856b423ad513df1ef8f867ff48
11+
Connection:
12+
- keep-alive
13+
User-Agent:
14+
- python-requests/2.31.0
15+
method: GET
16+
uri: http://localhost:8001/api/v2/objecttypes
17+
response:
18+
body:
19+
string: '{"count":2,"next":null,"previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]},{"url":"http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","uuid":"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","name":"Person","namePlural":"Persons","description":"","dataClassification":"open","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2023-10-24","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/1","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/2","http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3"]}]}'
20+
headers:
21+
Allow:
22+
- GET, POST, HEAD, OPTIONS
23+
Content-Length:
24+
- '1407'
25+
Content-Type:
26+
- application/json
27+
Referrer-Policy:
28+
- same-origin
29+
X-Content-Type-Options:
30+
- nosniff
31+
X-Frame-Options:
32+
- DENY
33+
status:
34+
code: 200
35+
message: OK
36+
version: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate, br
9+
Authorization:
10+
- Token 171be5abaf41e7856b423ad513df1ef8f867ff48
11+
Connection:
12+
- keep-alive
13+
User-Agent:
14+
- python-requests/2.31.0
15+
method: GET
16+
uri: http://localhost:8001/api/v2/objecttypes?page=1&pageSize=1
17+
response:
18+
body:
19+
string: '{"count":2,"next":"http://localhost:8001/api/v2/objecttypes?page=2&pageSize=1","previous":null,"results":[{"url":"http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f","uuid":"3edfdaf7-f469-470b-a391-bb7ea015bd6f","name":"Tree","namePlural":"Trees","description":"","dataClassification":"confidential","maintainerOrganization":"","maintainerDepartment":"","contactPerson":"","contactEmail":"","source":"","updateFrequency":"unknown","providerOrganization":"","documentationUrl":"","labels":{},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","allowGeometry":true,"versions":["http://localhost:8001/api/v2/objecttypes/3edfdaf7-f469-470b-a391-bb7ea015bd6f/versions/1"]}]}'
20+
headers:
21+
Allow:
22+
- GET, POST, HEAD, OPTIONS
23+
Content-Length:
24+
- '696'
25+
Content-Type:
26+
- application/json
27+
Referrer-Policy:
28+
- same-origin
29+
X-Content-Type-Options:
30+
- nosniff
31+
X-Frame-Options:
32+
- DENY
33+
status:
34+
code: 200
35+
message: OK
36+
version: 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from pathlib import Path
2+
from unittest.mock import patch
3+
4+
from django.test import TestCase
5+
6+
from zgw_consumers.constants import APITypes, AuthTypes
7+
from zgw_consumers.models import Service
8+
9+
from openforms.utils.tests.vcr import OFVCRMixin
10+
11+
from ..client import get_objecttypes_client
12+
from ..models import ObjectsAPIConfig
13+
14+
OBJECTTYPES_API_BASE_URL = "http://localhost:8001/api/v2/"
15+
16+
# The value is the API key loaded in the docker service:
17+
OBJECTTYPES_API_KEY = "171be5abaf41e7856b423ad513df1ef8f867ff48"
18+
19+
20+
class ObjecttypesClientTest(OFVCRMixin, TestCase):
21+
22+
VCR_TEST_FILES = Path(__file__).parent / "files"
23+
24+
def setUp(self) -> None:
25+
super().setUp()
26+
27+
patcher = patch(
28+
"openforms.registrations.contrib.objects_api.client.ObjectsAPIConfig.get_solo",
29+
return_value=ObjectsAPIConfig(
30+
objecttypes_service=Service(
31+
api_root=OBJECTTYPES_API_BASE_URL,
32+
api_type=APITypes.orc,
33+
oas="https://example.com/",
34+
header_key="Authorization",
35+
header_value=f"Token {OBJECTTYPES_API_KEY}",
36+
auth_type=AuthTypes.api_key,
37+
)
38+
),
39+
)
40+
41+
self.config_mock = patcher.start()
42+
self.addCleanup(patcher.stop)
43+
44+
def test_list_objecttypes(self):
45+
with get_objecttypes_client() as client:
46+
data = client.list_objecttypes()
47+
48+
self.assertEqual(len(data), 2)
49+
50+
def test_list_objectypes_pagination(self):
51+
with get_objecttypes_client() as client:
52+
data = client.list_objecttypes(page=1, page_size=1)
53+
54+
self.assertEqual(len(data), 1)
55+
56+
def test_list_objecttype_version(self):
57+
with get_objecttypes_client() as client:
58+
data = client.list_objecttype_versions(
59+
"8e46e0a5-b1b4-449b-b9e9-fa3cea655f48"
60+
)
61+
62+
self.assertEqual(len(data), 3)

0 commit comments

Comments
 (0)