Repository: encode/django-rest-framework

Issue:
3.15 missing package inflection
New issue in the `3.15` release where if you use `generateschema` and have a list in your output you will get a `ModuleNotFound` error.

```
 > [19/21] RUN poetry run python manage.py generateschema --file /code/templates/openapi-schema.yml:                                                                                                                                                                                                                                                                   
2.585 Traceback (most recent call last):                                                                                                                                                                                                                                                                                                                                                                                                 
2.586   File "/code/manage.py", line 22, in <module>                                                                                                                                                                                                                                                                                                                                                                                     
2.587     main()                                                                                                                                                                                                                                                                                                                                                                                                                         
2.588   File "/code/manage.py", line 18, in main                                                                                                                                                                                                                                                                                                                                                                                         
2.589     execute_from_command_line(sys.argv)
2.590   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
2.590     utility.execute()
2.591   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
2.592     self.fetch_command(subcommand).run_from_argv(self.argv)
2.593   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/django/core/management/base.py", line 412, in run_from_argv
2.593     self.execute(*args, **cmd_options)
2.594   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/django/core/management/base.py", line 458, in execute
2.595     output = self.handle(*args, **options)
2.596              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.600   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/rest_framework/management/commands/generateschema.py", line 43, in handle
2.601     schema = generator.get_schema(request=None, public=True)
2.602              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.606   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/rest_framework/schemas/openapi.py", line 80, in get_schema
2.608     operation = view.schema.get_operation(path, method)
2.608                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.608   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/rest_framework/schemas/openapi.py", line 146, in get_operation
2.608     operation['operationId'] = self.get_operation_id(path, method)
2.608                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.608   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/rest_framework/schemas/openapi.py", line 268, in get_operation_id
2.608     name = self.get_operation_id_base(path, method, action)
2.608            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.608   File "/root/.cache/pypoetry/virtualenvs/allfactors-django-MATOk_fk-py3.12/lib/python3.12/site-packages/rest_framework/schemas/openapi.py", line 250, in get_operation_id_base
2.608     from inflection import pluralize
2.608 ModuleNotFoundError: No module named 'inflection'
```


Discussion:
Ah yep, needs resolving.

Introduced by PR https://github.com/encode/django-rest-framework/pull/8017.

Ooptions...

* Revert the PR. (Marginally incorrect naming is better than broken behavior)
* Add the dependency
I vote for including the dependency

One other idea:

```
try:
    from inflection import pluralize
except ImportError:
    def pluralize(input):
        if not input.endswith('s'):
            input += "s"
```

Resolving patch:
diff --git a/rest_framework/compat.py b/rest_framework/compat.py
--- a/rest_framework/compat.py
+++ b/rest_framework/compat.py
@@ -46,6 +46,12 @@ def unicode_http_header(value):
 except ImportError:
     yaml = None
 
+# inflection is optional
+try:
+    import inflection
+except ImportError:
+    inflection = None
+
 
 # requests is optional
 try:
diff --git a/rest_framework/schemas/openapi.py b/rest_framework/schemas/openapi.py
--- a/rest_framework/schemas/openapi.py
+++ b/rest_framework/schemas/openapi.py
@@ -14,7 +14,7 @@
 from rest_framework import (
     RemovedInDRF315Warning, exceptions, renderers, serializers
 )
-from rest_framework.compat import uritemplate
+from rest_framework.compat import inflection, uritemplate
 from rest_framework.fields import _UnvalidatedField, empty
 from rest_framework.settings import api_settings
 
@@ -247,9 +247,8 @@ def get_operation_id_base(self, path, method, action):
                 name = name[:-len(action)]
 
         if action == 'list':
-            from inflection import pluralize
-
-            name = pluralize(name)
+            assert inflection, '`inflection` must be installed for OpenAPI schema support.'
+            name = inflection.pluralize(name)
 
         return name
 


Test patch: