Story #6714
closed[EPIC] drf builtin manage.py 'generateschema' command fails on pulp base viewsets
0%
Description
Attempting to use DRF's builtin openapi schema generation tool fails in the base viewsets get_serializer_class().
The get_serializer_class() expects a self.request to exist, but it is None as run by the 'generateschema' command.
(.venv) [newswoop:F31:galaxy_ng (sync_model_46 %)]$ ./compose run --rm api manage generateschema Compose Profile alikins Starting galaxy_ng_redis_1 ... Starting galaxy_ng_redis_1 ... done Installing path django-extensions in editable mode. Installing path alogging in editable mode. Installing path galaxy_ng in editable mode. Installing path pulp_ansible in editable mode. Installing path pulpcore in editable mode. Traceback (most recent call last): File "/venv/bin/django-admin", line 8, in sys.exit(execute_from_command_line()) File "/venv/lib64/python3.6/site-packages/django/core/management/init.py", line 381, in execute_from_command_line utility.execute() File "/venv/lib64/python3.6/site-packages/django/core/management/init.py", line 375, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/venv/lib64/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv self.execute(*args, **cmd_options) File "/venv/lib64/python3.6/site-packages/django/core/management/base.py", line 364, in execute output = self.handle(*args, **options) File "/venv/lib64/python3.6/site-packages/rest_framework/management/commands/generateschema.py", line 40, in handle schema = generator.get_schema(request=None, public=True) File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 64, in get_schema paths = self.get_paths(None if public else request) File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 47, in get_paths operation = view.schema.get_operation(path, method) File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 104, in get_operation operation['responses'] = self._get_responses(path, method) File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 489, in _get_responses serializer = self._get_serializer(path, method) File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 446, in _get_serializer return view.get_serializer() File "/venv/lib64/python3.6/site-packages/rest_framework/generics.py", line 108, in get_serializer serializer_class = self.get_serializer_class() File "/src/pulpcore/pulpcore/app/viewsets/task.py", line 86, in get_serializer_class return super().get_serializer_class() File "/src/pulpcore/pulpcore/app/viewsets/base.py", line 105, in get_serializer_class if 'minimal' in self.request.query_params: AttributeError: 'NoneType' object has no attribute 'query_params'
Updated by alikins over 3 years ago
Better formatted stacktrace:
(.venv) [newswoop:F31:galaxy_ng (sync_model_46 %)]$ ./compose run --rm api manage generateschema
Compose Profile alikins
Starting galaxy_ng_redis_1 ...
Starting galaxy_ng_redis_1 ... done
Installing path django-extensions in editable mode.
Installing path alogging in editable mode.
Installing path galaxy_ng in editable mode.
Installing path pulp_ansible in editable mode.
Installing path pulpcore in editable mode.
Traceback (most recent call last):
File "/venv/bin/django-admin", line 8, in <module>
sys.exit(execute_from_command_line())
File "/venv/lib64/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
utility.execute()
File "/venv/lib64/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/venv/lib64/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv
self.execute(*args, **cmd_options)
File "/venv/lib64/python3.6/site-packages/django/core/management/base.py", line 364, in execute
output = self.handle(*args, **options)
File "/venv/lib64/python3.6/site-packages/rest_framework/management/commands/generateschema.py", line 40, in handle
schema = generator.get_schema(request=None, public=True)
File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 64, in get_schema
paths = self.get_paths(None if public else request)
File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 47, in get_paths
operation = view.schema.get_operation(path, method)
File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 104, in get_operation
operation['responses'] = self._get_responses(path, method)
File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 489, in _get_responses
serializer = self._get_serializer(path, method)
File "/venv/lib64/python3.6/site-packages/rest_framework/schemas/openapi.py", line 446, in _get_serializer
return view.get_serializer()
File "/venv/lib64/python3.6/site-packages/rest_framework/generics.py", line 108, in get_serializer
serializer_class = self.get_serializer_class()
File "/src/pulpcore/pulpcore/app/viewsets/task.py", line 86, in get_serializer_class
return super().get_serializer_class()
File "/src/pulpcore/pulpcore/app/viewsets/base.py", line 105, in get_serializer_class
if 'minimal' in self.request.query_params:
AttributeError: 'NoneType' object has no attribute 'query_params'
Updated by dkliban@redhat.com over 3 years ago
What are you trying to achieve by using this command? I don't understand the use case.
Updated by alikins over 3 years ago
'django-manage generatescheme' is a django-rest-framework command that can be used to generate openapi v3 schema using drf's builtin introspect.
Nothing requires it at the moment, but it appears to be the way to automatically generate openapi schema for drf apps in the future since:
-
drf_yasg is somewhat maintained, but isn't actively planning on support the openapi v3 spec
-
drf claims it should be the main way to generate openapi v3 schema
At the moment, drf's 'generateschema' doesn't work at all because of the AttributeError mentioned above.
A fix like:
diff --git pulpcore/app/viewsets/base.py pulpcore/app/viewsets/base.py
index 213cea655..11272e63b 100644
--- pulpcore/app/viewsets/base.py
+++ pulpcore/app/viewsets/base.py
@@ -130,7 +130,7 @@ def get_serializer_class(self):
minimal_serializer_class = getattr(self, "minimal_serializer_class", None)
if minimal_serializer_class:
- if hasattr(self, "request"):
+ if hasattr(self, "request") and getattr(self, "request", None):
if "minimal" in self.request.query_params:
# the query param is a string, and non-empty strings evaluate True,
# so we need to do an actual string comparison to 'true'
Is enough for 'generateschema' to run without fatal error. So a step to supporting 'generateschema' and openapi v3.
Caveat: The schema generated by 'generateschema' for pulpcore is currently not very good, and misses some of the stuff the customized drf_yasg schema generation supports. So not really practical at the moment.
Updated by fao89 over 3 years ago
- Tracker changed from Issue to Story
- Subject changed from drf builtin manage.py 'generateschema' command fails on pulp base viewsets to [EPIC] drf builtin manage.py 'generateschema' command fails on pulp base viewsets
- % Done set to 0
Updated by fao89 over 3 years ago
I did a PoC on using openapi schema from DRF a while ago, and it felt like their schema generation was not mature yet, for example, they always return 200 on responses: https://github.com/encode/django-rest-framework/blob/3.11.0/rest_framework/schemas/openapi.py#L543-L554 here is the PoC: https://github.com/pulp/pulpcore/compare/master...fao89:openapi3
Updated by dkliban@redhat.com almost 3 years ago
- Status changed from NEW to CLOSED - WONTFIX
We will not work on this in the near future.