Removing and renaming Django's Python 2 related helpers

262 views
Skip to first unread message

Tim Graham

unread,
Jan 21, 2017, 3:55:51 PM1/21/17
to Django developers (Contributions to Django itself)
As we worked on removing Python 2 compatibility code from master this week [0], we collected a number of import shims and functions that are only needed for code that wants to support Python 2 [1].

So far there is django.utils.six, as well as some undocumented things:
  • django.utils.lru_cache
  • django.utils._os.abspathu, upath, npath
  • django.utils.decorators.available_attrs
  • django.utils.encoding.python_2_unicode_compatible
I'm advocating to remove the undocumented things in Django 3.0 (released Dec. 2019) or later without a deprecation. By that time, I hope third-party apps won't support Python 2 either and so part of adding Django 3.0 compatibility will include formally dropping support for Python 2 (if not done already) and removing usage of this stuff (a fairly easy find/replace, hopefully).

Others have advocated to deprecate all these things, but I don't see much advantage. If I were maintaining an app, I'd rather be able to use import shims without warnings until Python 2 is gone. What's your preference?

A similar concern applies to django.utils.http's urlquote() and urlquote_plus() (documented) and urlunquote() and urlunquote_plus() (undocumented). Claude has a PR that deprecates them [4] which I think is fine considering they are half documented.

A related issue is the naming of the force_text() / force_str() and smart_text() / smart_str() functions. Aymeric proposed a PR to change all force_text() usage in Django to force_str() (they function identically on Python 3) [2], however, I feel this might create some confusion. For example, when backporting to 1.11 and earlier, we'll have to change force_str() to force_text() for Python 2 compatibility. Third-party apps might also be confused on which function to use. Claude proposed a similar that changes ugettext() and ungettext() to gettext() / ngettext() [3]. Would it be less confusing to consider these changes when Python 2 is no longer supported by any version of Django?

[0] https://code.djangoproject.com/ticket/23919
[1] https://code.djangoproject.com/ticket/27753
[2] https://github.com/django/django/pull/7913
[3] https://github.com/django/django/pull/7916

Shai Berger

unread,
Jan 21, 2017, 4:41:59 PM1/21/17
to django-d...@googlegroups.com
On Saturday 21 January 2017 22:55:51 Tim Graham wrote:
>
> I'm advocating to remove the undocumented things in Django 3.0 (released
> Dec. 2019) or later without a deprecation. By that time, I hope third-party
> apps won't support Python 2 either and so part of adding Django 3.0
> compatibility will include formally dropping support for Python 2 (if not
> done already) and removing usage of this stuff (a fairly easy find/replace,
> hopefully).
>
> Others have advocated to deprecate all these things, but I don't see much
> advantage. If I were maintaining an app, I'd rather be able to use import
> shims without warnings until Python 2 is gone. What's your preference?
>

I think that in order to help 3rd-party apps manage the move towards dropping
Python 2 support, we should decouple the deprecation of Py2 shims from other
Django deprecations. So, I'm thinking we should have a new warning class,
something like "Python2DeprecationWarning"; this would be easy enough to
silence for people who want to keep using them -- we could even provide a
context-manager based on warnings.catch_warnings() that would specifically
silence this warning, so 3rd-parties could silence it on their own uses
easily.

That's eating the warnings cake while keeping it whole, as far as I can see.

Shai.

Tim Graham

unread,
Jan 21, 2017, 5:51:41 PM1/21/17
to Django developers (Contributions to Django itself)
Considering the things mentioned so far are zero maintenance effort for Django (the only downside I see is 30kB for the bundled six), I'd rather keep the shims until 2025 rather than spend any time on a more complex solution. These removals are all very straight forward find/replaces, so I don't think warnings provide much benefit in identifying them. Even if you want to check your third-party apps, you can grep your virtual environment directory. My 2 cents, but I'm an enthusiast and less interested users may find warnings useful, I suppose.

Adam Johnson

unread,
Jan 22, 2017, 11:08:33 AM1/22/17
to django-d...@googlegroups.com
I don't think a deprecation warning is necessary for removing the vendored libraries. The main things that are used are django.utils.six and django.utils.lru_cache which are both easily available separately on PyPI for Python 2/3 compatibility anyway. The warning would probably just make libraries move to the PyPI versions whilst they still support Python 2.

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscribe@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/b941c792-57c7-4913-82f3-68a2ce357390%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Adam

Aymeric Augustin

unread,
Jan 24, 2017, 6:53:01 AM1/24/17
to django-d...@googlegroups.com
Hello,

Django is earning a lot of goodwill from its well-defined deprecation policy. It was recently improved to allow pluggable apps to work without import shims and without deprecation warnings from one LTS to the next. I don’t know the exact details but I believe that's the intent.

Combined with a thorough documentation of backwards-incompatible changes, it helps many developers put up with changes, even those they don’t understand, disagree with, or require significant work to adapt applications.

For this reason, in the context of the transition from Python 2 to Python 3, which is very backwards incompatible for people who haven’t been able to anticipate it, I’m in favor of a generous application of the deprecation policy.

I’m +1 on deprecating rather than removing utilities that were mentioned in the documentation, notably python_2_unicode_compatible, which was a public API until it got merged into six and we started using six’ version.

I’m +0 on deprecating rather than removing modules that a developer of a pluggable app would reasonably use for Python 2 compatibility, such as django.utils.lru_cache or django.utils.six.

I’d just remove less visible functions such as django.utils._os.abspathu, provided they clearly fall in the “private API” bucket.

Best regards,

-- 
Aymeric.



--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.

Sam Willis

unread,
Jan 24, 2017, 6:21:53 PM1/24/17
to Django developers (Contributions to Django itself)
Hi,

An alternative option with 'six' is to replace it with an alias of six propper (not vendored), something like this:

# django/utils/six.py
try:
   
from six import *
except ImportError:
   
raise ImportError((
           
"`django.utils.six` is deprecated, install six from pypi "
           
"(https://pypi.python.org/pypi/six) instead. After installing it will be available at "
           
"`django.utils.six` until Django V2.xx."))
except:
   
import warnings
    warnings
.warn((
           
"The `django.utils.six` alias is deprecated and will be removed in Django V2.xx.",
           
DeprecationWarning, 2
       
)

That way it removes the need for it to be maintained in core but ensures that other Django apps that are supporting py2 and 3 don't break.

Sam

Tim Graham

unread,
Jan 25, 2017, 10:11:58 AM1/25/17
to Django developers (Contributions to Django itself)
If we go the deprecation route, when do you want to start those deprecations? If deprecation start in Django 2.0, the removal happens in Django 3.0 (December 2019). Do you think third-party apps will drop support for Python 2 by then?

For removal at a later date, the deprecations could start:
- in Django 2.2 for removal in Django 3.1 (August 2020)
- in Django 3.0 for removal in Django 4.0 (Dec. 2021)

(Sam, I don't see much advantage to your proposal about six, considering it's not adding any burden to Django.)

Aymeric Augustin

unread,
Jan 25, 2017, 10:30:40 AM1/25/17
to django-d...@googlegroups.com
Hello Tim,

On 25 Jan 2017, at 16:11, Tim Graham <timog...@gmail.com> wrote:

- in Django 2.2 for removal in Django 3.1 (August 2020) 
- in Django 3.0 for removal in Django 4.0 (Dec. 2021)

Either option seems fine to me.

Are there advantages to starting the deprecation in a LTS (2.2) vs. in the release that follows a LTS (3.0)?

-- 
Aymeric.



Tim Graham

unread,
Jan 25, 2017, 2:34:11 PM1/25/17
to Django developers (Contributions to Django itself)
A difference is that a deprecation starting in 2.2 is in 2 releases (2.2, 2.3) while the deprecation starting in 3.0 is in 3 releases (3.0, 3.1, 3.2).

Collin Anderson

unread,
Jan 30, 2017, 10:23:49 AM1/30/17
to django-d...@googlegroups.com
Hi All,

django.utils.six _is_ documented, so I think it should go through the normal deprecation timeline.


Seems fine to me to start the deprecation in 2.0, but I'm sure people would appreciate starting the timeline later.

Collin


--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscribe@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages