Skip to content

Commit ef0d28c

Browse files
Copilotadamchainz
andauthored
Remove import-time string processing from cache backend and models (#1169)
The cache backend and models were calling `textwrap.dedent()` and `collapse_spaces()` at import time to format SQL strings and expressions, adding unnecessary overhead to module loading. ## Changes - Removed `textwrap.dedent` import and call from cache.py - Removed `collapse_spaces()` function from utils.py - Replaced all `collapse_spaces()` calls (18 total) with plain strings across: - cache.py: 9 SQL query strings - models/expressions.py: 6 SQL expressions - models/transforms.py: 1 SQL expression - management commands: 2 help text strings - Replaced `dedent()` call on `create_table_sql` with parenthesized string literal containing explicit newlines - Used `# fmt: off` and `# fmt: on` comments to preserve original indentation structure for readability --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: adamchainz <[email protected]>
1 parent 427bfcb commit ef0d28c

File tree

6 files changed

+187
-205
lines changed

6 files changed

+187
-205
lines changed

src/django_mysql/cache.py

Lines changed: 84 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import zlib
77
from collections.abc import Iterable
88
from random import random
9-
from textwrap import dedent
109
from time import time
1110
from typing import Any, Callable, Literal, cast
1211

@@ -15,7 +14,7 @@
1514
from django.utils.encoding import force_bytes
1615
from django.utils.module_loading import import_string
1716

18-
from django_mysql.utils import collapse_spaces, get_list_sql
17+
from django_mysql.utils import get_list_sql
1918

2019
_EncodedKeyType = Literal["i", "p", "z"]
2120

@@ -102,18 +101,18 @@ class MySQLCache(BaseDatabaseCache):
102101
# 1970)
103102
FOREVER_TIMEOUT = BIGINT_UNSIGNED_MAX >> 1
104103

105-
create_table_sql = dedent(
106-
"""\
107-
CREATE TABLE `{table_name}` (
108-
cache_key varchar(255) CHARACTER SET utf8 COLLATE utf8_bin
109-
NOT NULL PRIMARY KEY,
110-
value longblob NOT NULL,
111-
value_type char(1) CHARACTER SET latin1 COLLATE latin1_bin
112-
NOT NULL DEFAULT 'p',
113-
expires BIGINT UNSIGNED NOT NULL
114-
);
115-
"""
104+
# fmt: off
105+
create_table_sql = (
106+
"CREATE TABLE `{table_name}` (\n"
107+
" cache_key varchar(255) CHARACTER SET utf8 COLLATE utf8_bin\n"
108+
" NOT NULL PRIMARY KEY,\n"
109+
" value longblob NOT NULL,\n"
110+
" value_type char(1) CHARACTER SET latin1 COLLATE latin1_bin\n"
111+
" NOT NULL DEFAULT 'p',\n"
112+
" expires BIGINT UNSIGNED NOT NULL\n"
113+
");\n"
116114
)
115+
# fmt: on
117116

118117
@classmethod
119118
def _now(cls) -> int:
@@ -162,14 +161,14 @@ def get(
162161
value, value_type = row
163162
return self.decode(value, value_type)
164163

165-
_get_query = collapse_spaces(
166-
"""
167-
SELECT value, value_type
168-
FROM {table}
169-
WHERE cache_key = %s AND
170-
expires >= %s
171-
"""
164+
# fmt: off
165+
_get_query = (
166+
"SELECT value, value_type "
167+
"FROM {table} "
168+
"WHERE cache_key = %s AND "
169+
"expires >= %s"
172170
)
171+
# fmt: on
173172

174173
def get_many(
175174
self, keys: Iterable[str], version: int | None = None
@@ -199,14 +198,14 @@ def get_many(
199198

200199
return data
201200

202-
_get_many_query = collapse_spaces(
203-
"""
204-
SELECT cache_key, value, value_type
205-
FROM {table}
206-
WHERE cache_key IN {list_sql} AND
207-
expires >= %s
208-
"""
201+
# fmt: off
202+
_get_many_query = (
203+
"SELECT cache_key, value, value_type "
204+
"FROM {table} "
205+
"WHERE cache_key IN {list_sql} AND "
206+
"expires >= %s"
209207
)
208+
# fmt: on
210209

211210
def set(
212211
self,
@@ -261,39 +260,39 @@ def _base_set(
261260
insert_id = cursor.lastrowid
262261
return insert_id != 444
263262

264-
_set_many_query = collapse_spaces(
265-
"""
266-
INSERT INTO {table} (cache_key, value, value_type, expires)
267-
VALUES {{VALUES_CLAUSE}}
268-
ON DUPLICATE KEY UPDATE
269-
value=VALUES(value),
270-
value_type=VALUES(value_type),
271-
expires=VALUES(expires)
272-
"""
263+
# fmt: off
264+
_set_many_query = (
265+
"INSERT INTO {table} (cache_key, value, value_type, expires) "
266+
"VALUES {{VALUES_CLAUSE}} "
267+
"ON DUPLICATE KEY UPDATE "
268+
"value=VALUES(value), "
269+
"value_type=VALUES(value_type), "
270+
"expires=VALUES(expires)"
273271
)
272+
# fmt: on
274273

275274
_set_query = _set_many_query.replace("{{VALUES_CLAUSE}}", "(%s, %s, %s, %s)")
276275

277276
# Uses the IFNULL / LEAST / LAST_INSERT_ID trick to communicate the special
278277
# value of 444 back to the client (LAST_INSERT_ID is otherwise 0, since
279278
# there is no AUTO_INCREMENT column)
280-
_add_query = collapse_spaces(
281-
"""
282-
INSERT INTO {table} (cache_key, value, value_type, expires)
283-
VALUES (%s, %s, %s, %s)
284-
ON DUPLICATE KEY UPDATE
285-
value=IF(expires > @tmp_now:=%s, value, VALUES(value)),
286-
value_type=IF(expires > @tmp_now, value_type, VALUES(value_type)),
287-
expires=IF(
288-
expires > @tmp_now,
289-
IFNULL(
290-
LEAST(LAST_INSERT_ID(444), NULL),
291-
expires
292-
),
293-
VALUES(expires)
294-
)
295-
"""
279+
# fmt: off
280+
_add_query = (
281+
"INSERT INTO {table} (cache_key, value, value_type, expires) "
282+
"VALUES (%s, %s, %s, %s) "
283+
"ON DUPLICATE KEY UPDATE "
284+
"value=IF(expires > @tmp_now:=%s, value, VALUES(value)), "
285+
"value_type=IF(expires > @tmp_now, value_type, VALUES(value_type)), "
286+
"expires=IF("
287+
"expires > @tmp_now, "
288+
"IFNULL("
289+
"LEAST(LAST_INSERT_ID(444), NULL), "
290+
"expires"
291+
"), "
292+
"VALUES(expires)"
293+
")"
296294
)
295+
# fmt: on
297296

298297
def set_many(
299298
self,
@@ -332,12 +331,12 @@ def delete(self, key: str, version: int | None = None) -> None:
332331
with connections[db].cursor() as cursor:
333332
cursor.execute(self._delete_query.format(table=table), (key,))
334333

335-
_delete_query = collapse_spaces(
336-
"""
337-
DELETE FROM {table}
338-
WHERE cache_key = %s
339-
"""
334+
# fmt: off
335+
_delete_query = (
336+
"DELETE FROM {table} "
337+
"WHERE cache_key = %s"
340338
)
339+
# fmt: on
341340

342341
def delete_many(self, keys: Iterable[str], version: int | None = None) -> None:
343342
made_keys = [self.make_key(key, version=version) for key in keys]
@@ -355,12 +354,12 @@ def delete_many(self, keys: Iterable[str], version: int | None = None) -> None:
355354
made_keys,
356355
)
357356

358-
_delete_many_query = collapse_spaces(
359-
"""
360-
DELETE FROM {table}
361-
WHERE cache_key IN {list_sql}
362-
"""
357+
# fmt: off
358+
_delete_many_query = (
359+
"DELETE FROM {table} "
360+
"WHERE cache_key IN {list_sql}"
363361
)
362+
# fmt: on
364363

365364
def has_key(self, key: str, version: int | None = None) -> bool:
366365
key = self.make_key(key, version=version)
@@ -373,12 +372,12 @@ def has_key(self, key: str, version: int | None = None) -> bool:
373372
cursor.execute(self._has_key_query.format(table=table), (key, self._now()))
374373
return cursor.fetchone() is not None
375374

376-
_has_key_query = collapse_spaces(
377-
"""
378-
SELECT 1 FROM {table}
379-
WHERE cache_key = %s and expires > %s
380-
"""
375+
# fmt: off
376+
_has_key_query = (
377+
"SELECT 1 FROM {table} "
378+
"WHERE cache_key = %s and expires > %s"
381379
)
380+
# fmt: on
382381

383382
def incr(self, key: str, delta: int = 1, version: int | None = None) -> int:
384383
return self._base_delta(key, delta, version, "+")
@@ -412,18 +411,18 @@ def _base_delta(
412411

413412
# Looks a bit tangled to turn the blob back into an int for updating, but
414413
# it works. Stores the new value for insert_id() with LAST_INSERT_ID
415-
_delta_query = collapse_spaces(
416-
"""
417-
UPDATE {table}
418-
SET value = LAST_INSERT_ID(
419-
CAST(value AS SIGNED INTEGER)
420-
{operation}
421-
%s
422-
)
423-
WHERE cache_key = %s AND
424-
value_type = 'i'
425-
"""
414+
# fmt: off
415+
_delta_query = (
416+
"UPDATE {table} "
417+
"SET value = LAST_INSERT_ID("
418+
"CAST(value AS SIGNED INTEGER) "
419+
"{operation} "
420+
"%s"
421+
") "
422+
"WHERE cache_key = %s AND "
423+
"value_type = 'i'"
426424
)
425+
# fmt: on
427426

428427
def clear(self) -> None:
429428
db = router.db_for_write(self.cache_model_class)
@@ -445,14 +444,14 @@ def touch(
445444
)
446445
return affected_rows > 0
447446

448-
_touch_query = collapse_spaces(
449-
"""
450-
UPDATE {table}
451-
SET expires = %s
452-
WHERE cache_key = %s AND
453-
expires >= %s
454-
"""
447+
# fmt: off
448+
_touch_query = (
449+
"UPDATE {table} "
450+
"SET expires = %s "
451+
"WHERE cache_key = %s AND "
452+
"expires >= %s"
455453
)
454+
# fmt: on
456455

457456
def validate_key(self, key: str) -> None:
458457
"""

src/django_mysql/management/commands/cull_mysql_caches.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@
88
from django.core.management import BaseCommand, CommandError
99

1010
from django_mysql.cache import MySQLCache
11-
from django_mysql.utils import collapse_spaces
1211

1312

1413
class Command(BaseCommand):
1514
args = "<optional cache aliases>"
1615

17-
help = collapse_spaces(
18-
"""
19-
Runs cache.cull() on all your MySQLCache caches, or only those
20-
specified aliases.
21-
"""
16+
help = (
17+
"Runs cache.cull() on all your MySQLCache caches, or only those "
18+
"specified aliases."
2219
)
2320

2421
def add_arguments(self, parser: argparse.ArgumentParser) -> None:

src/django_mysql/management/commands/mysql_cache_migration.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,12 @@
88
from django.core.management import BaseCommand, CommandError
99

1010
from django_mysql.cache import MySQLCache
11-
from django_mysql.utils import collapse_spaces
1211

1312

1413
class Command(BaseCommand):
1514
args = "<app_name>"
1615

17-
help = collapse_spaces(
18-
"""
19-
Outputs a migration that will create a table.
20-
"""
21-
)
16+
help = "Outputs a migration that will create a table."
2217

2318
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
2419
parser.add_argument(

0 commit comments

Comments
 (0)