Skip to content

Commit ec0ff40

Browse files
felixxmcarltongibson
authored andcommitted
Fixed #32355 -- Dropped support for Python 3.6 and 3.7
1 parent 9c6ba87 commit ec0ff40

File tree

33 files changed

+59
-274
lines changed

33 files changed

+59
-274
lines changed

INSTALL

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Thanks for downloading Django.
22

3-
To install it, make sure you have Python 3.6 or greater installed. Then run
3+
To install it, make sure you have Python 3.8 or greater installed. Then run
44
this command from the command prompt:
55

66
python -m pip install .

django/core/management/commands/compilemessages.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,7 @@ def compile_messages(self, locations):
154154
self.has_errors = True
155155
return
156156

157-
# PY37: Remove str() when dropping support for PY37.
158-
# https://bugs.python.org/issue31961
159-
args = [self.program, *self.program_options, '-o', str(mo_path), str(po_path)]
157+
args = [self.program, *self.program_options, '-o', mo_path, po_path]
160158
futures.append(executor.submit(popen_wrapper, args))
161159

162160
for future in concurrent.futures.as_completed(futures):

django/db/backends/postgresql/base.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,7 @@ def chunked_cursor(self):
261261
# For now, it's here so that every use of "threading" is
262262
# also async-compatible.
263263
try:
264-
if hasattr(asyncio, 'current_task'):
265-
# Python 3.7 and up
266-
current_task = asyncio.current_task()
267-
else:
268-
# Python 3.6
269-
current_task = asyncio.Task.current_task()
264+
current_task = asyncio.current_task()
270265
except RuntimeError:
271266
current_task = None
272267
# Current task can be none even if the current_task call didn't error

django/db/backends/sqlite3/base.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from django.utils.dateparse import parse_datetime, parse_time
2626
from django.utils.duration import duration_microseconds
2727
from django.utils.regex_helper import _lazy_re_compile
28-
from django.utils.version import PY38
2928

3029
from .client import DatabaseClient
3130
from .creation import DatabaseCreation
@@ -180,9 +179,7 @@ def get_connection_params(self):
180179
"settings.DATABASES is improperly configured. "
181180
"Please supply the NAME value.")
182181
kwargs = {
183-
# TODO: Remove str() when dropping support for PY36.
184-
# https://bugs.python.org/issue33496
185-
'database': str(settings_dict['NAME']),
182+
'database': settings_dict['NAME'],
186183
'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
187184
**settings_dict['OPTIONS'],
188185
}
@@ -206,13 +203,10 @@ def get_connection_params(self):
206203
@async_unsafe
207204
def get_new_connection(self, conn_params):
208205
conn = Database.connect(**conn_params)
209-
if PY38:
210-
create_deterministic_function = functools.partial(
211-
conn.create_function,
212-
deterministic=True,
213-
)
214-
else:
215-
create_deterministic_function = conn.create_function
206+
create_deterministic_function = functools.partial(
207+
conn.create_function,
208+
deterministic=True,
209+
)
216210
create_deterministic_function('django_date_extract', 2, _sqlite_datetime_extract)
217211
create_deterministic_function('django_date_trunc', 4, _sqlite_date_trunc)
218212
create_deterministic_function('django_datetime_cast_date', 3, _sqlite_datetime_cast_date)

django/db/backends/sqlite3/client.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,5 @@ class DatabaseClient(BaseDatabaseClient):
66

77
@classmethod
88
def settings_to_cmd_args_env(cls, settings_dict, parameters):
9-
args = [
10-
cls.executable_name,
11-
# TODO: Remove str() when dropping support for PY37. args
12-
# parameter accepts path-like objects on Windows since Python 3.8.
13-
str(settings_dict['NAME']),
14-
*parameters,
15-
]
9+
args = [cls.executable_name, settings_dict['NAME'], *parameters]
1610
return args, None

django/db/migrations/questioner.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ def ask_initial(self, app_label):
4444
except ImportError:
4545
return self.defaults.get("ask_initial", False)
4646
else:
47-
# getattr() needed on PY36 and older (replace with attribute access).
4847
if getattr(migrations_module, "__file__", None):
4948
filenames = os.listdir(os.path.dirname(migrations_module.__file__))
5049
elif hasattr(migrations_module, "__path__"):

django/http/cookie.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
# For backwards compatibility in Django 2.1.
44
SimpleCookie = cookies.SimpleCookie
55

6-
# Add support for the SameSite attribute (obsolete when PY37 is unsupported).
7-
cookies.Morsel._reserved.setdefault('samesite', 'SameSite')
8-
96

107
def parse_cookie(cookie):
118
"""

django/http/request.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,10 @@
1818
from django.utils.encoding import escape_uri_path, iri_to_uri
1919
from django.utils.functional import cached_property
2020
from django.utils.http import is_same_domain
21-
from django.utils.inspect import func_supports_parameter
2221
from django.utils.regex_helper import _lazy_re_compile
2322

2423
from .multipartparser import parse_header
2524

26-
# TODO: Remove when dropping support for PY37. inspect.signature() is used to
27-
# detect whether the max_num_fields argument is available as this security fix
28-
# was backported to Python 3.6.8 and 3.7.2, and may also have been applied by
29-
# downstream package maintainers to other versions in their repositories.
30-
if not func_supports_parameter(parse_qsl, 'max_num_fields'):
31-
from django.utils.http import parse_qsl
32-
33-
3425
RAISE_ERROR = object()
3526
host_validation_re = _lazy_re_compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9\.:]+\])(:\d+)?$")
3627

django/test/runner.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
teardown_test_environment,
2222
)
2323
from django.utils.datastructures import OrderedSet
24-
from django.utils.version import PY37
2524

2625
try:
2726
import ipdb as pdb
@@ -240,8 +239,8 @@ def addFailure(self, test, err):
240239
self.stop_if_failfast()
241240

242241
def addSubTest(self, test, subtest, err):
243-
# Follow Python 3.5's implementation of unittest.TestResult.addSubTest()
244-
# by not doing anything when a subtest is successful.
242+
# Follow Python's implementation of unittest.TestResult.addSubTest() by
243+
# not doing anything when a subtest is successful.
245244
if err is not None:
246245
# Call check_picklable() before check_subtest_picklable() since
247246
# check_picklable() performs the tblib check.
@@ -540,15 +539,14 @@ def add_arguments(cls, parser):
540539
'Output timings, including database set up and total run time.'
541540
),
542541
)
543-
if PY37:
544-
parser.add_argument(
545-
'-k', action='append', dest='test_name_patterns',
546-
help=(
547-
'Only run test methods and classes that match the pattern '
548-
'or substring. Can be used multiple times. Same as '
549-
'unittest -k option.'
550-
),
551-
)
542+
parser.add_argument(
543+
'-k', action='append', dest='test_name_patterns',
544+
help=(
545+
'Only run test methods and classes that match the pattern '
546+
'or substring. Can be used multiple times. Same as '
547+
'unittest -k option.'
548+
),
549+
)
552550

553551
def setup_test_environment(self, **kwargs):
554552
setup_test_environment(debug=self.debug_mode)

django/utils/autoreload.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,15 +231,11 @@ def get_child_arguments():
231231
exe_entrypoint = py_script.with_suffix('.exe')
232232
if exe_entrypoint.exists():
233233
# Should be executed directly, ignoring sys.executable.
234-
# TODO: Remove str() when dropping support for PY37.
235-
# args parameter accepts path-like on Windows from Python 3.8.
236-
return [str(exe_entrypoint), *sys.argv[1:]]
234+
return [exe_entrypoint, *sys.argv[1:]]
237235
script_entrypoint = py_script.with_name('%s-script.py' % py_script.name)
238236
if script_entrypoint.exists():
239237
# Should be executed as usual.
240-
# TODO: Remove str() when dropping support for PY37.
241-
# args parameter accepts path-like on Windows from Python 3.8.
242-
return [*args, str(script_entrypoint), *sys.argv[1:]]
238+
return [*args, script_entrypoint, *sys.argv[1:]]
243239
raise RuntimeError('Script %s does not exist.' % py_script)
244240
else:
245241
args += sys.argv

0 commit comments

Comments
 (0)