We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add OpenAPI Specification for the /datafiles/ endpoint and fix the incorrect specs
## Problem
In order to ensure the accuracy of the specs generated by drf-spectacular for /datafiles/ endpoint , we will generate an OpenAPI Specification specifically for this endpoint. This will allow us to verify its correctness by comparing it with the existing test cases and the DRF browsable API page and also confirm it with the front-end team.

## Proposed solution
* Implement custom preprocessing hook function  to filter out all endpoints except for the /datafiles/ endpoint.The hook function selectively retains only the endpoint paths that match the /datafiles/ 
* Update the Spectacular settings in the  _common_settings.py_ file to include the custom preprocessing hook.
* Configure the PREPROCESSING_HOOKS setting with the custom hook function, we ensure that only the /datafiles/ endpoint is considered during the OpenAPI specification generation process.
* Finally, generate the spec file using the _./manage.py spectacular --color --file schema.yml_ command



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `config/settings/common_settings.py`
Content:
```
1 """
2 Base settings to build other settings files upon.
3 
4 Generated by 'django-admin startproject' using Django 3.1.7.
5 
6 For more information on this file, see
7 https://docs.djangoproject.com/en/3.1/topics/settings/
8 
9 For the full list of settings and their values, see
10 https://docs.djangoproject.com/en/3.1/ref/settings/
11 """
12 
13 import os
14 from pathlib import Path
15 
16 from decouple import Csv, config as decouple_config
17 from dj_database_url import parse as db_url
18 
19 
20 # We use a 'tuple' with pipes as delimiters as decople naively splits the global
21 # variables on commas when casting to Csv()
22 def pipe_delim(pipe_string):
23     # Remove opening and closing brackets
24     pipe_string = pipe_string[1:-1]
25     # Split on pipe delim
26     return pipe_string.split("|")
27 
28 
29 # Build paths inside the project like this: BASE_DIR / 'subdir'.
30 BASE_DIR = Path(__file__).resolve().parent.parent.parent
31 
32 # Application definition
33 
34 INSTALLED_APPS = [
35     "django.contrib.admin",
36     "django.contrib.auth",
37     "django.contrib.contenttypes",
38     "django.contrib.sessions",
39     "django.contrib.messages",
40     "whitenoise.runserver_nostatic",
41     "django.contrib.staticfiles",
42     "rest_framework",
43     "django_filters",
44     "django_property_filter",
45     "drf_spectacular",
46     "mathesar",
47 ]
48 
49 MIDDLEWARE = [
50     "django.middleware.security.SecurityMiddleware",
51     "whitenoise.middleware.WhiteNoiseMiddleware",
52     "django.contrib.sessions.middleware.SessionMiddleware",
53     "django.middleware.common.CommonMiddleware",
54     "django.middleware.csrf.CsrfViewMiddleware",
55     "django.contrib.auth.middleware.AuthenticationMiddleware",
56     "django.contrib.messages.middleware.MessageMiddleware",
57     "django.middleware.clickjacking.XFrameOptionsMiddleware",
58     "mathesar.middleware.CursorClosedHandlerMiddleware",
59     "mathesar.middleware.PasswordChangeNeededMiddleware",
60     'django_userforeignkey.middleware.UserForeignKeyMiddleware',
61     'django_request_cache.middleware.RequestCacheMiddleware',
62 ]
63 
64 ROOT_URLCONF = "config.urls"
65 
66 TEMPLATES = [
67     {
68         "BACKEND": "django.template.backends.django.DjangoTemplates",
69         "DIRS": [],
70         "APP_DIRS": True,
71         "OPTIONS": {
72             "context_processors": [
73                 "config.context_processors.frontend_settings",
74                 "django.template.context_processors.debug",
75                 "django.template.context_processors.request",
76                 "django.contrib.auth.context_processors.auth",
77                 "django.contrib.messages.context_processors.messages",
78                 "mathesar.template_context_processors.base_template_extensions.script_extension_templates"
79             ],
80         },
81     },
82 ]
83 
84 WSGI_APPLICATION = "config.wsgi.application"
85 
86 # Database
87 # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
88 
89 # TODO: Add to documentation that database keys should not be than 128 characters.
90 
91 # MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'
92 # See pipe_delim above for why we use pipes as delimiters
93 DATABASES = {
94     db_key: db_url(url_string)
95     for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))
96 }
97 DATABASES[decouple_config('DJANGO_DATABASE_KEY', default="default")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url)
98 
99 for db_key, db_dict in DATABASES.items():
100     # Engine can be '.postgresql' or '.postgresql_psycopg2'
101     if not db_dict['ENGINE'].startswith('django.db.backends.postgresql'):
102         raise ValueError(
103             f"{db_key} is not a PostgreSQL database. "
104             f"{db_dict['ENGINE']} found for {db_key}'s engine."
105         )
106 
107 # pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'
108 # and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']
109 TEST = decouple_config('TEST', default=False, cast=bool)
110 if TEST:
111     for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):
112         DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}
113 
114 
115 # SECURITY WARNING: keep the secret key used in production secret!
116 SECRET_KEY = decouple_config('SECRET_KEY')
117 
118 # SECURITY WARNING: don't run with debug turned on in production!
119 DEBUG = decouple_config('DEBUG', default=False, cast=bool)
120 
121 ALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv())
122 
123 # Password validation
124 # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
125 
126 AUTH_PASSWORD_VALIDATORS = [
127     {
128         "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
129     },
130     {
131         "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
132     },
133     {
134         "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
135     },
136     {
137         "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
138     },
139 ]
140 
141 # Internationalization
142 # https://docs.djangoproject.com/en/3.1/topics/i18n/
143 
144 LANGUAGE_CODE = "en-us"
145 
146 TIME_ZONE = "UTC"
147 
148 USE_I18N = True
149 
150 USE_L10N = True
151 
152 USE_TZ = True
153 
154 # Static files (CSS, JavaScript, Images)
155 # https://docs.djangoproject.com/en/3.1/howto/static-files/
156 # https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/
157 
158 STATIC_URL = "/static/"
159 
160 # When running with DEBUG=False, the webserver needs to serve files from this location
161 # python manage.py collectstatic has to be run to collect all static files into this location
162 # The files need to served in brotli or gzip compressed format
163 STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
164 
165 # Media files (uploaded by the user)
166 
167 MEDIA_ROOT = os.path.join(BASE_DIR, '.media/')
168 
169 MEDIA_URL = "/media/"
170 
171 # Update Authentication classes, removed BasicAuthentication
172 # Defaults: https://www.django-rest-framework.org/api-guide/settings/
173 REST_FRAMEWORK = {
174     'DEFAULT_AUTHENTICATION_CLASSES': [
175         'rest_framework.authentication.TokenAuthentication',
176         'rest_framework.authentication.SessionAuthentication'
177     ],
178     'DEFAULT_PERMISSION_CLASSES': [
179         'rest_framework.permissions.IsAuthenticated',
180     ],
181     'DEFAULT_FILTER_BACKENDS': (
182         'django_filters.rest_framework.DjangoFilterBackend',
183         'rest_framework.filters.OrderingFilter',
184     ),
185     'TEST_REQUEST_DEFAULT_FORMAT': 'json',
186     'EXCEPTION_HANDLER':
187         'mathesar.exception_handlers.mathesar_exception_handler',
188     'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'
189 }
190 SPECTACULAR_SETTINGS = {
191     'TITLE': 'Mathesar API',
192     'DESCRIPTION': '',
193     'VERSION': '1.0.0',
194     'SERVE_INCLUDE_SCHEMA': False,
195     'POSTPROCESSING_HOOKS': [
196         'config.settings.openapi.remove_url_prefix_hook',
197     ],
198     # OTHER SETTINGS
199 }
200 FRIENDLY_ERRORS = {
201     'FIELD_ERRORS': {
202         # By default drf-friendly-errors does contain error codes for ListSerializer type
203         'ListSerializer': {
204             'required': 2007,
205             'null': 2027,
206             'invalid_choice': 2083,
207             'not_a_list': 2123,
208             'empty': 2093
209         },
210         'PermittedPkRelatedField': {
211             'required': 2007,
212             'null': 2027,
213             'does_not_exist': 2151,
214             'incorrect_type': 2161
215         },
216         'PermittedSlugRelatedField': {
217             'required': 2007, 'invalid': 2002, 'null': 2027,
218             'does_not_exist': 2151, 'incorrect_type': 2161
219         },
220     },
221     'EXCEPTION_DICT': {
222         'Http404': 4005
223     }
224 }
225 # Mathesar settings
226 MATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')
227 MATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')
228 MATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')
229 MATHESAR_CLIENT_DEV_URL = 'http://localhost:3000'
230 MATHESAR_UI_SOURCE_LOCATION = os.path.join(BASE_DIR, 'mathesar_ui/')
231 MATHESAR_CAPTURE_UNHANDLED_EXCEPTION = decouple_config('CAPTURE_UNHANDLED_EXCEPTION', default=False)
232 MATHESAR_STATIC_NON_CODE_FILES_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/non-code/')
233 
234 # UI source files have to be served by Django in order for static assets to be included during dev mode
235 # https://vitejs.dev/guide/assets.html
236 # https://vitejs.dev/guide/backend-integration.html
237 STATICFILES_DIRS = [MATHESAR_UI_SOURCE_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION] if MATHESAR_MODE == 'DEVELOPMENT' else [MATHESAR_UI_BUILD_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION]
238 STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
239 
240 # Accounts
241 AUTH_USER_MODEL = 'mathesar.User'
242 LOGIN_URL = '/auth/login/'
243 LOGIN_REDIRECT_URL = '/'
244 LOGOUT_REDIRECT_URL = LOGIN_URL
245 DRF_ACCESS_POLICY = {
246     'reusable_conditions': ['mathesar.api.permission_conditions']
247 }
248 # List of Template names that contains additional script tags to be added to the base template
249 BASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = []
250
```

Path: `config/settings/openapi.py`
Content:
```
1 def remove_url_prefix_hook(result, **kwargs):
2     # Remove namespace and version URL prefix from the operation Id of the generated API schema
3     for path, path_info in result['paths'].items():
4         for method, operation in path_info.items():
5             operation_id = operation.get('operationId')
6             if operation_id:
7                 if path.startswith('/api/db/v0/'):
8                     operation['operationId'] = operation_id.replace('db_v0_', '')
9                 elif path.startswith('/api/ui/v0/'):
10                     operation['operationId'] = operation_id.replace('ui_v0_', '')
11 
12     return result
13
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py
--- a/config/settings/common_settings.py
+++ b/config/settings/common_settings.py
@@ -192,6 +192,7 @@
     'DESCRIPTION': '',
     'VERSION': '1.0.0',
     'SERVE_INCLUDE_SCHEMA': False,
+    'PREPROCESSING_HOOKS': ['config.settings.openapi.custom_preprocessing_hook'],
     'POSTPROCESSING_HOOKS': [
         'config.settings.openapi.remove_url_prefix_hook',
     ],
diff --git a/config/settings/openapi.py b/config/settings/openapi.py
--- a/config/settings/openapi.py
+++ b/config/settings/openapi.py
@@ -1,3 +1,12 @@
+def custom_preprocessing_hook(endpoints):
+    filtered = []
+    for (path, path_regex, method, callback) in endpoints:
+        # Remove all but DRF API endpoints
+        if path.startswith("/api/db/v0/data_files/"):
+            filtered.append((path, path_regex, method, callback))
+    return filtered
+
+
 def remove_url_prefix_hook(result, **kwargs):
     # Remove namespace and version URL prefix from the operation Id of the generated API schema
     for path, path_info in result['paths'].items():

{"golden_diff": "diff --git a/config/settings/common_settings.py b/config/settings/common_settings.py\n--- a/config/settings/common_settings.py\n+++ b/config/settings/common_settings.py\n@@ -192,6 +192,7 @@\n     'DESCRIPTION': '',\n     'VERSION': '1.0.0',\n     'SERVE_INCLUDE_SCHEMA': False,\n+    'PREPROCESSING_HOOKS': ['config.settings.openapi.custom_preprocessing_hook'],\n     'POSTPROCESSING_HOOKS': [\n         'config.settings.openapi.remove_url_prefix_hook',\n     ],\ndiff --git a/config/settings/openapi.py b/config/settings/openapi.py\n--- a/config/settings/openapi.py\n+++ b/config/settings/openapi.py\n@@ -1,3 +1,12 @@\n+def custom_preprocessing_hook(endpoints):\n+    filtered = []\n+    for (path, path_regex, method, callback) in endpoints:\n+        # Remove all but DRF API endpoints\n+        if path.startswith(\"/api/db/v0/data_files/\"):\n+            filtered.append((path, path_regex, method, callback))\n+    return filtered\n+\n+\n def remove_url_prefix_hook(result, **kwargs):\n     # Remove namespace and version URL prefix from the operation Id of the generated API schema\n     for path, path_info in result['paths'].items():\n", "issue": "Add OpenAPI Specification for the /datafiles/ endpoint and fix the incorrect specs\n## Problem\r\nIn order to ensure the accuracy of the specs generated by drf-spectacular for /datafiles/ endpoint , we will generate an OpenAPI Specification specifically for this endpoint. This will allow us to verify its correctness by comparing it with the existing test cases and the DRF browsable API page and also confirm it with the front-end team.\r\n\r\n## Proposed solution\r\n* Implement custom preprocessing hook function  to filter out all endpoints except for the /datafiles/ endpoint.The hook function selectively retains only the endpoint paths that match the /datafiles/ \r\n* Update the Spectacular settings in the  _common_settings.py_ file to include the custom preprocessing hook.\r\n* Configure the PREPROCESSING_HOOKS setting with the custom hook function, we ensure that only the /datafiles/ endpoint is considered during the OpenAPI specification generation process.\r\n* Finally, generate the spec file using the _./manage.py spectacular --color --file schema.yml_ command\r\n\r\n\n", "before_files": [{"content": "\"\"\"\nBase settings to build other settings files upon.\n\nGenerated by 'django-admin startproject' using Django 3.1.7.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/3.1/topics/settings/\n\nFor the full list of settings and their values, see\nhttps://docs.djangoproject.com/en/3.1/ref/settings/\n\"\"\"\n\nimport os\nfrom pathlib import Path\n\nfrom decouple import Csv, config as decouple_config\nfrom dj_database_url import parse as db_url\n\n\n# We use a 'tuple' with pipes as delimiters as decople naively splits the global\n# variables on commas when casting to Csv()\ndef pipe_delim(pipe_string):\n    # Remove opening and closing brackets\n    pipe_string = pipe_string[1:-1]\n    # Split on pipe delim\n    return pipe_string.split(\"|\")\n\n\n# Build paths inside the project like this: BASE_DIR / 'subdir'.\nBASE_DIR = Path(__file__).resolve().parent.parent.parent\n\n# Application definition\n\nINSTALLED_APPS = [\n    \"django.contrib.admin\",\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.messages\",\n    \"whitenoise.runserver_nostatic\",\n    \"django.contrib.staticfiles\",\n    \"rest_framework\",\n    \"django_filters\",\n    \"django_property_filter\",\n    \"drf_spectacular\",\n    \"mathesar\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"whitenoise.middleware.WhiteNoiseMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"mathesar.middleware.CursorClosedHandlerMiddleware\",\n    \"mathesar.middleware.PasswordChangeNeededMiddleware\",\n    'django_userforeignkey.middleware.UserForeignKeyMiddleware',\n    'django_request_cache.middleware.RequestCacheMiddleware',\n]\n\nROOT_URLCONF = \"config.urls\"\n\nTEMPLATES = [\n    {\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        \"DIRS\": [],\n        \"APP_DIRS\": True,\n        \"OPTIONS\": {\n            \"context_processors\": [\n                \"config.context_processors.frontend_settings\",\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"mathesar.template_context_processors.base_template_extensions.script_extension_templates\"\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = \"config.wsgi.application\"\n\n# Database\n# https://docs.djangoproject.com/en/3.1/ref/settings/#databases\n\n# TODO: Add to documentation that database keys should not be than 128 characters.\n\n# MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'\n# See pipe_delim above for why we use pipes as delimiters\nDATABASES = {\n    db_key: db_url(url_string)\n    for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))\n}\nDATABASES[decouple_config('DJANGO_DATABASE_KEY', default=\"default\")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url)\n\nfor db_key, db_dict in DATABASES.items():\n    # Engine can be '.postgresql' or '.postgresql_psycopg2'\n    if not db_dict['ENGINE'].startswith('django.db.backends.postgresql'):\n        raise ValueError(\n            f\"{db_key} is not a PostgreSQL database. \"\n            f\"{db_dict['ENGINE']} found for {db_key}'s engine.\"\n        )\n\n# pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'\n# and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']\nTEST = decouple_config('TEST', default=False, cast=bool)\nif TEST:\n    for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):\n        DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}\n\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = decouple_config('SECRET_KEY')\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = decouple_config('DEBUG', default=False, cast=bool)\n\nALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv())\n\n# Password validation\n# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\",\n    },\n]\n\n# Internationalization\n# https://docs.djangoproject.com/en/3.1/topics/i18n/\n\nLANGUAGE_CODE = \"en-us\"\n\nTIME_ZONE = \"UTC\"\n\nUSE_I18N = True\n\nUSE_L10N = True\n\nUSE_TZ = True\n\n# Static files (CSS, JavaScript, Images)\n# https://docs.djangoproject.com/en/3.1/howto/static-files/\n# https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/\n\nSTATIC_URL = \"/static/\"\n\n# When running with DEBUG=False, the webserver needs to serve files from this location\n# python manage.py collectstatic has to be run to collect all static files into this location\n# The files need to served in brotli or gzip compressed format\nSTATIC_ROOT = os.path.join(BASE_DIR, 'static/')\n\n# Media files (uploaded by the user)\n\nMEDIA_ROOT = os.path.join(BASE_DIR, '.media/')\n\nMEDIA_URL = \"/media/\"\n\n# Update Authentication classes, removed BasicAuthentication\n# Defaults: https://www.django-rest-framework.org/api-guide/settings/\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication'\n    ],\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.IsAuthenticated',\n    ],\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n        'rest_framework.filters.OrderingFilter',\n    ),\n    'TEST_REQUEST_DEFAULT_FORMAT': 'json',\n    'EXCEPTION_HANDLER':\n        'mathesar.exception_handlers.mathesar_exception_handler',\n    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'\n}\nSPECTACULAR_SETTINGS = {\n    'TITLE': 'Mathesar API',\n    'DESCRIPTION': '',\n    'VERSION': '1.0.0',\n    'SERVE_INCLUDE_SCHEMA': False,\n    'POSTPROCESSING_HOOKS': [\n        'config.settings.openapi.remove_url_prefix_hook',\n    ],\n    # OTHER SETTINGS\n}\nFRIENDLY_ERRORS = {\n    'FIELD_ERRORS': {\n        # By default drf-friendly-errors does contain error codes for ListSerializer type\n        'ListSerializer': {\n            'required': 2007,\n            'null': 2027,\n            'invalid_choice': 2083,\n            'not_a_list': 2123,\n            'empty': 2093\n        },\n        'PermittedPkRelatedField': {\n            'required': 2007,\n            'null': 2027,\n            'does_not_exist': 2151,\n            'incorrect_type': 2161\n        },\n        'PermittedSlugRelatedField': {\n            'required': 2007, 'invalid': 2002, 'null': 2027,\n            'does_not_exist': 2151, 'incorrect_type': 2161\n        },\n    },\n    'EXCEPTION_DICT': {\n        'Http404': 4005\n    }\n}\n# Mathesar settings\nMATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')\nMATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')\nMATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')\nMATHESAR_CLIENT_DEV_URL = 'http://localhost:3000'\nMATHESAR_UI_SOURCE_LOCATION = os.path.join(BASE_DIR, 'mathesar_ui/')\nMATHESAR_CAPTURE_UNHANDLED_EXCEPTION = decouple_config('CAPTURE_UNHANDLED_EXCEPTION', default=False)\nMATHESAR_STATIC_NON_CODE_FILES_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/non-code/')\n\n# UI source files have to be served by Django in order for static assets to be included during dev mode\n# https://vitejs.dev/guide/assets.html\n# https://vitejs.dev/guide/backend-integration.html\nSTATICFILES_DIRS = [MATHESAR_UI_SOURCE_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION] if MATHESAR_MODE == 'DEVELOPMENT' else [MATHESAR_UI_BUILD_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION]\nSTATICFILES_STORAGE = \"whitenoise.storage.CompressedManifestStaticFilesStorage\"\n\n# Accounts\nAUTH_USER_MODEL = 'mathesar.User'\nLOGIN_URL = '/auth/login/'\nLOGIN_REDIRECT_URL = '/'\nLOGOUT_REDIRECT_URL = LOGIN_URL\nDRF_ACCESS_POLICY = {\n    'reusable_conditions': ['mathesar.api.permission_conditions']\n}\n# List of Template names that contains additional script tags to be added to the base template\nBASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = []\n", "path": "config/settings/common_settings.py"}, {"content": "def remove_url_prefix_hook(result, **kwargs):\n    # Remove namespace and version URL prefix from the operation Id of the generated API schema\n    for path, path_info in result['paths'].items():\n        for method, operation in path_info.items():\n            operation_id = operation.get('operationId')\n            if operation_id:\n                if path.startswith('/api/db/v0/'):\n                    operation['operationId'] = operation_id.replace('db_v0_', '')\n                elif path.startswith('/api/ui/v0/'):\n                    operation['operationId'] = operation_id.replace('ui_v0_', '')\n\n    return result\n", "path": "config/settings/openapi.py"}], "after_files": [{"content": "\"\"\"\nBase settings to build other settings files upon.\n\nGenerated by 'django-admin startproject' using Django 3.1.7.\n\nFor more information on this file, see\nhttps://docs.djangoproject.com/en/3.1/topics/settings/\n\nFor the full list of settings and their values, see\nhttps://docs.djangoproject.com/en/3.1/ref/settings/\n\"\"\"\n\nimport os\nfrom pathlib import Path\n\nfrom decouple import Csv, config as decouple_config\nfrom dj_database_url import parse as db_url\n\n\n# We use a 'tuple' with pipes as delimiters as decople naively splits the global\n# variables on commas when casting to Csv()\ndef pipe_delim(pipe_string):\n    # Remove opening and closing brackets\n    pipe_string = pipe_string[1:-1]\n    # Split on pipe delim\n    return pipe_string.split(\"|\")\n\n\n# Build paths inside the project like this: BASE_DIR / 'subdir'.\nBASE_DIR = Path(__file__).resolve().parent.parent.parent\n\n# Application definition\n\nINSTALLED_APPS = [\n    \"django.contrib.admin\",\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.messages\",\n    \"whitenoise.runserver_nostatic\",\n    \"django.contrib.staticfiles\",\n    \"rest_framework\",\n    \"django_filters\",\n    \"django_property_filter\",\n    \"drf_spectacular\",\n    \"mathesar\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"whitenoise.middleware.WhiteNoiseMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"mathesar.middleware.CursorClosedHandlerMiddleware\",\n    \"mathesar.middleware.PasswordChangeNeededMiddleware\",\n    'django_userforeignkey.middleware.UserForeignKeyMiddleware',\n    'django_request_cache.middleware.RequestCacheMiddleware',\n]\n\nROOT_URLCONF = \"config.urls\"\n\nTEMPLATES = [\n    {\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        \"DIRS\": [],\n        \"APP_DIRS\": True,\n        \"OPTIONS\": {\n            \"context_processors\": [\n                \"config.context_processors.frontend_settings\",\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"mathesar.template_context_processors.base_template_extensions.script_extension_templates\"\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = \"config.wsgi.application\"\n\n# Database\n# https://docs.djangoproject.com/en/3.1/ref/settings/#databases\n\n# TODO: Add to documentation that database keys should not be than 128 characters.\n\n# MATHESAR_DATABASES should be of the form '({db_name}|{db_url}), ({db_name}|{db_url})'\n# See pipe_delim above for why we use pipes as delimiters\nDATABASES = {\n    db_key: db_url(url_string)\n    for db_key, url_string in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim))\n}\nDATABASES[decouple_config('DJANGO_DATABASE_KEY', default=\"default\")] = decouple_config('DJANGO_DATABASE_URL', cast=db_url)\n\nfor db_key, db_dict in DATABASES.items():\n    # Engine can be '.postgresql' or '.postgresql_psycopg2'\n    if not db_dict['ENGINE'].startswith('django.db.backends.postgresql'):\n        raise ValueError(\n            f\"{db_key} is not a PostgreSQL database. \"\n            f\"{db_dict['ENGINE']} found for {db_key}'s engine.\"\n        )\n\n# pytest-django will create a new database named 'test_{DATABASES[table_db]['NAME']}'\n# and use it for our API tests if we don't specify DATABASES[table_db]['TEST']['NAME']\nTEST = decouple_config('TEST', default=False, cast=bool)\nif TEST:\n    for db_key, _ in decouple_config('MATHESAR_DATABASES', cast=Csv(pipe_delim)):\n        DATABASES[db_key]['TEST'] = {'NAME': DATABASES[db_key]['NAME']}\n\n\n# SECURITY WARNING: keep the secret key used in production secret!\nSECRET_KEY = decouple_config('SECRET_KEY')\n\n# SECURITY WARNING: don't run with debug turned on in production!\nDEBUG = decouple_config('DEBUG', default=False, cast=bool)\n\nALLOWED_HOSTS = decouple_config('ALLOWED_HOSTS', cast=Csv())\n\n# Password validation\n# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\",\n    },\n]\n\n# Internationalization\n# https://docs.djangoproject.com/en/3.1/topics/i18n/\n\nLANGUAGE_CODE = \"en-us\"\n\nTIME_ZONE = \"UTC\"\n\nUSE_I18N = True\n\nUSE_L10N = True\n\nUSE_TZ = True\n\n# Static files (CSS, JavaScript, Images)\n# https://docs.djangoproject.com/en/3.1/howto/static-files/\n# https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/\n\nSTATIC_URL = \"/static/\"\n\n# When running with DEBUG=False, the webserver needs to serve files from this location\n# python manage.py collectstatic has to be run to collect all static files into this location\n# The files need to served in brotli or gzip compressed format\nSTATIC_ROOT = os.path.join(BASE_DIR, 'static/')\n\n# Media files (uploaded by the user)\n\nMEDIA_ROOT = os.path.join(BASE_DIR, '.media/')\n\nMEDIA_URL = \"/media/\"\n\n# Update Authentication classes, removed BasicAuthentication\n# Defaults: https://www.django-rest-framework.org/api-guide/settings/\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication'\n    ],\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.IsAuthenticated',\n    ],\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n        'rest_framework.filters.OrderingFilter',\n    ),\n    'TEST_REQUEST_DEFAULT_FORMAT': 'json',\n    'EXCEPTION_HANDLER':\n        'mathesar.exception_handlers.mathesar_exception_handler',\n    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema'\n}\nSPECTACULAR_SETTINGS = {\n    'TITLE': 'Mathesar API',\n    'DESCRIPTION': '',\n    'VERSION': '1.0.0',\n    'SERVE_INCLUDE_SCHEMA': False,\n    'PREPROCESSING_HOOKS': ['config.settings.openapi.custom_preprocessing_hook'],\n    'POSTPROCESSING_HOOKS': [\n        'config.settings.openapi.remove_url_prefix_hook',\n    ],\n    # OTHER SETTINGS\n}\nFRIENDLY_ERRORS = {\n    'FIELD_ERRORS': {\n        # By default drf-friendly-errors does contain error codes for ListSerializer type\n        'ListSerializer': {\n            'required': 2007,\n            'null': 2027,\n            'invalid_choice': 2083,\n            'not_a_list': 2123,\n            'empty': 2093\n        },\n        'PermittedPkRelatedField': {\n            'required': 2007,\n            'null': 2027,\n            'does_not_exist': 2151,\n            'incorrect_type': 2161\n        },\n        'PermittedSlugRelatedField': {\n            'required': 2007, 'invalid': 2002, 'null': 2027,\n            'does_not_exist': 2151, 'incorrect_type': 2161\n        },\n    },\n    'EXCEPTION_DICT': {\n        'Http404': 4005\n    }\n}\n# Mathesar settings\nMATHESAR_MODE = decouple_config('MODE', default='PRODUCTION')\nMATHESAR_UI_BUILD_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/mathesar/')\nMATHESAR_MANIFEST_LOCATION = os.path.join(MATHESAR_UI_BUILD_LOCATION, 'manifest.json')\nMATHESAR_CLIENT_DEV_URL = 'http://localhost:3000'\nMATHESAR_UI_SOURCE_LOCATION = os.path.join(BASE_DIR, 'mathesar_ui/')\nMATHESAR_CAPTURE_UNHANDLED_EXCEPTION = decouple_config('CAPTURE_UNHANDLED_EXCEPTION', default=False)\nMATHESAR_STATIC_NON_CODE_FILES_LOCATION = os.path.join(BASE_DIR, 'mathesar/static/non-code/')\n\n# UI source files have to be served by Django in order for static assets to be included during dev mode\n# https://vitejs.dev/guide/assets.html\n# https://vitejs.dev/guide/backend-integration.html\nSTATICFILES_DIRS = [MATHESAR_UI_SOURCE_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION] if MATHESAR_MODE == 'DEVELOPMENT' else [MATHESAR_UI_BUILD_LOCATION, MATHESAR_STATIC_NON_CODE_FILES_LOCATION]\nSTATICFILES_STORAGE = \"whitenoise.storage.CompressedManifestStaticFilesStorage\"\n\n# Accounts\nAUTH_USER_MODEL = 'mathesar.User'\nLOGIN_URL = '/auth/login/'\nLOGIN_REDIRECT_URL = '/'\nLOGOUT_REDIRECT_URL = LOGIN_URL\nDRF_ACCESS_POLICY = {\n    'reusable_conditions': ['mathesar.api.permission_conditions']\n}\n# List of Template names that contains additional script tags to be added to the base template\nBASE_TEMPLATE_ADDITIONAL_SCRIPT_TEMPLATES = []\n", "path": "config/settings/common_settings.py"}, {"content": "def custom_preprocessing_hook(endpoints):\n    filtered = []\n    for (path, path_regex, method, callback) in endpoints:\n        # Remove all but DRF API endpoints\n        if path.startswith(\"/api/db/v0/data_files/\"):\n            filtered.append((path, path_regex, method, callback))\n    return filtered\n\n\ndef remove_url_prefix_hook(result, **kwargs):\n    # Remove namespace and version URL prefix from the operation Id of the generated API schema\n    for path, path_info in result['paths'].items():\n        for method, operation in path_info.items():\n            operation_id = operation.get('operationId')\n            if operation_id:\n                if path.startswith('/api/db/v0/'):\n                    operation['operationId'] = operation_id.replace('db_v0_', '')\n                elif path.startswith('/api/ui/v0/'):\n                    operation['operationId'] = operation_id.replace('ui_v0_', '')\n\n    return result\n", "path": "config/settings/openapi.py"}]}