-
diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
a
|
b
|
class AdminSite:
|
94 | 94 | |
95 | 95 | If a model is abstract, raise ImproperlyConfigured. |
96 | 96 | """ |
97 | | if not admin_class: |
98 | | admin_class = ModelAdmin |
| 97 | admin_class = admin_class or ModelAdmin |
99 | 98 | |
100 | 99 | if isinstance(model_or_iterable, ModelBase): |
101 | 100 | model_or_iterable = [model_or_iterable] |
-
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
a
|
b
|
class ChangeList:
|
86 | 86 | """ |
87 | 87 | Return all params except IGNORED_PARAMS. |
88 | 88 | """ |
89 | | if not params: |
90 | | params = self.params |
| 89 | params = params or self.params |
91 | 90 | lookup_params = params.copy() # a dictionary of the query string |
92 | 91 | # Remove all the parameters that are globally and systematically |
93 | 92 | # ignored. |
-
diff --git a/django/contrib/admindocs/utils.py b/django/contrib/admindocs/utils.py
a
|
b
|
def parse_rst(text, default_reference_context, thing_being_parsed=None):
|
71 | 71 | 'raw_enabled': False, |
72 | 72 | 'file_insertion_enabled': False, |
73 | 73 | } |
74 | | if thing_being_parsed: |
75 | | thing_being_parsed = force_bytes("<%s>" % thing_being_parsed) |
| 74 | thing_being_parsed = thing_being_parsed and force_bytes("<%s>" % thing_being_parsed) |
76 | 75 | # Wrap ``text`` in some reST that sets the default role to ``cmsreference``, |
77 | 76 | # then restores it. |
78 | 77 | source = """ |
-
diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py
a
|
b
|
class TemplateTagIndexView(BaseAdminDocsView):
|
75 | 75 | for module_name, library in builtin_libs + app_libs: |
76 | 76 | for tag_name, tag_func in library.tags.items(): |
77 | 77 | title, body, metadata = utils.parse_docstring(tag_func.__doc__) |
78 | | if title: |
79 | | title = utils.parse_rst(title, 'tag', _('tag:') + tag_name) |
80 | | if body: |
81 | | body = utils.parse_rst(body, 'tag', _('tag:') + tag_name) |
| 78 | title = title and utils.parse_rst(title, 'tag', _('tag:') + tag_name) |
| 79 | body = body and utils.parse_rst(body, 'tag', _('tag:') + tag_name) |
82 | 80 | for key in metadata: |
83 | 81 | metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name) |
84 | 82 | tag_library = module_name.split('.')[-1] |
… |
… |
class TemplateFilterIndexView(BaseAdminDocsView):
|
108 | 106 | for module_name, library in builtin_libs + app_libs: |
109 | 107 | for filter_name, filter_func in library.filters.items(): |
110 | 108 | title, body, metadata = utils.parse_docstring(filter_func.__doc__) |
111 | | if title: |
112 | | title = utils.parse_rst(title, 'filter', _('filter:') + filter_name) |
113 | | if body: |
114 | | body = utils.parse_rst(body, 'filter', _('filter:') + filter_name) |
| 109 | title = title and utils.parse_rst(title, 'filter', _('filter:') + filter_name) |
| 110 | body = body and utils.parse_rst(body, 'filter', _('filter:') + filter_name) |
115 | 111 | for key in metadata: |
116 | 112 | metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name) |
117 | 113 | tag_library = module_name.split('.')[-1] |
… |
… |
class ViewDetailView(BaseAdminDocsView):
|
174 | 170 | if view_func is None: |
175 | 171 | raise Http404 |
176 | 172 | title, body, metadata = utils.parse_docstring(view_func.__doc__) |
177 | | if title: |
178 | | title = utils.parse_rst(title, 'view', _('view:') + view) |
179 | | if body: |
180 | | body = utils.parse_rst(body, 'view', _('view:') + view) |
| 173 | title = title and utils.parse_rst(title, 'view', _('view:') + view) |
| 174 | body = body and utils.parse_rst(body, 'view', _('view:') + view) |
181 | 175 | for key in metadata: |
182 | 176 | metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view) |
183 | 177 | return super().get_context_data(**{ |
… |
… |
class ModelDetailView(BaseAdminDocsView):
|
215 | 209 | opts = model._meta |
216 | 210 | |
217 | 211 | title, body, metadata = utils.parse_docstring(model.__doc__) |
218 | | if title: |
219 | | title = utils.parse_rst(title, 'model', _('model:') + model_name) |
220 | | if body: |
221 | | body = utils.parse_rst(body, 'model', _('model:') + model_name) |
| 212 | title = title and utils.parse_rst(title, 'model', _('model:') + model_name) |
| 213 | body = body and utils.parse_rst(body, 'model', _('model:') + model_name) |
222 | 214 | |
223 | 215 | # Gather fields/field descriptions. |
224 | 216 | fields = [] |
… |
… |
class ModelDetailView(BaseAdminDocsView):
|
275 | 267 | except StopIteration: |
276 | 268 | continue |
277 | 269 | verbose = func.__doc__ |
278 | | if verbose: |
279 | | verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.model_name) |
| 270 | verbose = verbose and utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.model_name) |
280 | 271 | # If a method has no arguments, show it as a 'field', otherwise |
281 | 272 | # as a 'method with arguments'. |
282 | 273 | if func_has_no_args(func) and not func_accepts_kwargs(func) and not func_accepts_var_args(func): |
-
diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py
a
|
b
|
class UserAdmin(admin.ModelAdmin):
|
89 | 89 | |
90 | 90 | def lookup_allowed(self, lookup, value): |
91 | 91 | # See #20078: we don't want to allow any lookups involving passwords. |
92 | | if lookup.startswith('password'): |
93 | | return False |
94 | | return super().lookup_allowed(lookup, value) |
| 92 | return not lookup.startswith('password') and super().lookup_allowed(lookup, value) |
95 | 93 | |
96 | 94 | @sensitive_post_parameters_m |
97 | 95 | @csrf_protect_m |
-
diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
a
|
b
|
class ModelBackend:
|
82 | 82 | return user_obj._perm_cache |
83 | 83 | |
84 | 84 | def has_perm(self, user_obj, perm, obj=None): |
85 | | if not user_obj.is_active: |
86 | | return False |
87 | | return perm in self.get_all_permissions(user_obj, obj) |
| 85 | return user_obj.is_active and perm in self.get_all_permissions(user_obj, obj) |
88 | 86 | |
89 | 87 | def has_module_perms(self, user_obj, app_label): |
90 | 88 | """ |
-
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
a
|
b
|
def make_password(password, salt=None, hasher='default'):
|
74 | 74 | return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH) |
75 | 75 | hasher = get_hasher(hasher) |
76 | 76 | |
77 | | if not salt: |
78 | | salt = hasher.salt() |
| 77 | salt = salt or hasher.salt() |
79 | 78 | |
80 | 79 | return hasher.encode(password, salt) |
81 | 80 | |
… |
… |
class PBKDF2PasswordHasher(BasePasswordHasher):
|
244 | 243 | def encode(self, password, salt, iterations=None): |
245 | 244 | assert password is not None |
246 | 245 | assert salt and '$' not in salt |
247 | | if not iterations: |
248 | | iterations = self.iterations |
| 246 | iterations = iterations or self.iterations |
249 | 247 | hash = pbkdf2(password, salt, iterations, digest=self.digest) |
250 | 248 | hash = base64.b64encode(hash).decode('ascii').strip() |
251 | 249 | return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash) |
-
diff --git a/django/contrib/auth/views.py b/django/contrib/auth/views.py
a
|
b
|
def logout_then_login(request, login_url=None):
|
164 | 164 | """ |
165 | 165 | Log out the user if they are logged in. Then redirect to the login page. |
166 | 166 | """ |
167 | | if not login_url: |
168 | | login_url = settings.LOGIN_URL |
169 | | login_url = resolve_url(login_url) |
| 167 | login_url = resolve_url(login_url or settings.LOGIN_URL) |
170 | 168 | return LogoutView.as_view(next_page=login_url)(request) |
171 | 169 | |
172 | 170 | |
-
diff --git a/django/contrib/gis/gdal/raster/band.py b/django/contrib/gis/gdal/raster/band.py
a
|
b
|
class GDALBand(GDALRasterBase):
|
186 | 186 | |
187 | 187 | Allowed input data types are bytes, memoryview, list, tuple, and array. |
188 | 188 | """ |
189 | | if not offset: |
190 | | offset = (0, 0) |
191 | | |
192 | | if not size: |
193 | | size = (self.width - offset[0], self.height - offset[1]) |
194 | | |
195 | | if not shape: |
196 | | shape = size |
197 | | |
| 189 | offset = offset or (0, 0) |
| 190 | size = size or (self.width - offset[0], self.height - offset[1]) |
| 191 | shape = shape or size |
198 | 192 | if any(x <= 0 for x in size): |
199 | 193 | raise ValueError('Offset too big for this raster.') |
200 | 194 | |
-
diff --git a/django/contrib/gis/geoip2/base.py b/django/contrib/gis/geoip2/base.py
a
|
b
|
class GeoIP2:
|
73 | 73 | raise GeoIP2Exception('Invalid GeoIP caching option: %s' % cache) |
74 | 74 | |
75 | 75 | # Getting the GeoIP data path. |
| 76 | path = path or GEOIP_SETTINGS['GEOIP_PATH'] |
76 | 77 | if not path: |
77 | | path = GEOIP_SETTINGS['GEOIP_PATH'] |
78 | | if not path: |
79 | | raise GeoIP2Exception('GeoIP path must be provided via parameter or the GEOIP_PATH setting.') |
| 78 | raise GeoIP2Exception('GeoIP path must be provided via parameter or the GEOIP_PATH setting.') |
80 | 79 | if not isinstance(path, str): |
81 | 80 | raise TypeError('Invalid path type: %s' % type(path).__name__) |
82 | 81 | |
… |
… |
class GeoIP2:
|
115 | 114 | |
116 | 115 | @property |
117 | 116 | def _reader(self): |
118 | | if self._country: |
119 | | return self._country |
120 | | else: |
121 | | return self._city |
| 117 | return self._country or self._city |
122 | 118 | |
123 | 119 | @property |
124 | 120 | def _country_or_city(self): |
-
diff --git a/django/contrib/gis/geos/prototypes/io.py b/django/contrib/gis/geos/prototypes/io.py
a
|
b
|
thread_context = ThreadLocalIO()
|
300 | 300 | # These module-level routines return the I/O object that is local to the |
301 | 301 | # thread. If the I/O object does not exist yet it will be initialized. |
302 | 302 | def wkt_r(): |
303 | | if not thread_context.wkt_r: |
304 | | thread_context.wkt_r = _WKTReader() |
| 303 | thread_context.wkt_r = thread_context.wkt_r or _WKTReader() |
305 | 304 | return thread_context.wkt_r |
306 | 305 | |
307 | 306 | |
… |
… |
def wkt_w(dim=2, trim=False, precision=None):
|
316 | 315 | |
317 | 316 | |
318 | 317 | def wkb_r(): |
319 | | if not thread_context.wkb_r: |
320 | | thread_context.wkb_r = _WKBReader() |
| 318 | thread_context.wkb_r = thread_context.wkb_r or _WKBReader() |
321 | 319 | return thread_context.wkb_r |
322 | 320 | |
323 | 321 | |
-
diff --git a/django/contrib/gis/geos/prototypes/threadsafe.py b/django/contrib/gis/geos/prototypes/threadsafe.py
a
|
b
|
class GEOSFunc:
|
41 | 41 | |
42 | 42 | def __call__(self, *args): |
43 | 43 | # Create a context handle if one doesn't exist for this thread. |
44 | | if not self.thread_context.handle: |
45 | | self.thread_context.handle = GEOSContextHandle() |
| 44 | self.thread_context.handle = self.thread_context.handle or GEOSContextHandle() |
46 | 45 | # Call the threaded GEOS routine with the pointer of the context handle |
47 | 46 | # as the first argument. |
48 | 47 | return self.cfunc(self.thread_context.handle.ptr, *args) |
-
diff --git a/django/contrib/gis/utils/srs.py b/django/contrib/gis/utils/srs.py
a
|
b
|
def add_srs_entry(srs, auth_name='EPSG', auth_srid=None, ref_sys_name=None,
|
32 | 32 | of `django.db.DEFAULT_DB_ALIAS` (at the time of this writing, its value |
33 | 33 | is 'default'). |
34 | 34 | """ |
35 | | if not database: |
36 | | database = DEFAULT_DB_ALIAS |
| 35 | database = database or DEFAULT_DB_ALIAS |
37 | 36 | connection = connections[database] |
38 | 37 | |
39 | 38 | if not hasattr(connection.ops, 'spatial_version'): |
-
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
a
|
b
|
class SessionBase:
|
241 | 241 | |
242 | 242 | if isinstance(expiry, datetime): |
243 | 243 | return expiry |
244 | | if not expiry: # Checks both None and 0 cases |
245 | | expiry = settings.SESSION_COOKIE_AGE |
| 244 | expirity = expiry or settings.SESSION_COOKIE_AGE # Checks both None and 0 cases |
246 | 245 | return modification + timedelta(seconds=expiry) |
247 | 246 | |
248 | 247 | def set_expiry(self, value): |
-
diff --git a/django/contrib/sessions/backends/cached_db.py b/django/contrib/sessions/backends/cached_db.py
a
|
b
|
class SessionStore(DBStore):
|
41 | 41 | return data |
42 | 42 | |
43 | 43 | def exists(self, session_key): |
44 | | if session_key and (self.cache_key_prefix + session_key) in self._cache: |
45 | | return True |
46 | | return super().exists(session_key) |
| 44 | return session_key and (self.cache_key_prefix + session_key) in self._cache or super().exists(session_key) |
47 | 45 | |
48 | 46 | def save(self, must_create=False): |
49 | 47 | super().save(must_create) |
-
diff --git a/django/contrib/sessions/backends/file.py b/django/contrib/sessions/backends/file.py
a
|
b
|
class SessionStore(SessionBase):
|
27 | 27 | try: |
28 | 28 | return cls._storage_path |
29 | 29 | except AttributeError: |
30 | | storage_path = getattr(settings, "SESSION_FILE_PATH", None) |
31 | | if not storage_path: |
32 | | storage_path = tempfile.gettempdir() |
| 30 | storage_path = getattr(settings, "SESSION_FILE_PATH", None) or tempfile.gettempdir() |
33 | 31 | |
34 | 32 | # Make sure the storage path is valid. |
35 | 33 | if not os.path.isdir(storage_path): |
-
diff --git a/django/contrib/staticfiles/storage.py b/django/contrib/staticfiles/storage.py
a
|
b
|
class HashedFilesMixin:
|
85 | 85 | # `name` is the base name to construct the new hashed filename from. |
86 | 86 | parsed_name = urlsplit(unquote(name)) |
87 | 87 | clean_name = parsed_name.path.strip() |
88 | | if filename: |
89 | | filename = urlsplit(unquote(filename)).path.strip() |
90 | | filename = filename or clean_name |
| 88 | filename = (filename and urlsplit(unquote(filename)).path.strip()) or clean_name |
91 | 89 | opened = False |
92 | 90 | if content is None: |
93 | 91 | if not self.exists(filename): |
-
diff --git a/django/core/cache/backends/locmem.py b/django/core/cache/backends/locmem.py
a
|
b
|
class LocMemCache(BaseCache):
|
98 | 98 | |
99 | 99 | def _has_expired(self, key): |
100 | 100 | exp = self._expire_info.get(key, -1) |
101 | | if exp is None or exp > time.time(): |
102 | | return False |
103 | | return True |
| 101 | return exp is not None and exp <= time.time() |
104 | 102 | |
105 | 103 | def _cull(self): |
106 | 104 | if self._cull_frequency == 0: |
-
diff --git a/django/core/files/base.py b/django/core/files/base.py
a
|
b
|
class File(FileProxyMixin):
|
59 | 59 | Read the file and yield chunks of ``chunk_size`` bytes (defaults to |
60 | 60 | ``UploadedFile.DEFAULT_CHUNK_SIZE``). |
61 | 61 | """ |
62 | | if not chunk_size: |
63 | | chunk_size = self.DEFAULT_CHUNK_SIZE |
| 62 | chunk_size = chunk_size or self.DEFAULT_CHUNK_SIZE |
64 | 63 | |
65 | 64 | try: |
66 | 65 | self.seek(0) |
… |
… |
class File(FileProxyMixin):
|
81 | 80 | always return ``False`` -- there's no good reason to read from memory in |
82 | 81 | chunks. |
83 | 82 | """ |
84 | | if not chunk_size: |
85 | | chunk_size = self.DEFAULT_CHUNK_SIZE |
86 | | return self.size > chunk_size |
| 83 | return self.size > (chunk_size or self.DEFAULT_CHUNK_SIZE) |
87 | 84 | |
88 | 85 | def __iter__(self): |
89 | 86 | # Iterate over this file-like object by newlines |
-
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
a
|
b
|
def get_script_name(environ):
|
176 | 176 | # rewrites. Unfortunately not every Web server (lighttpd!) passes this |
177 | 177 | # information through all the time, so FORCE_SCRIPT_NAME, above, is still |
178 | 178 | # needed. |
179 | | script_url = get_bytes_from_wsgi(environ, 'SCRIPT_URL', '') |
180 | | if not script_url: |
181 | | script_url = get_bytes_from_wsgi(environ, 'REDIRECT_URL', '') |
| 179 | script_url = get_bytes_from_wsgi(environ, 'SCRIPT_URL', '') or get_bytes_from_wsgi(environ, 'REDIRECT_URL', '') |
182 | 180 | |
183 | 181 | if script_url: |
184 | 182 | if b'//' in script_url: |
-
diff --git a/django/core/mail/message.py b/django/core/mail/message.py
a
|
b
|
class EmailMessage:
|
309 | 309 | self.attachments.append(filename) |
310 | 310 | else: |
311 | 311 | assert content is not None |
312 | | |
313 | | if not mimetype: |
314 | | mimetype, _ = mimetypes.guess_type(filename) |
315 | | if not mimetype: |
316 | | mimetype = DEFAULT_ATTACHMENT_MIME_TYPE |
| 312 | mimetype = mimetype or mimetypes.guess_type(filename)[0] or DEFAULT_ATTACHMENT_MIME_TYPE |
317 | 313 | basetype, subtype = mimetype.split('/', 1) |
318 | 314 | |
319 | 315 | if basetype == 'text': |
-
diff --git a/django/core/management/color.py b/django/core/management/color.py
a
|
b
|
def supports_color():
|
19 | 19 | |
20 | 20 | # isatty is not always implemented, #6223. |
21 | 21 | is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() |
22 | | if not supported_platform or not is_a_tty: |
23 | | return False |
24 | | return True |
| 22 | return supported_platform and is_a_tty |
25 | 23 | |
26 | 24 | |
27 | 25 | class Style: |
-
diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py
a
|
b
|
class Command(BaseCommand):
|
502 | 502 | if os.path.abspath(dirpath).startswith(os.path.dirname(path)): |
503 | 503 | locale_dir = path |
504 | 504 | break |
505 | | if not locale_dir: |
506 | | locale_dir = self.default_locale_path or NO_LOCALE_DIR |
| 505 | locale_dir = locale_dir or self.default_locale_path or NO_LOCALE_DIR |
507 | 506 | all_files.append(self.translatable_file_class(dirpath, filename, locale_dir)) |
508 | 507 | return sorted(all_files) |
509 | 508 | |
-
diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py
a
|
b
|
class Serializer:
|
96 | 96 | self.handle_m2m_field(obj, field) |
97 | 97 | self.end_object(obj) |
98 | 98 | progress_bar.update(count) |
99 | | if self.first: |
100 | | self.first = False |
| 99 | self.first = self.first and False |
101 | 100 | self.end_serialization() |
102 | 101 | return self.getvalue() |
103 | 102 | |
-
diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py
a
|
b
|
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
61 | 61 | field.get_internal_type() == 'ForeignKey' and |
62 | 62 | field.db_constraint): |
63 | 63 | return False |
64 | | if self._is_limited_data_type(field): |
65 | | return False |
66 | | return create_index |
| 64 | return not self._is_limited_data_type(field) and create_index |
67 | 65 | |
68 | 66 | def _delete_composed_index(self, model, fields, *args): |
69 | 67 | """ |
-
diff --git a/django/db/backends/postgresql/creation.py b/django/db/backends/postgresql/creation.py
a
|
b
|
class DatabaseCreation(BaseDatabaseCreation):
|
16 | 16 | suffix += " ENCODING '{}'".format(encoding) |
17 | 17 | if template: |
18 | 18 | suffix += " TEMPLATE {}".format(self._quote_name(template)) |
19 | | if suffix: |
20 | | suffix = "WITH" + suffix |
21 | | return suffix |
| 19 | return suffix and "WITH" + suffix |
22 | 20 | |
23 | 21 | def sql_table_creation_suffix(self): |
24 | 22 | test_settings = self.connection.settings_dict['TEST'] |
-
diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py
a
|
b
|
class DatabaseOperations(BaseDatabaseOperations):
|
131 | 131 | sql = [] |
132 | 132 | for sequence_info in sequences: |
133 | 133 | table_name = sequence_info['table'] |
134 | | column_name = sequence_info['column'] |
135 | | if not column_name: |
| 134 | column_name = sequence_info['column'] or 'id' |
136 | 135 | # This will be the case if it's an m2m using an autogenerated |
137 | 136 | # intermediate table (see BaseDatabaseIntrospection.sequence_list) |
138 | | column_name = 'id' |
139 | 137 | sql.append("%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" % ( |
140 | 138 | style.SQL_KEYWORD('SELECT'), |
141 | 139 | style.SQL_TABLE(self.quote_name(table_name)), |
-
diff --git a/django/db/models/aggregates.py b/django/db/models/aggregates.py
a
|
b
|
class Aggregate(Func):
|
31 | 31 | return source_expressions |
32 | 32 | |
33 | 33 | def set_source_expressions(self, exprs): |
34 | | if self.filter: |
35 | | self.filter = exprs.pop() |
| 34 | self.filter = self.filer and exprs.pop() |
36 | 35 | return super().set_source_expressions(exprs) |
37 | 36 | |
38 | 37 | def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False): |
39 | 38 | # Aggregates are not allowed in UPDATE queries, so ignore for_save |
40 | 39 | c = super().resolve_expression(query, allow_joins, reuse, summarize) |
41 | | if c.filter: |
42 | | c.filter = c.filter.resolve_expression(query, allow_joins, reuse, summarize) |
| 40 | c.filter = c.filter and c.filter.resolve_expression(query, allow_joins, reuse, summarize) |
43 | 41 | if not summarize: |
44 | 42 | # Call Aggregate.get_source_expressions() to avoid |
45 | 43 | # returning self.filter and including that in this loop. |
-
diff --git a/django/db/models/base.py b/django/db/models/base.py
a
|
b
|
class Model(metaclass=ModelBase):
|
549 | 549 | self.__dict__.update(state) |
550 | 550 | |
551 | 551 | def _get_pk_val(self, meta=None): |
552 | | if not meta: |
553 | | meta = self._meta |
| 552 | meta = meta or self._meta |
554 | 553 | return getattr(self, meta.pk.attname) |
555 | 554 | |
556 | 555 | def _set_pk_val(self, value): |
… |
… |
class Model(metaclass=ModelBase):
|
852 | 851 | # exists. |
853 | 852 | return update_fields is not None or filtered.exists() |
854 | 853 | if self._meta.select_on_save and not forced_update: |
855 | | if filtered.exists(): |
| 854 | return (filtered.exists() and |
856 | 855 | # It may happen that the object is deleted from the DB right after |
857 | 856 | # this check, causing the subsequent UPDATE to return zero matching |
858 | 857 | # rows. The same result can occur in some rare cases when the |
… |
… |
class Model(metaclass=ModelBase):
|
860 | 859 | # successfully (a row is matched and updated). In order to |
861 | 860 | # distinguish these two cases, the object's existence in the |
862 | 861 | # database is again checked for if the UPDATE query returns 0. |
863 | | return filtered._update(values) > 0 or filtered.exists() |
864 | | else: |
865 | | return False |
| 862 | (filtered._update(values) > 0 or filtered.exists())) |
866 | 863 | return filtered._update(values) > 0 |
867 | 864 | |
868 | 865 | def _do_insert(self, manager, using, fields, update_pk, raw): |
-
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
a
|
b
|
class Field(RegisterLookupMixin):
|
694 | 694 | return self._db_tablespace or settings.DEFAULT_INDEX_TABLESPACE |
695 | 695 | |
696 | 696 | def set_attributes_from_name(self, name): |
697 | | if not self.name: |
698 | | self.name = name |
| 697 | self.name = self.name or name |
699 | 698 | self.attname, self.column = self.get_attname_column() |
700 | 699 | self.concrete = self.column is not None |
701 | 700 | if self.verbose_name is None and self.name: |
-
diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
a
|
b
|
class FileField(Field):
|
314 | 314 | if data is not None: |
315 | 315 | # This value will be converted to str and stored in the |
316 | 316 | # database, so leaving False as-is is not acceptable. |
317 | | if not data: |
318 | | data = '' |
319 | | setattr(instance, self.name, data) |
| 317 | setattr(instance, self.name, data or '') |
320 | 318 | |
321 | 319 | def formfield(self, **kwargs): |
322 | 320 | return super().formfield(**{ |
-
diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py
a
|
b
|
class FieldGetDbPrepValueMixin:
|
177 | 177 | def get_db_prep_lookup(self, value, connection): |
178 | 178 | # For relational fields, use the output_field of the 'field' attribute. |
179 | 179 | field = getattr(self.lhs.output_field, 'field', None) |
180 | | get_db_prep_value = getattr(field, 'get_db_prep_value', None) |
181 | | if not get_db_prep_value: |
182 | | get_db_prep_value = self.lhs.output_field.get_db_prep_value |
| 180 | get_db_prep_value = getattr(field, 'get_db_prep_value', None) or self.lhs.output_field.get_db_prep_value |
183 | 181 | return ( |
184 | 182 | '%s', |
185 | 183 | [get_db_prep_value(v, connection, prepared=True) for v in value] |
-
diff --git a/django/db/models/manager.py b/django/db/models/manager.py
a
|
b
|
class BaseManager:
|
107 | 107 | }) |
108 | 108 | |
109 | 109 | def contribute_to_class(self, model, name): |
110 | | if not self.name: |
111 | | self.name = name |
| 110 | self.name = self.name or name |
112 | 111 | self.model = model |
113 | 112 | |
114 | 113 | setattr(model, name, ManagerDescriptor(self)) |
-
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
a
|
b
|
class SQLCompiler:
|
521 | 521 | if grouping: |
522 | 522 | if distinct_fields: |
523 | 523 | raise NotImplementedError('annotate() + distinct(fields) is not implemented.') |
524 | | if not order_by: |
525 | | order_by = self.connection.ops.force_no_ordering() |
| 524 | order_by = order_by or self.connection.ops.force_no_ordering() |
526 | 525 | result.append('GROUP BY %s' % ', '.join(grouping)) |
527 | 526 | |
528 | 527 | if having: |
… |
… |
class SQLCompiler:
|
588 | 587 | if opts is None: |
589 | 588 | opts = self.query.get_meta() |
590 | 589 | only_load = self.deferred_to_columns() |
591 | | if not start_alias: |
592 | | start_alias = self.query.get_initial_alias() |
| 590 | start_alias = start_alias or self.query.get_initial_alias() |
593 | 591 | # The 'seen_models' is used to optimize checking the needed parent |
594 | 592 | # alias for a given field. This also includes None -> start_alias to |
595 | 593 | # be used by local fields. |
… |
… |
class SQLCompiler:
|
657 | 655 | # of the field is specified. |
658 | 656 | if field.is_relation and opts.ordering and getattr(field, 'attname', None) != name: |
659 | 657 | # Firstly, avoid infinite loops. |
660 | | if not already_seen: |
661 | | already_seen = set() |
| 658 | already_seen = already_seen or set() |
662 | 659 | join_tuple = tuple(getattr(self.query.alias_map[j], 'join_cols', None) for j in joins) |
663 | 660 | if join_tuple in already_seen: |
664 | 661 | raise FieldError('Infinite loop caused by ordering.') |
… |
… |
class SQLCompiler:
|
680 | 677 | same input, as the prefixes of get_ordering() and get_distinct() must |
681 | 678 | match. Executing SQL where this is not true is an error. |
682 | 679 | """ |
683 | | if not alias: |
684 | | alias = self.query.get_initial_alias() |
| 680 | alias = alias or self.query.get_initial_alias() |
685 | 681 | field, targets, opts, joins, path = self.query.setup_joins( |
686 | 682 | pieces, opts, alias) |
687 | 683 | alias = joins[-1] |
… |
… |
class SQLCompiler:
|
1037 | 1033 | is needed, as the filters describe an empty set. In that case, None is |
1038 | 1034 | returned, to avoid any unnecessary database interaction. |
1039 | 1035 | """ |
1040 | | if not result_type: |
1041 | | result_type = NO_RESULTS |
| 1036 | result_type = result_type or NO_RESULTS |
1042 | 1037 | try: |
1043 | 1038 | sql, params = self.as_sql() |
1044 | 1039 | if not sql: |
-
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
a
|
b
|
class Query:
|
805 | 805 | if isinstance(self.group_by, tuple): |
806 | 806 | self.group_by = tuple([col.relabeled_clone(change_map) for col in self.group_by]) |
807 | 807 | self.select = tuple([col.relabeled_clone(change_map) for col in self.select]) |
808 | | if self._annotations: |
809 | | self._annotations = OrderedDict( |
810 | | (key, col.relabeled_clone(change_map)) for key, col in self._annotations.items()) |
| 808 | self._annotations = self._annotations and OrderedDict( |
| 809 | (key, col.relabeled_clone(change_map)) for key, col in self._annotations.items()) |
811 | 810 | |
812 | 811 | # 2. Rename the alias in the internal table/alias datastructures. |
813 | 812 | for old_alias, new_alias in change_map.items(): |
… |
… |
class Query:
|
1061 | 1060 | and get_transform(). |
1062 | 1061 | """ |
1063 | 1062 | # __exact is the default lookup if one isn't given. |
1064 | | if not lookups: |
1065 | | lookups = ['exact'] |
| 1063 | lookups = lookups or ['exact'] |
1066 | 1064 | |
1067 | 1065 | for name in lookups[:-1]: |
1068 | 1066 | lhs = self.try_transform(lhs, name) |
… |
… |
class Query:
|
2050 | 2048 | # used. The proper fix would be to defer all decisions where |
2051 | 2049 | # is_nullable() is needed to the compiler stage, but that is not easy |
2052 | 2050 | # to do currently. |
2053 | | if connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls and field.empty_strings_allowed: |
2054 | | return True |
2055 | | else: |
2056 | | return field.null |
| 2051 | return connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls and field.empty_strings_allowed or field.null |
2057 | 2052 | |
2058 | 2053 | |
2059 | 2054 | def get_order_dir(field, default='ASC'): |
-
diff --git a/django/forms/boundfield.py b/django/forms/boundfield.py
a
|
b
|
class BoundField:
|
79 | 79 | attributes passed as attrs. If a widget isn't specified, use the |
80 | 80 | field's default widget. |
81 | 81 | """ |
82 | | if not widget: |
83 | | widget = self.field.widget |
| 82 | widget = widget or self.field.widget |
84 | 83 | |
85 | 84 | if self.field.localize: |
86 | 85 | widget.is_localized = True |
… |
… |
class BoundField:
|
219 | 218 | return data |
220 | 219 | |
221 | 220 | def build_widget_attrs(self, attrs, widget=None): |
222 | | if not widget: |
223 | | widget = self.field.widget |
| 221 | widget = widget or self.field.widget |
224 | 222 | attrs = dict(attrs) # Copy attrs to avoid modifying the argument. |
225 | 223 | if widget.use_required_attribute(self.initial) and self.field.required and self.form.use_required_attribute: |
226 | 224 | attrs['required'] = True |
-
diff --git a/django/forms/fields.py b/django/forms/fields.py
a
|
b
|
class FileField(Field):
|
591 | 591 | return data |
592 | 592 | |
593 | 593 | def has_changed(self, initial, data): |
594 | | if self.disabled: |
595 | | return False |
596 | | if data is None: |
597 | | return False |
598 | | return True |
| 594 | return not self.disabled and data is not None |
599 | 595 | |
600 | 596 | |
601 | 597 | class ImageField(FileField): |
-
diff --git a/django/http/request.py b/django/http/request.py
a
|
b
|
class QueryDict(MultiValueDict):
|
376 | 376 | |
377 | 377 | def __init__(self, query_string=None, mutable=False, encoding=None): |
378 | 378 | super().__init__() |
379 | | if not encoding: |
380 | | encoding = settings.DEFAULT_CHARSET |
381 | | self.encoding = encoding |
| 379 | self.encoding = encoding = encoding or settings.DEFAULT_CHARSET |
382 | 380 | query_string = query_string or '' |
383 | 381 | parse_qsl_kwargs = { |
384 | 382 | 'keep_blank_values': True, |
-
diff --git a/django/middleware/http.py b/django/middleware/http.py
a
|
b
|
class ConditionalGetMiddleware(MiddlewareMixin):
|
23 | 23 | |
24 | 24 | etag = response.get('ETag') |
25 | 25 | last_modified = response.get('Last-Modified') |
26 | | if last_modified: |
27 | | last_modified = parse_http_date_safe(last_modified) |
| 26 | last_modified = last_modified and parse_http_date_safe(last_modified) |
28 | 27 | |
29 | 28 | if etag or last_modified: |
30 | 29 | return get_conditional_response( |
-
diff --git a/django/test/client.py b/django/test/client.py
a
|
b
|
def encode_file(boundary, key, file):
|
236 | 236 | |
237 | 237 | if content_type is None: |
238 | 238 | content_type = 'application/octet-stream' |
239 | | if not filename: |
240 | | filename = key |
| 239 | filename = filename or key |
241 | 240 | return [ |
242 | 241 | to_bytes('--%s' % boundary), |
243 | 242 | to_bytes('Content-Disposition: form-data; name="%s"; filename="%s"' |
-
diff --git a/django/test/html.py b/django/test/html.py
a
|
b
|
class Element:
|
71 | 71 | other_value = other_attr |
72 | 72 | if attr != other_attr or value != other_value: |
73 | 73 | return False |
74 | | if self.children != element.children: |
75 | | return False |
76 | | return True |
| 74 | return self.children == element.children |
77 | 75 | |
78 | 76 | def __hash__(self): |
79 | 77 | return hash((self.name,) + tuple(a for a in self.attributes)) |
-
diff --git a/django/test/utils.py b/django/test/utils.py
a
|
b
|
class Approximate:
|
50 | 50 | return repr(self.val) |
51 | 51 | |
52 | 52 | def __eq__(self, other): |
53 | | if self.val == other: |
54 | | return True |
55 | | return round(abs(self.val - other), self.places) == 0 |
| 53 | return self.val == other or round(abs(self.val - other), self.places) == 0 |
56 | 54 | |
57 | 55 | |
58 | 56 | class ContextList(list): |
… |
… |
def teardown_databases(old_config, verbosity, parallel=0, keepdb=False):
|
300 | 298 | |
301 | 299 | |
302 | 300 | def get_runner(settings, test_runner_class=None): |
303 | | if not test_runner_class: |
304 | | test_runner_class = settings.TEST_RUNNER |
305 | | |
| 301 | test_runner_class = test_runner_class or settings.TEST_RUNNER |
306 | 302 | test_path = test_runner_class.split('.') |
307 | 303 | # Allow for relative paths |
308 | 304 | if len(test_path) > 1: |
-
diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py
a
|
b
|
class URLResolver:
|
393 | 393 | warnings = [] |
394 | 394 | for pattern in self.url_patterns: |
395 | 395 | warnings.extend(check_resolver(pattern)) |
396 | | if not warnings: |
397 | | warnings = self.pattern.check() |
398 | | return warnings |
| 396 | return warnings or self.pattern.check() |
399 | 397 | |
400 | 398 | def _populate(self): |
401 | 399 | # Short-circuit if called recursively in this thread to prevent |
-
diff --git a/django/utils/cache.py b/django/utils/cache.py
a
|
b
|
def get_conditional_response(request, etag=None, last_modified=None, response=No
|
142 | 142 | # Get HTTP request headers. |
143 | 143 | if_match_etags = parse_etags(request.META.get('HTTP_IF_MATCH', '')) |
144 | 144 | if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE') |
145 | | if if_unmodified_since: |
146 | | if_unmodified_since = parse_http_date_safe(if_unmodified_since) |
| 145 | if_unmodified_since = if_unmodified_since and parse_http_date_safe(if_unmodified_since) |
147 | 146 | if_none_match_etags = parse_etags(request.META.get('HTTP_IF_NONE_MATCH', '')) |
148 | 147 | if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE') |
149 | | if if_modified_since: |
150 | | if_modified_since = parse_http_date_safe(if_modified_since) |
| 148 | if_modified_since = if_modified_since and parse_http_date_safe(if_modified_since) |
151 | 149 | |
152 | 150 | # Step 1 of section 6 of RFC 7232: Test the If-Match precondition. |
153 | 151 | if if_match_etags and not _if_match_passes(etag, if_match_etags): |
-
diff --git a/django/utils/crypto.py b/django/utils/crypto.py
a
|
b
|
def pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
78 | 78 | """Return the hash of password using pbkdf2.""" |
79 | 79 | if digest is None: |
80 | 80 | digest = hashlib.sha256 |
81 | | if not dklen: |
82 | | dklen = None |
| 81 | dklen = dklen or None |
83 | 82 | password = force_bytes(password) |
84 | 83 | salt = force_bytes(salt) |
85 | 84 | return hashlib.pbkdf2_hmac(digest().name, password, salt, iterations, dklen) |
-
diff --git a/django/utils/dateparse.py b/django/utils/dateparse.py
a
|
b
|
def parse_time(value):
|
89 | 89 | match = time_re.match(value) |
90 | 90 | if match: |
91 | 91 | kw = match.groupdict() |
92 | | if kw['microsecond']: |
93 | | kw['microsecond'] = kw['microsecond'].ljust(6, '0') |
| 92 | kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0') |
94 | 93 | kw = {k: int(v) for k, v in kw.items() if v is not None} |
95 | 94 | return datetime.time(**kw) |
96 | 95 | |
… |
… |
def parse_datetime(value):
|
107 | 106 | match = datetime_re.match(value) |
108 | 107 | if match: |
109 | 108 | kw = match.groupdict() |
110 | | if kw['microsecond']: |
111 | | kw['microsecond'] = kw['microsecond'].ljust(6, '0') |
| 109 | kw['microsecond'] = kw['microsecond'] and kw['microsecond'].ljust(6, '0') |
112 | 110 | tzinfo = kw.pop('tzinfo') |
113 | 111 | if tzinfo == 'Z': |
114 | 112 | tzinfo = utc |
-
diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py
a
|
b
|
class MiddlewareMixin:
|
88 | 88 | response = None |
89 | 89 | if hasattr(self, 'process_request'): |
90 | 90 | response = self.process_request(request) |
91 | | if not response: |
92 | | response = self.get_response(request) |
| 91 | response = response or self.get_response(request) |
93 | 92 | if hasattr(self, 'process_response'): |
94 | 93 | response = self.process_response(request, response) |
95 | 94 | return response |
-
diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py
a
|
b
|
class SyndicationFeed:
|
86 | 86 | feed_url=None, feed_copyright=None, feed_guid=None, ttl=None, **kwargs): |
87 | 87 | def to_str(s): |
88 | 88 | return str(s) if s is not None else s |
89 | | if categories: |
90 | | categories = [str(c) for c in categories] |
| 89 | categories = categories and [str(c) for c in categories] |
91 | 90 | self.feed = { |
92 | 91 | 'title': to_str(title), |
93 | 92 | 'link': iri_to_uri(link), |
… |
… |
class SyndicationFeed:
|
117 | 116 | """ |
118 | 117 | def to_str(s): |
119 | 118 | return str(s) if s is not None else s |
120 | | if categories: |
121 | | categories = [to_str(c) for c in categories] |
| 119 | categories = categories and [to_str(c) for c in categories] |
122 | 120 | self.items.append({ |
123 | 121 | 'title': to_str(title), |
124 | 122 | 'link': iri_to_uri(link), |
-
diff --git a/django/utils/numberformat.py b/django/utils/numberformat.py
a
|
b
|
def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='',
|
42 | 42 | int_part, dec_part = str_number, '' |
43 | 43 | if decimal_pos is not None: |
44 | 44 | dec_part = dec_part + ('0' * (decimal_pos - len(dec_part))) |
45 | | if dec_part: |
46 | | dec_part = decimal_sep + dec_part |
| 45 | dec_part = dec_part and decimal_sep + dec_part |
47 | 46 | # grouping |
48 | 47 | if use_grouping: |
49 | 48 | try: |
-
diff --git a/django/utils/timesince.py b/django/utils/timesince.py
a
|
b
|
def timesince(d, now=None, reversed=False):
|
35 | 35 | if now and not isinstance(now, datetime.datetime): |
36 | 36 | now = datetime.datetime(now.year, now.month, now.day) |
37 | 37 | |
38 | | if not now: |
39 | | now = datetime.datetime.now(utc if is_aware(d) else None) |
| 38 | now = now or datetime.datetime.now(utc if is_aware(d) else None) |
40 | 39 | |
41 | 40 | if reversed: |
42 | 41 | d, now = now, d |
-
diff --git a/django/views/i18n.py b/django/views/i18n.py
a
|
b
|
def set_language(request):
|
35 | 35 | if ((next or not request.is_ajax()) and |
36 | 36 | not is_safe_url(url=next, allowed_hosts={request.get_host()}, require_https=request.is_secure())): |
37 | 37 | next = request.META.get('HTTP_REFERER') |
38 | | if next: |
39 | | next = unquote(next) # HTTP_REFERER may be encoded. |
| 38 | next = next and unquote(next) # HTTP_REFERER may be encoded. |
40 | 39 | if not is_safe_url(url=next, allowed_hosts={request.get_host()}, require_https=request.is_secure()): |
41 | 40 | next = '/' |
42 | 41 | response = HttpResponseRedirect(next) if next else HttpResponse(status=204) |
-
diff --git a/tests/auth_tests/test_auth_backends.py b/tests/auth_tests/test_auth_backends.py
a
|
b
|
class SimpleRowlevelBackend:
|
339 | 339 | return False |
340 | 340 | |
341 | 341 | def has_module_perms(self, user, app_label): |
342 | | if not user.is_anonymous and not user.is_active: |
343 | | return False |
344 | | return app_label == "app1" |
| 342 | return (user.is_anonymous or user.is_active) and app_label == "app1" |
345 | 343 | |
346 | 344 | def get_all_permissions(self, user, obj=None): |
347 | 345 | if not obj: |
-
diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py
a
|
b
|
class DumpDataAssertMixin:
|
51 | 51 | natural_foreign_keys=False, natural_primary_keys=False, |
52 | 52 | use_base_manager=False, exclude_list=[], primary_keys=''): |
53 | 53 | new_io = StringIO() |
54 | | if filename: |
55 | | filename = os.path.join(tempfile.gettempdir(), filename) |
| 54 | filename = filename and os.path.join(tempfile.gettempdir(), filename) |
56 | 55 | management.call_command('dumpdata', *args, **{'format': format, |
57 | 56 | 'stdout': new_io, |
58 | 57 | 'stderr': new_io, |
-
diff --git a/tests/gis_tests/test_data.py b/tests/gis_tests/test_data.py
a
|
b
|
class TestGeom(TestObj):
|
62 | 62 | self.coords = tuplize(coords) |
63 | 63 | if centroid: |
64 | 64 | self.centroid = tuple(centroid) |
65 | | if ext_ring_cs: |
66 | | ext_ring_cs = tuplize(ext_ring_cs) |
67 | | self.ext_ring_cs = ext_ring_cs |
| 65 | self.ext_ring_cs = ext_ring_cs and tuplize(ext_ring_cs) |
68 | 66 | |
69 | 67 | super().__init__(**kwargs) |
70 | 68 | |
-
diff --git a/tests/multiple_database/routers.py b/tests/multiple_database/routers.py
a
|
b
|
class AuthRouter:
|
43 | 43 | |
44 | 44 | def allow_relation(self, obj1, obj2, **hints): |
45 | 45 | "Allow any relation if a model in Auth is involved" |
46 | | if obj1._meta.app_label == 'auth' or obj2._meta.app_label == 'auth': |
47 | | return True |
48 | | return None |
| 46 | return obj1._meta.app_label == 'auth' or obj2._meta.app_label == 'auth' or None |
49 | 47 | |
50 | 48 | def allow_migrate(self, db, app_label, **hints): |
51 | 49 | "Make sure the auth app only appears on the 'other' db" |