Skip to content

Commit

Permalink
Refs #23919 -- Removed misc references to Python 2.
Browse files Browse the repository at this point in the history
  • Loading branch information
timgraham committed Jan 22, 2017
1 parent c222122 commit d170c63
Show file tree
Hide file tree
Showing 34 changed files with 40 additions and 167 deletions.
9 changes: 1 addition & 8 deletions INSTALL
@@ -1,17 +1,10 @@
Thanks for downloading Django.

To install it, make sure you have Python 2.7 or greater installed. Then run
To install it, make sure you have Python 3.4 or greater installed. Then run
this command from the command prompt:

python setup.py install

If you're upgrading from a previous version, you need to remove it first.

AS AN ALTERNATIVE, you can just copy the entire "django" directory to Python's
site-packages directory, which is located wherever your Python installation
lives. Some places you might check are:

/usr/lib/python2.7/site-packages (Unix, Python 2.7)
C:\\PYTHON\site-packages (Windows)

For more detailed instructions, see docs/intro/install.txt.
7 changes: 3 additions & 4 deletions django/apps/config.py
Expand Up @@ -17,7 +17,7 @@ def __init__(self, app_name, app_module):
self.name = app_name

# Root module for the application eg. <module 'django.contrib.admin'
# from 'django/contrib/admin/__init__.pyc'>.
# from 'django/contrib/admin/__init__.py'>.
self.module = app_module

# Reference to the Apps registry that holds this AppConfig. Set by the
Expand All @@ -37,13 +37,12 @@ def __init__(self, app_name, app_module):
self.verbose_name = self.label.title()

# Filesystem path to the application directory eg.
# u'/usr/lib/python2.7/dist-packages/django/contrib/admin'. Unicode on
# Python 2 and a str on Python 3.
# '/path/to/django/contrib/admin'.
if not hasattr(self, 'path'):
self.path = self._path_from_module(app_module)

# Module containing models eg. <module 'django.contrib.admin.models'
# from 'django/contrib/admin/models.pyc'>. Set by import_models().
# from 'django/contrib/admin/models.py'>. Set by import_models().
# None if the application doesn't have a models module.
self.models_module = None

Expand Down
19 changes: 6 additions & 13 deletions django/conf/project_template/manage.py-tpl
Expand Up @@ -6,17 +6,10 @@ if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
9 changes: 0 additions & 9 deletions django/contrib/gis/measure.py
Expand Up @@ -159,19 +159,13 @@ def __truediv__(self, other):
else:
raise TypeError('%(class)s must be divided with number or %(class)s' % {"class": pretty_name(self)})

def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)

def __itruediv__(self, other):
if isinstance(other, NUMERIC_TYPES):
self.standard /= float(other)
return self
else:
raise TypeError('%(class)s must be divided with number' % {"class": pretty_name(self)})

def __idiv__(self, other): # Python 2 compatibility
return type(self).__itruediv__(self, other)

def __bool__(self):
return bool(self.standard)

Expand Down Expand Up @@ -333,9 +327,6 @@ def __truediv__(self, other):
else:
raise TypeError('%(class)s must be divided by a number' % {"class": pretty_name(self)})

def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)


# Shortcuts
D = Distance
Expand Down
2 changes: 1 addition & 1 deletion django/core/checks/model_checks.py
Expand Up @@ -64,7 +64,7 @@ def extract_operation(obj):
operation, args, keywords = obj, [], {}
while hasattr(operation, 'func'):
# The or clauses are redundant but work around a bug (#25945) in
# functools.partial in Python 3 <= 3.5.1 and Python 2 <= 2.7.11.
# functools.partial in Python <= 3.5.1.
args.extend(getattr(operation, 'args', []) or [])
keywords.update(getattr(operation, 'keywords', {}) or {})
operation = operation.func
Expand Down
11 changes: 5 additions & 6 deletions django/core/files/temp.py
Expand Up @@ -9,8 +9,8 @@
more general issue of opening a file for writing and reading in multiple
processes in a manner that works across platforms.
Also note that the custom version of NamedTemporaryFile does not support the
full range of keyword arguments available in Python 2.6+ and 3.0+.
The custom version of NamedTemporaryFile doesn't support the same keyword
arguments available in tempfile.NamedTemporaryFile.
1: https://mail.python.org/pipermail/python-list/2005-December/336957.html
2: http://bugs.python.org/issue14243
Expand All @@ -30,10 +30,9 @@ class TemporaryFile(FileProxyMixin):
Temporary file object constructor that supports reopening of the
temporary file in Windows.
Note that unlike tempfile.NamedTemporaryFile from the standard library,
__init__() does not support the 'delete' keyword argument in
Python 2.6+, or the 'delete', 'buffering', 'encoding', or 'newline'
keyword arguments in Python 3.0+.
Unlike tempfile.NamedTemporaryFile from the standard library,
__init__() doesn't support the 'delete', 'buffering', 'encoding', or
'newline' keyword arguments.
"""
def __init__(self, mode='w+b', bufsize=-1, suffix='', prefix='', dir=None):
fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
Expand Down
1 change: 0 additions & 1 deletion django/core/servers/basehttp.py
Expand Up @@ -83,7 +83,6 @@ def handle_error(self, request, client_address):
super(WSGIServer, self).handle_error(request, client_address)


# Inheriting from object required on Python 2.
class ServerHandler(simple_server.ServerHandler):
def handle_error(self):
# Ignore broken pipe errors, otherwise pass on
Expand Down
1 change: 0 additions & 1 deletion django/db/backends/mysql/base.py
Expand Up @@ -2,7 +2,6 @@
MySQL database backend for Django.
Requires mysqlclient: https://pypi.python.org/pypi/mysqlclient/
MySQLdb is supported for Python 2 only: http://sourceforge.net/projects/mysql-python
"""
import re
import sys
Expand Down
2 changes: 1 addition & 1 deletion django/db/backends/oracle/introspection.py
Expand Up @@ -81,7 +81,7 @@ def get_table_description(self, cursor, table_name):
self.cache_bust_counter))
description = []
for desc in cursor.description:
name = force_text(desc[0]) # cx_Oracle always returns a 'str' on both Python 2 and 3
name = force_text(desc[0]) # cx_Oracle always returns a 'str'
internal_size, default = field_map[name]
name = name % {} # cx_Oracle, for some reason, doubles percent signs.
description.append(FieldInfo(*(name.lower(),) + desc[1:3] + (internal_size,) + desc[4:] + (default,)))
Expand Down
16 changes: 3 additions & 13 deletions django/db/migrations/serializer.py
Expand Up @@ -160,24 +160,14 @@ def serialize(self):
if "<" not in self.value.__qualname__: # Qualname can include <locals>
return "%s.%s" % \
(self.value.__module__, self.value.__qualname__), {"import %s" % self.value.__module__}
# Python 2/fallback version
# Fallback version
module_name = self.value.__module__
# Make sure it's actually there and not an unbound method
# Make sure it's actually there
module = import_module(module_name)
if not hasattr(module, self.value.__name__):
raise ValueError(
"Could not find function %s in %s.\n"
"Please note that due to Python 2 limitations, you cannot "
"serialize unbound method functions (e.g. a method "
"declared and used in the same class body). Please move "
"the function into the main module body to use migrations.\n"
"For more information, see "
"https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values"
% (self.value.__name__, module_name, get_docs_version())
"Could not find function %s in %s.\n" % (self.value.__name__, module_name)
)
# Needed on Python 2 only
if module_name == '__builtin__':
return self.value.__name__, set()
return "%s.%s" % (module_name, self.value.__name__), {"import %s" % module_name}


Expand Down
6 changes: 0 additions & 6 deletions django/db/models/expressions.py
Expand Up @@ -60,9 +60,6 @@ def __mul__(self, other):
def __truediv__(self, other):
return self._combine(other, self.DIV, False)

def __div__(self, other): # Python 2 compatibility
return type(self).__truediv__(self, other)

def __mod__(self, other):
return self._combine(other, self.MOD, False)

Expand Down Expand Up @@ -103,9 +100,6 @@ def __rmul__(self, other):
def __rtruediv__(self, other):
return self._combine(other, self.DIV, True)

def __rdiv__(self, other): # Python 2 compatibility
return type(self).__rtruediv__(self, other)

def __rmod__(self, other):
return self._combine(other, self.MOD, True)

Expand Down
5 changes: 1 addition & 4 deletions django/db/models/query_utils.py
Expand Up @@ -27,11 +27,8 @@ class InvalidQuery(Exception):

def subclasses(cls):
yield cls
# Python 2 lacks 'yield from', which could replace the inner loop
for subclass in cls.__subclasses__():
# yield from subclasses(subclass)
for item in subclasses(subclass):
yield item
yield from subclasses(subclass)


class QueryWrapper:
Expand Down
10 changes: 2 additions & 8 deletions django/db/models/sql/compiler.py
Expand Up @@ -875,14 +875,8 @@ def execute_sql(self, result_type=MULTI, chunked_fetch=False):
try:
cursor.execute(sql, params)
except Exception:
try:
# Might fail for server-side cursors (e.g. connection closed)
cursor.close()
except Exception:
# Ignore clean up errors and raise the original error instead.
# Python 2 doesn't chain exceptions. Remove this error
# silencing when dropping Python 2 compatibility.
pass
# Might fail for server-side cursors (e.g. connection closed)
cursor.close()
raise

if result_type == CURSOR:
Expand Down
6 changes: 1 addition & 5 deletions django/forms/utils.py
@@ -1,5 +1,6 @@
import json
import sys
from collections import UserList

from django.conf import settings
from django.core.exceptions import ValidationError # backwards compatibility
Expand All @@ -8,11 +9,6 @@
from django.utils.html import escape, format_html, format_html_join, html_safe
from django.utils.translation import ugettext_lazy as _

try:
from collections import UserList
except ImportError: # Python 2
from UserList import UserList


def pretty_name(name):
"""Converts 'first_name' to 'First name'"""
Expand Down
2 changes: 1 addition & 1 deletion django/test/utils.py
Expand Up @@ -310,7 +310,7 @@ def get_runner(settings, test_runner_class=None):
test_runner_class = settings.TEST_RUNNER

test_path = test_runner_class.split('.')
# Allow for Python 2.5 relative paths
# Allow for relative paths
if len(test_path) > 1:
test_module_name = '.'.join(test_path[:-1])
else:
Expand Down
2 changes: 1 addition & 1 deletion django/utils/deconstruct.py
Expand Up @@ -24,7 +24,7 @@ def deconstruct(obj):
Returns a 3-tuple of class import path, positional arguments,
and keyword arguments.
"""
# Python 2/fallback version
# Fallback version
if path:
module_name, _, name = path.rpartition('.')
else:
Expand Down
4 changes: 1 addition & 3 deletions django/utils/html.py
Expand Up @@ -172,9 +172,7 @@ def strip_tags(value):
while '<' in value and '>' in value:
new_value = _strip_once(value)
if len(new_value) >= len(value):
# _strip_once was not able to detect more tags or length increased
# due to http://bugs.python.org/issue20288
# (affects Python 2 < 2.7.7 and Python 3 < 3.3.5)
# _strip_once was not able to detect more tags
break
value = new_value
return value
Expand Down
4 changes: 1 addition & 3 deletions django/utils/html_parser.py
Expand Up @@ -11,9 +11,7 @@ class HTMLParseError(Exception):
class HTMLParser(html.parser.HTMLParser):
"""Explicitly set convert_charrefs to be False.
This silences a deprecation warning on Python 3.4, but we can't do
it at call time because Python 2.7 does not have the keyword
argument.
This silences a deprecation warning on Python 3.4.
"""
def __init__(self, convert_charrefs=False, **kwargs):
html.parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs)
9 changes: 1 addition & 8 deletions django/utils/translation/trans_real.py
Expand Up @@ -101,7 +101,6 @@ def __init__(self, language, domain=None, localedirs=None):
gettext_module.GNUTranslations.__init__(self)
if domain is not None:
self.domain = domain
self.set_output_charset('utf-8') # For Python 2 gettext() (#25720)

self.__language = language
self.__to_language = to_language(language)
Expand Down Expand Up @@ -326,11 +325,7 @@ def do_translate(message, translation_function):


def gettext(message):
"""
Returns a string of the translation of the message.
Returns a string on Python 3 and an UTF-8-encoded bytestring on Python 2.
"""
"""Return a string of the translation of the message."""
return do_translate(message, 'gettext')


Expand Down Expand Up @@ -372,8 +367,6 @@ def ngettext(singular, plural, number):
"""
Returns a string of the translation of either the singular or plural,
based on the number.
Returns a string on Python 3 and an UTF-8-encoded bytestring on Python 2.
"""
return do_ntranslate(singular, plural, number, 'ngettext')

Expand Down
4 changes: 2 additions & 2 deletions docs/ref/applications.txt
Expand Up @@ -206,12 +206,12 @@ Read-only attributes
.. attribute:: AppConfig.module

Root module for the application, e.g. ``<module 'django.contrib.admin' from
'django/contrib/admin/__init__.pyc'>``.
'django/contrib/admin/__init__.py'>``.

.. attribute:: AppConfig.models_module

Module containing the models, e.g. ``<module 'django.contrib.admin.models'
from 'django/contrib/admin/models.pyc'>``.
from 'django/contrib/admin/models.py'>``.

It may be ``None`` if the application doesn't contain a ``models`` module.
Note that the database related signals such as
Expand Down
4 changes: 0 additions & 4 deletions tests/admin_changelist/tests.py
Expand Up @@ -568,10 +568,6 @@ def test_no_list_display_links(self):
self.assertNotContains(response, '<a href="%s">' % link)

def test_tuple_list_display(self):
"""
Regression test for #17128
(ChangeList failing under Python 2.5 after r16319)
"""
swallow = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2')
swallow2 = Swallow.objects.create(origin='Africa', load='12.34', speed='22.2')
swallow_o2o = SwallowOneToOne.objects.create(swallow=swallow2)
Expand Down
3 changes: 0 additions & 3 deletions tests/admin_scripts/tests.py
Expand Up @@ -101,9 +101,6 @@ def remove_settings(self, filename, is_dir=False):
if sys.platform.startswith('java'):
# Jython produces module$py.class files
os.remove(re.sub(r'\.py$', '$py.class', full_name))
else:
# CPython produces module.pyc files
os.remove(full_name + 'c')
except OSError:
pass
# Also remove a __pycache__ directory, if it exists
Expand Down
3 changes: 1 addition & 2 deletions tests/admin_views/admin.py
Expand Up @@ -971,8 +971,7 @@ def get_formsets_with_inlines(self, request, obj=None):
# related ForeignKey object not registered in admin
# related OneToOne object registered in admin
# related OneToOne object not registered in admin
# when deleting Book so as exercise all four troublesome (w.r.t escaping
# and calling force_text to avoid problems on Python 2.3) paths through
# when deleting Book so as exercise all four paths through
# contrib.admin.utils's get_deleted_objects function.
site.register(Book, inlines=[ChapterInline])
site.register(Promo)
Expand Down
16 changes: 1 addition & 15 deletions tests/auth_tests/test_context_processors.py
Expand Up @@ -130,21 +130,7 @@ def test_user_attrs(self):
# bug #12037 is tested by the {% url %} in the template:
self.assertContains(response, "url: /userpage/super/")

# See if this object can be used for queries where a Q() comparing
# a user can be used with another Q() (in an AND or OR fashion).
# This simulates what a template tag might do with the user from the
# context. Note that we don't need to execute a query, just build it.
#
# The failure case (bug #12049) on Python 2.4 with a LazyObject-wrapped
# User is a fatal TypeError: "function() takes at least 2 arguments
# (0 given)" deep inside deepcopy().
#
# Python 2.5 and 2.6 succeeded, but logged internally caught exception
# spew:
#
# Exception RuntimeError: 'maximum recursion depth exceeded while
# calling a Python object' in <type 'exceptions.AttributeError'>
# ignored"
# A Q() comparing a user and with another Q() (in an AND or OR fashion).
Q(user=response.context['user']) & Q(someflag=True)

# Tests for user equality. This is hard because User defines
Expand Down

0 comments on commit d170c63

Please sign in to comment.