Skip to content

Commit 5708327

Browse files
jdufresnefelixxm
authored andcommitted
Fixed #23433 -- Deprecated django-admin.py entry point in favor of django-admin.
Unify on the entry point created by setuptools entry_points feature.
1 parent 8eb0f73 commit 5708327

10 files changed

Lines changed: 79 additions & 32 deletions

File tree

django/bin/django-admin.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
#!/usr/bin/env python
2+
# When the django-admin.py deprecation ends, remove this script.
3+
import warnings
4+
25
from django.core import management
36

7+
try:
8+
from django.utils.deprecation import RemovedInDjango40Warning
9+
except ImportError:
10+
raise ImportError(
11+
'django-admin.py was deprecated in Django 3.1 and removed in Django '
12+
'4.0. Please manually remove this script from your virtual environment '
13+
'and use django-admin instead.'
14+
)
15+
416
if __name__ == "__main__":
17+
warnings.warn(
18+
'django-admin.py is deprecated in favor of django-admin.',
19+
RemovedInDjango40Warning,
20+
)
521
management.execute_from_command_line()

docs/faq/troubleshooting.txt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,9 @@ Problems running ``django-admin``
1414
-----------------------------------
1515

1616
:doc:`django-admin </ref/django-admin>` should be on your system path if you
17-
installed Django via ``pip``. If it's not on your path, you can find it in
18-
``site-packages/django/bin``, where ``site-packages`` is a directory within
19-
your Python installation. Consider symlinking to :doc:`django-admin
20-
</ref/django-admin>` from some place on your path, such as
21-
:file:`/usr/local/bin`.
22-
23-
If ``django-admin`` doesn't work but ``django-admin.py`` does, you're probably
24-
using a version of Django that doesn't match the version of this documentation.
25-
``django-admin`` is new in Django 1.7.
17+
installed Django via ``pip``. If it's not in your path, ensure you have your
18+
virtual environment activated and you can try running the equivalent command
19+
``python -m django``.
2620

2721
macOS permissions
2822
-----------------

docs/internals/contributing/writing-documentation.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ define some extra description units:
287287
:ticket:`12345`
288288

289289
Django's documentation uses a custom ``console`` directive for documenting
290-
command-line examples involving ``django-admin.py``, ``manage.py``, ``python``,
290+
command-line examples involving ``django-admin``, ``manage.py``, ``python``,
291291
etc.). In the HTML documentation, it renders a two-tab UI, with one tab showing
292292
a Unix-style command prompt and a second tab showing a Windows prompt.
293293

docs/internals/deprecation.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ details on these changes.
4242
* The ``django.db.models.query_utils.InvalidQuery`` exception class will be
4343
removed.
4444

45+
* The ``django-admin.py`` entry point will be removed.
46+
4547
See the :ref:`Django 3.1 release notes <deprecated-features-3.1>` for more
4648
details on these changes.
4749

docs/ref/django-admin.txt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,8 @@ does the same thing as ``django-admin`` but also sets the
1111
project's ``settings.py`` file.
1212

1313
The ``django-admin`` script should be on your system path if you installed
14-
Django via ``pip``. If it's not on your path, you can find it in
15-
``site-packages/django/bin`` within your Python installation. Consider
16-
symlinking it from some place on your path, such as ``/usr/local/bin``.
17-
18-
For Windows users, who do not have symlinking functionality available, you can
19-
copy ``django-admin.exe`` to a location on your existing path or edit the
20-
``PATH`` settings (under ``Settings - Control Panel - System - Advanced -
21-
Environment...``) to point to its installed location.
14+
Django via ``pip``. If it's not in your path, ensure you have your virtual
15+
environment activated.
2216

2317
Generally, when working on a single Django project, it's easier to use
2418
``manage.py`` than ``django-admin``. If you need to switch between multiple

docs/releases/3.1.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ Miscellaneous
384384
:class:`~django.core.exceptions.FieldDoesNotExist` and
385385
:class:`~django.core.exceptions.FieldError`.
386386

387+
* The ``django-admin.py`` entry point is deprecated in favor of
388+
``django-admin``.
389+
387390
.. _removed-features-3.1:
388391

389392
Features removed in 3.1

extras/django_bash_completion

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# #########################################################################
2-
# This bash script adds tab-completion feature to django-admin.py and
3-
# manage.py.
1+
# #############################################################################
2+
# This bash script adds tab-completion feature to django-admin and manage.py.
43
#
54
# Testing it out without installing
65
# =================================
@@ -37,6 +36,7 @@ _django_completion()
3736
COMP_CWORD=$COMP_CWORD \
3837
DJANGO_AUTO_COMPLETE=1 $1 ) )
3938
}
39+
# When the django-admin.py deprecation ends, remove django-admin.py.
4040
complete -F _django_completion -o default django-admin.py manage.py django-admin
4141

4242
_python_django_completion()

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ project_urls =
3434
[options]
3535
python_requires = >=3.6
3636
packages = find:
37+
# When the django-admin.py deprecation ends, remove "scripts".
3738
scripts = django/bin/django-admin.py
3839
include_package_data = true
3940
zip_safe = false
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import subprocess
2+
import sys
3+
from pathlib import Path
4+
5+
import django
6+
from django.test import SimpleTestCase
7+
8+
9+
class DeprecationTests(SimpleTestCase):
10+
DEPRECATION_MESSAGE = (
11+
b'RemovedInDjango40Warning: django-admin.py is deprecated in favor of '
12+
b'django-admin.'
13+
)
14+
15+
def _run_test(self, args):
16+
p = subprocess.run(
17+
[sys.executable, *args],
18+
stdout=subprocess.PIPE,
19+
stderr=subprocess.PIPE,
20+
check=True,
21+
)
22+
return p.stdout, p.stderr
23+
24+
def test_django_admin_py_deprecated(self):
25+
django_admin_py = Path(django.__file__).parent / 'bin' / 'django-admin.py'
26+
_, err = self._run_test(['-Wd', django_admin_py, '--version'])
27+
self.assertIn(self.DEPRECATION_MESSAGE, err)
28+
29+
def test_main_not_deprecated(self):
30+
_, err = self._run_test(['-Wd', '-m', 'django', '--version'])
31+
self.assertNotIn(self.DEPRECATION_MESSAGE, err)
32+
33+
def test_django_admin_py_equivalent_main(self):
34+
django_admin_py = Path(django.__file__).parent / 'bin' / 'django-admin.py'
35+
django_admin_py_out, _ = self._run_test([django_admin_py, '--version'])
36+
django_out, _ = self._run_test(['-m', 'django', '--version'])
37+
self.assertEqual(django_admin_py_out, django_out)

tests/admin_scripts/tests.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from io import StringIO
1515
from unittest import mock
1616

17-
import django
1817
from django import conf, get_version
1918
from django.conf import settings
2019
from django.core.management import (
@@ -125,8 +124,7 @@ def run_test(self, args, settings_file=None, apps=None):
125124
return p.stdout, p.stderr
126125

127126
def run_django_admin(self, args, settings_file=None):
128-
script_dir = os.path.abspath(os.path.join(os.path.dirname(django.__file__), 'bin'))
129-
return self.run_test([os.path.join(script_dir, 'django-admin.py'), *args], settings_file)
127+
return self.run_test(['-m', 'django', *args], settings_file)
130128

131129
def run_manage(self, args, settings_file=None, manage_py=None):
132130
template_manage_py = (
@@ -1898,7 +1896,12 @@ def test_simple_project(self):
18981896
# running again..
18991897
out, err = self.run_django_admin(args)
19001898
self.assertNoOutput(out)
1901-
self.assertOutput(err, "already exists")
1899+
self.assertOutput(
1900+
err,
1901+
"CommandError: 'testproject' conflicts with the name of an "
1902+
"existing Python module and cannot be used as a project name. "
1903+
"Please try another name.",
1904+
)
19021905

19031906
def test_invalid_project_name(self):
19041907
"Make sure the startproject management command validates a project name"
@@ -2160,8 +2163,10 @@ def test_importable_target_name(self):
21602163
)
21612164

21622165
def test_overlaying_app(self):
2163-
self.run_django_admin(['startapp', 'app1'])
2164-
out, err = self.run_django_admin(['startapp', 'app2', 'app1'])
2166+
# Use a subdirectory so it is outside the PYTHONPATH.
2167+
os.makedirs(os.path.join(self.test_dir, 'apps/app1'))
2168+
self.run_django_admin(['startapp', 'app1', 'apps/app1'])
2169+
out, err = self.run_django_admin(['startapp', 'app2', 'apps/app1'])
21652170
self.assertOutput(
21662171
err,
21672172
"already exists. Overlaying an app into an existing directory "
@@ -2261,11 +2266,6 @@ def test_pks_parsing(self):
22612266
class MainModule(AdminScriptTestCase):
22622267
"""python -m django works like django-admin."""
22632268

2264-
def test_runs_django_admin(self):
2265-
cmd_out, _ = self.run_django_admin(['--version'])
2266-
mod_out, _ = self.run_test(['-m', 'django', '--version'])
2267-
self.assertEqual(mod_out, cmd_out)
2268-
22692269
def test_program_name_in_help(self):
22702270
out, err = self.run_test(['-m', 'django', 'help'])
22712271
self.assertOutput(out, "Type 'python -m django help <subcommand>' for help on a specific subcommand.")

0 commit comments

Comments
 (0)