commonground-api-common 2.6.3__py3-none-any.whl → 2.6.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: commonground-api-common
3
- Version: 2.6.3
3
+ Version: 2.6.5
4
4
  Summary: Commonground API tooling
5
5
  Home-page: https://github.com/maykinmedia/commonground-api-common
6
6
  Author: Maykin Media, VNG-Realisatie
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Programming Language :: Python :: 3 :: Only
19
19
  Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
21
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
23
  Requires-Dist: django>=4.2.0
23
24
  Requires-Dist: django-filter<=25.1,>=23.1
@@ -33,7 +34,6 @@ Requires-Dist: zgw-consumers>=0.35.1
33
34
  Requires-Dist: oyaml
34
35
  Requires-Dist: PyJWT>=2.1.1
35
36
  Requires-Dist: requests
36
- Requires-Dist: requests-mock
37
37
  Requires-Dist: coreapi
38
38
  Requires-Dist: ape-pie
39
39
  Provides-Extra: markdown-docs
@@ -50,19 +50,18 @@ Requires-Dist: pytest-django; extra == "tests"
50
50
  Requires-Dist: pytest-dotenv; extra == "tests"
51
51
  Requires-Dist: pytest-factoryboy; extra == "tests"
52
52
  Requires-Dist: tox; extra == "tests"
53
- Requires-Dist: isort; extra == "tests"
54
- Requires-Dist: black; extra == "tests"
53
+ Requires-Dist: ruff; extra == "tests"
55
54
  Requires-Dist: requests-mock; extra == "tests"
56
55
  Requires-Dist: freezegun; extra == "tests"
57
56
  Requires-Dist: zgw-consumers-oas; extra == "tests"
58
57
  Requires-Dist: djangorestframework-gis; extra == "tests"
59
58
  Requires-Dist: drf-extra-fields; extra == "tests"
59
+ Provides-Extra: oas
60
+ Requires-Dist: requests-mock; extra == "oas"
60
61
  Provides-Extra: testutils
61
62
  Requires-Dist: zgw-consumers-oas; extra == "testutils"
62
63
  Provides-Extra: setup-configuration
63
64
  Requires-Dist: django-setup-configuration>=0.7.0; extra == "setup-configuration"
64
- Provides-Extra: pep8
65
- Requires-Dist: flake8; extra == "pep8"
66
65
  Provides-Extra: coverage
67
66
  Requires-Dist: pytest-cov; extra == "coverage"
68
67
  Provides-Extra: docs
@@ -76,7 +75,12 @@ Requires-Dist: bump2version; extra == "release"
76
75
  Commonground-API-common - Tooling voor RESTful APIs
77
76
  ===================================================
78
77
 
79
- |build-status| |code-quality| |coverage| |docs| |black|
78
+
79
+ :Version: 2.6.5
80
+ :Source: https://github.com/maykinmedia/commonground-api-common
81
+ :PythonVersion: 3.12
82
+
83
+ |build-status| |code-quality| |coverage| |docs| |ruff|
80
84
 
81
85
  |python-versions| |django-versions| |pypi-version|
82
86
 
@@ -158,7 +162,8 @@ Features
158
162
  .. |pypi-version| image:: https://img.shields.io/pypi/v/commonground-api-common.svg
159
163
  :target: https://pypi.org/project/commonground-api-common/
160
164
 
161
- .. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
162
- :target: https://github.com/psf/black
165
+ .. |ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
166
+ :target: https://github.com/astral-sh/ruff
167
+ :alt: Ruff
163
168
 
164
169
  .. _documentatie: https://commonground-api-common.readthedocs.io/en/latest/?badge=latest
@@ -1,40 +1,41 @@
1
- commonground_api_common-2.6.3.data/scripts/generate_schema,sha256=OpKgzlFc_uzA3TVW_vHSYXAD_feLaCdTEnkWjIcxVzA,280
2
- vng_api_common/__init__.py,sha256=uJ6TLK18jhCrL0aclBja7NzlAGLAyZjVpX-gq3d461k,22
3
- vng_api_common/admin.py,sha256=iFtUPGf-ha0I-bXgq8QIFrP23Kzk_H3FlgAjt0U-ip0,259
1
+ commonground_api_common-2.6.5.data/scripts/generate_schema,sha256=OpKgzlFc_uzA3TVW_vHSYXAD_feLaCdTEnkWjIcxVzA,280
2
+ vng_api_common/__init__.py,sha256=b8L3dijps7oaMPmOpJzOuXwvOcbIuro9wWmuPwiL87o,22
3
+ vng_api_common/admin.py,sha256=WiD6afzO9sJh_Nz7TKsxCiGm49vS0qQH1PxyXnGpEt8,204
4
4
  vng_api_common/apps.py,sha256=QQiJXRmjX9Q91oh0P9fvVnHe3NSYd1cEcUUBw0HLBCA,3690
5
5
  vng_api_common/checks.py,sha256=tOyfV7MMLGh4anrd_W30LvJCxiyQ4sFs1mGd9mtrEc0,1175
6
6
  vng_api_common/choices.py,sha256=dboFRoM34GpRUpxB9WexexccopcQSogu1QIyY4B9ACY,541
7
- vng_api_common/client.py,sha256=HNLc86RwczAudPBDgH_zQncE19OUaLyhSnacQRxJO0c,1972
7
+ vng_api_common/client.py,sha256=2qLi5BvSiPZ2J93X7_-WFx7F9qBv-y3FhSt5e31QBVo,1971
8
8
  vng_api_common/compat.py,sha256=n4jDFSPzXnh-D_VXjftKMCJYj_q_t6eJrUTWLayl8jQ,768
9
- vng_api_common/constants.py,sha256=yYtnYId9alRuhGBoqaO8lkXYi_ATi2FW-wEDGRpiRuQ,10948
9
+ vng_api_common/constants.py,sha256=_diFyf14vYCdRX8Ewb9IgaK4t8od6zuG_W48TxWL-Lo,11121
10
10
  vng_api_common/decorators.py,sha256=_p-mAyi5Na_-ll00ErcQ3mRoZNCsJzYDAliXn50Bmes,278
11
- vng_api_common/descriptors.py,sha256=RFOqnDn5PEX0-qXb_r4_9wdEvuck5wNxT4tcrP95KaE,3136
11
+ vng_api_common/descriptors.py,sha256=QJX9GINLnxpFDViyfX1SfSq3mowkN9Oq2tvj34qqkE4,3129
12
12
  vng_api_common/doc.py,sha256=a4Wm6Y-Va-tBsLwZFjPX_oA4PppkDR4wpIiw9q7NLd4,1167
13
13
  vng_api_common/exception_handling.py,sha256=Z8Si1-GPWaTtsgaFI_zLOvlnLVLM8jqfgFIimX8eo-8,4759
14
14
  vng_api_common/exceptions.py,sha256=7Qk5dlETjoQjZeGRKei4PkeLACLoZOMrMiuyi-yn6Kk,615
15
15
  vng_api_common/fields.py,sha256=SXY0HB9NiDVmlKdjBDy3b55E4rn-qboiIMBr_eOBuZE,6302
16
- vng_api_common/filters.py,sha256=oPivwrES1BQgSUg1jD9hJab7dyoO3VbZDVbbRRiW2SQ,5618
16
+ vng_api_common/filters.py,sha256=E0Di4HsvaQUFfORn4uzxiVTCcJKeGMfnGSS9BNaX9Mg,3746
17
+ vng_api_common/filters_backend.py,sha256=VUJB6Ya8gwM4DVCffAy0Z3czGMRK6ZEQ8Kq7Rpdhjws,2041
17
18
  vng_api_common/filtersets.py,sha256=CpmuOg6jGKFDwVeCusax-CBI7tv-EuOSBLwewdkLu1Y,1256
18
19
  vng_api_common/generators.py,sha256=88yQN5-vRFUegfzQcsZtlpbtQyn_zZQwvs20OidPK7M,1239
19
20
  vng_api_common/geo.py,sha256=AZbrw0rwGYOmaSUk8JJSkx-4_tVrfT_cgggh9omRwhU,1862
20
21
  vng_api_common/middleware.py,sha256=2DRw0hPpvUMqwoH1Ze8S7tDB16lmj4Bnd6vN5ijkGM8,875
21
- vng_api_common/mocks.py,sha256=0sELLs-uy2ndu29m5P6FN_p1ehNhYv7IoRayYPs379Y,6200
22
+ vng_api_common/mocks.py,sha256=9vL4t-CLIFFgL6MxeyaQy1UP91lrObYI-s3-0h2q3YU,6209
22
23
  vng_api_common/models.py,sha256=3WgpCWQpkCOrMCtqp7EbnP681II43Sg_cch8ZOm4EcU,1707
23
24
  vng_api_common/oas.py,sha256=ATqqNM7zkDMoK3E-cxNh_c65n6YCrP96KxCFYfkEVK0,2523
24
25
  vng_api_common/pagination.py,sha256=U2zojaSHgEIzCEMBzx9r3KLpAujMCdM0ndH3AT6ik1U,734
25
26
  vng_api_common/permissions.py,sha256=ayDxk9Wt8j0yO57FhZ8XaRkPET4lAqd8SSw3m4o3EGs,7562
26
27
  vng_api_common/polymorphism.py,sha256=N-x39pG2unD4N0ZbxFvuhE8ibPaJ0eKeqfvAJW3NnEU,6623
27
- vng_api_common/routers.py,sha256=hEnhBulkgMM-7W_lYaykKTgTBj3-avl7DGsR9P7BbTU,1897
28
+ vng_api_common/routers.py,sha256=UVx7g7UCw7kSQswSVN8fwOGNO0y9vWeHTXHPuMT0h7c,1897
28
29
  vng_api_common/schema.py,sha256=axs2Q8IXwpHNd5WscQg5xOErL6bWhP8WFItTt4xCFO4,16305
29
30
  vng_api_common/scopes.py,sha256=PGs6CkXorAAdWXGFY1bSy-jmsPn122Njen9aFFOpFIQ,2351
30
31
  vng_api_common/search.py,sha256=yehS6boCOk1JXLCqAMU-B62hWtbTBSf_WKIVGPgp0Mg,1045
31
- vng_api_common/serializers.py,sha256=D0DEw-iw4se1MLAlDw25G6q4g1BTEL3VXcuvMTj6qlk,13462
32
+ vng_api_common/serializers.py,sha256=ohdUC11RGMxZQcN2ekLappgT4SbYz12o4GZ7maVS3RY,13464
32
33
  vng_api_common/urls.py,sha256=9IWHYLlEIIHNaZ_Zq02qNQ2HJpETb7o-89r7yBM_tQs,270
33
34
  vng_api_common/utils.py,sha256=EHqVjZhtqnbU7YrqgYIBss28Sd19jtnTLNaMWLfj3Zw,8203
34
- vng_api_common/validators.py,sha256=ejaFZvFXFaBlqxjA2_07NSHKHlG5pejrfC_GHjwCj6E,12852
35
+ vng_api_common/validators.py,sha256=oXCSuX1S2vtOW3qlPMNOCHo2W-4R0pkcXnZb2xV9ILs,12845
35
36
  vng_api_common/version.py,sha256=yJV9_yTM7Qnzg0zGNkJQkN9Uai3I_ZUkcyseJRPRk5I,129
36
- vng_api_common/views.py,sha256=pxpI2dl22I9auTYvRJ-Rx-_NHAKgo1F2QwQJF6WIjrE,7603
37
- vng_api_common/viewsets.py,sha256=z5pzvSymFiiuCjP_-uuW-3OJKZY_psPAt8fWeWySU0c,2278
37
+ vng_api_common/views.py,sha256=ARqNuPlrZ0ctzkHTNs7NMyzrji2LvRmrmzrSNmtS-v0,7603
38
+ vng_api_common/viewsets.py,sha256=jAXKHFRBhNKzkjugpYnXkE2zKvCWwKwZA6_VoiTWjvw,2286
38
39
  vng_api_common/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
40
  vng_api_common/api/permissions.py,sha256=okbwiscxlAtbQWTCRDLL2reOxgj0rRDZeDcrtXAYq00,739
40
41
  vng_api_common/api/serializers.py,sha256=F1od8SZxgIlGVTSd_x5eTxacL6x8HbNn35O9z1zjio4,213
@@ -44,7 +45,7 @@ vng_api_common/audittrails/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
44
45
  vng_api_common/audittrails/admin.py,sha256=mrRK9KhvFlRWcmsq-DM9cJdwtpBUciMa4DvtEIYfirQ,301
45
46
  vng_api_common/audittrails/apps.py,sha256=eM4RMMgqXq_Hm1Il-dUlO0rtXJVP0DgAFQBW25epzdw,111
46
47
  vng_api_common/audittrails/audits.py,sha256=44_vry_9XPZoyKUJeMhhf4xr0OsCndgzGGxRqa65_d0,337
47
- vng_api_common/audittrails/models.py,sha256=O1GhyJlZaDYPTwKcZE45J2Fl1q02BGtYciu-QdjzBsQ,3596
48
+ vng_api_common/audittrails/models.py,sha256=ja3SUY8cdcAMfjp2h4J7QiWikqa1gaCrtHPg_Z7-UIw,3581
48
49
  vng_api_common/audittrails/utils.py,sha256=fhDQ-iaSGE8mWkcE9LXySI_pYfn7Xpao-n1m699h_hk,1316
49
50
  vng_api_common/audittrails/viewsets.py,sha256=K0AMPHYU6w_Z1cAww_itzfHjeqzZhIAi1m3cUHcXp30,8105
50
51
  vng_api_common/audittrails/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -76,9 +77,9 @@ vng_api_common/audittrails/migrations/_operations.py,sha256=UOMv0zAK8CIQ73cSu6ww
76
77
  vng_api_common/authorizations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
78
  vng_api_common/authorizations/admin.py,sha256=Tk0yYKbb005E0XZaYYWbucMf_K5M8Hhz62wSBDi8rhM,813
78
79
  vng_api_common/authorizations/middleware.py,sha256=KJ3znCXPRMOVqSur62SmBjvC6RcKxtcWq1rzaHdYR98,8416
79
- vng_api_common/authorizations/models.py,sha256=slIYxSktxCxSg03Nfb2mhsQse17b93KWE-rdPdMv8Ik,5199
80
+ vng_api_common/authorizations/models.py,sha256=-PwbFceloUz6pbfFp2DB3YfioC2xq63YDm-EVc3U3HE,5160
80
81
  vng_api_common/authorizations/serializers.py,sha256=3HeKWEqhI3UWwI8SttC4rEID-Epbk7SWsC-bEjolbaw,5151
81
- vng_api_common/authorizations/utils.py,sha256=GmwTy5GhYk3e1VU4LpdfYdr8VD-R8p00hUY11QBbOhc,555
82
+ vng_api_common/authorizations/utils.py,sha256=GSeHVXia-GHGCN_E4u671r4pGssvcyp9osKFf8Fc8v4,590
82
83
  vng_api_common/authorizations/validators.py,sha256=u7fKm0QgGy8fiAeYmIEB9Gy-yIE9C-tC2ZpnNQBXPso,2816
83
84
  vng_api_common/authorizations/migrations/0001_initial.py,sha256=ooAZtQeDtWgDxXzAP-KnSyyFYLRPM-PMrK5RgOnTPjQ,4360
84
85
  vng_api_common/authorizations/migrations/0002_authorizationsconfig.py,sha256=m4taH6ClHI-YHYGGOKaq_qYXGx9lq1InXOGLQKg9MSw,1364
@@ -103,10 +104,10 @@ vng_api_common/caching/decorators.py,sha256=lU5dnBjD9aHjoYaV32FlYxY7VFZPdMZe26fV
103
104
  vng_api_common/caching/etags.py,sha256=3zY0DTdwt19QHsxFLK1wqQ3K98JfO6Uxr6tFuixichg,7337
104
105
  vng_api_common/caching/introspection.py,sha256=JKeEuTiyWp1oN1Fg27j5-2btROz9NcLxxfzSZuVVJ9w,575
105
106
  vng_api_common/caching/models.py,sha256=RroS9HFiKNXDV59Odh0x8BO8Az8E81v4gwuprF1A1qg,988
106
- vng_api_common/caching/registry.py,sha256=mY1r99x7m0DQ1BN9lZF2zMjFj_oDNq7urxDkOH7-8Yg,6205
107
+ vng_api_common/caching/registry.py,sha256=oXE4kMnVpdp7qvb_goVkCTY5qeY8kB3EDKVX65fPtYc,6207
107
108
  vng_api_common/caching/signals.py,sha256=78ej5cVan-JpNHKzZNAfs0m2ON_TXKphe8ZKtP-6FVY,4615
108
109
  vng_api_common/conf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
- vng_api_common/conf/api.py,sha256=lKQWJyRjhQugA6UJuJb7BHZfXd2ZnFsYRLmsehDdaQg,3150
110
+ vng_api_common/conf/api.py,sha256=tNShwZevKpJ6n713pPGPuUpThcPq-057JAd3xSHW5sU,3158
110
111
  vng_api_common/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
112
  vng_api_common/contrib/setup_configuration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
113
  vng_api_common/contrib/setup_configuration/models.py,sha256=1-G0hXeRe-x6GYtsAaQeMGXq0-cwU5LMb8KTQWj-pQk,1201
@@ -183,7 +184,7 @@ vng_api_common/tests/auth.py,sha256=IKDWTEFv4Bign4F70-ibsFcnJqRxEJaXvqaPQJWa1xY,
183
184
  vng_api_common/tests/caching.py,sha256=zfIw5cRRvO9cekHZZKfRqZc8cx5IfJUYNmcH6cuIMg4,624
184
185
  vng_api_common/tests/schema.py,sha256=WDvifDQQiKqIpQijpeQ7rYkFroJmuPuHe7zNhl1Bigk,2293
185
186
  vng_api_common/tests/urls.py,sha256=PFrYzQbBC0TFPMEn3uPhcBG0IQs9JsEPqckicJT1UA4,2159
186
- commonground_api_common-2.6.3.dist-info/METADATA,sha256=xAiksqZyWhVPcglOXU0hf8Mh6YvvTDOsbuRGrZdHlAY,6969
187
- commonground_api_common-2.6.3.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
188
- commonground_api_common-2.6.3.dist-info/top_level.txt,sha256=vPismc83zPzWXTmlNCCwfDlFV9iygJYxNJW5iDjKTgw,15
189
- commonground_api_common-2.6.3.dist-info/RECORD,,
187
+ commonground_api_common-2.6.5.dist-info/METADATA,sha256=2AptFlJ9JnnorQ-x3r2Ep60TKF7f6oxpSfM82GB32aM,7129
188
+ commonground_api_common-2.6.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
189
+ commonground_api_common-2.6.5.dist-info/top_level.txt,sha256=vPismc83zPzWXTmlNCCwfDlFV9iygJYxNJW5iDjKTgw,15
190
+ commonground_api_common-2.6.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1 +1 @@
1
- __version__ = "2.6.3"
1
+ __version__ = "2.6.5"
vng_api_common/admin.py CHANGED
@@ -1,5 +1,4 @@
1
1
  from django.contrib import admin
2
- from django.utils.translation import gettext_lazy as _
3
2
 
4
3
  from .models import JWTSecret
5
4
 
@@ -20,8 +20,7 @@ class AuditTrail(models.Model):
20
20
  max_length=255,
21
21
  blank=True,
22
22
  help_text=_(
23
- 'Een globaal "request" ID om een verzoek door het '
24
- "netwerk heen te traceren."
23
+ 'Een globaal "request" ID om een verzoek door het netwerk heen te traceren.'
25
24
  ),
26
25
  )
27
26
  bron = models.CharField(
@@ -11,7 +11,6 @@ from zgw_consumers.constants import APITypes, AuthTypes
11
11
  from vng_api_common.client import Client, get_client
12
12
 
13
13
  from ..constants import ComponentTypes, VertrouwelijkheidsAanduiding
14
- from ..decorators import field_default
15
14
  from ..fields import VertrouwelijkheidsAanduidingField
16
15
  from ..models import APIMixin
17
16
 
@@ -1,18 +1,27 @@
1
- def generate_jwt(client_id, secret, user_id, user_representation):
2
- from zgw_consumers.client import ZGWAuth
1
+ import time
3
2
 
4
- class FakeService:
5
- def __init__(self, **kwargs):
6
- for key, value in kwargs.items():
7
- setattr(self, key, value)
3
+ import jwt
8
4
 
9
- auth = ZGWAuth(
10
- service=FakeService( # type: ignore
11
- client_id=client_id,
12
- secret=secret,
13
- user_id=user_id,
14
- user_representation=user_representation,
15
- jwt_valid_for=5 * 60,
16
- )
17
- )
18
- return f"Bearer {auth._token}"
5
+
6
+ def generate_jwt(
7
+ client_id: str,
8
+ secret: str,
9
+ user_id: str,
10
+ user_representation: str,
11
+ jwt_valid_for: int | None = None,
12
+ ) -> str:
13
+ iat = int(time.time())
14
+ payload = {
15
+ # standard claims
16
+ "iss": client_id,
17
+ "iat": iat,
18
+ # custom claims
19
+ "client_id": client_id,
20
+ "user_id": user_id,
21
+ "user_representation": user_representation,
22
+ }
23
+ if jwt_valid_for:
24
+ payload["exp"] = iat + jwt_valid_for
25
+
26
+ token = jwt.encode(payload, secret, algorithm="HS256")
27
+ return f"Bearer {token}"
@@ -64,9 +64,9 @@ class Dependency:
64
64
  instance: models.Model,
65
65
  is_delete: bool = False,
66
66
  ) -> Iterable[models.Model]:
67
- assert isinstance(
68
- instance, self.source_model
69
- ), "Instance is not of expected model class"
67
+ assert isinstance(instance, self.source_model), (
68
+ "Instance is not of expected model class"
69
+ )
70
70
 
71
71
  reverse_relation_field = self.field.remote_field
72
72
 
vng_api_common/client.py CHANGED
@@ -40,7 +40,6 @@ class Client(APIClient):
40
40
  def request(
41
41
  self, method: str | bytes, url: str | bytes, *args, **kwargs
42
42
  ) -> Response:
43
-
44
43
  headers = kwargs.pop("headers", {})
45
44
  headers.setdefault("Accept", "application/json")
46
45
  headers.setdefault("Content-Type", "application/json")
@@ -33,7 +33,7 @@ BASE_REST_FRAMEWORK = {
33
33
  # of applications
34
34
  "DEFAULT_AUTHENTICATION_CLASSES": (),
35
35
  "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning",
36
- "DEFAULT_FILTER_BACKENDS": ("vng_api_common.filters.Backend",),
36
+ "DEFAULT_FILTER_BACKENDS": ("vng_api_common.filters_backend.Backend",),
37
37
  #
38
38
  # # Filtering
39
39
  "ORDERING_PARAM": "ordering", # 'ordering',
@@ -88,28 +88,40 @@ class RolTypes(models.TextChoices):
88
88
 
89
89
 
90
90
  class Archiefnominatie(models.TextChoices):
91
- blijvend_bewaren = "blijvend_bewaren", _(
92
- "Het zaakdossier moet bewaard blijven en op de Archiefactiedatum "
93
- "overgedragen worden naar een archiefbewaarplaats."
91
+ blijvend_bewaren = (
92
+ "blijvend_bewaren",
93
+ _(
94
+ "Het zaakdossier moet bewaard blijven en op de Archiefactiedatum "
95
+ "overgedragen worden naar een archiefbewaarplaats."
96
+ ),
94
97
  )
95
- vernietigen = "vernietigen", _(
96
- "Het zaakdossier moet op of na de Archiefactiedatum vernietigd worden."
98
+ vernietigen = (
99
+ "vernietigen",
100
+ _("Het zaakdossier moet op of na de Archiefactiedatum vernietigd worden."),
97
101
  )
98
102
 
99
103
 
100
104
  class Archiefstatus(models.TextChoices):
101
- nog_te_archiveren = "nog_te_archiveren", _(
102
- "De zaak cq. het zaakdossier is nog niet als geheel gearchiveerd."
105
+ nog_te_archiveren = (
106
+ "nog_te_archiveren",
107
+ _("De zaak cq. het zaakdossier is nog niet als geheel gearchiveerd."),
103
108
  )
104
- gearchiveerd = "gearchiveerd", _(
105
- "De zaak cq. het zaakdossier is als geheel niet-wijzigbaar bewaarbaar gemaakt."
109
+ gearchiveerd = (
110
+ "gearchiveerd",
111
+ _(
112
+ "De zaak cq. het zaakdossier is als geheel niet-wijzigbaar bewaarbaar gemaakt."
113
+ ),
106
114
  )
107
- gearchiveerd_procestermijn_onbekend = "gearchiveerd_procestermijn_onbekend", _(
108
- "De zaak cq. het zaakdossier is als geheel niet-wijzigbaar bewaarbaar gemaakt "
109
- "maar de vernietigingsdatum kan nog niet bepaald worden."
115
+ gearchiveerd_procestermijn_onbekend = (
116
+ "gearchiveerd_procestermijn_onbekend",
117
+ _(
118
+ "De zaak cq. het zaakdossier is als geheel niet-wijzigbaar bewaarbaar gemaakt "
119
+ "maar de vernietigingsdatum kan nog niet bepaald worden."
120
+ ),
110
121
  )
111
- overgedragen = "overgedragen", _(
112
- "De zaak cq. het zaakdossier is overgebracht naar een archiefbewaarplaats."
122
+ overgedragen = (
123
+ "overgedragen",
124
+ _("De zaak cq. het zaakdossier is overgebracht naar een archiefbewaarplaats."),
113
125
  )
114
126
 
115
127
 
@@ -190,17 +202,20 @@ class ZaakobjectTypes(models.TextChoices):
190
202
  buurt = "buurt", _("Buurt")
191
203
  enkelvoudig_document = "enkelvoudig_document", _("Enkelvoudig document")
192
204
  gemeente = "gemeente", _("Gemeente")
193
- gemeentelijke_openbare_ruimte = "gemeentelijke_openbare_ruimte", _(
194
- "Gemeentelijke openbare ruimte"
205
+ gemeentelijke_openbare_ruimte = (
206
+ "gemeentelijke_openbare_ruimte",
207
+ _("Gemeentelijke openbare ruimte"),
195
208
  )
196
209
  huishouden = "huishouden", _("Huishouden")
197
210
  inrichtingselement = "inrichtingselement", _("Inrichtingselement")
198
- kadastrale_onroerende_zaak = "kadastrale_onroerende_zaak", _(
199
- "Kadastrale onroerende zaak"
211
+ kadastrale_onroerende_zaak = (
212
+ "kadastrale_onroerende_zaak",
213
+ _("Kadastrale onroerende zaak"),
200
214
  )
201
215
  kunstwerkdeel = "kunstwerkdeel", _("Kunstwerkdeel")
202
- maatschappelijke_activiteit = "maatschappelijke_activiteit", _(
203
- "Maatschappelijke activiteit"
216
+ maatschappelijke_activiteit = (
217
+ "maatschappelijke_activiteit",
218
+ _("Maatschappelijke activiteit"),
204
219
  )
205
220
  medewerker = "medewerker", _("Medewerker")
206
221
  natuurlijk_persoon = "natuurlijk_persoon", _("Natuurlijk persoon")
@@ -30,9 +30,9 @@ class GegevensGroepType:
30
30
  self.none_for_empty = none_for_empty
31
31
 
32
32
  all_fields_known = set(self.optional).issubset(set(mapping.keys()))
33
- assert (
34
- all_fields_known
35
- ), "The fields in 'optional' must be a subset of the mapping keys"
33
+ assert all_fields_known, (
34
+ "The fields in 'optional' must be a subset of the mapping keys"
35
+ )
36
36
 
37
37
  # check if it's optional or not
38
38
  self.required = (
@@ -45,7 +45,7 @@ class GegevensGroepType:
45
45
  fields = ", ".join(
46
46
  [
47
47
  field if field not in self.optional else f"{field} (optional)"
48
- for field in self.mapping.keys()
48
+ for field in self.mapping
49
49
  ]
50
50
  )
51
51
  return "<GegevensGroepType: fields=%r required=%r>" % (fields, self.required)
vng_api_common/filters.py CHANGED
@@ -1,71 +1,22 @@
1
1
  import logging
2
- from urllib.parse import urlencode, urlparse
2
+ from urllib.parse import urlparse
3
3
 
4
4
  from django.core.exceptions import ValidationError
5
5
  from django.core.validators import URLValidator
6
6
  from django.db import models
7
7
  from django.forms.widgets import URLInput
8
- from django.http import QueryDict
9
8
  from django.utils.translation import gettext_lazy as _
10
9
 
11
10
  from django_filters import fields, filters
12
11
  from django_filters.constants import EMPTY_VALUES
13
- from django_filters.rest_framework import DjangoFilterBackend
14
- from djangorestframework_camel_case.parser import CamelCaseJSONParser
15
- from djangorestframework_camel_case.render import CamelCaseJSONRenderer
16
- from djangorestframework_camel_case.util import underscoreize
17
- from rest_framework.request import Request
18
- from rest_framework.views import APIView
19
12
 
20
13
  from .constants import FILTER_URL_DID_NOT_RESOLVE
21
- from .search import is_search_view
22
14
  from .utils import NotAViewSet, get_resource_for_path
23
15
  from .validators import validate_rsin
24
16
 
25
17
  logger = logging.getLogger(__name__)
26
18
 
27
19
 
28
- class Backend(DjangoFilterBackend):
29
- def _is_camel_case(self, view):
30
- return any(
31
- issubclass(parser, CamelCaseJSONParser) for parser in view.parser_classes
32
- ) or any(
33
- issubclass(renderer, CamelCaseJSONRenderer)
34
- for renderer in view.renderer_classes
35
- )
36
-
37
- def _transform_query_params(self, view, query_params: QueryDict) -> QueryDict:
38
- if not self._is_camel_case(view):
39
- return query_params
40
-
41
- # data can be a regular dict if it's coming from a serializer
42
- if hasattr(query_params, "lists"):
43
- data = dict(query_params.lists())
44
- else:
45
- data = query_params
46
-
47
- transformed = underscoreize(data)
48
-
49
- return QueryDict(urlencode(transformed, doseq=True))
50
-
51
- def get_filterset_kwargs(
52
- self, request: Request, queryset: models.QuerySet, view: APIView
53
- ):
54
- """
55
- Get the initialization parameters for the filterset.
56
-
57
- * filter on request.data if request.query_params is empty
58
- * do the camelCase transformation of filter parameters
59
- """
60
- kwargs = super().get_filterset_kwargs(request, queryset, view)
61
- filter_parameters = (
62
- request.query_params if not is_search_view(view) else request.data
63
- )
64
- query_params = self._transform_query_params(view, filter_parameters)
65
- kwargs["data"] = query_params
66
- return kwargs
67
-
68
-
69
20
  class URLModelChoiceField(fields.ModelChoiceField):
70
21
  widget = URLInput
71
22
 
@@ -122,7 +73,7 @@ class URLModelChoiceFilter(filters.ModelChoiceFilter):
122
73
 
123
74
  def __init__(self, *args, **kwargs):
124
75
  super().__init__(*args, **kwargs)
125
- self.instance_path = kwargs.get("instance_path", None)
76
+ self.instance_path = kwargs.get("instance_path")
126
77
  self.queryset = kwargs.get("queryset")
127
78
 
128
79
  @property
@@ -0,0 +1,60 @@
1
+ import logging
2
+ from urllib.parse import urlencode
3
+
4
+ from django.db import models
5
+ from django.http import QueryDict
6
+
7
+ from django_filters.rest_framework import DjangoFilterBackend
8
+ from djangorestframework_camel_case.parser import CamelCaseJSONParser
9
+ from djangorestframework_camel_case.render import CamelCaseJSONRenderer
10
+ from djangorestframework_camel_case.util import underscoreize
11
+ from rest_framework.request import Request
12
+ from rest_framework.views import APIView
13
+
14
+ from .filtersets import FilterSet
15
+ from .search import is_search_view
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class Backend(DjangoFilterBackend):
21
+ filterset_base = FilterSet
22
+
23
+ def _is_camel_case(self, view):
24
+ return any(
25
+ issubclass(parser, CamelCaseJSONParser) for parser in view.parser_classes
26
+ ) or any(
27
+ issubclass(renderer, CamelCaseJSONRenderer)
28
+ for renderer in view.renderer_classes
29
+ )
30
+
31
+ def _transform_query_params(self, view, query_params: QueryDict) -> QueryDict:
32
+ if not self._is_camel_case(view):
33
+ return query_params
34
+
35
+ # data can be a regular dict if it's coming from a serializer
36
+ if hasattr(query_params, "lists"):
37
+ data = dict(query_params.lists())
38
+ else:
39
+ data = query_params
40
+
41
+ transformed = underscoreize(data)
42
+
43
+ return QueryDict(urlencode(transformed, doseq=True))
44
+
45
+ def get_filterset_kwargs(
46
+ self, request: Request, queryset: models.QuerySet, view: APIView
47
+ ):
48
+ """
49
+ Get the initialization parameters for the filterset.
50
+
51
+ * filter on request.data if request.query_params is empty
52
+ * do the camelCase transformation of filter parameters
53
+ """
54
+ kwargs = super().get_filterset_kwargs(request, queryset, view)
55
+ filter_parameters = (
56
+ request.query_params if not is_search_view(view) else request.data
57
+ )
58
+ query_params = self._transform_query_params(view, filter_parameters)
59
+ kwargs["data"] = query_params
60
+ return kwargs
vng_api_common/mocks.py CHANGED
@@ -3,7 +3,7 @@ from urllib.parse import urlparse
3
3
 
4
4
  UUID_PATTERN = re.compile(
5
5
  r"[0-9a-f]{8}\-[0-9a-f]{4}\-4[0-9a-f]{3}\-[89ab][0-9a-f]{3}\-[0-9a-f]{12}",
6
- flags=re.I,
6
+ flags=re.IGNORECASE,
7
7
  )
8
8
 
9
9
 
vng_api_common/routers.py CHANGED
@@ -55,7 +55,7 @@ class DefaultRouter(NestedRegisteringMixin, routers.DefaultRouter):
55
55
  APIRootView = APIRootView
56
56
 
57
57
 
58
- class nested:
58
+ class Nested:
59
59
  def __init__(self, prefix, viewset, nested=None, **kwargs):
60
60
  self.prefix = prefix
61
61
  self.viewset = viewset
@@ -63,4 +63,4 @@ class nested:
63
63
  self.kwargs = kwargs
64
64
 
65
65
  def __repr__(self):
66
- return "nested(prefix={!r}, viewset={!r}".format(self.prefix, self.viewset)
66
+ return "Nested(prefix={!r}, viewset={!r}".format(self.prefix, self.viewset)
@@ -104,12 +104,12 @@ class GegevensGroepSerializerMetaclass(serializers.SerializerMetaclass):
104
104
  def __new__(cls, name, bases, attrs):
105
105
  Meta = attrs.get("Meta")
106
106
  if Meta:
107
- assert hasattr(
108
- Meta, "model"
109
- ), "The 'model' class must be defined on the Meta."
110
- assert hasattr(
111
- Meta, "gegevensgroep"
112
- ), "The 'gegevensgroep' name must be defined on the Meta."
107
+ assert hasattr(Meta, "model"), (
108
+ "The 'model' class must be defined on the Meta."
109
+ )
110
+ assert hasattr(Meta, "gegevensgroep"), (
111
+ "The 'gegevensgroep' name must be defined on the Meta."
112
+ )
113
113
 
114
114
  gegevensgroep = getattr(Meta.model, Meta.gegevensgroep)
115
115
  Meta.fields = []
@@ -391,6 +391,6 @@ class CachedNestedHyperlinkedRelatedField(CacheMixin, NestedHyperlinkedRelatedFi
391
391
  return None
392
392
 
393
393
  # Replace the placeholder from the cached base URI with the actual identifier
394
- for k, v in self.parent_lookup_kwargs.items():
394
+ for v in self.parent_lookup_kwargs.values():
395
395
  url = url.replace(v, str(get_nested_fk_attribute(obj, v)))
396
396
  return url
@@ -234,7 +234,7 @@ class ResourceValidator(URLValidator):
234
234
  # at this point, we know the URL actually exists
235
235
  try:
236
236
  obj = response.json()
237
- except json.JSONDecodeError as exc:
237
+ except json.JSONDecodeError:
238
238
  logger.info(
239
239
  "URL %s doesn't seem to point to a JSON endpoint", url, exc_info=1
240
240
  )
vng_api_common/views.py CHANGED
@@ -117,7 +117,7 @@ def _test_sites_config(request: HttpRequest) -> list:
117
117
  return []
118
118
  return [
119
119
  (_("Site domain"), domain, request.get_host() == domain),
120
- (_("HTTPS"), settings.IS_HTTPS, settings.IS_HTTPS == request.is_secure()),
120
+ (_("HTTPS"), settings.IS_HTTPS, request.is_secure() == settings.IS_HTTPS),
121
121
  ]
122
122
 
123
123
 
@@ -6,7 +6,7 @@ from rest_framework.pagination import PageNumberPagination
6
6
  from rest_framework.settings import api_settings
7
7
  from rest_framework_nested.viewsets import NestedViewSetMixin # noqa
8
8
 
9
- from .filters import Backend
9
+ from .filters_backend import Backend
10
10
  from .utils import underscore_to_camel
11
11
 
12
12