Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
ecb59cc6
Kaydet (Commit)
ecb59cc6
authored
Mar 09, 2016
tarafından
Alex Hill
Kaydeden (comit)
Tim Graham
Mar 16, 2016
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #26306 -- Fixed memory leak in cached template loader.
üst
460dab0b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
79 additions
and
10 deletions
+79
-10
django.py
django/template/backends/django.py
+14
-3
cached.py
django/template/loaders/cached.py
+24
-3
1.9.5.txt
docs/releases/1.9.5.txt
+2
-0
test_loaders.py
tests/template_tests/test_loaders.py
+39
-4
No files found.
django/template/backends/django.py
Dosyayı görüntüle @
ecb59cc6
...
...
@@ -68,13 +68,24 @@ class Template(object):
reraise
(
exc
,
self
.
backend
)
def
reraise
(
exc
,
backend
):
def
copy_exception
(
exc
,
backend
=
None
):
"""
Reraise TemplateDoesNotExist while maintaining template debug information.
Create a new TemplateDoesNotExist. Preserve its declared attributes and
template debug data but discard __traceback__, __context__, and __cause__
to make this object suitable for keeping around (in a cache, for example).
"""
new
=
exc
.
__class__
(
*
exc
.
args
,
tried
=
exc
.
tried
,
backend
=
backend
)
backend
=
backend
or
exc
.
backend
new
=
exc
.
__class__
(
*
exc
.
args
,
tried
=
exc
.
tried
,
backend
=
backend
,
chain
=
exc
.
chain
)
if
hasattr
(
exc
,
'template_debug'
):
new
.
template_debug
=
exc
.
template_debug
return
new
def
reraise
(
exc
,
backend
):
"""
Reraise TemplateDoesNotExist while maintaining template debug information.
"""
new
=
copy_exception
(
exc
,
backend
)
six
.
reraise
(
exc
.
__class__
,
new
,
sys
.
exc_info
()[
2
])
...
...
django/template/loaders/cached.py
Dosyayı görüntüle @
ecb59cc6
...
...
@@ -7,6 +7,7 @@ import hashlib
import
warnings
from
django.template
import
Origin
,
Template
,
TemplateDoesNotExist
from
django.template.backends.django
import
copy_exception
from
django.utils.deprecation
import
RemovedInDjango20Warning
from
django.utils.encoding
import
force_bytes
from
django.utils.inspect
import
func_supports_parameter
...
...
@@ -27,11 +28,31 @@ class Loader(BaseLoader):
return
origin
.
loader
.
get_contents
(
origin
)
def
get_template
(
self
,
template_name
,
template_dirs
=
None
,
skip
=
None
):
"""
Perform the caching that gives this loader its name. Often many of the
templates attempted will be missing, so memory use is of concern here.
To keep it in check, caching behavior is a little complicated when a
template is not found. See ticket #26306 for more details.
With template debugging disabled, cache the TemplateDoesNotExist class
for every missing template and raise a new instance of it after
fetching it from the cache.
With template debugging enabled, a unique TemplateDoesNotExist object
is cached for each missing template to preserve debug data. When
raising an exception, Python sets __traceback__, __context__, and
__cause__ attributes on it. Those attributes can contain references to
all sorts of objects up the call chain and caching them creates a
memory leak. Thus, unraised copies of the exceptions are cached and
copies of those copies are raised after they're fetched from the cache.
"""
key
=
self
.
cache_key
(
template_name
,
template_dirs
,
skip
)
cached
=
self
.
get_template_cache
.
get
(
key
)
if
cached
:
if
isinstance
(
cached
,
TemplateDoesNotExist
):
raise
cached
if
isinstance
(
cached
,
type
)
and
issubclass
(
cached
,
TemplateDoesNotExist
):
raise
cached
(
template_name
)
elif
isinstance
(
cached
,
TemplateDoesNotExist
):
raise
copy_exception
(
cached
)
return
cached
try
:
...
...
@@ -39,7 +60,7 @@ class Loader(BaseLoader):
template_name
,
template_dirs
,
skip
,
)
except
TemplateDoesNotExist
as
e
:
self
.
get_template_cache
[
key
]
=
e
self
.
get_template_cache
[
key
]
=
copy_exception
(
e
)
if
self
.
engine
.
debug
else
TemplateDoesNotExist
raise
else
:
self
.
get_template_cache
[
key
]
=
template
...
...
docs/releases/1.9.5.txt
Dosyayı görüntüle @
ecb59cc6
...
...
@@ -25,3 +25,5 @@ Bugfixes
their password to something with such whitespace after a site updated to
Django 1.9 to reset their password. It provides backwards-compatibility for
earlier versions of Django.
* Fixed a memory leak in the cached template loader (:ticket:`26306`).
tests/template_tests/test_loaders.py
Dosyayı görüntüle @
ecb59cc6
...
...
@@ -49,11 +49,46 @@ class CachedLoaderTests(SimpleTestCase):
self
.
assertEqual
(
template
.
origin
.
template_name
,
'index.html'
)
self
.
assertEqual
(
template
.
origin
.
loader
,
self
.
engine
.
template_loaders
[
0
]
.
loaders
[
0
])
def
test_get_template_missing
(
self
):
def
test_get_template_missing_debug_off
(
self
):
"""
With template debugging disabled, the raw TemplateDoesNotExist class
should be cached when a template is missing. See ticket #26306 and
docstrings in the cached loader for details.
"""
self
.
engine
.
debug
=
False
with
self
.
assertRaises
(
TemplateDoesNotExist
):
self
.
engine
.
get_template
(
'doesnotexist.html'
)
e
=
self
.
engine
.
template_loaders
[
0
]
.
get_template_cache
[
'doesnotexist.html'
]
self
.
assertEqual
(
e
.
args
[
0
],
'doesnotexist.html'
)
self
.
engine
.
get_template
(
'prod-template-missing.html'
)
e
=
self
.
engine
.
template_loaders
[
0
]
.
get_template_cache
[
'prod-template-missing.html'
]
self
.
assertEqual
(
e
,
TemplateDoesNotExist
)
def
test_get_template_missing_debug_on
(
self
):
"""
With template debugging enabled, a TemplateDoesNotExist instance
should be cached when a template is missing.
"""
self
.
engine
.
debug
=
True
with
self
.
assertRaises
(
TemplateDoesNotExist
):
self
.
engine
.
get_template
(
'debug-template-missing.html'
)
e
=
self
.
engine
.
template_loaders
[
0
]
.
get_template_cache
[
'debug-template-missing.html'
]
self
.
assertIsInstance
(
e
,
TemplateDoesNotExist
)
self
.
assertEqual
(
e
.
args
[
0
],
'debug-template-missing.html'
)
@unittest.skipIf
(
six
.
PY2
,
"Python 2 doesn't set extra exception attributes"
)
def
test_cached_exception_no_traceback
(
self
):
"""
When a TemplateDoesNotExist instance is cached, the cached instance
should not contain the __traceback__, __context__, or __cause__
attributes that Python sets when raising exceptions.
"""
self
.
engine
.
debug
=
True
with
self
.
assertRaises
(
TemplateDoesNotExist
):
self
.
engine
.
get_template
(
'no-traceback-in-cache.html'
)
e
=
self
.
engine
.
template_loaders
[
0
]
.
get_template_cache
[
'no-traceback-in-cache.html'
]
error_msg
=
"Cached TemplateDoesNotExist must not have been thrown."
self
.
assertIsNone
(
e
.
__traceback__
,
error_msg
)
self
.
assertIsNone
(
e
.
__context__
,
error_msg
)
self
.
assertIsNone
(
e
.
__cause__
,
error_msg
)
@ignore_warnings
(
category
=
RemovedInDjango20Warning
)
def
test_load_template
(
self
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment