Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fdc50c3a
Commit
fdc50c3a
authored
Nov 29, 2017
by
Jeremy Bowman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PLAT-1419 Make edxmako a proper template backend
parent
989c3a30
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
308 additions
and
239 deletions
+308
-239
cms/djangoapps/contentstore/views/helpers.py
+3
-3
cms/envs/common.py
+41
-20
common/djangoapps/edxmako/__init__.py
+10
-0
common/djangoapps/edxmako/apps.py
+5
-2
common/djangoapps/edxmako/backend.py
+67
-0
common/djangoapps/edxmako/makoloader.py
+5
-4
common/djangoapps/edxmako/management/__init__.py
+0
-0
common/djangoapps/edxmako/management/commands/__init__.py
+0
-0
common/djangoapps/edxmako/request_context.py
+0
-19
common/djangoapps/edxmako/shortcuts.py
+14
-43
common/djangoapps/edxmako/template.py
+65
-23
common/djangoapps/edxmako/templatetag_helpers.py
+0
-52
common/lib/capa/capa/checker.py
+5
-8
lms/djangoapps/static_template_view/views.py
+3
-3
lms/envs/common.py
+62
-45
lms/envs/test.py
+1
-1
openedx/core/djangoapps/credit/email_utils.py
+1
-1
openedx/core/djangoapps/debug/views.py
+2
-2
openedx/core/lib/derived.py
+16
-11
openedx/core/lib/tests/test_derived.py
+8
-2
No files found.
cms/djangoapps/contentstore/views/helpers.py
View file @
fdc50c3a
...
@@ -44,11 +44,11 @@ def event(request):
...
@@ -44,11 +44,11 @@ def event(request):
return
HttpResponse
(
status
=
204
)
return
HttpResponse
(
status
=
204
)
def
render_from_lms
(
template_name
,
dictionary
,
context
=
None
,
namespace
=
'main'
):
def
render_from_lms
(
template_name
,
dictionary
,
namespace
=
'main'
):
"""
"""
Render a template using the LMS M
AKO_TEMPLATES
Render a template using the LMS M
ako templates
"""
"""
return
render_to_string
(
template_name
,
dictionary
,
context
,
namespace
=
"lms."
+
namespace
)
return
render_to_string
(
template_name
,
dictionary
,
namespace
=
"lms."
+
namespace
)
def
get_parent_xblock
(
xblock
):
def
get_parent_xblock
(
xblock
):
...
...
cms/envs/common.py
View file @
fdc50c3a
...
@@ -119,7 +119,7 @@ from lms.envs.common import (
...
@@ -119,7 +119,7 @@ from lms.envs.common import (
VIDEO_TRANSCRIPTS_SETTINGS
,
VIDEO_TRANSCRIPTS_SETTINGS
,
# Methods to derive settings
# Methods to derive settings
_make_ma
in_mako_template
s
,
_make_ma
ko_template_dir
s
,
_make_locale_paths
,
_make_locale_paths
,
)
)
from
path
import
Path
as
path
from
path
import
Path
as
path
...
@@ -134,7 +134,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
...
@@ -134,7 +134,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
get_theme_base_dirs_from_settings
get_theme_base_dirs_from_settings
)
)
from
openedx.core.lib.license
import
LicenseMixin
from
openedx.core.lib.license
import
LicenseMixin
from
openedx.core.lib.derived
import
derived
,
derived_
dict
_entry
from
openedx.core.lib.derived
import
derived
,
derived_
collection
_entry
from
openedx.core.release
import
doc_version
from
openedx.core.release
import
doc_version
############################ FEATURE CONFIGURATION #############################
############################ FEATURE CONFIGURATION #############################
...
@@ -310,11 +310,9 @@ GEOIPV6_PATH = REPO_ROOT / "common/static/data/geoip/GeoIPv6.dat"
...
@@ -310,11 +310,9 @@ GEOIPV6_PATH = REPO_ROOT / "common/static/data/geoip/GeoIPv6.dat"
############################# TEMPLATE CONFIGURATION #############################
############################# TEMPLATE CONFIGURATION #############################
# Mako templating
# Mako templating
# TODO: Move the Mako templating into a different engine in TEMPLATES below.
import
tempfile
import
tempfile
MAKO_MODULE_DIR
=
os
.
path
.
join
(
tempfile
.
gettempdir
(),
'mako_cms'
)
MAKO_MODULE_DIR
=
os
.
path
.
join
(
tempfile
.
gettempdir
(),
'mako_cms'
)
MAKO_TEMPLATES
=
{}
MAKO_TEMPLATE_DIRS_BASE
=
[
MAIN_MAKO_TEMPLATES_BASE
=
[
PROJECT_ROOT
/
'templates'
,
PROJECT_ROOT
/
'templates'
,
COMMON_ROOT
/
'templates'
,
COMMON_ROOT
/
'templates'
,
COMMON_ROOT
/
'djangoapps'
/
'pipeline_mako'
/
'templates'
,
COMMON_ROOT
/
'djangoapps'
/
'pipeline_mako'
/
'templates'
,
...
@@ -324,19 +322,27 @@ MAIN_MAKO_TEMPLATES_BASE = [
...
@@ -324,19 +322,27 @@ MAIN_MAKO_TEMPLATES_BASE = [
OPENEDX_ROOT
/
'core'
/
'lib'
/
'license'
/
'templates'
,
OPENEDX_ROOT
/
'core'
/
'lib'
/
'license'
/
'templates'
,
CMS_ROOT
/
'djangoapps'
/
'pipeline_js'
/
'templates'
,
CMS_ROOT
/
'djangoapps'
/
'pipeline_js'
/
'templates'
,
]
]
MAKO_TEMPLATES
[
'lms.main'
]
=
lms
.
envs
.
common
.
MAIN_MAKO_TEMPLATES_BASE
MAKO_TEMPLATES
[
'main'
]
=
_make_main_mako_templates
CONTEXT_PROCESSORS
=
(
derived_dict_entry
(
'MAKO_TEMPLATES'
,
'main'
)
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
'dealer.contrib.django.staff.context_processor'
,
# access git revision
'help_tokens.context_processor'
,
)
# Django templating
# Django templating
TEMPLATES
=
[
TEMPLATES
=
[
{
{
'NAME'
:
'django'
,
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
# Don't look for template source files inside installed applications.
# Don't look for template source files inside installed applications.
'APP_DIRS'
:
False
,
'APP_DIRS'
:
False
,
# Instead, look for template source files in these dirs.
# Instead, look for template source files in these dirs.
'DIRS'
:
MAIN_MAKO_TEMPLATES_BASE
,
'DIRS'
:
_make_mako_template_dirs
,
# Options specific to this backend.
# Options specific to this backend.
'OPTIONS'
:
{
'OPTIONS'
:
{
'loaders'
:
(
'loaders'
:
(
...
@@ -346,21 +352,36 @@ TEMPLATES = [
...
@@ -346,21 +352,36 @@ TEMPLATES = [
'edxmako.makoloader.MakoFilesystemLoader'
,
'edxmako.makoloader.MakoFilesystemLoader'
,
'edxmako.makoloader.MakoAppDirectoriesLoader'
,
'edxmako.makoloader.MakoAppDirectoriesLoader'
,
),
),
'context_processors'
:
(
'context_processors'
:
CONTEXT_PROCESSORS
,
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
'dealer.contrib.django.staff.context_processor'
,
# access git revision
'help_tokens.context_processor'
,
),
# Change 'debug' in your environment settings files - not here.
# Change 'debug' in your environment settings files - not here.
'debug'
:
False
'debug'
:
False
}
}
}
},
{
'NAME'
:
'mako'
,
'BACKEND'
:
'edxmako.backend.Mako'
,
'APP_DIRS'
:
False
,
'DIRS'
:
_make_mako_template_dirs
,
'OPTIONS'
:
{
'context_processors'
:
CONTEXT_PROCESSORS
,
'debug'
:
False
,
}
},
{
# This separate copy of the Mako backend is used to render previews using the LMS templates
'NAME'
:
'preview'
,
'BACKEND'
:
'edxmako.backend.Mako'
,
'APP_DIRS'
:
False
,
'DIRS'
:
lms
.
envs
.
common
.
MAKO_TEMPLATE_DIRS_BASE
,
'OPTIONS'
:
{
'context_processors'
:
CONTEXT_PROCESSORS
,
'debug'
:
False
,
'namespace'
:
'lms.main'
,
}
},
]
]
derived_collection_entry
(
'TEMPLATES'
,
0
,
'DIRS'
)
derived_collection_entry
(
'TEMPLATES'
,
1
,
'DIRS'
)
DEFAULT_TEMPLATE_ENGINE
=
TEMPLATES
[
0
]
DEFAULT_TEMPLATE_ENGINE
=
TEMPLATES
[
0
]
##############################################################################
##############################################################################
...
...
common/djangoapps/edxmako/__init__.py
View file @
fdc50c3a
...
@@ -14,3 +14,13 @@
...
@@ -14,3 +14,13 @@
LOOKUP
=
{}
LOOKUP
=
{}
from
.paths
import
add_lookup
,
lookup_template
,
clear_lookups
,
save_lookups
from
.paths
import
add_lookup
,
lookup_template
,
clear_lookups
,
save_lookups
class
Engines
(
object
):
"""
Aliases for the available template engines.
Note that the preview engine is only configured for cms.
"""
DJANGO
=
'django'
MAKO
=
'mako'
PREVIEW
=
'preview'
common/djangoapps/edxmako/apps.py
View file @
fdc50c3a
...
@@ -20,8 +20,11 @@ class EdxMakoConfig(AppConfig):
...
@@ -20,8 +20,11 @@ class EdxMakoConfig(AppConfig):
IMPORTANT: This method can be called multiple times during application startup. Any changes to this method
IMPORTANT: This method can be called multiple times during application startup. Any changes to this method
must be safe for multiple callers during startup phase.
must be safe for multiple callers during startup phase.
"""
"""
template_locations
=
settings
.
MAKO_TEMPLATES
for
backend
in
settings
.
TEMPLATES
:
for
namespace
,
directories
in
template_locations
.
items
():
if
'edxmako'
not
in
backend
[
'BACKEND'
]:
continue
namespace
=
backend
[
'OPTIONS'
]
.
get
(
'namespace'
,
'main'
)
directories
=
backend
[
'DIRS'
]
clear_lookups
(
namespace
)
clear_lookups
(
namespace
)
for
directory
in
directories
:
for
directory
in
directories
:
add_lookup
(
namespace
,
directory
)
add_lookup
(
namespace
,
directory
)
common/djangoapps/edxmako/backend.py
0 → 100644
View file @
fdc50c3a
"""
Django template system engine for Mako templates.
"""
from
__future__
import
absolute_import
,
unicode_literals
import
logging
from
django.template
import
TemplateDoesNotExist
,
TemplateSyntaxError
from
django.template.backends.base
import
BaseEngine
from
django.template.context
import
_builtin_context_processors
from
django.utils.functional
import
cached_property
from
django.utils.module_loading
import
import_string
from
mako.exceptions
import
MakoException
,
TopLevelLookupException
,
text_error_template
from
openedx.core.djangoapps.theming.helpers
import
get_template_path
from
.paths
import
lookup_template
from
.template
import
Template
LOGGER
=
logging
.
getLogger
(
__name__
)
class
Mako
(
BaseEngine
):
"""
A Mako template engine to be added to the ``TEMPLATES`` Django setting.
"""
app_dirname
=
'templates'
def
__init__
(
self
,
params
):
"""
Fetches template options, initializing BaseEngine properties,
and assigning our Mako default settings.
Note that OPTIONS contains backend-specific settings.
:param params: This is simply the template dict you
define in your settings file.
"""
params
=
params
.
copy
()
options
=
params
.
pop
(
'OPTIONS'
)
.
copy
()
super
(
Mako
,
self
)
.
__init__
(
params
)
self
.
context_processors
=
options
.
pop
(
'context_processors'
,
[])
self
.
namespace
=
options
.
pop
(
'namespace'
,
'main'
)
def
from_string
(
self
,
template_code
):
try
:
return
Template
(
template_code
)
except
MakoException
:
message
=
text_error_template
()
.
render
()
raise
TemplateSyntaxError
(
message
)
def
get_template
(
self
,
template_name
):
"""
Loads and returns a template for the given name.
"""
template_name
=
get_template_path
(
template_name
)
try
:
return
Template
(
lookup_template
(
self
.
namespace
,
template_name
),
engine
=
self
)
except
TopLevelLookupException
:
raise
TemplateDoesNotExist
(
template_name
)
@cached_property
def
template_context_processors
(
self
):
"""
Collect and cache the active context processors.
"""
context_processors
=
_builtin_context_processors
context_processors
+=
tuple
(
self
.
context_processors
)
return
tuple
(
import_string
(
path
)
for
path
in
context_processors
)
common/djangoapps/edxmako/makoloader.py
View file @
fdc50c3a
...
@@ -2,7 +2,7 @@ import logging
...
@@ -2,7 +2,7 @@ import logging
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.exceptions
import
ImproperlyConfigured
from
django.core.exceptions
import
ImproperlyConfigured
from
django.template
import
Engine
from
django.template
import
Engine
,
engines
from
django.template.base
import
TemplateDoesNotExist
from
django.template.base
import
TemplateDoesNotExist
from
django.template.loaders.app_directories
import
Loader
as
AppDirectoriesLoader
from
django.template.loaders.app_directories
import
Loader
as
AppDirectoriesLoader
from
django.template.loaders.filesystem
import
Loader
as
FilesystemLoader
from
django.template.loaders.filesystem
import
Loader
as
FilesystemLoader
...
@@ -16,8 +16,8 @@ log = logging.getLogger(__name__)
...
@@ -16,8 +16,8 @@ log = logging.getLogger(__name__)
class
MakoLoader
(
object
):
class
MakoLoader
(
object
):
"""
"""
This is a Django loader object which will load the template as a
This is a Django loader object which will load the template as a
Mako template if the first line is "## mako". It is based off
Base
Loader
Mako template if the first line is "## mako". It is based off Loader
in django.template.loader.
in django.template.loader
s.base
.
We need this in order to be able to include mako templates inside main_django.html.
We need this in order to be able to include mako templates inside main_django.html.
"""
"""
...
@@ -53,7 +53,8 @@ class MakoLoader(object):
...
@@ -53,7 +53,8 @@ class MakoLoader(object):
output_encoding
=
'utf-8'
,
output_encoding
=
'utf-8'
,
default_filters
=
[
'decode.utf8'
],
default_filters
=
[
'decode.utf8'
],
encoding_errors
=
'replace'
,
encoding_errors
=
'replace'
,
uri
=
template_name
)
uri
=
template_name
,
engine
=
engines
[
'mako'
])
return
template
,
None
return
template
,
None
else
:
else
:
# This is a regular template
# This is a regular template
...
...
common/djangoapps/edxmako/management/__init__.py
deleted
100644 → 0
View file @
989c3a30
common/djangoapps/edxmako/management/commands/__init__.py
deleted
100644 → 0
View file @
989c3a30
common/djangoapps/edxmako/request_context.py
View file @
fdc50c3a
...
@@ -20,24 +20,12 @@ Methods for creating RequestContext for using with Mako templates.
...
@@ -20,24 +20,12 @@ Methods for creating RequestContext for using with Mako templates.
from
crum
import
get_current_request
from
crum
import
get_current_request
from
django.conf
import
settings
from
django.template
import
RequestContext
from
django.template
import
RequestContext
from
django.template.context
import
_builtin_context_processors
from
django.utils.module_loading
import
import_string
import
request_cache
import
request_cache
from
util.request
import
safe_get_host
from
util.request
import
safe_get_host
def
get_template_context_processors
():
"""
Returns the context processors defined in settings.TEMPLATES.
"""
context_processors
=
_builtin_context_processors
context_processors
+=
tuple
(
settings
.
DEFAULT_TEMPLATE_ENGINE
[
'OPTIONS'
][
'context_processors'
])
return
tuple
(
import_string
(
path
)
for
path
in
context_processors
)
def
get_template_request_context
(
request
=
None
):
def
get_template_request_context
(
request
=
None
):
"""
"""
Returns the template processing context to use for the current request,
Returns the template processing context to use for the current request,
...
@@ -60,13 +48,6 @@ def get_template_request_context(request=None):
...
@@ -60,13 +48,6 @@ def get_template_request_context(request=None):
context
[
'is_secure'
]
=
request
.
is_secure
()
context
[
'is_secure'
]
=
request
.
is_secure
()
context
[
'site'
]
=
safe_get_host
(
request
)
context
[
'site'
]
=
safe_get_host
(
request
)
# This used to happen when a RequestContext object was initialized but was
# moved to a different part of the logic when template engines were introduced.
# Since we are not using template engines we do this here.
# https://github.com/django/django/commit/37505b6397058bcc3460f23d48a7de9641cd6ef0
for
processor
in
get_template_context_processors
():
context
.
update
(
processor
(
request
))
request_cache_dict
[
cache_key
]
=
context
request_cache_dict
[
cache_key
]
=
context
return
context
return
context
common/djangoapps/edxmako/shortcuts.py
View file @
fdc50c3a
...
@@ -18,12 +18,12 @@ from urlparse import urljoin
...
@@ -18,12 +18,12 @@ from urlparse import urljoin
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
from
django.template
import
Context
from
django.template
import
engines
from
edxmako
import
lookup_template
from
edxmako.request_context
import
get_template_request_context
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.theming.helpers
import
get_template_path
,
is_request_in_themed_site
from
openedx.core.djangoapps.theming.helpers
import
is_request_in_themed_site
from
.
import
Engines
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -131,7 +131,7 @@ def footer_context_processor(request): # pylint: disable=unused-argument
...
@@ -131,7 +131,7 @@ def footer_context_processor(request): # pylint: disable=unused-argument
)
)
def
render_to_string
(
template_name
,
dictionary
,
context
=
None
,
namespace
=
'main'
,
request
=
None
):
def
render_to_string
(
template_name
,
dictionary
,
namespace
=
'main'
,
request
=
None
):
"""
"""
Render a Mako template to as a string.
Render a Mako template to as a string.
...
@@ -147,52 +147,23 @@ def render_to_string(template_name, dictionary, context=None, namespace='main',
...
@@ -147,52 +147,23 @@ def render_to_string(template_name, dictionary, context=None, namespace='main',
from the template paths specified in configuration.
from the template paths specified in configuration.
dictionary: A dictionary of variables to insert into the template during
dictionary: A dictionary of variables to insert into the template during
rendering.
rendering.
context: A :class:`~django.template.Context` with values to make
available to the template.
namespace: The Mako namespace to find the named template in.
namespace: The Mako namespace to find the named template in.
request: The request to use to construct the RequestContext for rendering
request: The request to use to construct the RequestContext for rendering
this template. If not supplied, the current request will be used.
this template. If not supplied, the current request will be used.
"""
"""
if
namespace
==
'lms.main'
:
engine
=
engines
[
Engines
.
PREVIEW
]
else
:
engine
=
engines
[
Engines
.
MAKO
]
template
=
engine
.
get_template
(
template_name
)
return
template
.
render
(
dictionary
,
request
)
template_name
=
get_template_path
(
template_name
)
def
render_to_response
(
template_name
,
dictionary
=
None
,
namespace
=
'main'
,
request
=
None
,
**
kwargs
):
context_instance
=
Context
(
dictionary
)
# add dictionary to context_instance
context_instance
.
update
(
dictionary
or
{})
# collapse context_instance to a single dictionary for mako
context_dictionary
=
{}
context_instance
[
'settings'
]
=
settings
context_instance
[
'EDX_ROOT_URL'
]
=
settings
.
EDX_ROOT_URL
context_instance
[
'marketing_link'
]
=
marketing_link
context_instance
[
'is_any_marketing_link_set'
]
=
is_any_marketing_link_set
context_instance
[
'is_marketing_link_set'
]
=
is_marketing_link_set
# In various testing contexts, there might not be a current request context.
request_context
=
get_template_request_context
(
request
)
if
request_context
:
for
item
in
request_context
:
context_dictionary
.
update
(
item
)
for
item
in
context_instance
:
context_dictionary
.
update
(
item
)
if
context
:
context_dictionary
.
update
(
context
)
# "Fix" CSRF token by evaluating the lazy object
KEY_CSRF_TOKENS
=
(
'csrf_token'
,
'csrf'
)
for
key
in
KEY_CSRF_TOKENS
:
if
key
in
context_dictionary
:
context_dictionary
[
key
]
=
unicode
(
context_dictionary
[
key
])
# fetch and render template
template
=
lookup_template
(
namespace
,
template_name
)
return
template
.
render_unicode
(
**
context_dictionary
)
def
render_to_response
(
template_name
,
dictionary
=
None
,
context_instance
=
None
,
namespace
=
'main'
,
request
=
None
,
**
kwargs
):
"""
"""
Returns a HttpResponse whose content is filled with the result of calling
Returns a HttpResponse whose content is filled with the result of calling
lookup.get_template(args[0]).render with the passed arguments.
lookup.get_template(args[0]).render with the passed arguments.
"""
"""
dictionary
=
dictionary
or
{}
dictionary
=
dictionary
or
{}
return
HttpResponse
(
render_to_string
(
template_name
,
dictionary
,
context_instance
,
namespace
,
request
),
**
kwargs
)
return
HttpResponse
(
render_to_string
(
template_name
,
dictionary
,
namespace
,
request
),
**
kwargs
)
common/djangoapps/edxmako/template.py
View file @
fdc50c3a
...
@@ -13,47 +13,89 @@
...
@@ -13,47 +13,89 @@
# limitations under the License.
# limitations under the License.
from
django.conf
import
settings
from
django.conf
import
settings
from
django.template
import
Context
,
engines
from
mako.template
import
Template
as
MakoTemplate
from
mako.template
import
Template
as
MakoTemplate
from
six
import
text_type
import
edxmako
from
.
import
Engines
,
LOOKUP
from
edxmako
.request_context
import
get_template_request_context
from
.request_context
import
get_template_request_context
from
edxmako.shortcuts
import
marketing_link
from
.shortcuts
import
is_any_marketing_link_set
,
is_marketing_link_set
,
marketing_link
KEY_CSRF_TOKENS
=
(
'csrf_token'
,
'csrf'
)
# TODO: We should make this a Django Template subclass that simply has the MakoTemplate inside of it? (Intead of inheriting from MakoTemplate)
class
Template
(
object
):
class
Template
(
MakoTemplate
):
"""
"""
This bridges the gap between a Mako template and a
djan
o template. It can
This bridges the gap between a Mako template and a
Djang
o template. It can
be rendered like it is a
d
jango template because the arguments are transformed
be rendered like it is a
D
jango template because the arguments are transformed
in a way that MakoTemplate can understand.
in a way that MakoTemplate can understand.
"""
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""Overrides base __init__ to provide django variable overrides"""
"""Overrides base __init__ to provide django variable overrides"""
if
not
kwargs
.
get
(
'no_django'
,
False
):
self
.
engine
=
kwargs
.
pop
(
'engine'
,
engines
[
Engines
.
MAKO
])
kwargs
[
'lookup'
]
=
edxmako
.
LOOKUP
[
'main'
]
if
len
(
args
)
and
isinstance
(
args
[
0
],
MakoTemplate
):
super
(
Template
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
mako_template
=
args
[
0
]
else
:
kwargs
[
'lookup'
]
=
LOOKUP
[
'main'
]
self
.
mako_template
=
MakoTemplate
(
*
args
,
**
kwargs
)
def
render
(
self
,
context
_instanc
e
):
def
render
(
self
,
context
=
None
,
request
=
Non
e
):
"""
"""
This takes a render call with a context (from Django) and translates
This takes a render call with a context (from Django) and translates
it to a render call on the mako template.
it to a render call on the mako template.
"""
"""
# collapse context_instance to a single dictionary for mako
context_object
=
self
.
_get_context_object
(
request
)
context_dictionary
=
{}
context_dictionary
=
self
.
_get_context_processors_output_dict
(
context_object
)
if
isinstance
(
context
,
Context
):
context_dictionary
.
update
(
context
.
flatten
())
elif
context
is
not
None
:
context_dictionary
.
update
(
context
)
self
.
_add_core_context
(
context_dictionary
)
self
.
_evaluate_lazy_csrf_tokens
(
context_dictionary
)
return
self
.
mako_template
.
render_unicode
(
**
context_dictionary
)
@staticmethod
def
_get_context_object
(
request
):
"""
Get a Django RequestContext or Context, as appropriate for the situation.
In some tests, there might not be a current request.
"""
request_context
=
get_template_request_context
(
request
)
if
request_context
is
not
None
:
return
request_context
else
:
return
Context
({})
# In various testing contexts, there might not be a current request context.
def
_get_context_processors_output_dict
(
self
,
context_object
):
request_context
=
get_template_request_context
()
"""
if
request_context
:
Run the context processors for the given context and get the output as a new dictionary.
for
item
in
request_context
:
"""
context_dictionary
.
update
(
item
)
with
context_object
.
bind_template
(
self
):
for
item
in
context_instance
:
return
context_object
.
flatten
()
context_dictionary
.
update
(
item
)
@staticmethod
def
_add_core_context
(
context_dictionary
):
"""
Add to the given dictionary context variables which should always be
present, even when context processors aren't run during tests. Using
a context processor should almost always be preferred to adding more
variables here.
"""
context_dictionary
[
'settings'
]
=
settings
context_dictionary
[
'settings'
]
=
settings
context_dictionary
[
'EDX_ROOT_URL'
]
=
settings
.
EDX_ROOT_URL
context_dictionary
[
'EDX_ROOT_URL'
]
=
settings
.
EDX_ROOT_URL
context_dictionary
[
'django_context'
]
=
context_instance
context_dictionary
[
'marketing_link'
]
=
marketing_link
context_dictionary
[
'marketing_link'
]
=
marketing_link
context_dictionary
[
'is_any_marketing_link_set'
]
=
is_any_marketing_link_set
context_dictionary
[
'is_marketing_link_set'
]
=
is_marketing_link_set
return
super
(
Template
,
self
)
.
render_unicode
(
**
context_dictionary
)
@staticmethod
def
_evaluate_lazy_csrf_tokens
(
context_dictionary
):
"""
Evaluate any lazily-evaluated CSRF tokens in the given context.
"""
for
key
in
KEY_CSRF_TOKENS
:
if
key
in
context_dictionary
:
context_dictionary
[
key
]
=
text_type
(
context_dictionary
[
key
])
common/djangoapps/edxmako/templatetag_helpers.py
deleted
100644 → 0
View file @
989c3a30
from
django.template
import
loader
from
django.template.base
import
Context
,
Template
from
django.template.loader
import
get_template
,
select_template
def
django_template_include
(
file_name
,
mako_context
):
"""
This can be used within a mako template to include a django template
in the way that a django-style {
%
include
%
} does. Pass it context
which can be the mako context ('context') or a dictionary.
"""
dictionary
=
dict
(
mako_context
)
return
loader
.
render_to_string
(
file_name
,
dictionary
=
dictionary
)
def
render_inclusion
(
func
,
file_name
,
takes_context
,
django_context
,
*
args
,
**
kwargs
):
"""
This allows a mako template to call a template tag function (written
for django templates) that is an "inclusion tag". These functions are
decorated with @register.inclusion_tag.
-func: This is the function that is registered as an inclusion tag.
You must import it directly using a python import statement.
-file_name: This is the filename of the template, passed into the
@register.inclusion_tag statement.
-takes_context: This is a parameter of the @register.inclusion_tag.
-django_context: This is an instance of the django context. If this
is a mako template rendered through the regular django rendering calls,
a copy of the django context is available as 'django_context'.
-*args and **kwargs are the arguments to func.
"""
if
takes_context
:
args
=
[
django_context
]
+
list
(
args
)
_dict
=
func
(
*
args
,
**
kwargs
)
if
isinstance
(
file_name
,
Template
):
t
=
file_name
elif
not
isinstance
(
file_name
,
basestring
)
and
is_iterable
(
file_name
):
t
=
select_template
(
file_name
)
else
:
t
=
get_template
(
file_name
)
nodelist
=
t
.
nodelist
new_context
=
Context
(
_dict
)
csrf_token
=
django_context
.
get
(
'csrf_token'
,
None
)
if
csrf_token
is
not
None
:
new_context
[
'csrf_token'
]
=
csrf_token
return
nodelist
.
render
(
new_context
)
common/lib/capa/capa/checker.py
View file @
fdc50c3a
...
@@ -24,14 +24,11 @@ class DemoSystem(object):
...
@@ -24,14 +24,11 @@ class DemoSystem(object):
self
.
lookup
=
TemplateLookup
(
directories
=
[
path
(
__file__
)
.
dirname
()
/
'templates'
])
self
.
lookup
=
TemplateLookup
(
directories
=
[
path
(
__file__
)
.
dirname
()
/
'templates'
])
self
.
DEBUG
=
True
self
.
DEBUG
=
True
def
render_template
(
self
,
template_filename
,
dictionary
,
context
=
None
):
def
render_template
(
self
,
template_filename
,
dictionary
):
if
context
is
None
:
"""
context
=
{}
Render the specified template with the given dictionary of context data.
"""
context_dict
=
{}
return
self
.
lookup
.
get_template
(
template_filename
)
.
render
(
**
dictionary
)
context_dict
.
update
(
dictionary
)
context_dict
.
update
(
context
)
return
self
.
lookup
.
get_template
(
template_filename
)
.
render
(
**
context_dict
)
def
main
():
def
main
():
...
...
lms/djangoapps/static_template_view/views.py
View file @
fdc50c3a
...
@@ -8,8 +8,8 @@ import mimetypes
...
@@ -8,8 +8,8 @@ import mimetypes
from
django.conf
import
settings
from
django.conf
import
settings
from
django.http
import
Http404
,
HttpResponseNotFound
,
HttpResponseServerError
from
django.http
import
Http404
,
HttpResponseNotFound
,
HttpResponseServerError
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
django.template
import
TemplateDoesNotExist
from
django.views.decorators.csrf
import
ensure_csrf_cookie
from
django.views.decorators.csrf
import
ensure_csrf_cookie
from
mako.exceptions
import
TopLevelLookupException
from
edxmako.shortcuts
import
render_to_response
,
render_to_string
from
edxmako.shortcuts
import
render_to_response
,
render_to_string
from
util.cache
import
cache_if_anonymous
from
util.cache
import
cache_if_anonymous
...
@@ -51,7 +51,7 @@ def render(request, template):
...
@@ -51,7 +51,7 @@ def render(request, template):
if
template
==
'honor.html'
:
if
template
==
'honor.html'
:
context
[
'allow_iframing'
]
=
True
context
[
'allow_iframing'
]
=
True
return
render_to_response
(
'static_templates/'
+
template
,
context
,
content_type
=
content_type
)
return
render_to_response
(
'static_templates/'
+
template
,
context
,
content_type
=
content_type
)
except
T
opLevelLookupException
:
except
T
emplateDoesNotExist
:
raise
Http404
raise
Http404
...
@@ -68,7 +68,7 @@ def render_press_release(request, slug):
...
@@ -68,7 +68,7 @@ def render_press_release(request, slug):
template
=
slug
.
lower
()
.
replace
(
'-'
,
'_'
)
+
".html"
template
=
slug
.
lower
()
.
replace
(
'-'
,
'_'
)
+
".html"
try
:
try
:
resp
=
render_to_response
(
'static_templates/press_releases/'
+
template
,
{})
resp
=
render_to_response
(
'static_templates/press_releases/'
+
template
,
{})
except
T
opLevelLookupException
:
except
T
emplateDoesNotExist
:
raise
Http404
raise
Http404
else
:
else
:
return
resp
return
resp
...
...
lms/envs/common.py
View file @
fdc50c3a
...
@@ -43,7 +43,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
...
@@ -43,7 +43,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
get_themes_unchecked
,
get_themes_unchecked
,
get_theme_base_dirs_from_settings
get_theme_base_dirs_from_settings
)
)
from
openedx.core.lib.derived
import
derived
,
derived_
dict
_entry
from
openedx.core.lib.derived
import
derived
,
derived_
collection
_entry
from
openedx.core.release
import
doc_version
from
openedx.core.release
import
doc_version
from
xmodule.modulestore.modulestore_settings
import
update_module_store_settings
from
xmodule.modulestore.modulestore_settings
import
update_module_store_settings
from
xmodule.modulestore.edit_info
import
EditInfoMixin
from
xmodule.modulestore.edit_info
import
EditInfoMixin
...
@@ -535,11 +535,9 @@ OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
...
@@ -535,11 +535,9 @@ OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
################################## TEMPLATE CONFIGURATION #####################################
################################## TEMPLATE CONFIGURATION #####################################
# Mako templating
# Mako templating
# TODO: Move the Mako templating into a different engine in TEMPLATES below.
import
tempfile
import
tempfile
MAKO_MODULE_DIR
=
os
.
path
.
join
(
tempfile
.
gettempdir
(),
'mako_lms'
)
MAKO_MODULE_DIR
=
os
.
path
.
join
(
tempfile
.
gettempdir
(),
'mako_lms'
)
MAKO_TEMPLATES
=
{}
MAKO_TEMPLATE_DIRS_BASE
=
[
MAIN_MAKO_TEMPLATES_BASE
=
[
PROJECT_ROOT
/
'templates'
,
PROJECT_ROOT
/
'templates'
,
COMMON_ROOT
/
'templates'
,
COMMON_ROOT
/
'templates'
,
COMMON_ROOT
/
'lib'
/
'capa'
/
'capa'
/
'templates'
,
COMMON_ROOT
/
'lib'
/
'capa'
/
'capa'
/
'templates'
,
...
@@ -550,24 +548,55 @@ MAIN_MAKO_TEMPLATES_BASE = [
...
@@ -550,24 +548,55 @@ MAIN_MAKO_TEMPLATES_BASE = [
]
]
def
_make_ma
in_mako_template
s
(
settings
):
def
_make_ma
ko_template_dir
s
(
settings
):
"""
"""
Derives the final M
AKO_TEMPLATES['main'] setting
from other settings.
Derives the final M
ako template directories list
from other settings.
"""
"""
if
settings
.
ENABLE_COMPREHENSIVE_THEMING
:
if
settings
.
ENABLE_COMPREHENSIVE_THEMING
:
themes_dirs
=
get_theme_base_dirs_from_settings
(
settings
.
COMPREHENSIVE_THEME_DIRS
)
themes_dirs
=
get_theme_base_dirs_from_settings
(
settings
.
COMPREHENSIVE_THEME_DIRS
)
for
theme
in
get_themes_unchecked
(
themes_dirs
,
PROJECT_ROOT
):
for
theme
in
get_themes_unchecked
(
themes_dirs
,
settings
.
PROJECT_ROOT
):
if
theme
.
themes_base_dir
not
in
settings
.
MA
IN_MAKO_TEMPLATE
S_BASE
:
if
theme
.
themes_base_dir
not
in
settings
.
MA
KO_TEMPLATE_DIR
S_BASE
:
settings
.
MA
IN_MAKO_TEMPLATE
S_BASE
.
insert
(
0
,
theme
.
themes_base_dir
)
settings
.
MA
KO_TEMPLATE_DIR
S_BASE
.
insert
(
0
,
theme
.
themes_base_dir
)
if
settings
.
FEATURES
.
get
(
'USE_MICROSITES'
,
False
)
and
getattr
(
settings
,
"MICROSITE_CONFIGURATION"
,
False
):
if
settings
.
FEATURES
.
get
(
'USE_MICROSITES'
,
False
)
and
getattr
(
settings
,
"MICROSITE_CONFIGURATION"
,
False
):
settings
.
MAIN_MAKO_TEMPLATES_BASE
.
insert
(
0
,
settings
.
MICROSITE_ROOT_DIR
)
settings
.
MAKO_TEMPLATE_DIRS_BASE
.
insert
(
0
,
settings
.
MICROSITE_ROOT_DIR
)
return
settings
.
MAIN_MAKO_TEMPLATES_BASE
return
settings
.
MAKO_TEMPLATE_DIRS_BASE
MAKO_TEMPLATES
[
'main'
]
=
_make_main_mako_templates
derived_dict_entry
(
'MAKO_TEMPLATES'
,
'main'
)
CONTEXT_PROCESSORS
=
[
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
# Added for django-wiki
'django.template.context_processors.media'
,
'django.template.context_processors.tz'
,
'django.contrib.messages.context_processors.messages'
,
'sekizai.context_processors.sekizai'
,
# Hack to get required link URLs to password reset templates
'edxmako.shortcuts.marketing_link_context_processor'
,
# Shoppingcart processor (detects if request.user has a cart)
'shoppingcart.context_processor.user_has_cart_context_processor'
,
# Timezone processor (sends language and time_zone preference)
'courseware.context_processor.user_timezone_locale_prefs'
,
# Allows the open edX footer to be leveraged in Django Templates.
'edxmako.shortcuts.footer_context_processor'
,
# Online contextual help
'help_tokens.context_processor'
,
'openedx.core.djangoapps.site_configuration.context_processors.configuration_context'
]
# Django templating
# Django templating
TEMPLATES
=
[
TEMPLATES
=
[
{
{
'NAME'
:
'django'
,
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
# Don't look for template source files inside installed applications.
# Don't look for template source files inside installed applications.
'APP_DIRS'
:
False
,
'APP_DIRS'
:
False
,
...
@@ -588,41 +617,27 @@ TEMPLATES = [
...
@@ -588,41 +617,27 @@ TEMPLATES = [
'edxmako.makoloader.MakoFilesystemLoader'
,
'edxmako.makoloader.MakoFilesystemLoader'
,
'edxmako.makoloader.MakoAppDirectoriesLoader'
,
'edxmako.makoloader.MakoAppDirectoriesLoader'
,
],
],
'context_processors'
:
[
'context_processors'
:
CONTEXT_PROCESSORS
,
'django.template.context_processors.request'
,
'django.template.context_processors.static'
,
'django.contrib.messages.context_processors.messages'
,
'django.template.context_processors.i18n'
,
'django.contrib.auth.context_processors.auth'
,
# this is required for admin
'django.template.context_processors.csrf'
,
# Added for django-wiki
'django.template.context_processors.media'
,
'django.template.context_processors.tz'
,
'django.contrib.messages.context_processors.messages'
,
'sekizai.context_processors.sekizai'
,
# Hack to get required link URLs to password reset templates
'edxmako.shortcuts.marketing_link_context_processor'
,
# Shoppingcart processor (detects if request.user has a cart)
'shoppingcart.context_processor.user_has_cart_context_processor'
,
# Timezone processor (sends language and time_zone preference)
'courseware.context_processor.user_timezone_locale_prefs'
,
# Allows the open edX footer to be leveraged in Django Templates.
'edxmako.shortcuts.footer_context_processor'
,
# Online contextual help
'help_tokens.context_processor'
,
'openedx.core.djangoapps.site_configuration.context_processors.configuration_context'
],
# Change 'debug' in your environment settings files - not here.
# Change 'debug' in your environment settings files - not here.
'debug'
:
False
'debug'
:
False
}
}
}
},
{
'NAME'
:
'mako'
,
'BACKEND'
:
'edxmako.backend.Mako'
,
# Don't look for template source files inside installed applications.
'APP_DIRS'
:
False
,
# Instead, look for template source files in these dirs.
'DIRS'
:
_make_mako_template_dirs
,
# Options specific to this backend.
'OPTIONS'
:
{
'context_processors'
:
CONTEXT_PROCESSORS
,
# Change 'debug' in your environment settings files - not here.
'debug'
:
False
,
}
},
]
]
derived_collection_entry
(
'TEMPLATES'
,
1
,
'DIRS'
)
DEFAULT_TEMPLATE_ENGINE
=
TEMPLATES
[
0
]
DEFAULT_TEMPLATE_ENGINE
=
TEMPLATES
[
0
]
DEFAULT_TEMPLATE_ENGINE_DIRS
=
DEFAULT_TEMPLATE_ENGINE
[
'DIRS'
][:]
DEFAULT_TEMPLATE_ENGINE_DIRS
=
DEFAULT_TEMPLATE_ENGINE
[
'DIRS'
][:]
...
@@ -634,8 +649,10 @@ def _add_microsite_dirs_to_default_template_engine(settings):
...
@@ -634,8 +649,10 @@ def _add_microsite_dirs_to_default_template_engine(settings):
if
settings
.
FEATURES
.
get
(
'USE_MICROSITES'
,
False
)
and
getattr
(
settings
,
"MICROSITE_CONFIGURATION"
,
False
):
if
settings
.
FEATURES
.
get
(
'USE_MICROSITES'
,
False
)
and
getattr
(
settings
,
"MICROSITE_CONFIGURATION"
,
False
):
DEFAULT_TEMPLATE_ENGINE_DIRS
.
append
(
settings
.
MICROSITE_ROOT_DIR
)
DEFAULT_TEMPLATE_ENGINE_DIRS
.
append
(
settings
.
MICROSITE_ROOT_DIR
)
return
DEFAULT_TEMPLATE_ENGINE_DIRS
return
DEFAULT_TEMPLATE_ENGINE_DIRS
DEFAULT_TEMPLATE_ENGINE
[
'DIRS'
]
=
_add_microsite_dirs_to_default_template_engine
DEFAULT_TEMPLATE_ENGINE
[
'DIRS'
]
=
_add_microsite_dirs_to_default_template_engine
derived_
dict
_entry
(
'DEFAULT_TEMPLATE_ENGINE'
,
'DIRS'
)
derived_
collection
_entry
(
'DEFAULT_TEMPLATE_ENGINE'
,
'DIRS'
)
###############################################################################################
###############################################################################################
...
...
lms/envs/test.py
View file @
fdc50c3a
...
@@ -491,7 +491,7 @@ MICROSITE_LOGISTRATION_HOSTNAME = 'logistration.testserver'
...
@@ -491,7 +491,7 @@ MICROSITE_LOGISTRATION_HOSTNAME = 'logistration.testserver'
TEST_THEME
=
COMMON_ROOT
/
"test"
/
"test-theme"
TEST_THEME
=
COMMON_ROOT
/
"test"
/
"test-theme"
# add extra template directory for test-only templates
# add extra template directory for test-only templates
MA
IN_MAKO_TEMPLATE
S_BASE
.
extend
([
MA
KO_TEMPLATE_DIR
S_BASE
.
extend
([
COMMON_ROOT
/
'test'
/
'templates'
,
COMMON_ROOT
/
'test'
/
'templates'
,
COMMON_ROOT
/
'test'
/
'test_sites'
,
COMMON_ROOT
/
'test'
/
'test_sites'
,
REPO_ROOT
/
'openedx'
/
'core'
/
'djangolib'
/
'tests'
/
'templates'
,
REPO_ROOT
/
'openedx'
/
'core'
/
'djangolib'
/
'tests'
/
'templates'
,
...
...
openedx/core/djangoapps/credit/email_utils.py
View file @
fdc50c3a
...
@@ -113,7 +113,7 @@ def send_credit_notifications(username, course_key):
...
@@ -113,7 +113,7 @@ def send_credit_notifications(username, course_key):
else
:
else
:
email_body_content
=
''
email_body_content
=
''
email_body
=
Template
(
email_body_content
)
.
render
(
[
context
]
)
email_body
=
Template
(
email_body_content
)
.
render
(
context
)
msg_alternative
.
attach
(
SafeMIMEText
(
email_body
,
_subtype
=
'html'
,
_charset
=
'utf-8'
))
msg_alternative
.
attach
(
SafeMIMEText
(
email_body
,
_subtype
=
'html'
,
_charset
=
'utf-8'
))
# attach logo image
# attach logo image
...
...
openedx/core/djangoapps/debug/views.py
View file @
fdc50c3a
...
@@ -4,9 +4,9 @@ These views will NOT be shown on production: trying to access them will result
...
@@ -4,9 +4,9 @@ These views will NOT be shown on production: trying to access them will result
in a 404 error.
in a 404 error.
"""
"""
from
django.http
import
HttpResponseNotFound
from
django.http
import
HttpResponseNotFound
from
django.template
import
TemplateDoesNotExist
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
edxmako.shortcuts
import
render_to_response
from
edxmako.shortcuts
import
render_to_response
from
mako.exceptions
import
TopLevelLookupException
from
openedx.core.djangoapps.util.user_messages
import
PageLevelMessages
from
openedx.core.djangoapps.util.user_messages
import
PageLevelMessages
...
@@ -51,5 +51,5 @@ def show_reference_template(request, template):
...
@@ -51,5 +51,5 @@ def show_reference_template(request, template):
PageLevelMessages
.
register_error_message
(
request
,
_
(
'This is a test error'
))
PageLevelMessages
.
register_error_message
(
request
,
_
(
'This is a test error'
))
return
render_to_response
(
template
,
context
)
return
render_to_response
(
template
,
context
)
except
T
opLevelLookupException
:
except
T
emplateDoesNotExist
:
return
HttpResponseNotFound
(
'Missing template {template}'
.
format
(
template
=
template
))
return
HttpResponseNotFound
(
'Missing template {template}'
.
format
(
template
=
template
))
openedx/core/lib/derived.py
View file @
fdc50c3a
...
@@ -17,21 +17,23 @@ def derived(*settings):
...
@@ -17,21 +17,23 @@ def derived(*settings):
Can be called multiple times to add more derived settings.
Can be called multiple times to add more derived settings.
Args:
Args:
settings (
list): List of s
etting names to register.
settings (
str): S
etting names to register.
"""
"""
__DERIVED
.
extend
(
settings
)
__DERIVED
.
extend
(
settings
)
def
derived_
dict_entry
(
setting_dict
,
key
):
def
derived_
collection_entry
(
collection_name
,
*
accessors
):
"""
"""
Registers a setting which is a dictionary
and needs a derived value for a particular ke
y.
Registers a setting which is a dictionary
or list and needs a derived value for a particular entr
y.
Can be called multiple times to add more derived settings.
Can be called multiple times to add more derived settings.
Args:
Args:
setting_dict (str): Name of setting which contains a dictionary.
collection_name (str): Name of setting which contains a dictionary or list.
key (str): Name of key in the setting dictionary which will be derived.
accessors (int|str): Sequence of dictionary keys and list indices in the collection (and
collections within it) leading to the value which will be derived.
For example: 0, 'DIRS'.
"""
"""
__DERIVED
.
append
((
setting_dict
,
key
))
__DERIVED
.
append
((
collection_name
,
accessors
))
def
derive_settings
(
module_name
):
def
derive_settings
(
module_name
):
...
@@ -52,13 +54,16 @@ def derive_settings(module_name):
...
@@ -52,13 +54,16 @@ def derive_settings(module_name):
elif
isinstance
(
derived
,
tuple
):
elif
isinstance
(
derived
,
tuple
):
# If a tuple, two elements are expected - else ignore.
# If a tuple, two elements are expected - else ignore.
if
len
(
derived
)
==
2
:
if
len
(
derived
)
==
2
:
# Both elements are expected to be strings.
# The first element is the name of the attribute which is expected to be a dictionary or list.
# The first string is the attribute which is expected to be a dictionary.
# The second element is a list of string keys in that dictionary leading to a derived setting.
# The second string is a key in that dictionary containing a derived setting.
collection
=
getattr
(
module
,
derived
[
0
])
setting
=
getattr
(
module
,
derived
[
0
])[
derived
[
1
]]
accessors
=
derived
[
1
]
for
accessor
in
accessors
[:
-
1
]:
collection
=
collection
[
accessor
]
setting
=
collection
[
accessors
[
-
1
]]
if
callable
(
setting
):
if
callable
(
setting
):
setting_val
=
setting
(
module
)
setting_val
=
setting
(
module
)
getattr
(
module
,
derived
[
0
])
.
update
({
derived
[
1
]:
setting_val
})
collection
[
accessors
[
-
1
]]
=
setting_val
def
clear_for_tests
():
def
clear_for_tests
():
...
...
openedx/core/lib/tests/test_derived.py
View file @
fdc50c3a
...
@@ -4,7 +4,7 @@ Tests for derived.py
...
@@ -4,7 +4,7 @@ Tests for derived.py
import
sys
import
sys
from
unittest
import
TestCase
from
unittest
import
TestCase
from
openedx.core.lib.derived
import
derived
,
derive_settings
,
clear_for_tests
from
openedx.core.lib.derived
import
derived
,
derive
d_collection_entry
,
derive
_settings
,
clear_for_tests
class
TestDerivedSettings
(
TestCase
):
class
TestDerivedSettings
(
TestCase
):
...
@@ -22,7 +22,9 @@ class TestDerivedSettings(TestCase):
...
@@ -22,7 +22,9 @@ class TestDerivedSettings(TestCase):
derived
(
'DERIVED_VALUE'
,
'ANOTHER_DERIVED_VALUE'
)
derived
(
'DERIVED_VALUE'
,
'ANOTHER_DERIVED_VALUE'
)
self
.
module
.
DICT_VALUE
=
{}
self
.
module
.
DICT_VALUE
=
{}
self
.
module
.
DICT_VALUE
[
'test_key'
]
=
lambda
settings
:
settings
.
DERIVED_VALUE
*
3
self
.
module
.
DICT_VALUE
[
'test_key'
]
=
lambda
settings
:
settings
.
DERIVED_VALUE
*
3
derived
((
'DICT_VALUE'
,
'test_key'
))
derived_collection_entry
(
'DICT_VALUE'
,
'test_key'
)
self
.
module
.
DICT_VALUE
[
'list_key'
]
=
[
'not derived'
,
lambda
settings
:
settings
.
DERIVED_VALUE
]
derived_collection_entry
(
'DICT_VALUE'
,
'list_key'
,
1
)
def
test_derived_settings_are_derived
(
self
):
def
test_derived_settings_are_derived
(
self
):
derive_settings
(
__name__
)
derive_settings
(
__name__
)
...
@@ -42,3 +44,7 @@ class TestDerivedSettings(TestCase):
...
@@ -42,3 +44,7 @@ class TestDerivedSettings(TestCase):
def
test_derived_dict_settings
(
self
):
def
test_derived_dict_settings
(
self
):
derive_settings
(
__name__
)
derive_settings
(
__name__
)
self
.
assertEqual
(
self
.
module
.
DICT_VALUE
[
'test_key'
],
'mutter paneermutter paneermutter paneer'
)
self
.
assertEqual
(
self
.
module
.
DICT_VALUE
[
'test_key'
],
'mutter paneermutter paneermutter paneer'
)
def
test_derived_nested_settings
(
self
):
derive_settings
(
__name__
)
self
.
assertEqual
(
self
.
module
.
DICT_VALUE
[
'list_key'
][
1
],
'mutter paneer'
)
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