app/django/utils/maxlength.py
author Todd Larsen <tlarsen@google.com>
Sat, 04 Oct 2008 07:14:11 +0000
changeset 281 7caa8951cbc9
parent 54 03e267d67478
permissions -rw-r--r--
Url and Page classes used to encapsulate the "site map" information (URL regular expressions, Django views, menu item names, etc.) and the relation between pages in the site map. There are still lots of TODOs in this first pass. Patch by: Todd Larsen Review by: to-be-reviewed

"""
Utilities for providing backwards compatibility for the maxlength argument,
which has been replaced by max_length. See ticket #2101.
"""

from warnings import warn

def get_maxlength(self):
    return self.max_length

def set_maxlength(self, value):
    self.max_length = value

def legacy_maxlength(max_length, maxlength):
    """
    Consolidates max_length and maxlength, providing backwards compatibilty
    for the legacy "maxlength" argument.

    If one of max_length or maxlength is given, then that value is returned.
    If both are given, a TypeError is raised. If maxlength is used at all, a
    deprecation warning is issued.
    """
    if maxlength is not None:
        warn("maxlength is deprecated. Use max_length instead.", DeprecationWarning, stacklevel=3)
        if max_length is not None:
            raise TypeError("Field cannot take both the max_length argument and the legacy maxlength argument.")
        max_length = maxlength
    return max_length

def remove_maxlength(func):
    """
    A decorator to be used on a class's __init__ that provides backwards
    compatibilty for the legacy "maxlength" keyword argument, i.e.
        name = models.CharField(maxlength=20)

    It does this by changing the passed "maxlength" keyword argument
    (if it exists) into a "max_length" keyword argument.
    """
    def inner(self, *args, **kwargs):
        max_length = kwargs.get('max_length', None)
        # pop maxlength because we don't want this going to __init__.
        maxlength = kwargs.pop('maxlength', None)
        max_length = legacy_maxlength(max_length, maxlength)
        # Only set the max_length keyword argument if we got a value back.
        if max_length is not None:
            kwargs['max_length'] = max_length
        func(self, *args, **kwargs)
    return inner

# This metaclass is used in two places, and should be removed when legacy
# support for maxlength is dropped.
#   * oldforms.FormField
#   * db.models.fields.Field

class LegacyMaxlength(type):
    """
    Metaclass for providing backwards compatibility support for the
    "maxlength" keyword argument.
    """
    def __init__(cls, name, bases, attrs):
        super(LegacyMaxlength, cls).__init__(name, bases, attrs)
        # Decorate the class's __init__ to remove any maxlength keyword.
        cls.__init__ = remove_maxlength(cls.__init__)
        # Support accessing and setting to the legacy maxlength attribute.
        cls.maxlength = property(get_maxlength, set_maxlength)