mirror of https://github.com/django/django.git
Fixed #34983 -- Deprecated django.utils.itercompat.is_iterable().
This commit is contained in:
parent
eabfa2d0e3
commit
5e28cd3f2c
|
@ -1,3 +1,5 @@
|
|||
from collections.abc import Iterable
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib import auth
|
||||
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
|
||||
|
@ -8,7 +10,6 @@ from django.core.mail import send_mail
|
|||
from django.db import models
|
||||
from django.db.models.manager import EmptyManager
|
||||
from django.utils import timezone
|
||||
from django.utils.itercompat import is_iterable
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .validators import UnicodeUsernameValidator
|
||||
|
@ -315,7 +316,7 @@ class PermissionsMixin(models.Model):
|
|||
Return True if the user has each of the specified permissions. If
|
||||
object is passed, check if the user has all required perms for it.
|
||||
"""
|
||||
if not is_iterable(perm_list) or isinstance(perm_list, str):
|
||||
if not isinstance(perm_list, Iterable) or isinstance(perm_list, str):
|
||||
raise ValueError("perm_list must be an iterable of permissions.")
|
||||
return all(self.has_perm(perm, obj) for perm in perm_list)
|
||||
|
||||
|
@ -480,7 +481,7 @@ class AnonymousUser:
|
|||
return _user_has_perm(self, perm, obj=obj)
|
||||
|
||||
def has_perms(self, perm_list, obj=None):
|
||||
if not is_iterable(perm_list) or isinstance(perm_list, str):
|
||||
if not isinstance(perm_list, Iterable) or isinstance(perm_list, str):
|
||||
raise ValueError("perm_list must be an iterable of permissions.")
|
||||
return all(self.has_perm(perm, obj) for perm in perm_list)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from collections.abc import Iterable
|
||||
from itertools import chain
|
||||
|
||||
from django.utils.inspect import func_accepts_kwargs
|
||||
from django.utils.itercompat import is_iterable
|
||||
|
||||
|
||||
class Tags:
|
||||
|
@ -86,7 +86,7 @@ class CheckRegistry:
|
|||
|
||||
for check in checks:
|
||||
new_errors = check(app_configs=app_configs, databases=databases)
|
||||
if not is_iterable(new_errors):
|
||||
if not isinstance(new_errors, Iterable):
|
||||
raise TypeError(
|
||||
"The function %r did not return a list. All functions "
|
||||
"registered with the checks registry must return a list." % check,
|
||||
|
|
|
@ -5,6 +5,7 @@ import operator
|
|||
import uuid
|
||||
import warnings
|
||||
from base64 import b64decode, b64encode
|
||||
from collections.abc import Iterable
|
||||
from functools import partialmethod, total_ordering
|
||||
|
||||
from django import forms
|
||||
|
@ -31,7 +32,6 @@ from django.utils.dateparse import (
|
|||
from django.utils.duration import duration_microseconds, duration_string
|
||||
from django.utils.functional import Promise, cached_property
|
||||
from django.utils.ipv6 import clean_ipv6_address
|
||||
from django.utils.itercompat import is_iterable
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
@ -317,13 +317,13 @@ class Field(RegisterLookupMixin):
|
|||
|
||||
@classmethod
|
||||
def _choices_is_value(cls, value):
|
||||
return isinstance(value, (str, Promise)) or not is_iterable(value)
|
||||
return isinstance(value, (str, Promise)) or not isinstance(value, Iterable)
|
||||
|
||||
def _check_choices(self):
|
||||
if not self.choices:
|
||||
return []
|
||||
|
||||
if not is_iterable(self.choices) or isinstance(self.choices, str):
|
||||
if not isinstance(self.choices, Iterable) or isinstance(self.choices, str):
|
||||
return [
|
||||
checks.Error(
|
||||
"'choices' must be a mapping (e.g. a dictionary) or an iterable "
|
||||
|
|
|
@ -3,6 +3,7 @@ import re
|
|||
import sys
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from collections.abc import Iterable
|
||||
from datetime import datetime
|
||||
from itertools import cycle as itertools_cycle
|
||||
from itertools import groupby
|
||||
|
@ -10,7 +11,6 @@ from itertools import groupby
|
|||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
from django.utils.html import conditional_escape, escape, format_html
|
||||
from django.utils.itercompat import is_iterable
|
||||
from django.utils.lorem_ipsum import paragraphs, words
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
|
@ -1198,7 +1198,7 @@ def query_string(context, query_dict=None, **kwargs):
|
|||
if value is None:
|
||||
if key in query_dict:
|
||||
del query_dict[key]
|
||||
elif is_iterable(value) and not isinstance(value, str):
|
||||
elif isinstance(value, Iterable) and not isinstance(value, str):
|
||||
query_dict.setlist(key, value)
|
||||
else:
|
||||
query_dict[key] = value
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from collections.abc import Iterable
|
||||
from functools import wraps
|
||||
from importlib import import_module
|
||||
from inspect import getfullargspec, unwrap
|
||||
|
||||
from django.utils.html import conditional_escape
|
||||
from django.utils.itercompat import is_iterable
|
||||
|
||||
from .base import Node, Template, token_kwargs
|
||||
from .exceptions import TemplateSyntaxError
|
||||
|
@ -263,7 +263,9 @@ class InclusionNode(TagHelperNode):
|
|||
t = self.filename
|
||||
elif isinstance(getattr(self.filename, "template", None), Template):
|
||||
t = self.filename.template
|
||||
elif not isinstance(self.filename, str) and is_iterable(self.filename):
|
||||
elif not isinstance(self.filename, str) and isinstance(
|
||||
self.filename, Iterable
|
||||
):
|
||||
t = context.template.engine.select_template(self.filename)
|
||||
else:
|
||||
t = context.template.engine.get_template(self.filename)
|
||||
|
|
|
@ -2,6 +2,7 @@ import json
|
|||
import mimetypes
|
||||
import os
|
||||
import sys
|
||||
from collections.abc import Iterable
|
||||
from copy import copy
|
||||
from functools import partial
|
||||
from http import HTTPStatus
|
||||
|
@ -25,7 +26,6 @@ from django.urls import resolve
|
|||
from django.utils.encoding import force_bytes
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.itercompat import is_iterable
|
||||
from django.utils.regex_helper import _lazy_re_compile
|
||||
|
||||
__all__ = (
|
||||
|
@ -303,7 +303,7 @@ def encode_multipart(boundary, data):
|
|||
)
|
||||
elif is_file(value):
|
||||
lines.extend(encode_file(boundary, key, value))
|
||||
elif not isinstance(value, str) and is_iterable(value):
|
||||
elif not isinstance(value, str) and isinstance(value, Iterable):
|
||||
for item in value:
|
||||
if is_file(item):
|
||||
lines.extend(encode_file(boundary, key, item))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.utils.itercompat import is_iterable
|
||||
from collections.abc import Iterable
|
||||
|
||||
|
||||
def make_hashable(value):
|
||||
|
@ -19,7 +19,7 @@ def make_hashable(value):
|
|||
try:
|
||||
hash(value)
|
||||
except TypeError:
|
||||
if is_iterable(value):
|
||||
if isinstance(value, Iterable):
|
||||
return tuple(map(make_hashable, value))
|
||||
# Non-hashable, non-iterable.
|
||||
raise
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
# RemovedInDjango60Warning: Remove this entire module.
|
||||
|
||||
import warnings
|
||||
|
||||
from django.utils.deprecation import RemovedInDjango60Warning
|
||||
|
||||
|
||||
def is_iterable(x):
|
||||
"An implementation independent way of checking for iterables"
|
||||
warnings.warn(
|
||||
"django.utils.itercompat.is_iterable() is deprecated. "
|
||||
"Use isinstance(..., collections.abc.Iterable) instead.",
|
||||
RemovedInDjango60Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
try:
|
||||
iter(x)
|
||||
except TypeError:
|
||||
|
|
|
@ -59,6 +59,9 @@ details on these changes.
|
|||
* The ``ModelAdmin.log_deletion()`` and ``LogEntryManager.log_action()``
|
||||
methods will be removed.
|
||||
|
||||
* The undocumented ``django.utils.itercompat.is_iterable()`` function and the
|
||||
``django.utils.itercompat`` module will be removed.
|
||||
|
||||
.. _deprecation-removed-in-5.1:
|
||||
|
||||
5.1
|
||||
|
|
|
@ -303,6 +303,10 @@ Miscellaneous
|
|||
``ModelAdmin.log_deletions()`` and ``LogEntryManager.log_actions()``
|
||||
instead.
|
||||
|
||||
* The undocumented ``django.utils.itercompat.is_iterable()`` function and the
|
||||
``django.utils.itercompat`` module are deprecated. Use
|
||||
``isinstance(..., collections.abc.Iterable)`` instead.
|
||||
|
||||
Features removed in 5.1
|
||||
=======================
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# RemovedInDjango60Warning: Remove this entire module.
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango60Warning
|
||||
from django.utils.itercompat import is_iterable
|
||||
|
||||
|
||||
class TestIterCompat(SimpleTestCase):
|
||||
def test_is_iterable_deprecation(self):
|
||||
msg = (
|
||||
"django.utils.itercompat.is_iterable() is deprecated. "
|
||||
"Use isinstance(..., collections.abc.Iterable) instead."
|
||||
)
|
||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
|
||||
is_iterable([])
|
Loading…
Reference in New Issue