Fixed #23891 -- Moved deprecation of IPAddressField to system check framework.

Thanks Markus Holtermann for review.
This commit is contained in:
Tim Graham 2014-12-30 15:45:03 -05:00
parent a7aaabfaf1
commit 40a8504357
11 changed files with 51 additions and 30 deletions

View File

@ -334,6 +334,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
command.execute( command.execute(
stdin=sentinel, stdin=sentinel,
stdout=six.StringIO(), stdout=six.StringIO(),
stderr=six.StringIO(),
interactive=False, interactive=False,
verbosity=0, verbosity=0,
username='janet', username='janet',
@ -344,6 +345,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
command = createsuperuser.Command() command = createsuperuser.Command()
command.execute( command.execute(
stdout=six.StringIO(), stdout=six.StringIO(),
stderr=six.StringIO(),
interactive=False, interactive=False,
verbosity=0, verbosity=0,
username='joe', username='joe',

View File

@ -20,7 +20,6 @@ from django import forms
from django.core import exceptions, validators, checks from django.core import exceptions, validators, checks
from django.utils.datastructures import DictWrapper from django.utils.datastructures import DictWrapper
from django.utils.dateparse import parse_date, parse_datetime, parse_time, parse_duration from django.utils.dateparse import parse_date, parse_datetime, parse_time, parse_duration
from django.utils.deprecation import RemovedInDjango19Warning
from django.utils.duration import duration_string from django.utils.duration import duration_string
from django.utils.functional import cached_property, curry, total_ordering, Promise from django.utils.functional import cached_property, curry, total_ordering, Promise
from django.utils.text import capfirst from django.utils.text import capfirst
@ -1836,8 +1835,6 @@ class IPAddressField(Field):
description = _("IPv4 address") description = _("IPv4 address")
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
warnings.warn("IPAddressField has been deprecated. Use GenericIPAddressField instead.",
RemovedInDjango19Warning)
kwargs['max_length'] = 15 kwargs['max_length'] = 15
super(IPAddressField, self).__init__(*args, **kwargs) super(IPAddressField, self).__init__(*args, **kwargs)
@ -1860,6 +1857,19 @@ class IPAddressField(Field):
defaults.update(kwargs) defaults.update(kwargs)
return super(IPAddressField, self).formfield(**defaults) return super(IPAddressField, self).formfield(**defaults)
def check(self, **kwargs):
errors = super(IPAddressField, self).check(**kwargs)
errors.append(
checks.Warning(
'IPAddressField has been deprecated. Support for it '
'(except in historical migrations) will be removed in Django 1.9.',
hint='Use GenericIPAddressField instead.',
obj=self,
id='fields.W900',
)
)
return errors
class GenericIPAddressField(Field): class GenericIPAddressField(Field):
empty_strings_allowed = True empty_strings_allowed = True

View File

@ -159,7 +159,8 @@ details on these changes.
is loaded. In particular, it won't be possible to import models inside is loaded. In particular, it won't be possible to import models inside
the root package of their application. the root package of their application.
* The model and form ``IPAddressField`` will be removed. * The model and form ``IPAddressField`` will be removed. A stub field will
remain for compatibility with historical migrations.
* ``AppCommand.handle_app()`` will no longer be supported. * ``AppCommand.handle_app()`` will no longer be supported.

View File

@ -95,6 +95,8 @@ Fields
* **fields.E160**: The options ``auto_now``, ``auto_now_add``, and ``default`` * **fields.E160**: The options ``auto_now``, ``auto_now_add``, and ``default``
are mutually exclusive. Only one of these options may be present. are mutually exclusive. Only one of these options may be present.
* **fields.W161**: Fixed default value provided. * **fields.W161**: Fixed default value provided.
* **fields.W900**: ``IPAddressField`` has been deprecated. Support for it
(except in historical migrations) will be removed in Django 1.9.
File Fields File Fields
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@ -192,3 +192,8 @@ Bugfixes
* Prevented a crash on apps without migrations when running ``migrate --list`` * Prevented a crash on apps without migrations when running ``migrate --list``
(:ticket:`23366`). (:ticket:`23366`).
* The deprecation of ``IPAddressField`` is now handled through the system
check framework (with error code ``fields.W900``) so that deprecation
warnings aren't displayed if the field only appears in historical migrations
(:ticket:`23891`).

View File

@ -9,7 +9,8 @@ from django.forms import (
ModelMultipleChoiceField, MultipleChoiceField, RegexField, ModelMultipleChoiceField, MultipleChoiceField, RegexField,
SplitDateTimeField, TimeField, URLField, utils, ValidationError, SplitDateTimeField, TimeField, URLField, utils, ValidationError,
) )
from django.test import TestCase from django.test import ignore_warnings, TestCase
from django.utils.deprecation import RemovedInDjango19Warning
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
@ -196,6 +197,7 @@ class FormsErrorMessagesTestCase(TestCase, AssertFormErrorsMixin):
self.assertFormErrors(['REQUIRED'], f.clean, '') self.assertFormErrors(['REQUIRED'], f.clean, '')
self.assertFormErrors(['INVALID DATE', 'INVALID TIME'], f.clean, ['a', 'b']) self.assertFormErrors(['INVALID DATE', 'INVALID TIME'], f.clean, ['a', 'b'])
@ignore_warnings(category=RemovedInDjango19Warning)
def test_ipaddressfield(self): def test_ipaddressfield(self):
e = { e = {
'required': 'REQUIRED', 'required': 'REQUIRED',

View File

@ -11,10 +11,11 @@ from django.forms import (
) )
from django.forms.extras import SelectDateWidget from django.forms.extras import SelectDateWidget
from django.forms.utils import ErrorList from django.forms.utils import ErrorList
from django.test import TestCase, override_settings from django.test import TestCase, ignore_warnings, override_settings
from django.utils import six from django.utils import six
from django.utils import translation from django.utils import translation
from django.utils.dates import MONTHS_AP from django.utils.dates import MONTHS_AP
from django.utils.deprecation import RemovedInDjango19Warning
from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
from .test_error_messages import AssertFormErrorsMixin from .test_error_messages import AssertFormErrorsMixin
@ -482,6 +483,7 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
self.assertEqual(f.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00') self.assertEqual(f.cleaned_data['field1'], 'some text,JP,2007-04-25 06:24:00')
@ignore_warnings(category=RemovedInDjango19Warning)
def test_ipaddress(self): def test_ipaddress(self):
f = IPAddressField() f = IPAddressField()
self.assertFormErrors(['This field is required.'], f.clean, '') self.assertFormErrors(['This field is required.'], f.clean, '')

View File

@ -1,10 +1,7 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from __future__ import unicode_literals from __future__ import unicode_literals
import warnings
from django.db import models from django.db import models
from django.utils.deprecation import RemovedInDjango19Warning
class People(models.Model): class People(models.Model):
@ -62,9 +59,7 @@ class ColumnTypes(models.Model):
file_path_field = models.FilePathField() file_path_field = models.FilePathField()
float_field = models.FloatField() float_field = models.FloatField()
int_field = models.IntegerField() int_field = models.IntegerField()
with warnings.catch_warnings(): ip_address_field = models.IPAddressField()
warnings.simplefilter("ignore", category=RemovedInDjango19Warning)
ip_address_field = models.IPAddressField()
gen_ip_adress_field = models.GenericIPAddressField(protocol="ipv4") gen_ip_adress_field = models.GenericIPAddressField(protocol="ipv4")
pos_int_field = models.PositiveIntegerField() pos_int_field = models.PositiveIntegerField()
pos_small_int_field = models.PositiveSmallIntegerField() pos_small_int_field = models.PositiveSmallIntegerField()

View File

@ -20,7 +20,6 @@ from django.db.models.fields import (
from django.db.models.fields.files import FileField, ImageField from django.db.models.fields.files import FileField, ImageField
from django.utils import six from django.utils import six
from django.utils.functional import lazy from django.utils.functional import lazy
from django.test.utils import override_settings
from .models import ( from .models import (
Foo, Bar, Whiz, BigD, BigS, BigIntegerModel, Post, NullBooleanModel, Foo, Bar, Whiz, BigD, BigS, BigIntegerModel, Post, NullBooleanModel,
@ -182,11 +181,11 @@ class ForeignKeyTests(test.TestCase):
fk_model_empty = FkToChar.objects.select_related('out').get(id=fk_model_empty.pk) fk_model_empty = FkToChar.objects.select_related('out').get(id=fk_model_empty.pk)
self.assertEqual(fk_model_empty.out, char_model_empty) self.assertEqual(fk_model_empty.out, char_model_empty)
@override_settings(INSTALLED_APPS=['django.contrib.auth', 'django.contrib.contenttypes', 'model_fields'])
def test_warning_when_unique_true_on_fk(self): def test_warning_when_unique_true_on_fk(self):
class FKUniqueTrue(models.Model): class FKUniqueTrue(models.Model):
fk_field = models.ForeignKey(Foo, unique=True) fk_field = models.ForeignKey(Foo, unique=True)
model = FKUniqueTrue()
expected_warnings = [ expected_warnings = [
checks.Warning( checks.Warning(
'Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.', 'Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.',
@ -195,7 +194,7 @@ class ForeignKeyTests(test.TestCase):
id='fields.W342', id='fields.W342',
) )
] ]
warnings = checks.run_checks() warnings = model.check()
self.assertEqual(warnings, expected_warnings) self.assertEqual(warnings, expected_warnings)
def test_related_name_converted_to_text(self): def test_related_name_converted_to_text(self):
@ -799,7 +798,6 @@ class PromiseTest(test.TestCase):
int) int)
def test_IPAddressField(self): def test_IPAddressField(self):
# Deprecation silenced in runtests.py
lazy_func = lazy(lambda: '127.0.0.1', six.text_type) lazy_func = lazy(lambda: '127.0.0.1', six.text_type)
self.assertIsInstance( self.assertIsInstance(
IPAddressField().get_prep_value(lazy_func()), IPAddressField().get_prep_value(lazy_func()),
@ -809,6 +807,22 @@ class PromiseTest(test.TestCase):
IPAddressField().get_prep_value(lazy_func()), IPAddressField().get_prep_value(lazy_func()),
six.text_type) six.text_type)
def test_IPAddressField_deprecated(self):
class IPAddressModel(models.Model):
ip = IPAddressField()
model = IPAddressModel()
self.assertEqual(
model.check(),
[checks.Warning(
'IPAddressField has been deprecated. Support for it '
'(except in historical migrations) will be removed in Django 1.9.',
hint='Use GenericIPAddressField instead.',
obj=IPAddressModel._meta.get_field('ip'),
id='fields.W900',
)],
)
def test_GenericIPAddressField(self): def test_GenericIPAddressField(self):
lazy_func = lazy(lambda: '127.0.0.1', six.text_type) lazy_func = lazy(lambda: '127.0.0.1', six.text_type)
self.assertIsInstance( self.assertIsInstance(

View File

@ -246,11 +246,6 @@ def django_tests(verbosity, interactive, failfast, keepdb, reverse, test_labels)
'initial_data fixtures are deprecated. Use data migrations instead.', 'initial_data fixtures are deprecated. Use data migrations instead.',
RemovedInDjango19Warning RemovedInDjango19Warning
) )
warnings.filterwarnings(
'ignore',
'IPAddressField has been deprecated. Use GenericIPAddressField instead.',
RemovedInDjango19Warning
)
failures = test_runner.run_tests( failures = test_runner.run_tests(
test_labels or get_installed(), extra_tests=extra_tests) test_labels or get_installed(), extra_tests=extra_tests)

View File

@ -4,14 +4,11 @@ A test spanning all the capabilities of all the serializers.
This class sets up a model for each model field type This class sets up a model for each model field type
(except for image types, because of the Pillow dependency). (except for image types, because of the Pillow dependency).
""" """
import warnings
from django.db import models from django.db import models
from django.contrib.contenttypes.fields import ( from django.contrib.contenttypes.fields import (
GenericForeignKey, GenericRelation GenericForeignKey, GenericRelation
) )
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils.deprecation import RemovedInDjango19Warning
# The following classes are for testing basic data # The following classes are for testing basic data
# marshalling, including NULL values, where allowed. # marshalling, including NULL values, where allowed.
@ -69,9 +66,7 @@ class BigIntegerData(models.Model):
class IPAddressData(models.Model): class IPAddressData(models.Model):
with warnings.catch_warnings(): data = models.IPAddressField(null=True)
warnings.simplefilter("ignore", category=RemovedInDjango19Warning)
data = models.IPAddressField(null=True)
class GenericIPAddressData(models.Model): class GenericIPAddressData(models.Model):
@ -251,9 +246,7 @@ class IntegerPKData(models.Model):
class IPAddressPKData(models.Model): class IPAddressPKData(models.Model):
with warnings.catch_warnings(record=True) as w: data = models.IPAddressField(primary_key=True)
warnings.simplefilter("always")
data = models.IPAddressField(primary_key=True)
class GenericIPAddressPKData(models.Model): class GenericIPAddressPKData(models.Model):