commonground-api-common 2.2.0__py3-none-any.whl → 2.3.0__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.
Files changed (45) hide show
  1. commonground_api_common-2.2.0.data/scripts/patch_content_types → commonground_api_common-2.3.0.data/scripts/generate_schema +2 -4
  2. {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/METADATA +10 -3
  3. {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/RECORD +25 -38
  4. {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/WHEEL +1 -1
  5. vng_api_common/__init__.py +1 -1
  6. vng_api_common/api/views.py +1 -0
  7. vng_api_common/apps.py +43 -26
  8. vng_api_common/audittrails/utils.py +44 -0
  9. vng_api_common/conf/api.py +33 -45
  10. vng_api_common/contrib/setup_configuration/models.py +14 -0
  11. vng_api_common/contrib/setup_configuration/steps.py +24 -1
  12. vng_api_common/extensions/file.py +26 -0
  13. vng_api_common/extensions/gegevensgroep.py +16 -0
  14. vng_api_common/extensions/geojson.py +270 -0
  15. vng_api_common/extensions/hyperlink.py +37 -0
  16. vng_api_common/extensions/polymorphic.py +68 -0
  17. vng_api_common/extensions/query.py +20 -0
  18. vng_api_common/filters.py +0 -1
  19. vng_api_common/generators.py +12 -113
  20. vng_api_common/notifications/api/views.py +3 -3
  21. vng_api_common/oas.py +6 -7
  22. vng_api_common/schema.py +414 -158
  23. vng_api_common/views.py +1 -1
  24. commonground_api_common-2.2.0.data/scripts/generate_schema +0 -39
  25. commonground_api_common-2.2.0.data/scripts/use_external_components +0 -16
  26. vng_api_common/inspectors/cache.py +0 -57
  27. vng_api_common/inspectors/fields.py +0 -126
  28. vng_api_common/inspectors/files.py +0 -121
  29. vng_api_common/inspectors/geojson.py +0 -360
  30. vng_api_common/inspectors/polymorphic.py +0 -72
  31. vng_api_common/inspectors/query.py +0 -91
  32. vng_api_common/inspectors/utils.py +0 -40
  33. vng_api_common/inspectors/view.py +0 -547
  34. vng_api_common/management/__init__.py +0 -0
  35. vng_api_common/management/commands/__init__.py +0 -0
  36. vng_api_common/management/commands/generate_autorisaties.py +0 -43
  37. vng_api_common/management/commands/generate_notificaties.py +0 -40
  38. vng_api_common/management/commands/generate_swagger.py +0 -197
  39. vng_api_common/management/commands/patch_error_contenttypes.py +0 -61
  40. vng_api_common/management/commands/use_external_components.py +0 -94
  41. vng_api_common/templates/vng_api_common/api_schema_to_markdown_table.md +0 -16
  42. vng_api_common/templates/vng_api_common/autorisaties.md +0 -15
  43. vng_api_common/templates/vng_api_common/notificaties.md +0 -24
  44. {commonground_api_common-2.2.0.dist-info → commonground_api_common-2.3.0.dist-info}/top_level.txt +0 -0
  45. /vng_api_common/{inspectors → extensions}/__init__.py +0 -0
@@ -1,197 +0,0 @@
1
- import logging
2
- import os
3
-
4
- from django.apps import apps
5
- from django.conf import settings
6
- from django.contrib.auth import get_user_model
7
- from django.core.exceptions import ImproperlyConfigured
8
- from django.template.loader import render_to_string
9
- from django.urls import NoReverseMatch, reverse
10
- from django.utils.module_loading import import_string
11
-
12
- from drf_yasg import openapi
13
- from drf_yasg.app_settings import swagger_settings
14
- from drf_yasg.management.commands import generate_swagger
15
- from rest_framework.settings import api_settings
16
-
17
- from ...version import get_major_version
18
-
19
-
20
- class Table:
21
- def __init__(self, resource: str):
22
- self.resource = resource
23
- self.rows = []
24
-
25
-
26
- class Row:
27
- def __init__(
28
- self,
29
- label: str,
30
- description: str,
31
- type: str,
32
- required: bool,
33
- create: bool,
34
- read: bool,
35
- update: bool,
36
- delete: bool,
37
- ):
38
- self.label = label
39
- self.description = description
40
- self.type = type
41
- self.required = required
42
- self.create = create
43
- self.read = read
44
- self.update = update
45
- self.delete = delete
46
-
47
-
48
- class Command(generate_swagger.Command):
49
- """
50
- Patches to the provided command to modify the schema.
51
- """
52
-
53
- leave_locale_alone = True
54
-
55
- def add_arguments(self, parser):
56
- super().add_arguments(parser)
57
- parser.add_argument("--to-markdown-table", action="store_true")
58
-
59
- parser.add_argument(
60
- "--info", dest="info", default=None, help="Path to schema info object"
61
- )
62
-
63
- parser.add_argument(
64
- "--urlconf",
65
- dest="urlconf",
66
- default=None,
67
- help="Urlconf for schema generator",
68
- )
69
-
70
- def get_mock_request(self, *args, **kwargs):
71
- request = super().get_mock_request(*args, **kwargs)
72
- request.version = api_settings.DEFAULT_VERSION
73
- return request
74
-
75
- def write_schema(self, schema, stream, format):
76
- del schema.host
77
- del schema.schemes
78
- super().write_schema(schema, stream, format)
79
-
80
- # need to overwrite the generator class...
81
- def handle(
82
- self,
83
- output_file,
84
- overwrite,
85
- format,
86
- api_url,
87
- mock,
88
- api_version,
89
- user,
90
- private,
91
- generator_class_name,
92
- info=None,
93
- urlconf=None,
94
- **options,
95
- ):
96
- # disable logs of WARNING and below
97
- logging.disable(logging.WARNING)
98
-
99
- if info:
100
- info = import_string(info)
101
- else:
102
- info = getattr(swagger_settings, "DEFAULT_INFO", None)
103
-
104
- if not isinstance(info, openapi.Info):
105
- raise ImproperlyConfigured(
106
- 'settings.SWAGGER_SETTINGS["DEFAULT_INFO"] should be an '
107
- "import string pointing to an openapi.Info object"
108
- )
109
-
110
- if not format:
111
- if os.path.splitext(output_file)[1] in (".yml", ".yaml"):
112
- format = "yaml"
113
- format = format or "json"
114
-
115
- try:
116
- api_root = reverse("api-root", kwargs={"version": get_major_version()})
117
- except NoReverseMatch:
118
- api_root = reverse("api-root")
119
-
120
- api_url = (
121
- api_url
122
- or swagger_settings.DEFAULT_API_URL # noqa
123
- or f"http://example.com{api_root}" # noqa
124
- )
125
-
126
- if user:
127
- # Only call get_user_model if --user was passed in order to
128
- # avoid crashing if auth is not configured in the project
129
- user = get_user_model().objects.get(username=user)
130
-
131
- mock = mock or private or (user is not None) or (api_version is not None)
132
- if mock and not api_url:
133
- raise ImproperlyConfigured(
134
- "--mock-request requires an API url; either provide "
135
- "the --url argument or set the DEFAULT_API_URL setting"
136
- )
137
-
138
- request = None
139
- if mock:
140
- request = self.get_mock_request(api_url, format, user)
141
-
142
- api_version = api_version or api_settings.DEFAULT_VERSION
143
- if request and api_version:
144
- request.version = api_version
145
-
146
- generator = self.get_schema_generator(
147
- generator_class_name, info, settings.API_VERSION, api_url
148
- )
149
- schema = self.get_schema(generator, request, not private)
150
-
151
- if output_file == "-":
152
- self.write_schema(schema, self.stdout, format)
153
- else:
154
- with open(output_file, "w", encoding="utf8") as stream:
155
- if options["to_markdown_table"]:
156
- self.to_markdown_table(schema, stream)
157
- else:
158
- self.write_schema(schema, stream, format)
159
-
160
- def to_markdown_table(self, schema, stream):
161
- template = "vng_api_common/api_schema_to_markdown_table.md"
162
- tables = []
163
-
164
- whitelist = [model._meta.object_name for model in apps.get_models()]
165
-
166
- for resource, definition in schema.definitions.items():
167
- if resource not in whitelist:
168
- continue
169
-
170
- if not hasattr(definition, "properties"):
171
- continue
172
-
173
- table = Table(resource)
174
- for field, _schema in definition.properties.items():
175
- if isinstance(_schema, openapi.SchemaRef):
176
- continue
177
- required = (
178
- hasattr(definition, "required") and field in definition.required
179
- )
180
-
181
- readonly = getattr(_schema, "readOnly", False)
182
- table.rows.append(
183
- Row(
184
- label=field,
185
- description=getattr(_schema, "description", ""),
186
- type=_schema.type,
187
- required=required,
188
- create=not readonly,
189
- read=True,
190
- update=not readonly,
191
- delete=not readonly,
192
- )
193
- )
194
- tables.append(table)
195
-
196
- markdown = render_to_string(template, context={"tables": tables})
197
- stream.write(markdown)
@@ -1,61 +0,0 @@
1
- """
2
- Patch the content-type of error responses.
3
-
4
- Due to the changes between Swagger 2.0 and OpenAPI 3.0, we cannot handle
5
- this at the Python level.
6
- """
7
-
8
- from django.core.management import BaseCommand
9
-
10
- import oyaml as yaml
11
-
12
- from ...views import ERROR_CONTENT_TYPE
13
-
14
-
15
- class Command(BaseCommand):
16
- help = "Patch the error-response content types in the OAS 3 spec"
17
-
18
- def add_arguments(self, parser):
19
- parser.add_argument(
20
- "api-spec", help="Path to the openapi spec. Will be overwritten!"
21
- )
22
-
23
- def patch_response(self, response):
24
- content = {}
25
-
26
- for contenttype, _response in response["content"].items():
27
- contenttype = ERROR_CONTENT_TYPE
28
- content[contenttype] = _response
29
-
30
- response["content"] = content
31
-
32
- def handle(self, **options):
33
- source = options["api-spec"]
34
-
35
- # Enforce the file to be read as UTF-8 to prevent any platform
36
- # dependent encoding.
37
- with open(source, "r", encoding="utf8") as infile:
38
- spec = yaml.safe_load(infile)
39
-
40
- for endpoint in spec["paths"].values():
41
- for data in endpoint.values():
42
- # filter the available request methods
43
- if not "responses" in data:
44
- continue
45
-
46
- for status, response in data["responses"].items():
47
- # Only edit the error responses which are defined directly
48
- # and not referencing existing error responses
49
- if not (400 <= int(status) < 600) or not "content" in response:
50
- continue
51
-
52
- self.patch_response(response)
53
-
54
- for status, response in spec["components"]["responses"].items():
55
- if not (400 <= int(status) < 600):
56
- continue
57
-
58
- self.patch_response(response)
59
-
60
- with open(source, "w", encoding="utf8") as outfile:
61
- yaml.dump(spec, outfile, default_flow_style=False)
@@ -1,94 +0,0 @@
1
- """
2
- Replace internal references to external for reusable components
3
-
4
- Due to the limitations of drf_yasg we cannot handle this at the Python level
5
- """
6
-
7
- import os.path
8
-
9
- from django.conf import settings
10
- from django.core.management import BaseCommand
11
-
12
- import oyaml as yaml
13
- import requests
14
-
15
-
16
- class QuotedString(str):
17
- pass
18
-
19
-
20
- def quoted_scalar(dumper, data):
21
- # a representer to force quotations on scalars
22
- return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="'")
23
-
24
-
25
- def replace_refs(source: dict, replace_dict: dict) -> None:
26
- for k, v in source.items():
27
- if isinstance(v, dict):
28
- replace_refs(v, replace_dict)
29
-
30
- if k != "$ref":
31
- continue
32
-
33
- if v in replace_dict:
34
- source[k] = QuotedString(replace_dict[v])
35
-
36
-
37
- class Command(BaseCommand):
38
- help = "Replace internal references to external for reusable components"
39
-
40
- def add_arguments(self, parser):
41
- parser.add_argument(
42
- "api-spec", help="Path to the openapi spec. Will be overwritten!"
43
- )
44
- parser.add_argument(
45
- "output", help="Path to the yaml file with external components"
46
- )
47
-
48
- def handle(self, **options):
49
- source = options["api-spec"]
50
- output = options["output"]
51
- common_url = settings.COMMON_SPEC
52
- try:
53
- response = requests.get(common_url)
54
- response.raise_for_status()
55
- common_yaml = response.text
56
- except requests.exceptions.RequestException:
57
- return
58
-
59
- common_spec = yaml.safe_load(common_yaml)
60
- common_components = common_spec["components"]
61
-
62
- with open(source, "r", encoding="utf8") as infile:
63
- spec = yaml.safe_load(infile)
64
- components = spec["components"]
65
- refs = {}
66
-
67
- for scope, scope_items in components.items():
68
- if scope not in common_components:
69
- continue
70
-
71
- for item, item_spec in scope_items.copy().items():
72
- if item not in common_components[scope]:
73
- continue
74
-
75
- common_item_spec = common_components[scope][item]
76
- if item_spec == common_item_spec:
77
- # add ref to replace
78
- ref = f"#/components/{scope}/{item}"
79
- refs[ref] = f"{common_url}{ref}"
80
-
81
- # remove item from internal components
82
- del components[scope][item]
83
-
84
- # remove empty components
85
- for scope, scope_items in components.copy().items():
86
- if not scope_items:
87
- del components[scope]
88
-
89
- # replace all refs
90
- replace_refs(spec, refs)
91
-
92
- with open(output, "w", encoding="utf8") as outfile:
93
- yaml.add_representer(QuotedString, quoted_scalar)
94
- yaml.dump(spec, outfile, default_flow_style=False)
@@ -1,16 +0,0 @@
1
- {% load vng_api_common %}# Resources
2
-
3
- Dit document beschrijft de (RGBZ-)objecttypen die als resources ontsloten
4
- worden met de beschikbare attributen.
5
-
6
- {% for table in tables %}
7
- ## {{ table.resource }}
8
-
9
- Objecttype op [GEMMA Online]({{ table.resource|gemmaonline_url }})
10
-
11
- | Attribuut | Omschrijving | Type | Verplicht | CRUD* |
12
- | --- | --- | --- | --- | --- |{% for row in table.rows %}
13
- | {{ row.label|md_table_cell }} | {{ row.description|md_table_cell }} | {{ row.type|md_table_cell }} | {{ row.required|yesno:"ja,nee" }} | {{ row|crud }} |{% endfor %}
14
- {% endfor %}
15
-
16
- * Create, Read, Update, Delete
@@ -1,15 +0,0 @@
1
- {% load vng_api_common markup_tags %}
2
- # Autorisaties
3
- ## Scopes voor {{ project_name }} API
4
-
5
- Scopes worden typisch per component gedefinieerd en geven aan welke rechten er zijn.
6
- Zie de repository van de [Autorisaties API](https://github.com/VNG-Realisatie/autorisaties-api)
7
-
8
- {% for scope in scopes %}
9
- ### {{ scope.label }}
10
-
11
- **Scope**
12
- `{{ scope.label }}`
13
-
14
- {{ scope.description|default:"" }}
15
- {% endfor %}
@@ -1,24 +0,0 @@
1
- ## Notificaties
2
- ## Berichtkenmerken voor {{ project_name }} API
3
-
4
- Kanalen worden typisch per component gedefinieerd. Producers versturen berichten op bepaalde kanalen,
5
- consumers ontvangen deze. Consumers abonneren zich via een notificatiecomponent (zoals {{ 'https://notificaties-api.vng.cloud/api/v1/schema/'|urlize }}) op berichten.
6
-
7
- Hieronder staan de kanalen beschreven die door deze component gebruikt worden, met de kenmerken bij elk bericht.
8
-
9
- De architectuur van de notificaties staat beschreven op {{ 'https://github.com/VNG-Realisatie/notificaties-api'|urlize }}.
10
-
11
- {% for kanaal in kanalen %}
12
- ### {{ kanaal.label }}
13
-
14
- **Kanaal**
15
- `{{ kanaal.label }}`
16
-
17
- {{ kanaal.description|default:""|urlize }}
18
-
19
- **Resources en acties**
20
-
21
- {% for resource, actions in kanaal.get_usage %}
22
- * <code>{{ resource }}</code>: {{ actions|join:", " }}
23
- {% endfor %}
24
- {% endfor %}
File without changes