mirror of https://github.com/django/django.git
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
|
# Can't perform any active locale changes during this command, because
|
||||||
# setting might not be available at all.
|
# setting might not be available at all.
|
||||||
leave_locale_alone = True
|
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):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument('name', help='Name of the application or project.')
|
parser.add_argument('name', help='Name of the application or project.')
|
||||||
|
@ -139,6 +144,11 @@ class TemplateCommand(BaseCommand):
|
||||||
old_path = path.join(root, filename)
|
old_path = path.join(root, filename)
|
||||||
new_path = path.join(top_dir, relative_dir,
|
new_path = path.join(top_dir, relative_dir,
|
||||||
filename.replace(base_name, name))
|
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):
|
if path.exists(new_path):
|
||||||
raise CommandError("%s already exists, overlaying a "
|
raise CommandError("%s already exists, overlaying a "
|
||||||
"project or app into an existing "
|
"project or app into an existing "
|
||||||
|
@ -149,7 +159,7 @@ class TemplateCommand(BaseCommand):
|
||||||
# accidentally render Django templates files
|
# accidentally render Django templates files
|
||||||
with open(old_path, 'rb') as template_file:
|
with open(old_path, 'rb') as template_file:
|
||||||
content = template_file.read()
|
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')
|
content = content.decode('utf-8')
|
||||||
template = Engine().from_string(content)
|
template = Engine().from_string(content)
|
||||||
content = template.render(context)
|
content = template.render(context)
|
||||||
|
|
|
@ -1175,6 +1175,15 @@ files is:
|
||||||
To work around this problem, you can use the :ttag:`templatetag`
|
To work around this problem, you can use the :ttag:`templatetag`
|
||||||
templatetag to "escape" the various parts of the template syntax.
|
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/
|
.. _source: https://github.com/django/django/tree/master/django/conf/app_template/
|
||||||
|
|
||||||
startproject
|
startproject
|
||||||
|
|
|
@ -4,7 +4,24 @@ Django 1.9.2 release notes
|
||||||
|
|
||||||
*Under development*
|
*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
|
Bugfixes
|
||||||
========
|
========
|
||||||
|
|
|
@ -1017,7 +1017,7 @@ a Django application with this structure::
|
||||||
``SyntaxError`` when installing Django setuptools 5.5.x
|
``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 ...
|
Compiling django/conf/app_template/apps.py ...
|
||||||
File "django/conf/app_template/apps.py", line 4
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
work.
|
||||||
:ref:`harmless SyntaxErrors <syntax-error-old-setuptools-django-19>` also.
|
|
||||||
|
|
||||||
2. Take a look at virtualenv_ and virtualenvwrapper_. These tools provide
|
2. Take a look at virtualenv_ and virtualenvwrapper_. These tools provide
|
||||||
isolated Python environments, which are more practical than installing
|
isolated Python environments, which are more practical than installing
|
||||||
|
|
|
@ -181,7 +181,7 @@ class AdminScriptTestCase(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
conf_dir = os.path.dirname(upath(conf.__file__))
|
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')
|
test_manage_py = os.path.join(self.test_dir, 'manage.py')
|
||||||
shutil.copyfile(template_manage_py, test_manage_py)
|
shutil.copyfile(template_manage_py, test_manage_py)
|
||||||
|
|
|
@ -1,13 +1,28 @@
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from django import conf
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
from django.utils._os import upath
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(six.PY2,
|
@unittest.skipIf(six.PY2,
|
||||||
'Python 2 cannot import the project template because '
|
'Python 2 cannot import the project template because '
|
||||||
'django/conf/project_template doesn\'t have an __init__.py file.')
|
'django/conf/project_template doesn\'t have an __init__.py file.')
|
||||||
class TestStartProjectSettings(TestCase):
|
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):
|
def test_middleware_classes_headers(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue