Fixed #25968 -- Changed project/app templates to use a "py-tpl" suffix.
Debian packages unconditionally byte-compile .py files on installation and do not silence errors by design. Therefore, we need a way of shipping these invalid .py files without a .py extension but ensuring that when we template them, they end up as .py. We don't special-case .py files so that the all the TemplateCommand command-line options (eg. extra_files and extensions) still work entirely as expected and it may even be useful for other formats too.
This commit is contained in:
parent
9c43d8252a
commit
abc0777b63
|
@ -42,6 +42,11 @@ class TemplateCommand(BaseCommand):
|
|||
# Can't perform any active locale changes during this command, because
|
||||
# setting might not be available at all.
|
||||
leave_locale_alone = True
|
||||
# Rewrite the following suffixes when determining the target filename.
|
||||
rewrite_template_suffixes = (
|
||||
# Allow shipping invalid .py files without byte-compilation.
|
||||
('.py-tpl', '.py'),
|
||||
)
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('name', help='Name of the application or project.')
|
||||
|
@ -139,6 +144,11 @@ class TemplateCommand(BaseCommand):
|
|||
old_path = path.join(root, filename)
|
||||
new_path = path.join(top_dir, relative_dir,
|
||||
filename.replace(base_name, name))
|
||||
for old_suffix, new_suffix in self.rewrite_template_suffixes:
|
||||
if new_path.endswith(old_suffix):
|
||||
new_path = new_path[:-len(old_suffix)] + new_suffix
|
||||
break # Only rewrite once
|
||||
|
||||
if path.exists(new_path):
|
||||
raise CommandError("%s already exists, overlaying a "
|
||||
"project or app into an existing "
|
||||
|
@ -149,7 +159,7 @@ class TemplateCommand(BaseCommand):
|
|||
# accidentally render Django templates files
|
||||
with open(old_path, 'rb') as template_file:
|
||||
content = template_file.read()
|
||||
if filename.endswith(extensions) or filename in extra_files:
|
||||
if new_path.endswith(extensions) or filename in extra_files:
|
||||
content = content.decode('utf-8')
|
||||
template = Engine().from_string(content)
|
||||
content = template.render(context)
|
||||
|
|
|
@ -1175,6 +1175,15 @@ files is:
|
|||
To work around this problem, you can use the :ttag:`templatetag`
|
||||
templatetag to "escape" the various parts of the template syntax.
|
||||
|
||||
In addition, to allow Python template files that contain Django template
|
||||
language syntax while also preventing packaging systems from trying to
|
||||
byte-compile invalid ``*.py`` files, template files ending with ``.py-tpl``
|
||||
will be renamed to ``.py``.
|
||||
|
||||
.. versionchanged:: 1.9.2
|
||||
|
||||
Renaming of ``.py-tpl`` to ``.py`` was added.
|
||||
|
||||
.. _source: https://github.com/django/django/tree/master/django/conf/app_template/
|
||||
|
||||
startproject
|
||||
|
|
|
@ -4,7 +4,24 @@ Django 1.9.2 release notes
|
|||
|
||||
*Under development*
|
||||
|
||||
Django 1.9.2 fixes several bugs in 1.9.1.
|
||||
Django 1.9.2 fixes several bugs in 1.9.1 and makes a small backwards
|
||||
incompatible change that hopefully doesn't affect any users.
|
||||
|
||||
Backwards incompatible change: ``.py-tpl`` files rewritten in project/app templates
|
||||
===================================================================================
|
||||
|
||||
The addition of some Django template language syntax to the default app
|
||||
template in Django 1.9 means those files now have some invalid Python syntax.
|
||||
This causes difficulties for packaging systems that unconditionally
|
||||
byte-compile ``*.py`` files.
|
||||
|
||||
To remedy this, a ``.py-tpl`` suffix is now used for the project and app
|
||||
template files included in Django. The ``.py-tpl`` suffix is replaced with
|
||||
``.py`` by the ``startproject`` and ``startapp`` commands. For example, a
|
||||
template with the filename ``manage.py-tpl`` will be created as ``manage.py``.
|
||||
|
||||
Please file a ticket if you have a custom project template containing
|
||||
``.py-tpl`` files and find this behavior problematic.
|
||||
|
||||
Bugfixes
|
||||
========
|
||||
|
|
|
@ -1017,7 +1017,7 @@ a Django application with this structure::
|
|||
``SyntaxError`` when installing Django setuptools 5.5.x
|
||||
-------------------------------------------------------
|
||||
|
||||
When installing Django 1.9+ with setuptools 5.5.x, you'll see::
|
||||
When installing Django 1.9 or 1.9.1 with setuptools 5.5.x, you'll see::
|
||||
|
||||
Compiling django/conf/app_template/apps.py ...
|
||||
File "django/conf/app_template/apps.py", line 4
|
||||
|
@ -1034,7 +1034,8 @@ When installing Django 1.9+ with setuptools 5.5.x, you'll see::
|
|||
It's safe to ignore these errors (Django will still install just fine), but you
|
||||
can avoid them by upgrading setuptools to a more recent version. If you're
|
||||
using pip, you can upgrade pip using ``pip install -U pip`` which will also
|
||||
upgrade setuptools.
|
||||
upgrade setuptools. This is resolved in later versions of Django as described
|
||||
in the :doc:`/releases/1.9.2`.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
|
|
@ -165,8 +165,7 @@ This is the recommended way to install Django.
|
|||
1. Install pip_. The easiest is to use the `standalone pip installer`_. If your
|
||||
distribution already has ``pip`` installed, you might need to update it if
|
||||
it's outdated. If it's outdated, you'll know because installation won't
|
||||
work. If you're using an old version of setuptools, you might see some
|
||||
:ref:`harmless SyntaxErrors <syntax-error-old-setuptools-django-19>` also.
|
||||
work.
|
||||
|
||||
2. Take a look at virtualenv_ and virtualenvwrapper_. These tools provide
|
||||
isolated Python environments, which are more practical than installing
|
||||
|
|
|
@ -181,7 +181,7 @@ class AdminScriptTestCase(unittest.TestCase):
|
|||
pass
|
||||
|
||||
conf_dir = os.path.dirname(upath(conf.__file__))
|
||||
template_manage_py = os.path.join(conf_dir, 'project_template', 'manage.py')
|
||||
template_manage_py = os.path.join(conf_dir, 'project_template', 'manage.py-tpl')
|
||||
|
||||
test_manage_py = os.path.join(self.test_dir, 'manage.py')
|
||||
shutil.copyfile(template_manage_py, test_manage_py)
|
||||
|
|
|
@ -1,13 +1,28 @@
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
|
||||
from django import conf
|
||||
from django.test import TestCase
|
||||
from django.utils import six
|
||||
from django.utils._os import upath
|
||||
|
||||
|
||||
@unittest.skipIf(six.PY2,
|
||||
'Python 2 cannot import the project template because '
|
||||
'django/conf/project_template doesn\'t have an __init__.py file.')
|
||||
class TestStartProjectSettings(TestCase):
|
||||
def setUp(self):
|
||||
# Ensure settings.py exists
|
||||
project_dir = os.path.join(
|
||||
os.path.dirname(upath(conf.__file__)),
|
||||
'project_template',
|
||||
'project_name',
|
||||
)
|
||||
template_settings_py = os.path.join(project_dir, 'settings.py-tpl')
|
||||
test_settings_py = os.path.join(project_dir, 'settings.py')
|
||||
shutil.copyfile(template_settings_py, test_settings_py)
|
||||
self.addCleanup(os.remove, test_settings_py)
|
||||
|
||||
def test_middleware_classes_headers(self):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue