From f6acd1d271122d66de8061e75ae26137ddf02658 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 18 Jan 2017 11:51:29 -0500 Subject: [PATCH] Refs #23919 -- Removed Python 2 notes in docs. --- docs/conf.py | 1 - docs/faq/install.txt | 13 +- docs/faq/troubleshooting.txt | 9 - docs/howto/custom-management-commands.txt | 4 - docs/howto/custom-model-fields.txt | 10 +- docs/howto/deployment/checklist.txt | 16 - docs/howto/outputting-csv.txt | 21 - docs/index.txt | 1 - .../contributing/writing-code/javascript.txt | 4 +- .../contributing/writing-code/unit-tests.txt | 16 +- docs/intro/contributing.txt | 6 +- docs/intro/overview.txt | 4 +- docs/intro/reusable-apps.txt | 4 +- docs/ref/applications.txt | 11 +- docs/ref/checks.txt | 6 +- docs/ref/contrib/admin/actions.txt | 2 +- docs/ref/contrib/admin/index.txt | 16 +- docs/ref/contrib/auth.txt | 11 +- docs/ref/contrib/contenttypes.txt | 2 +- docs/ref/contrib/gis/commands.txt | 4 +- docs/ref/contrib/gis/layermapping.txt | 2 +- docs/ref/contrib/gis/tutorial.txt | 2 +- docs/ref/contrib/postgres/fields.txt | 8 +- docs/ref/databases.txt | 53 +-- docs/ref/exceptions.txt | 6 +- docs/ref/files/file.txt | 3 +- docs/ref/forms/api.txt | 8 +- docs/ref/forms/fields.txt | 11 +- docs/ref/models/querysets.txt | 2 +- docs/ref/request-response.txt | 21 - docs/ref/templates/language.txt | 6 +- docs/ref/unicode.txt | 35 +- docs/ref/urlresolvers.txt | 2 +- docs/ref/utils.txt | 69 ++-- docs/releases/1.4.11.txt | 2 +- docs/releases/1.4.17.txt | 2 +- docs/releases/1.4.18.txt | 2 +- docs/releases/1.5.6.txt | 2 +- docs/releases/1.5.txt | 6 +- docs/releases/1.6.2.txt | 2 +- docs/releases/1.6.3.txt | 2 +- docs/releases/1.6.9.txt | 2 +- docs/releases/1.7.2.txt | 2 +- docs/releases/1.8.7.txt | 2 +- docs/topics/auth/customizing.txt | 2 +- docs/topics/cache.txt | 3 +- .../class-based-views/generic-display.txt | 4 +- docs/topics/db/examples/many_to_many.txt | 4 +- docs/topics/db/examples/many_to_one.txt | 11 +- docs/topics/db/examples/one_to_one.txt | 6 +- docs/topics/db/models.txt | 9 +- docs/topics/db/queries.txt | 6 +- docs/topics/forms/modelforms.txt | 2 +- docs/topics/i18n/translation.txt | 6 +- docs/topics/index.txt | 1 - docs/topics/install.txt | 4 +- docs/topics/migrations.txt | 20 +- docs/topics/pagination.txt | 2 +- docs/topics/python3.txt | 369 ------------------ docs/topics/testing/overview.txt | 6 +- docs/topics/testing/tools.txt | 2 +- 61 files changed, 139 insertions(+), 731 deletions(-) delete mode 100644 docs/topics/python3.txt diff --git a/docs/conf.py b/docs/conf.py index 2b42f44268..14877cd05d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -134,7 +134,6 @@ pygments_style = 'trac' intersphinx_mapping = { 'python': ('https://docs.python.org/3/', None), 'sphinx': ('http://sphinx-doc.org/', None), - 'six': ('https://pythonhosted.org/six/', None), 'psycopg2': ('http://initd.org/psycopg/docs/', None), } diff --git a/docs/faq/install.txt b/docs/faq/install.txt index ea27b11db8..622334348e 100644 --- a/docs/faq/install.txt +++ b/docs/faq/install.txt @@ -65,18 +65,11 @@ is the last version to support Python 3.3. What Python version should I use with Django? ============================================= -As of Django 1.6, Python 3 support is considered stable and you can safely use -it in production. See also :doc:`/topics/python3`. However, the community is -still in the process of migrating third-party packages and applications to -Python 3. - -If you're starting a new project, and the dependencies you plan to use work on -Python 3, you should use Python 3. If they don't, consider contributing to the -porting efforts, or stick to Python 2. +Python 3 is recommended. Django 1.11 is the last version to support Python 2.7. +Support for Python 2.7 and Django 1.11 ends in 2020. Since newer versions of Python are often faster, have more features, and are -better supported, all else being equal, we recommend that you use the latest -2.x.y or 3.x.y release. +better supported, the latest version of Python 3 is recommended. You don't lose anything in Django by using an older release, but you don't take advantage of the improvements and optimizations in newer Python releases. diff --git a/docs/faq/troubleshooting.txt b/docs/faq/troubleshooting.txt index 1b2efd552f..5a56c6daa3 100644 --- a/docs/faq/troubleshooting.txt +++ b/docs/faq/troubleshooting.txt @@ -55,15 +55,6 @@ pitfalls producing this error: case, please refer to your system documentation to learn how you can change this to a UTF-8 locale. -* You created raw bytestrings, which is easy to do on Python 2:: - - my_string = 'café' - - Either use the ``u''`` prefix or even better, add the - ``from __future__ import unicode_literals`` line at the top of your file - so that your code will be compatible with Python 3.2 which doesn't support - the ``u''`` prefix. - Related resources: * :doc:`Unicode in Django ` diff --git a/docs/howto/custom-management-commands.txt b/docs/howto/custom-management-commands.txt index 620681ab35..51db07e540 100644 --- a/docs/howto/custom-management-commands.txt +++ b/docs/howto/custom-management-commands.txt @@ -26,10 +26,6 @@ directory whose name doesn't begin with an underscore. For example:: tests.py views.py -On Python 2, be sure to include ``__init__.py`` files in both the -``management`` and ``management/commands`` directories as done above or your -command will not be detected. - In this example, the ``closepoll`` command will be made available to any project that includes the ``polls`` application in :setting:`INSTALLED_APPS`. diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt index a5f2048272..09d00e0928 100644 --- a/docs/howto/custom-model-fields.txt +++ b/docs/howto/custom-model-fields.txt @@ -704,14 +704,12 @@ smoothly: a field that's similar to what you want and extend it a little bit, instead of creating an entirely new field from scratch. -2. Put a ``__str__()`` (``__unicode__()`` on Python 2) method on the class you're - wrapping up as a field. There are a lot of places where the default - behavior of the field code is to call +2. Put a ``__str__()`` method on the class you're wrapping up as a field. There + are a lot of places where the default behavior of the field code is to call :func:`~django.utils.encoding.force_text` on the value. (In our examples in this document, ``value`` would be a ``Hand`` instance, not a - ``HandField``). So if your ``__str__()`` method (``__unicode__()`` on - Python 2) automatically converts to the string form of your Python object, - you can save yourself a lot of work. + ``HandField``). So if your ``__str__()`` method automatically converts to + the string form of your Python object, you can save yourself a lot of work. Writing a ``FileField`` subclass ================================ diff --git a/docs/howto/deployment/checklist.txt b/docs/howto/deployment/checklist.txt index 8d7c27b04f..d6820f7e79 100644 --- a/docs/howto/deployment/checklist.txt +++ b/docs/howto/deployment/checklist.txt @@ -250,19 +250,3 @@ details about the default templates: * :ref:`http_internal_server_error_view` * :ref:`http_forbidden_view` * :ref:`http_bad_request_view` - -Python Options -============== - -It's strongly recommended that you invoke the Python process running your -Django application using the `-R`_ option or with the :envvar:`PYTHONHASHSEED` -environment variable set to ``random``. This option is enabled by default -starting with Python 3.3. - -These options help protect your site from denial-of-service (DoS) -attacks triggered by carefully crafted inputs. Such an attack can -drastically increase CPU usage by causing worst-case performance when -creating ``dict`` instances. See `oCERT advisory #2011-003 -`_ for more information. - -.. _-r: https://docs.python.org/2/using/cmdline.html#cmdoption-R diff --git a/docs/howto/outputting-csv.txt b/docs/howto/outputting-csv.txt index 26a0c4eb1f..98824284ed 100644 --- a/docs/howto/outputting-csv.txt +++ b/docs/howto/outputting-csv.txt @@ -53,26 +53,6 @@ mention: about escaping strings with quotes or commas in them. Just pass ``writerow()`` your raw strings, and it'll do the right thing. -.. admonition:: Handling Unicode on Python 2 - - Python 2's :mod:`csv` module does not support Unicode input. Since Django - uses Unicode internally this means strings read from sources such as - :class:`~django.http.HttpRequest` are potentially problematic. There are a - few options for handling this: - - * Manually encode all Unicode objects to a compatible encoding. - - * Use the ``UnicodeWriter`` class provided in the `csv module's examples - section`_. - - * Use the `python-unicodecsv module`_, which aims to be a drop-in - replacement for :mod:`csv` that gracefully handles Unicode. - - For more information, see the Python documentation of the :mod:`csv` module. - - .. _`csv module's examples section`: https://docs.python.org/2/library/csv.html#examples - .. _`python-unicodecsv module`: https://github.com/jdunck/python-unicodecsv - .. _streaming-csv-files: Streaming large CSV files @@ -89,7 +69,6 @@ the assembly and transmission of a large CSV file:: import csv - from django.utils.six.moves import range from django.http import StreamingHttpResponse class Echo(object): diff --git a/docs/index.txt b/docs/index.txt index ab38fa02f9..9c4f393041 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -282,7 +282,6 @@ Django aims to be compatible with multiple different flavors and versions of Python: * :doc:`Jython support ` -* :doc:`Python 3 compatibility ` Geographic framework ==================== diff --git a/docs/internals/contributing/writing-code/javascript.txt b/docs/internals/contributing/writing-code/javascript.txt index 3d10c48f00..be0e43a3b6 100644 --- a/docs/internals/contributing/writing-code/javascript.txt +++ b/docs/internals/contributing/writing-code/javascript.txt @@ -122,8 +122,8 @@ browser. To measure code coverage when running the tests, you need to view that file over HTTP. To view code coverage: -* Execute ``python -m http.server`` (or ``python -m SimpleHTTPServer`` on - Python 2) from the root directory (not from inside ``js_tests``). +* Execute ``python -m http.server`` from the root directory (not from inside + ``js_tests``). * Open http://localhost:8000/js_tests/tests.html in your web browser. Testing from the command line diff --git a/docs/internals/contributing/writing-code/unit-tests.txt b/docs/internals/contributing/writing-code/unit-tests.txt index 7c0e65bf71..74ec363b5a 100644 --- a/docs/internals/contributing/writing-code/unit-tests.txt +++ b/docs/internals/contributing/writing-code/unit-tests.txt @@ -31,7 +31,7 @@ Next, clone your fork, install some requirements, and run the tests:: $ git clone git@github.com:YourGitHubName/django.git django-repo $ cd django-repo/tests $ pip install -e .. - $ pip install -r requirements/py3.txt # Python 2: py2.txt + $ pip install -r requirements/py3.txt $ ./runtests.py Installing the requirements will likely require some operating system packages @@ -39,8 +39,7 @@ that your computer doesn't have installed. You can usually figure out which package to install by doing a Web search for the last line or so of the error message. Try adding your operating system to the search query if needed. -If you have trouble installing the requirements, you can skip that step, except -on Python 2, where you must ``pip install mock``. See +If you have trouble installing the requirements, you can skip that step. See :ref:`running-unit-tests-dependencies` for details on installing the optional test dependencies. If you don't have an optional dependency installed, the tests that require it will be skipped. @@ -75,9 +74,8 @@ command from any place in the Django source tree:: By default, ``tox`` runs the test suite with the bundled test settings file for SQLite, ``flake8``, ``isort``, and the documentation spelling checker. In addition to the system dependencies noted elsewhere in this documentation, -the commands ``python2`` and ``python3`` must be on your path and linked to -the appropriate versions of Python. A list of default environments can be seen -as follows:: +the command ``python3`` must be on your path and linked to the appropriate +version of Python. A list of default environments can be seen as follows:: $ tox -l py3 @@ -225,7 +223,6 @@ dependencies: * argon2-cffi_ 16.1.0+ * bcrypt_ * docutils_ -* enum34_ (Python 2 only) * geoip2_ * jinja2_ 2.7+ * numpy_ @@ -234,7 +231,6 @@ dependencies: * pytz_ (required) * setuptools_ * memcached_, plus a :ref:`supported Python binding ` -* mock_ (for Python 2) * gettext_ (:ref:`gettext_on_windows`) * selenium_ * sqlparse_ @@ -243,7 +239,7 @@ You can find these dependencies in `pip requirements files`_ inside the ``tests/requirements`` directory of the Django source tree and install them like so:: - $ pip install -r tests/requirements/py3.txt # Python 2: py2.txt + $ pip install -r tests/requirements/py3.txt If you encounter an error during the installation, your system might be missing a dependency for one or more of the Python packages. Consult the failing @@ -265,7 +261,6 @@ associated tests will be skipped. .. _argon2-cffi: https://pypi.python.org/pypi/argon2_cffi .. _bcrypt: https://pypi.python.org/pypi/bcrypt .. _docutils: https://pypi.python.org/pypi/docutils -.. _enum34: https://pypi.python.org/pypi/enum34 .. _geoip2: https://pypi.python.org/pypi/geoip2 .. _jinja2: https://pypi.python.org/pypi/jinja2 .. _numpy: https://pypi.python.org/pypi/numpy @@ -274,7 +269,6 @@ associated tests will be skipped. .. _pytz: https://pypi.python.org/pypi/pytz/ .. _setuptools: https://pypi.python.org/pypi/setuptools/ .. _memcached: http://memcached.org/ -.. _mock: https://pypi.python.org/pypi/mock .. _gettext: https://www.gnu.org/software/gettext/manual/gettext.html .. _selenium: https://pypi.python.org/pypi/selenium .. _sqlparse: https://pypi.python.org/pypi/sqlparse diff --git a/docs/intro/contributing.txt b/docs/intro/contributing.txt index 75414410f2..6ae51b8502 100644 --- a/docs/intro/contributing.txt +++ b/docs/intro/contributing.txt @@ -70,9 +70,9 @@ probably got the answers. .. admonition:: Python 3 required! - This tutorial assumes you are using Python 3. Get the latest version at - `Python's download page `_ or with your - operating system's package manager. + The current development version of Django doesn't support Python 2.7. Get + Python 3 at `Python's download page `_ or + with your operating system's package manager. .. admonition:: For Windows users diff --git a/docs/intro/overview.txt b/docs/intro/overview.txt index 011d1695a0..1381892bb9 100644 --- a/docs/intro/overview.txt +++ b/docs/intro/overview.txt @@ -33,7 +33,7 @@ database-schema problems. Here's a quick example: class Reporter(models.Model): full_name = models.CharField(max_length=70) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.full_name class Article(models.Model): @@ -42,7 +42,7 @@ database-schema problems. Here's a quick example: content = models.TextField() reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.headline Install it diff --git a/docs/intro/reusable-apps.txt b/docs/intro/reusable-apps.txt index 6901766047..c8ff7a7f83 100644 --- a/docs/intro/reusable-apps.txt +++ b/docs/intro/reusable-apps.txt @@ -220,10 +220,8 @@ this. For a small app like polls, this process isn't too difficult. 'License :: OSI Approved :: BSD License', # example license 'Operating System :: OS Independent', 'Programming Language :: Python', - # Replace these appropriately if you are stuck on Python 2. - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', ], diff --git a/docs/ref/applications.txt b/docs/ref/applications.txt index 8663e65222..1cff9aafa4 100644 --- a/docs/ref/applications.txt +++ b/docs/ref/applications.txt @@ -295,13 +295,12 @@ Methods .. _namespace package: -Namespace packages as apps (Python 3.3+) ----------------------------------------- +Namespace packages as apps +-------------------------- -Python versions 3.3 and later support Python packages without an -``__init__.py`` file. These packages are known as "namespace packages" and may -be spread across multiple directories at different locations on ``sys.path`` -(see :pep:`420`). +Python packages without an ``__init__.py`` file are known as "namespace +packages" and may be spread across multiple directories at different locations +on ``sys.path`` (see :pep:`420`). Django applications require a single base filesystem path where Django (depending on configuration) will search for templates, static assets, diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index 13ef44053e..518ed507af 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -45,9 +45,9 @@ Constructor arguments are: ``obj`` Optional. An object providing context for the message (for example, the model where the problem was discovered). The object should be a model, - field, or manager or any other object that defines ``__str__`` method (on - Python 2 you need to define ``__unicode__`` method). The method is used - while reporting all messages and its result precedes the message. + field, or manager or any other object that defines a ``__str__()`` method. + The method is used while reporting all messages and its result precedes the + message. ``id`` Optional string. A unique identifier for the issue. Identifiers should diff --git a/docs/ref/contrib/admin/actions.txt b/docs/ref/contrib/admin/actions.txt index e98d8d2aef..039d8d37d6 100644 --- a/docs/ref/contrib/admin/actions.txt +++ b/docs/ref/contrib/admin/actions.txt @@ -57,7 +57,7 @@ simple news application with an ``Article`` model:: body = models.TextField() status = models.CharField(max_length=1, choices=STATUS_CHOICES) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.title A common task we might perform with a model like this is to update an diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 1fa3843c73..74faef6a75 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -137,10 +137,8 @@ The ``register`` decorator You can't use this decorator if you have to reference your model admin class in its ``__init__()`` method, e.g. - ``super(PersonAdmin, self).__init__(*args, **kwargs)``. If you are using - Python 3 and don't have to worry about supporting Python 2, you can - use ``super().__init__(*args, **kwargs)`` . Otherwise, you'll have to use - ``admin.site.register()`` instead of this decorator. + ``super(PersonAdmin, self).__init__(*args, **kwargs)``. You can use + ``super().__init__(*args, **kwargs)``. Discovery of admin files ------------------------ @@ -543,8 +541,7 @@ subclass:: list_display = ('first_name', 'last_name') If you don't set ``list_display``, the admin site will display a single - column that displays the ``__str__()`` (``__unicode__()`` on Python 2) - representation of each object. + column that displays the ``__str__()`` representation of each object. You have four possible values that can be used in ``list_display``: @@ -594,7 +591,7 @@ subclass:: A few special cases to note about ``list_display``: * If the field is a ``ForeignKey``, Django will display the - ``__str__()`` (``__unicode__()`` on Python 2) of the related object. + ``__str__()`` of the related object. * ``ManyToManyField`` fields aren't supported, because that would entail executing a separate SQL statement for each row in the table. @@ -681,9 +678,8 @@ subclass:: class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'born_in_fifties') - * The ``__str__()`` (``__unicode__()`` on Python 2) method is just - as valid in ``list_display`` as any other model method, so it's - perfectly OK to do this:: + * The ``__str__()`` method is just as valid in ``list_display`` as any + other model method, so it's perfectly OK to do this:: list_display = ('__str__', 'some_other_field') diff --git a/docs/ref/contrib/auth.txt b/docs/ref/contrib/auth.txt index c049deb439..a269230643 100644 --- a/docs/ref/contrib/auth.txt +++ b/docs/ref/contrib/auth.txt @@ -137,12 +137,11 @@ Attributes .. attribute:: username_validator Points to a validator instance used to validate usernames. Defaults to - :class:`validators.UnicodeUsernameValidator` on Python 3 and - :class:`validators.ASCIIUsernameValidator` on Python 2. + :class:`validators.UnicodeUsernameValidator`. To change the default username validator, you can subclass the ``User`` model and set this attribute to a different validator instance. For - example, to use ASCII usernames on Python 3:: + example, to use ASCII usernames:: from django.contrib.auth.models import User from django.contrib.auth.validators import ASCIIUsernameValidator @@ -390,14 +389,12 @@ Validators .. class:: validators.ASCIIUsernameValidator A field validator allowing only ASCII letters, in addition to ``@``, ``.``, - ``+``, ``-``, and ``_``. The default validator for ``User.username`` on - Python 2. + ``+``, ``-``, and ``_``. .. class:: validators.UnicodeUsernameValidator A field validator allowing Unicode letters, in addition to ``@``, ``.``, - ``+``, ``-``, and ``_``. The default validator for ``User.username`` on - Python 3. + ``+``, ``-``, and ``_``. The default validator for ``User.username``. .. _topics-auth-signals: diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt index 33e690d97c..e5635ef59e 100644 --- a/docs/ref/contrib/contenttypes.txt +++ b/docs/ref/contrib/contenttypes.txt @@ -251,7 +251,7 @@ A simple example is a tagging system, which might look like this:: object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.tag A normal :class:`~django.db.models.ForeignKey` can only "point diff --git a/docs/ref/contrib/gis/commands.txt b/docs/ref/contrib/gis/commands.txt index 77fa915396..eeb6ca0513 100644 --- a/docs/ref/contrib/gis/commands.txt +++ b/docs/ref/contrib/gis/commands.txt @@ -63,8 +63,8 @@ of using ``ogrinspect`` :ref:`in the tutorial `. .. django-admin-option:: --name-field NAME_FIELD - Generates a ``__str__`` routine (``__unicode__`` on Python 2) on the model - that will return the given field name. + Generates a ``__str__()`` method on the model that returns the given field + name. .. django-admin-option:: --no-imports diff --git a/docs/ref/contrib/gis/layermapping.txt b/docs/ref/contrib/gis/layermapping.txt index 06cded679b..f273fa9c20 100644 --- a/docs/ref/contrib/gis/layermapping.txt +++ b/docs/ref/contrib/gis/layermapping.txt @@ -58,7 +58,7 @@ Example name = models.CharField(max_length=25) # corresponds to the 'str' field poly = models.PolygonField(srid=4269) # we want our model in a different SRID - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return 'Name: %s' % self.name 3. Use :class:`LayerMapping` to extract all the features and place them in the diff --git a/docs/ref/contrib/gis/tutorial.txt b/docs/ref/contrib/gis/tutorial.txt index cc518a999c..22e3b075ad 100644 --- a/docs/ref/contrib/gis/tutorial.txt +++ b/docs/ref/contrib/gis/tutorial.txt @@ -216,7 +216,7 @@ model to represent this data:: mpoly = models.MultiPolygonField() # Returns the string representation of the model. - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name Note that the ``models`` module is imported from ``django.contrib.gis.db``. diff --git a/docs/ref/contrib/postgres/fields.txt b/docs/ref/contrib/postgres/fields.txt index 5a79d8879d..f0f320b725 100644 --- a/docs/ref/contrib/postgres/fields.txt +++ b/docs/ref/contrib/postgres/fields.txt @@ -104,7 +104,7 @@ We will use the following example model:: name = models.CharField(max_length=200) tags = ArrayField(models.CharField(max_length=200), blank=True) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name .. fieldlookup:: arrayfield.contains @@ -313,7 +313,7 @@ We will use the following example model:: name = models.CharField(max_length=200) data = HStoreField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name .. fieldlookup:: hstorefield.key @@ -521,7 +521,7 @@ We will use the following example model:: name = models.CharField(max_length=200) data = JSONField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name .. fieldlookup:: jsonfield.key @@ -680,7 +680,7 @@ model:: ages = IntegerRangeField() start = models.DateTimeField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name We will also use the following example objects:: diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt index 03fed7db24..5ba10664d4 100644 --- a/docs/ref/databases.txt +++ b/docs/ref/databases.txt @@ -273,24 +273,18 @@ running ``migrate``:: MySQL DB API Drivers -------------------- -The Python Database API is described in :pep:`249`. MySQL has three prominent -drivers that implement this API: +MySQL has a couple drivers that implement the Python Database API described in +:pep:`249`: -- `MySQLdb`_ is a native driver that has been developed and supported for over - a decade by Andy Dustman. -- `mysqlclient`_ is a fork of ``MySQLdb`` which notably supports Python 3 and - can be used as a drop-in replacement for MySQLdb. At the time of this writing, - this is **the recommended choice** for using MySQL with Django. +- `mysqlclient`_ is a native driver. It's **the recommended choice**. - `MySQL Connector/Python`_ is a pure Python driver from Oracle that does not require the MySQL client library or any Python modules outside the standard library. -.. _MySQLdb: https://pypi.python.org/pypi/MySQL-python/1.2.4 .. _mysqlclient: https://pypi.python.org/pypi/mysqlclient .. _MySQL Connector/Python: https://dev.mysql.com/downloads/connector/python -All these drivers are thread-safe and provide connection pooling. ``MySQLdb`` -is the only one not supporting Python 3 currently. +All these drivers are thread-safe and provide connection pooling. In addition to a DB API driver, Django needs an adapter to access the database drivers from its ORM. Django provides an adapter for MySQLdb/mysqlclient while @@ -298,30 +292,10 @@ MySQL Connector/Python includes `its own`_. .. _its own: https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html -MySQLdb -~~~~~~~ - -Django requires MySQLdb version 1.2.1p2 or later. - -At the time of writing, the latest release of MySQLdb (1.2.5) doesn't support -Python 3. In order to use MySQLdb under Python 3, you'll have to install -``mysqlclient`` instead. - -.. note:: - There are known issues with the way MySQLdb converts date strings into - datetime objects. Specifically, date strings with value ``0000-00-00`` are - valid for MySQL but will be converted into ``None`` by MySQLdb. - - This means you should be careful while using :djadmin:`loaddata` and - :djadmin:`dumpdata` with rows that may have ``0000-00-00`` values, as they - will be converted to ``None``. - mysqlclient ~~~~~~~~~~~ -Django requires `mysqlclient`_ 1.3.3 or later. Note that Python 3.2 is not -supported. Except for the Python 3.3+ support, mysqlclient should mostly behave -the same as MySQLDB. +Django requires `mysqlclient`_ 1.3.3 or later. MySQL Connector/Python ~~~~~~~~~~~~~~~~~~~~~~ @@ -689,23 +663,6 @@ substring filtering. .. _documented at sqlite.org: https://www.sqlite.org/faq.html#q18 -Old SQLite and ``CASE`` expressions ------------------------------------ - -SQLite 3.6.23.1 and older contains a bug when `handling query parameters`_ in -a ``CASE`` expression that contains an ``ELSE`` and arithmetic. - -SQLite 3.6.23.1 was released in March 2010, and most current binary -distributions for different platforms include a newer version of SQLite, with -the notable exception of the Python 2.7 installers for Windows. - -As of this writing, the latest release for Windows - Python 2.7.10 - includes -SQLite 3.6.21. You can install ``pysqlite2`` or replace ``sqlite3.dll`` (by -default installed in ``C:\Python27\DLLs``) with a newer version from -https://www.sqlite.org/ to remedy this issue. - -.. _handling query parameters: https://code.djangoproject.com/ticket/24148 - .. _using-newer-versions-of-pysqlite: Using newer versions of the SQLite DB-API 2.0 driver diff --git a/docs/ref/exceptions.txt b/docs/ref/exceptions.txt index 79afe702a1..7057b90804 100644 --- a/docs/ref/exceptions.txt +++ b/docs/ref/exceptions.txt @@ -217,11 +217,7 @@ Specification v2.0, for further information. As per :pep:`3134`, a ``__cause__`` attribute is set with the original (underlying) database exception, allowing access to any additional -information provided. (Note that this attribute is available under -both Python 2 and Python 3, although :pep:`3134` normally only applies -to Python 3. To avoid unexpected differences with Python 3, Django will also -ensure that the exception made available via ``__cause__`` has a usable -``__traceback__`` attribute.) +information provided. .. exception:: models.ProtectedError diff --git a/docs/ref/files/file.txt b/docs/ref/files/file.txt index 4169b74b88..803f060c29 100644 --- a/docs/ref/files/file.txt +++ b/docs/ref/files/file.txt @@ -97,8 +97,7 @@ The ``File`` class .. versionchanged:: 1.11 - The ``readable()`` and ``writable()`` methods were added and the - ``seekable()`` method was made available on Python 2. + The ``readable()`` and ``writable()`` methods were added. .. currentmodule:: django.core.files.base diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index 1c4185156d..e64e25d241 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -810,12 +810,11 @@ Customizing the error list format By default, forms use ``django.forms.utils.ErrorList`` to format validation errors. If you'd like to use an alternate class for displaying errors, you can -pass that in at construction time (replace ``__str__`` by ``__unicode__`` on -Python 2):: +pass that in at construction time:: >>> from django.forms.utils import ErrorList >>> class DivErrorList(ErrorList): - ... def __str__(self): # __unicode__ on Python 2 + ... def __str__(self): ... return self.as_divs() ... def as_divs(self): ... if not self: return '' @@ -840,8 +839,7 @@ they're not the only way a form object can be displayed. Used to display HTML or access attributes for a single field of a :class:`Form` instance. - The ``__str__()`` (``__unicode__`` on Python 2) method of this - object displays the HTML for this field. + The ``__str__()`` method of this object displays the HTML for this field. To retrieve a single ``BoundField``, use dictionary lookup syntax on your form using the field's name as the key:: diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt index 8dfe26aa79..2008e65b95 100644 --- a/docs/ref/forms/fields.txt +++ b/docs/ref/forms/fields.txt @@ -1183,12 +1183,11 @@ method:: ... - The ``__str__`` (``__unicode__`` on Python 2) method of the model will be - called to generate string representations of the objects for use in the - field's choices; to provide customized representations, subclass - ``ModelChoiceField`` and override ``label_from_instance``. This method will - receive a model object, and should return a string suitable for representing - it. For example:: + The ``__str__()`` method of the model will be called to generate string + representations of the objects for use in the field's choices. To provide + customized representations, subclass ``ModelChoiceField`` and override + ``label_from_instance``. This method will receive a model object and should + return a string suitable for representing it. For example:: from django.forms import ModelChoiceField diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index ddacf25769..18e81a7da8 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -1002,7 +1002,7 @@ For example, suppose you have these models:: name = models.CharField(max_length=50) toppings = models.ManyToManyField(Topping) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return "%s (%s)" % ( self.name, ", ".join(topping.name for topping in self.toppings.all()), diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index 40ba20738e..a6f80feb2e 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -480,21 +480,6 @@ a subclass of dictionary. Exceptions are outlined here: >>> q.items() [('a', '3')] -.. method:: QueryDict.iteritems() - - Just like the standard dictionary ``iteritems()`` method. Like - :meth:`QueryDict.items()` this uses the same last-value logic as - :meth:`QueryDict.__getitem__()`. - - Available only on Python 2. - -.. method:: QueryDict.iterlists() - - Like :meth:`QueryDict.iteritems()` except it includes all values, as a list, - for each member of the dictionary. - - Available only on Python 2. - .. method:: QueryDict.values() Just like the standard dictionary ``values()`` method, except this uses the @@ -504,12 +489,6 @@ a subclass of dictionary. Exceptions are outlined here: >>> q.values() ['3'] -.. method:: QueryDict.itervalues() - - Just like :meth:`QueryDict.values()`, except an iterator. - - Available only on Python 2. - In addition, ``QueryDict`` has the following methods: .. method:: QueryDict.copy() diff --git a/docs/ref/templates/language.txt b/docs/ref/templates/language.txt index d6f13a637f..430ada3a2f 100644 --- a/docs/ref/templates/language.txt +++ b/docs/ref/templates/language.txt @@ -105,13 +105,13 @@ Use a dot (``.``) to access attributes of a variable. override dictionary lookup. For example, consider the following code snippet that attempts to loop over a ``collections.defaultdict``:: - {% for k, v in defaultdict.iteritems %} + {% for k, v in defaultdict.items %} Do something with k and v here... {% endfor %} Because dictionary lookup happens first, that behavior kicks in and provides - a default value instead of using the intended ``.iteritems()`` - method. In this case, consider converting to a dictionary first. + a default value instead of using the intended ``.items()`` method. In this + case, consider converting to a dictionary first. In the above example, ``{{ section.title }}`` will be replaced with the ``title`` attribute of the ``section`` object. diff --git a/docs/ref/unicode.txt b/docs/ref/unicode.txt index c167fd55b3..d493ce56ad 100644 --- a/docs/ref/unicode.txt +++ b/docs/ref/unicode.txt @@ -48,29 +48,7 @@ General string handling Whenever you use strings with Django -- e.g., in database lookups, template rendering or anywhere else -- you have two choices for encoding those strings. -You can use Unicode strings, or you can use normal strings (sometimes called -"bytestrings") that are encoded using UTF-8. - -In Python 3, the logic is reversed, that is normal strings are Unicode, and -when you want to specifically create a bytestring, you have to prefix the -string with a 'b'. As we are doing in Django code from version 1.5, -we recommend that you import ``unicode_literals`` from the __future__ library -in your code. Then, when you specifically want to create a bytestring literal, -prefix the string with 'b'. - -Python 2 legacy:: - - my_string = "This is a bytestring" - my_unicode = u"This is an Unicode string" - -Python 2 with unicode literals or Python 3:: - - from __future__ import unicode_literals - - my_string = b"This is a bytestring" - my_unicode = "This is an Unicode string" - -See also :doc:`Python 3 compatibility `. +You can use normal Unicode strings or bytestrings (starting with a 'b'). .. warning:: @@ -114,7 +92,7 @@ imported. Normally, you won't have to worry about lazy translations. Just be aware that if you examine an object and it claims to be a ``django.utils.functional.__proxy__`` object, it is a lazy translation. -Calling ``unicode()`` with the lazy translation as the argument will generate a +Calling ``str()`` with the lazy translation as the argument will generate a Unicode string in the current locale. For more details about lazy translation objects, refer to the @@ -140,12 +118,9 @@ for converting back and forth between Unicode and bytestrings. ``strings_only`` parameter, if set to True, will result in Python numbers, booleans and ``None`` not being converted to a string (they keep their original types). The ``errors`` parameter takes any of the values - that are accepted by Python's ``unicode()`` function for its error + that are accepted by Python's ``str()`` function for its error handling. - If you pass ``smart_text()`` an object that has a ``__unicode__`` - method, it will use that method to do the conversion. - * ``force_text(s, encoding='utf-8', strings_only=False, errors='strict')`` is identical to ``smart_text()`` in almost all cases. The difference is when the first argument is a :ref:`lazy @@ -292,8 +267,6 @@ You can pass either Unicode strings or UTF-8 bytestrings as arguments to ``filter()`` methods and the like in the database API. The following two querysets are identical:: - from __future__ import unicode_literals - qs = People.objects.filter(name__contains='Å') qs = People.objects.filter(name__contains=b'\xc3\x85') # UTF-8 encoding of Å @@ -302,7 +275,6 @@ Templates You can use either Unicode or bytestrings when creating templates manually:: - from __future__ import unicode_literals from django.template import Template t1 = Template(b'This is a bytestring template.') t2 = Template('This is a Unicode template.') @@ -373,7 +345,6 @@ characters. The following code example demonstrates that everything except email addresses can be non-ASCII:: - from __future__ import unicode_literals from django.core.mail import EmailMessage subject = 'My visit to Sør-Trøndelag' diff --git a/docs/ref/urlresolvers.txt b/docs/ref/urlresolvers.txt index 6e3ec595b1..9d462637ef 100644 --- a/docs/ref/urlresolvers.txt +++ b/docs/ref/urlresolvers.txt @@ -175,9 +175,9 @@ A :class:`ResolverMatch` object can also be assigned to a triple:: One possible use of :func:`~django.urls.resolve` would be to test whether a view would raise a ``Http404`` error before redirecting to it:: + from urllib.parse import urlparse from django.urls import resolve from django.http import HttpResponseRedirect, Http404 - from django.utils.six.moves.urllib.parse import urlparse def myview(request): next = request.META.get('HTTP_REFERER', None) or '/' diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 79787227e2..550facd142 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -203,16 +203,12 @@ The functions defined in this module share the following properties: .. function:: smart_text(s, encoding='utf-8', strings_only=False, errors='strict') - Returns a text object representing ``s`` -- ``unicode`` on Python 2 and - ``str`` on Python 3. Treats bytestrings using the ``encoding`` codec. + Returns a ``str`` object representing ``s``. Treats bytestrings using the + ``encoding`` codec. If ``strings_only`` is ``True``, don't convert (some) non-string-like objects. -.. function:: smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict') - - Historical name of :func:`smart_text`. Only available under Python 2. - .. function:: is_protected_type(obj) Determine if the object instance is of a protected type. @@ -228,10 +224,6 @@ The functions defined in this module share the following properties: If ``strings_only`` is ``True``, don't convert (some) non-string-like objects. -.. function:: force_unicode(s, encoding='utf-8', strings_only=False, errors='strict') - - Historical name of :func:`force_text`. Only available under Python 2. - .. function:: smart_bytes(s, encoding='utf-8', strings_only=False, errors='strict') Returns a bytestring version of ``s``, encoded as specified in @@ -250,16 +242,20 @@ The functions defined in this module share the following properties: .. function:: smart_str(s, encoding='utf-8', strings_only=False, errors='strict') - Alias of :func:`smart_bytes` on Python 2 and :func:`smart_text` on Python - 3. This function returns a ``str`` or a lazy string. + Alias of :func:`smart_text`. This function returns a ``str`` or a lazy + string. - For instance, this is suitable for writing to :data:`sys.stdout` on - Python 2 and 3. + For instance, this is suitable for writing to :data:`sys.stdout`. + + Alias of :func:`smart_bytes` on Python 2 (in older versions of Django that + support it). .. function:: force_str(s, encoding='utf-8', strings_only=False, errors='strict') - Alias of :func:`force_bytes` on Python 2 and :func:`force_text` on Python - 3. This function always returns a ``str``. + Alias of :func:`force_text`. This function always returns a ``str``. + + Alias of :func:`force_bytes` on Python 2 (in older versions of Django that + support it). .. function:: iri_to_uri(iri) @@ -538,23 +534,22 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004 For example:: - from django.utils import six from django.utils.functional import keep_lazy, keep_lazy_text def fancy_utility_function(s, ...): # Do some conversion on string 's' ... - fancy_utility_function = keep_lazy(six.text_type)(fancy_utility_function) + fancy_utility_function = keep_lazy(str)(fancy_utility_function) # Or more succinctly: - @keep_lazy(six.text_type) + @keep_lazy(str) def fancy_utility_function(s, ...): ... The ``keep_lazy()`` decorator takes a number of extra arguments (``*args``) specifying the type(s) that the original function can return. A common use case is to have functions that return text. For these, you can just - pass the ``six.text_type`` type to ``keep_lazy`` (or even simpler, use the + pass the ``str`` type to ``keep_lazy`` (or even simpler, use the :func:`keep_lazy_text` decorator described in the next section). Using this decorator means you can write your function and assume that the @@ -563,16 +558,15 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004 .. function:: keep_lazy_text(func) - A shortcut for ``keep_lazy(six.text_type)(func)``. + A shortcut for ``keep_lazy(str)(func)``. If you have a function that returns text and you want to be able to take lazy arguments while delaying their evaluation, simply use this decorator:: - from django.utils import six from django.utils.functional import keep_lazy, keep_lazy_text # Our previous example was: - @keep_lazy(six.text_type) + @keep_lazy(str) def fancy_utility_function(s, ...): ... @@ -680,11 +674,9 @@ escaping HTML. classes whose output doesn't require HTML escaping. This decorator defines the ``__html__()`` method on the decorated class - by wrapping the ``__unicode__()`` (Python 2) or ``__str__()`` (Python 3) - in :meth:`~django.utils.safestring.mark_safe`. Ensure the ``__unicode__()`` - or ``__str__()`` method does indeed return text that doesn't require HTML - escaping. - + by wrapping ``__str__()`` in :meth:`~django.utils.safestring.mark_safe`. + Ensure the ``__str__()`` method does indeed return text that doesn't + require HTML escaping. ``django.utils.http`` ===================== @@ -737,13 +729,11 @@ escaping HTML. .. function:: base36_to_int(s) - Converts a base 36 string to an integer. On Python 2 the output is - guaranteed to be an ``int`` and not a ``long``. + Converts a base 36 string to an integer. .. function:: int_to_base36(i) - Converts a positive integer to a base 36 string. On Python 2 ``i`` must be - smaller than `sys.maxint`_. + Converts a positive integer to a base 36 string. .. _sys.maxint: https://docs.python.org/2/library/sys.html#sys.maxint @@ -798,17 +788,16 @@ appropriate entities. .. class:: SafeString A ``str`` subclass that has been specifically marked as "safe" - (requires no further escaping) for HTML output purposes. This is - :class:`SafeBytes` on Python 2 and :class:`SafeText` on Python 3. + (requires no further escaping) for HTML output purposes. Alias of + :class:`SafeText`. + + Alias of :class:`SafeBytes` on Python 2 (in older versions of Django that + support it). .. class:: SafeText - A ``str`` (in Python 3) or ``unicode`` (in Python 2) subclass - that has been specifically marked as "safe" for HTML output purposes. - -.. class:: SafeUnicode - - Historical name of :class:`SafeText`. Only available under Python 2. + A ``str`` subclass that has been specifically marked as "safe" for HTML + output purposes. .. function:: mark_safe(s) diff --git a/docs/releases/1.4.11.txt b/docs/releases/1.4.11.txt index 990f511e71..4d5c555fca 100644 --- a/docs/releases/1.4.11.txt +++ b/docs/releases/1.4.11.txt @@ -5,7 +5,7 @@ Django 1.4.11 release notes *April 21, 2014* Django 1.4.11 fixes three security issues in 1.4.10. Additionally, -Django's vendored version of six, :mod:`django.utils.six`, has been +Django's vendored version of six, ``django.utils.six``, has been upgraded to the latest release (1.6.1). Unexpected code execution using ``reverse()`` diff --git a/docs/releases/1.4.17.txt b/docs/releases/1.4.17.txt index 8c6a5de3bf..f66bca433d 100644 --- a/docs/releases/1.4.17.txt +++ b/docs/releases/1.4.17.txt @@ -6,7 +6,7 @@ Django 1.4.17 release notes Django 1.4.17 fixes a regression in the 1.4.14 security release. -Additionally, Django's vendored version of six, :mod:`django.utils.six`, has +Additionally, Django's vendored version of six, ``django.utils.six``, has been upgraded to the latest release (1.9.0). Bugfixes diff --git a/docs/releases/1.4.18.txt b/docs/releases/1.4.18.txt index 418808d6cc..124d271bc4 100644 --- a/docs/releases/1.4.18.txt +++ b/docs/releases/1.4.18.txt @@ -64,5 +64,5 @@ Bugfixes ======== * To maintain compatibility with Python 2.5, Django's vendored version of six, - :mod:`django.utils.six`, has been downgraded to 1.8.0 which is the last + ``django.utils.six``, has been downgraded to 1.8.0 which is the last version to support Python 2.5. diff --git a/docs/releases/1.5.6.txt b/docs/releases/1.5.6.txt index 915dd7e22a..c5be83dd57 100644 --- a/docs/releases/1.5.6.txt +++ b/docs/releases/1.5.6.txt @@ -113,5 +113,5 @@ Bugfixes ``UnboundLocalError`` if :func:`~django.contrib.auth.get_user_model` raised an error (#21439). -Additionally, Django's vendored version of six, :mod:`django.utils.six`, +Additionally, Django's vendored version of six, ``django.utils.six``, has been upgraded to the latest release (1.6.1). diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt index cbd1d48cfe..af8de1ea12 100644 --- a/docs/releases/1.5.txt +++ b/docs/releases/1.5.txt @@ -107,9 +107,9 @@ to Python 3, so it's unlikely that a real-world application will have all its dependencies satisfied under Python 3. Thus, we're recommending that Django 1.5 not be used in production under Python -3. Instead, use this opportunity to begin :doc:`porting applications to Python 3 -`. If you're an author of a pluggable component, we encourage you -to start porting now. +3. Instead, use this opportunity to begin porting applications to Python 3. If +you're an author of a pluggable component, we encourage you to start porting +now. We plan to offer first-class, production-ready support for Python 3 in our next release, Django 1.6. diff --git a/docs/releases/1.6.2.txt b/docs/releases/1.6.2.txt index 90599bcb57..d7a1bc099b 100644 --- a/docs/releases/1.6.2.txt +++ b/docs/releases/1.6.2.txt @@ -48,5 +48,5 @@ several bugs in 1.6.1: through :func:`~django.utils.safestring.mark_safe` and could end up being double-escaped (:ticket:`21882`). -Additionally, Django's vendored version of six, :mod:`django.utils.six` has been +Additionally, Django's vendored version of six, ``django.utils.six`` has been upgraded to the latest release (1.5.2). diff --git a/docs/releases/1.6.3.txt b/docs/releases/1.6.3.txt index 0cba7d59af..4091e793c5 100644 --- a/docs/releases/1.6.3.txt +++ b/docs/releases/1.6.3.txt @@ -179,5 +179,5 @@ Other bugfixes and changes query to include an unnecessary join (:ticket:`21760`). -Additionally, Django's vendored version of six, :mod:`django.utils.six` has been +Additionally, Django's vendored version of six, ``django.utils.six`` has been upgraded to the latest release (1.6.1). diff --git a/docs/releases/1.6.9.txt b/docs/releases/1.6.9.txt index 38785f9623..239cd7c896 100644 --- a/docs/releases/1.6.9.txt +++ b/docs/releases/1.6.9.txt @@ -6,7 +6,7 @@ Django 1.6.9 release notes Django 1.6.9 fixes a regression in the 1.6.6 security release. -Additionally, Django's vendored version of six, :mod:`django.utils.six`, has +Additionally, Django's vendored version of six, ``django.utils.six``, has been upgraded to the latest release (1.9.0). Bugfixes diff --git a/docs/releases/1.7.2.txt b/docs/releases/1.7.2.txt index 056f432978..2b6725265e 100644 --- a/docs/releases/1.7.2.txt +++ b/docs/releases/1.7.2.txt @@ -6,7 +6,7 @@ Django 1.7.2 release notes Django 1.7.2 fixes several bugs in 1.7.1. -Additionally, Django's vendored version of six, :mod:`django.utils.six`, has +Additionally, Django's vendored version of six, ``django.utils.six``, has been upgraded to the latest release (1.9.0). Bugfixes diff --git a/docs/releases/1.8.7.txt b/docs/releases/1.8.7.txt index 7da30a1a02..98598f665b 100644 --- a/docs/releases/1.8.7.txt +++ b/docs/releases/1.8.7.txt @@ -6,7 +6,7 @@ Django 1.8.7 release notes Django 1.8.7 fixes a security issue and several bugs in 1.8.6. -Additionally, Django's vendored version of six, :mod:`django.utils.six`, has +Additionally, Django's vendored version of six, ``django.utils.six``, has been upgraded to the latest release (1.10.0). Fixed settings leak possibility in ``date`` template filter diff --git a/docs/topics/auth/customizing.txt b/docs/topics/auth/customizing.txt index 0f750adc2b..c4fd73cebc 100644 --- a/docs/topics/auth/customizing.txt +++ b/docs/topics/auth/customizing.txt @@ -1060,7 +1060,7 @@ authentication app:: # The user is identified by their email address return self.email - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.email def has_perm(self, perm, obj=None): diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index fc10025ce5..6c8c736363 100644 --- a/docs/topics/cache.txt +++ b/docs/topics/cache.txt @@ -805,8 +805,7 @@ The basic interface is ``set(key, value, timeout)`` and ``get(key)``:: >>> cache.get('my_key') 'hello, world!' -``key`` should be a ``str`` (or ``unicode`` on Python 2), and ``value`` can be -any picklable Python object. +``key`` should be a ``str``, and ``value`` can be any picklable Python object. The ``timeout`` argument is optional and defaults to the ``timeout`` argument of the appropriate backend in the :setting:`CACHES` setting (explained above). diff --git a/docs/topics/class-based-views/generic-display.txt b/docs/topics/class-based-views/generic-display.txt index 076afba678..bb848d6147 100644 --- a/docs/topics/class-based-views/generic-display.txt +++ b/docs/topics/class-based-views/generic-display.txt @@ -87,7 +87,7 @@ We'll be using these models:: class Meta: ordering = ["-name"] - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Author(models.Model): @@ -96,7 +96,7 @@ We'll be using these models:: email = models.EmailField() headshot = models.ImageField(upload_to='author_headshots') - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Book(models.Model): diff --git a/docs/topics/db/examples/many_to_many.txt b/docs/topics/db/examples/many_to_many.txt index 5c77dc08e4..7173faaeca 100644 --- a/docs/topics/db/examples/many_to_many.txt +++ b/docs/topics/db/examples/many_to_many.txt @@ -17,7 +17,7 @@ objects, and a ``Publication`` has multiple ``Article`` objects: class Publication(models.Model): title = models.CharField(max_length=30) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.title class Meta: @@ -27,7 +27,7 @@ objects, and a ``Publication`` has multiple ``Article`` objects: headline = models.CharField(max_length=100) publications = models.ManyToManyField(Publication) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.headline class Meta: diff --git a/docs/topics/db/examples/many_to_one.txt b/docs/topics/db/examples/many_to_one.txt index c57d996460..7ccaa94bc2 100644 --- a/docs/topics/db/examples/many_to_one.txt +++ b/docs/topics/db/examples/many_to_one.txt @@ -11,7 +11,7 @@ To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`: last_name = models.CharField(max_length=30) email = models.EmailField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return "%s %s" % (self.first_name, self.last_name) class Article(models.Model): @@ -19,7 +19,7 @@ To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`: pub_date = models.DateField() reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.headline class Meta: @@ -64,13 +64,6 @@ Article objects have access to their related Reporter objects:: >>> r = a.reporter -On Python 2, these are strings of type ``str`` instead of unicode strings -because that's what was used in the creation of this reporter (and we haven't -refreshed the data from the database, which always returns unicode strings):: - - >>> r.first_name, r.last_name - ('John', 'Smith') - Create an Article via the Reporter object:: >>> new_article = r.article_set.create(headline="John's second story", pub_date=date(2005, 7, 29)) diff --git a/docs/topics/db/examples/one_to_one.txt b/docs/topics/db/examples/one_to_one.txt index 72d918861e..7588825a02 100644 --- a/docs/topics/db/examples/one_to_one.txt +++ b/docs/topics/db/examples/one_to_one.txt @@ -13,7 +13,7 @@ In this example, a ``Place`` optionally can be a ``Restaurant``:: name = models.CharField(max_length=50) address = models.CharField(max_length=80) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return "%s the place" % self.name class Restaurant(models.Model): @@ -25,14 +25,14 @@ In this example, a ``Place`` optionally can be a ``Restaurant``:: serves_hot_dogs = models.BooleanField(default=False) serves_pizza = models.BooleanField(default=False) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return "%s the restaurant" % self.place.name class Waiter(models.Model): restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE) name = models.CharField(max_length=50) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return "%s the waiter at %s" % (self.name, self.restaurant) What follows are examples of operations that can be performed using the Python diff --git a/docs/topics/db/models.txt b/docs/topics/db/models.txt index 1ce164f532..9bafb85120 100644 --- a/docs/topics/db/models.txt +++ b/docs/topics/db/models.txt @@ -445,14 +445,14 @@ something like this:: class Person(models.Model): name = models.CharField(max_length=128) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership') - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Membership(models.Model): @@ -761,7 +761,7 @@ of :ref:`methods automatically given to each model `. You can override most of these -- see `overriding predefined model methods`_, below -- but there are a couple that you'll almost always want to define: -:meth:`~Model.__str__` (Python 3) +:meth:`~Model.__str__` A Python "magic method" that returns a unicode "representation" of any object. This is what Python and Django will use whenever a model instance needs to be coerced and displayed as a plain string. Most @@ -771,9 +771,6 @@ below -- but there are a couple that you'll almost always want to define: You'll always want to define this method; the default isn't very helpful at all. -``__unicode__()`` (Python 2) - Python 2 equivalent of ``__str__()``. - :meth:`~Model.get_absolute_url` This tells Django how to calculate the URL for an object. Django uses this in its admin interface, and any time it needs to figure out a URL diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 21ae388fa8..016aef9867 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -23,14 +23,14 @@ models, which comprise a Weblog application: name = models.CharField(max_length=100) tagline = models.TextField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=200) email = models.EmailField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Entry(models.Model): @@ -44,7 +44,7 @@ models, which comprise a Weblog application: n_pingbacks = models.IntegerField() rating = models.IntegerField() - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.headline Creating objects diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index b0115cef7e..a3a8179169 100644 --- a/docs/topics/forms/modelforms.txt +++ b/docs/topics/forms/modelforms.txt @@ -169,7 +169,7 @@ Consider this set of models:: title = models.CharField(max_length=3, choices=TITLE_CHOICES) birth_date = models.DateField(blank=True, null=True) - def __str__(self): # __unicode__ on Python 2 + def __str__(self): return self.name class Book(models.Model): diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt index bb3796a32e..2dd47bd808 100644 --- a/docs/topics/i18n/translation.txt +++ b/docs/topics/i18n/translation.txt @@ -431,9 +431,6 @@ strings before passing them to non-Django code:: requests.post('https://example.com/send', data={'body': str(body)}) -Use ``unicode`` in place of ``str`` on Python 2, or :data:`six.text_type` to -support Python 2 and 3. - If you try to use a ``ugettext_lazy()`` result where a bytestring (a :class:`bytes` object) is expected, things won't work as expected since a ``ugettext_lazy()`` object doesn't know how to convert itself to a bytestring. @@ -534,12 +531,11 @@ For any other case where you would like to delay the translation, but have to pass the translatable string as argument to another function, you can wrap this function inside a lazy call yourself. For example:: - from django.utils import six # Python 3 compatibility from django.utils.functional import lazy from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ - mark_safe_lazy = lazy(mark_safe, six.text_type) + mark_safe_lazy = lazy(mark_safe, str) And then later:: diff --git a/docs/topics/index.txt b/docs/topics/index.txt index 6f85baddb6..6e9d7d74a5 100644 --- a/docs/topics/index.txt +++ b/docs/topics/index.txt @@ -24,7 +24,6 @@ Introductions to all the key parts of Django you'll need to know: i18n/index logging pagination - python3 security performance serialization diff --git a/docs/topics/install.txt b/docs/topics/install.txt index 5bdd98596d..dff170f733 100644 --- a/docs/topics/install.txt +++ b/docs/topics/install.txt @@ -171,7 +171,7 @@ This is the recommended way to install Django. isolated Python environments, which are more practical than installing packages systemwide. They also allow installing packages without administrator privileges. The :doc:`contributing tutorial - ` walks through how to create a virtualenv on Python 3. + ` walks through how to create a virtualenv. 3. After you've created and activated a virtual environment, enter the command ``pip install Django`` at the shell prompt. @@ -227,7 +227,7 @@ latest bug fixes and improvements, follow these instructions: 3. Make sure that the Python interpreter can load Django's code. The most convenient way to do this is to use virtualenv_, virtualenvwrapper_, and pip_. The :doc:`contributing tutorial ` walks through - how to create a virtualenv on Python 3. + how to create a virtualenv. 4. After setting up and activating the virtualenv, run the following command: diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt index 5475e7b385..3910d31321 100644 --- a/docs/topics/migrations.txt +++ b/docs/topics/migrations.txt @@ -665,6 +665,7 @@ Django can serialize the following: - ``LazyObject`` instances which wrap a serializable value. - Any Django field - Any function or method reference (e.g. ``datetime.datetime.today``) (must be in module's top-level scope) +- Unbound methods used from within the class body - Any class reference (must be in module's top-level scope) - Anything with a custom ``deconstruct()`` method (:ref:`see below `) @@ -672,31 +673,12 @@ Django can serialize the following: Serialization support for ``uuid.UUID`` was added. -Django can serialize the following on Python 3 only: - -- Unbound methods used from within the class body (see below) - Django cannot serialize: - Nested classes - Arbitrary class instances (e.g. ``MyClass(4.3, 5.7)``) - Lambdas -Due to the fact ``__qualname__`` was only introduced in Python 3, Django can only -serialize the following pattern (an unbound method used within the class body) -on Python 3, and will fail to serialize a reference to it on Python 2:: - - class MyModel(models.Model): - - def upload_to(self): - return "something dynamic" - - my_file = models.FileField(upload_to=upload_to) - -If you are using Python 2, we recommend you move your methods for upload_to -and similar arguments that accept callables (e.g. ``default``) to live in -the main module body, rather than the class body. - .. _custom-deconstruct-method: Adding a ``deconstruct()`` method diff --git a/docs/topics/pagination.txt b/docs/topics/pagination.txt index d2737fd522..41ee51290e 100644 --- a/docs/topics/pagination.txt +++ b/docs/topics/pagination.txt @@ -24,7 +24,7 @@ page:: 4 >>> p.num_pages 2 - >>> type(p.page_range) # `` in Python 2. + >>> type(p.page_range) >>> p.page_range range(1, 3) diff --git a/docs/topics/python3.txt b/docs/topics/python3.txt deleted file mode 100644 index 5b40f57bd3..0000000000 --- a/docs/topics/python3.txt +++ /dev/null @@ -1,369 +0,0 @@ -=================== -Porting to Python 3 -=================== - -Django 1.5 is the first version of Django to support Python 3. The same code -runs both on Python 2 (≥ 2.6.5) and Python 3 (≥ 3.2), thanks to the six_ -compatibility layer. - -.. _six: https://pythonhosted.org/six/ - -This document is primarily targeted at authors of pluggable applications -who want to support both Python 2 and 3. It also describes guidelines that -apply to Django's code. - -Philosophy -========== - -This document assumes that you are familiar with the changes between Python 2 -and Python 3. If you aren't, read :ref:`Python's official porting guide -` first. Refreshing your knowledge of unicode handling on -Python 2 and 3 will help; the `Pragmatic Unicode`_ presentation is a good -resource. - -Django uses the *Python 2/3 Compatible Source* strategy. Of course, you're -free to chose another strategy for your own code, especially if you don't need -to stay compatible with Python 2. But authors of pluggable applications are -encouraged to use the same porting strategy as Django itself. - -Writing compatible code is much easier if you target Python ≥ 2.6. Django 1.5 -introduces compatibility tools such as :mod:`django.utils.six`, which is a -customized version of the :mod:`six module `. For convenience, -forwards-compatible aliases were introduced in Django 1.4.2. If your -application takes advantage of these tools, it will require Django ≥ 1.4.2. - -Obviously, writing compatible source code adds some overhead, and that can -cause frustration. Django's developers have found that attempting to write -Python 3 code that's compatible with Python 2 is much more rewarding than the -opposite. Not only does that make your code more future-proof, but Python 3's -advantages (like the saner string handling) start shining quickly. Dealing -with Python 2 becomes a backwards compatibility requirement, and we as -developers are used to dealing with such constraints. - -Porting tools provided by Django are inspired by this philosophy, and it's -reflected throughout this guide. - -.. _Pragmatic Unicode: http://nedbatchelder.com/text/unipain.html - -Porting tips -============ - -Unicode literals ----------------- - -This step consists in: - -- Adding ``from __future__ import unicode_literals`` at the top of your Python - modules -- it's best to put it in each and every module, otherwise you'll - keep checking the top of your files to see which mode is in effect; -- Removing the ``u`` prefix before unicode strings; -- Adding a ``b`` prefix before bytestrings. - -Performing these changes systematically guarantees backwards compatibility. - -However, Django applications generally don't need bytestrings, since Django -only exposes unicode interfaces to the programmer. Python 3 discourages using -bytestrings, except for binary data or byte-oriented interfaces. Python 2 -makes bytestrings and unicode strings effectively interchangeable, as long as -they only contain ASCII data. Take advantage of this to use unicode strings -wherever possible and avoid the ``b`` prefixes. - -.. note:: - - Python 2's ``u`` prefix is a syntax error in Python 3.2 but it will be - allowed again in Python 3.3 thanks to :pep:`414`. Thus, this - transformation is optional if you target Python ≥ 3.3. It's still - recommended, per the "write Python 3 code" philosophy. - -String handling ---------------- - -Python 2's `unicode`_ type was renamed :class:`str` in Python 3, -``str()`` was renamed :class:`bytes`, and `basestring`_ disappeared. -six_ provides :ref:`tools ` to deal with these -changes. - -Django also contains several string related classes and functions in the -:mod:`django.utils.encoding` and :mod:`django.utils.safestring` modules. Their -names used the words ``str``, which doesn't mean the same thing in Python 2 -and Python 3, and ``unicode``, which doesn't exist in Python 3. In order to -avoid ambiguity and confusion these concepts were renamed ``bytes`` and -``text``. - -Here are the name changes in :mod:`django.utils.encoding`: - -================== ================== -Old name New name -================== ================== -``smart_str`` ``smart_bytes`` -``smart_unicode`` ``smart_text`` -``force_unicode`` ``force_text`` -================== ================== - -For backwards compatibility, the old names still work on Python 2. Under -Python 3, ``smart_str`` is an alias for ``smart_text``. - -For forwards compatibility, the new names work as of Django 1.4.2. - -.. note:: - - :mod:`django.utils.encoding` was deeply refactored in Django 1.5 to - provide a more consistent API. Check its documentation for more - information. - -:mod:`django.utils.safestring` is mostly used via the -:func:`~django.utils.safestring.mark_safe` function, which didn't change. In -case you're using the internals, here are the name changes: - -================== ================== -Old name New name -================== ================== -``SafeString`` ``SafeBytes`` -``SafeUnicode`` ``SafeText`` -================== ================== - -For backwards compatibility, the old names still work on Python 2. On Python 3, -``SafeString`` is an alias for ``SafeText``. - -For forwards compatibility, the new names work as of Django 1.4.2. - -``__str__()`` and ``__unicode__()`` methods -------------------------------------------- - -In Python 2, the object model specifies :meth:`~object.__str__` and -` __unicode__()`_ methods. If these methods exist, they must return -``str`` (bytes) and ``unicode`` (text) respectively. - -The ``print`` statement and the :class:`str` built-in call -:meth:`~object.__str__` to determine the human-readable representation of an -object. The ``unicode`` built-in calls ` __unicode__()`_ if it -exists, and otherwise falls back to :meth:`~object.__str__` and decodes the -result with the system encoding. Conversely, the -:class:`~django.db.models.Model` base class automatically derives -:meth:`~object.__str__` from ` __unicode__()`_ by encoding to UTF-8. - -In Python 3, there's simply :meth:`~object.__str__`, which must return ``str`` -(text). - -(It is also possible to define :meth:`~object.__bytes__`, but Django applications -have little use for that method, because they hardly ever deal with ``bytes``.) - -Finally, note that :meth:`~object.__repr__` must return a ``str`` on all -versions of Python. - -:class:`dict` and :class:`dict`-like classes --------------------------------------------- - -:meth:`dict.keys`, :meth:`dict.items` and :meth:`dict.values` return lists in -Python 2 and iterators in Python 3. :class:`~django.http.QueryDict` and the -:class:`dict`-like classes defined in ``django.utils.datastructures`` -behave likewise in Python 3. - -six_ provides compatibility functions to work around this change: -:func:`~six.iterkeys`, :func:`~six.iteritems`, and :func:`~six.itervalues`. -It also contains an undocumented ``iterlists`` function that works well for -``django.utils.datastructures.MultiValueDict`` and its subclasses. - -:class:`~django.http.HttpRequest` and :class:`~django.http.HttpResponse` objects --------------------------------------------------------------------------------- - -According to :pep:`3333`: - -- headers are always ``str`` objects, -- input and output streams are always ``bytes`` objects. - -Specifically, :attr:`HttpResponse.content ` -contains ``bytes``, which may become an issue if you compare it with a -``str`` in your tests. The preferred solution is to rely on -:meth:`~django.test.SimpleTestCase.assertContains` and -:meth:`~django.test.SimpleTestCase.assertNotContains`. These methods accept a -response and a unicode string as arguments. - -Coding guidelines -================= - -The following guidelines are enforced in Django's source code. They're also -recommended for third-party applications that follow the same porting strategy. - -Syntax requirements -------------------- - -Unicode -~~~~~~~ - -In Python 3, all strings are considered Unicode by default. The ``unicode`` -type from Python 2 is called ``str`` in Python 3, and ``str`` becomes -``bytes``. - -You mustn't use the ``u`` prefix before a unicode string literal because it's -a syntax error in Python 3.2. You must prefix byte strings with ``b``. - -In order to enable the same behavior in Python 2, every module must import -``unicode_literals`` from ``__future__``:: - - from __future__ import unicode_literals - - my_string = "This is an unicode literal" - my_bytestring = b"This is a bytestring" - -If you need a byte string literal under Python 2 and a unicode string literal -under Python 3, use the :class:`str` builtin:: - - str('my string') - -In Python 3, there aren't any automatic conversions between ``str`` and -``bytes``, and the :mod:`codecs` module became more strict. :meth:`str.encode` -always returns ``bytes``, and ``bytes.decode`` always returns ``str``. As a -consequence, the following pattern is sometimes necessary:: - - value = value.encode('ascii', 'ignore').decode('ascii') - -Be cautious if you have to `index bytestrings`_. - -.. _index bytestrings: https://docs.python.org/3/howto/pyporting.html#text-versus-binary-data - -Exceptions -~~~~~~~~~~ - -When you capture exceptions, use the ``as`` keyword:: - - try: - ... - except MyException as exc: - ... - -This older syntax was removed in Python 3:: - - try: - ... - except MyException, exc: # Don't do that! - ... - -The syntax to reraise an exception with a different traceback also changed. -Use :func:`six.reraise`. - -Magic methods -------------- - -Use the patterns below to handle magic methods renamed in Python 3. - -Iterators -~~~~~~~~~ - -:: - - class MyIterator(six.Iterator): - def __iter__(self): - return self # implement some logic here - - def __next__(self): - raise StopIteration # implement some logic here - -Boolean evaluation -~~~~~~~~~~~~~~~~~~ - -:: - - class MyBoolean(object): - - def __bool__(self): - return True # implement some logic here - - def __nonzero__(self): # Python 2 compatibility - return type(self).__bool__(self) - -Division -~~~~~~~~ - -:: - - class MyDivisible(object): - - def __truediv__(self, other): - return self / other # implement some logic here - - def __div__(self, other): # Python 2 compatibility - return type(self).__truediv__(self, other) - - def __itruediv__(self, other): - return self // other # implement some logic here - - def __idiv__(self, other): # Python 2 compatibility - return type(self).__itruediv__(self, other) - -Special methods are looked up on the class and not on the instance to reflect -the behavior of the Python interpreter. - -.. module: django.utils.six - -Writing compatible code with six --------------------------------- - -six_ is the canonical compatibility library for supporting Python 2 and 3 in -a single codebase. Read its documentation! - -A :mod:`customized version of six ` is bundled with Django -as of version 1.4.2. You can import it as ``django.utils.six``. - -Here are the most common changes required to write compatible code. - -.. _string-handling-with-six: - -String handling -~~~~~~~~~~~~~~~ - -The ``basestring`` and ``unicode`` types were removed in Python 3, and the -meaning of ``str`` changed. To test these types, use the following idioms:: - - isinstance(myvalue, six.string_types) # replacement for basestring - isinstance(myvalue, six.text_type) # replacement for unicode - isinstance(myvalue, bytes) # replacement for str - -Python ≥ 2.6 provides ``bytes`` as an alias for ``str``, so you don't need -:data:`six.binary_type`. - -``long`` -~~~~~~~~ - -The ``long`` type no longer exists in Python 3. ``1L`` is a syntax error. Use -:data:`six.integer_types` check if a value is an integer or a long:: - - isinstance(myvalue, six.integer_types) # replacement for (int, long) - -``xrange`` -~~~~~~~~~~ - -If you use ``xrange`` on Python 2, import ``six.moves.range`` and use that -instead. You can also import ``six.moves.xrange`` (it's equivalent to -``six.moves.range``) but the first technique allows you to simply drop the -import when dropping support for Python 2. - -Moved modules -~~~~~~~~~~~~~ - -Some modules were renamed in Python 3. The ``django.utils.six.moves`` -module (based on the :mod:`six.moves module `) provides a -compatible location to import them. - -``PY2`` -~~~~~~~ - -If you need different code in Python 2 and Python 3, check :data:`six.PY2`:: - - if six.PY2: - # compatibility code for Python 2 - -This is a last resort solution when :mod:`six` doesn't provide an appropriate -function. - -.. module:: django.utils.six - -Django customized version of ``six`` ------------------------------------- - -The version of six bundled with Django (``django.utils.six``) includes a few -customizations for internal use only. - -.. _unicode: https://docs.python.org/2/library/functions.html#unicode -.. _ __unicode__(): https://docs.python.org/2/reference/datamodel.html#object.__unicode__ -.. _basestring: https://docs.python.org/2/library/functions.html#basestring diff --git a/docs/topics/testing/overview.txt b/docs/topics/testing/overview.txt index 245ee07079..5687e07e2e 100644 --- a/docs/topics/testing/overview.txt +++ b/docs/topics/testing/overview.txt @@ -177,9 +177,9 @@ control the particular collation used by the test database. See the :doc:`settings documentation ` for details of these and other advanced settings. -If using an SQLite in-memory database with Python 3.4+ and SQLite 3.7.13+, -`shared cache `_ will be enabled, so -you can write tests with ability to share the database between threads. +If using an SQLite in-memory database with SQLite 3.7.13+, `shared cache +`_ is enabled, so you can write tests +with ability to share the database between threads. .. admonition:: Finding data from your production database when running tests? diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt index b8c799619e..91f9690827 100644 --- a/docs/topics/testing/tools.txt +++ b/docs/topics/testing/tools.txt @@ -1708,9 +1708,9 @@ Management commands can be tested with the :func:`~django.core.management.call_command` function. The output can be redirected into a ``StringIO`` instance:: + from io import StringIO from django.core.management import call_command from django.test import TestCase - from django.utils.six import StringIO class ClosepollTest(TestCase): def test_command_output(self):