Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/rest_framework/settings.py: 67%

63 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1""" 

2Settings for REST framework are all namespaced in the REST_FRAMEWORK setting. 

3For example your project's `settings.py` file might look like this: 

4 

5REST_FRAMEWORK = { 

6 'DEFAULT_RENDERER_CLASSES': [ 

7 'rest_framework.renderers.JSONRenderer', 

8 'rest_framework.renderers.TemplateHTMLRenderer', 

9 ], 

10 'DEFAULT_PARSER_CLASSES': [ 

11 'rest_framework.parsers.JSONParser', 

12 'rest_framework.parsers.FormParser', 

13 'rest_framework.parsers.MultiPartParser', 

14 ], 

15} 

16 

17This module provides the `api_setting` object, that is used to access 

18REST framework settings, checking for user settings first, then falling 

19back to the defaults. 

20""" 

21from django.conf import settings 

22from django.test.signals import setting_changed 

23from django.utils.module_loading import import_string 

24 

25from rest_framework import ISO_8601 

26 

27DEFAULTS = { 

28 # Base API policies 

29 'DEFAULT_RENDERER_CLASSES': [ 

30 'rest_framework.renderers.JSONRenderer', 

31 'rest_framework.renderers.BrowsableAPIRenderer', 

32 ], 

33 'DEFAULT_PARSER_CLASSES': [ 

34 'rest_framework.parsers.JSONParser', 

35 'rest_framework.parsers.FormParser', 

36 'rest_framework.parsers.MultiPartParser' 

37 ], 

38 'DEFAULT_AUTHENTICATION_CLASSES': [ 

39 'rest_framework.authentication.SessionAuthentication', 

40 'rest_framework.authentication.BasicAuthentication' 

41 ], 

42 'DEFAULT_PERMISSION_CLASSES': [ 

43 'rest_framework.permissions.AllowAny', 

44 ], 

45 'DEFAULT_THROTTLE_CLASSES': [], 

46 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation', 

47 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata', 

48 'DEFAULT_VERSIONING_CLASS': None, 

49 

50 # Generic view behavior 

51 'DEFAULT_PAGINATION_CLASS': None, 

52 'DEFAULT_FILTER_BACKENDS': [], 

53 

54 # Schema 

55 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema', 

56 

57 # Throttling 

58 'DEFAULT_THROTTLE_RATES': { 

59 'user': None, 

60 'anon': None, 

61 }, 

62 'NUM_PROXIES': None, 

63 

64 # Pagination 

65 'PAGE_SIZE': None, 

66 

67 # Filtering 

68 'SEARCH_PARAM': 'search', 

69 'ORDERING_PARAM': 'ordering', 

70 

71 # Versioning 

72 'DEFAULT_VERSION': None, 

73 'ALLOWED_VERSIONS': None, 

74 'VERSION_PARAM': 'version', 

75 

76 # Authentication 

77 'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser', 

78 'UNAUTHENTICATED_TOKEN': None, 

79 

80 # View configuration 

81 'VIEW_NAME_FUNCTION': 'rest_framework.views.get_view_name', 

82 'VIEW_DESCRIPTION_FUNCTION': 'rest_framework.views.get_view_description', 

83 

84 # Exception handling 

85 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', 

86 'NON_FIELD_ERRORS_KEY': 'non_field_errors', 

87 

88 # Testing 

89 'TEST_REQUEST_RENDERER_CLASSES': [ 

90 'rest_framework.renderers.MultiPartRenderer', 

91 'rest_framework.renderers.JSONRenderer' 

92 ], 

93 'TEST_REQUEST_DEFAULT_FORMAT': 'multipart', 

94 

95 # Hyperlink settings 

96 'URL_FORMAT_OVERRIDE': 'format', 

97 'FORMAT_SUFFIX_KWARG': 'format', 

98 'URL_FIELD_NAME': 'url', 

99 

100 # Input and output formats 

101 'DATE_FORMAT': ISO_8601, 

102 'DATE_INPUT_FORMATS': [ISO_8601], 

103 

104 'DATETIME_FORMAT': ISO_8601, 

105 'DATETIME_INPUT_FORMATS': [ISO_8601], 

106 

107 'TIME_FORMAT': ISO_8601, 

108 'TIME_INPUT_FORMATS': [ISO_8601], 

109 

110 # Encoding 

111 'UNICODE_JSON': True, 

112 'COMPACT_JSON': True, 

113 'STRICT_JSON': True, 

114 'COERCE_DECIMAL_TO_STRING': True, 

115 'UPLOADED_FILES_USE_URL': True, 

116 

117 # Browseable API 

118 'HTML_SELECT_CUTOFF': 1000, 

119 'HTML_SELECT_CUTOFF_TEXT': "More than {count} items...", 

120 

121 # Schemas 

122 'SCHEMA_COERCE_PATH_PK': True, 

123 'SCHEMA_COERCE_METHOD_NAMES': { 

124 'retrieve': 'read', 

125 'destroy': 'delete' 

126 }, 

127} 

128 

129 

130# List of settings that may be in string import notation. 

131IMPORT_STRINGS = [ 

132 'DEFAULT_RENDERER_CLASSES', 

133 'DEFAULT_PARSER_CLASSES', 

134 'DEFAULT_AUTHENTICATION_CLASSES', 

135 'DEFAULT_PERMISSION_CLASSES', 

136 'DEFAULT_THROTTLE_CLASSES', 

137 'DEFAULT_CONTENT_NEGOTIATION_CLASS', 

138 'DEFAULT_METADATA_CLASS', 

139 'DEFAULT_VERSIONING_CLASS', 

140 'DEFAULT_PAGINATION_CLASS', 

141 'DEFAULT_FILTER_BACKENDS', 

142 'DEFAULT_SCHEMA_CLASS', 

143 'EXCEPTION_HANDLER', 

144 'TEST_REQUEST_RENDERER_CLASSES', 

145 'UNAUTHENTICATED_USER', 

146 'UNAUTHENTICATED_TOKEN', 

147 'VIEW_NAME_FUNCTION', 

148 'VIEW_DESCRIPTION_FUNCTION' 

149] 

150 

151 

152# List of settings that have been removed 

153REMOVED_SETTINGS = [ 

154 'PAGINATE_BY', 'PAGINATE_BY_PARAM', 'MAX_PAGINATE_BY', 

155] 

156 

157 

158def perform_import(val, setting_name): 

159 """ 

160 If the given setting is a string import notation, 

161 then perform the necessary import or imports. 

162 """ 

163 if val is None: 

164 return None 

165 elif isinstance(val, str): 

166 return import_from_string(val, setting_name) 

167 elif isinstance(val, (list, tuple)): 167 ↛ 169line 167 didn't jump to line 169, because the condition on line 167 was never false

168 return [import_from_string(item, setting_name) for item in val] 

169 return val 

170 

171 

172def import_from_string(val, setting_name): 

173 """ 

174 Attempt to import a class from a string representation. 

175 """ 

176 try: 

177 return import_string(val) 

178 except ImportError as e: 

179 msg = "Could not import '%s' for API setting '%s'. %s: %s." % (val, setting_name, e.__class__.__name__, e) 

180 raise ImportError(msg) 

181 

182 

183class APISettings: 

184 """ 

185 A settings object that allows REST Framework settings to be accessed as 

186 properties. For example: 

187 

188 from rest_framework.settings import api_settings 

189 print(api_settings.DEFAULT_RENDERER_CLASSES) 

190 

191 Any setting with string import paths will be automatically resolved 

192 and return the class, rather than the string literal. 

193 

194 Note: 

195 This is an internal class that is only compatible with settings namespaced 

196 under the REST_FRAMEWORK name. It is not intended to be used by 3rd-party 

197 apps, and test helpers like `override_settings` may not work as expected. 

198 """ 

199 def __init__(self, user_settings=None, defaults=None, import_strings=None): 

200 if user_settings: 200 ↛ 201line 200 didn't jump to line 201, because the condition on line 200 was never true

201 self._user_settings = self.__check_user_settings(user_settings) 

202 self.defaults = defaults or DEFAULTS 

203 self.import_strings = import_strings or IMPORT_STRINGS 

204 self._cached_attrs = set() 

205 

206 @property 

207 def user_settings(self): 

208 if not hasattr(self, '_user_settings'): 

209 self._user_settings = getattr(settings, 'REST_FRAMEWORK', {}) 

210 return self._user_settings 

211 

212 def __getattr__(self, attr): 

213 if attr not in self.defaults: 

214 raise AttributeError("Invalid API setting: '%s'" % attr) 

215 

216 try: 

217 # Check if present in user settings 

218 val = self.user_settings[attr] 

219 except KeyError: 

220 # Fall back to defaults 

221 val = self.defaults[attr] 

222 

223 # Coerce import strings into classes 

224 if attr in self.import_strings: 

225 val = perform_import(val, attr) 

226 

227 # Cache the result 

228 self._cached_attrs.add(attr) 

229 setattr(self, attr, val) 

230 return val 

231 

232 def __check_user_settings(self, user_settings): 

233 SETTINGS_DOC = "https://www.django-rest-framework.org/api-guide/settings/" 

234 for setting in REMOVED_SETTINGS: 

235 if setting in user_settings: 

236 raise RuntimeError("The '%s' setting has been removed. Please refer to '%s' for available settings." % (setting, SETTINGS_DOC)) 

237 return user_settings 

238 

239 def reload(self): 

240 for attr in self._cached_attrs: 

241 delattr(self, attr) 

242 self._cached_attrs.clear() 

243 if hasattr(self, '_user_settings'): 

244 delattr(self, '_user_settings') 

245 

246 

247api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) 

248 

249 

250def reload_api_settings(*args, **kwargs): 

251 setting = kwargs['setting'] 

252 if setting == 'REST_FRAMEWORK': 

253 api_settings.reload() 

254 

255 

256setting_changed.connect(reload_api_settings)