Last active
July 9, 2021 05:45
-
-
Save treyhunner/b2ed8d21857a7e8ff416497c66afdf0b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# django.template.defaulttags.autoescape rewritten using Python 3.10's match/case statement | |
@register.tag | |
def autoescape(parser, token): | |
""" | |
Force autoescape behavior for this block. | |
""" | |
# token.split_contents() isn't useful here because this tag doesn't accept variable as arguments | |
match token.contents.split(): | |
case [_, ('on' | 'off') as arg]: | |
nodelist = parser.parse(('endautoescape',)) | |
parser.delete_first_token() | |
return AutoEscapeControlNode((arg == 'on'), nodelist) | |
case [_, _]: | |
raise TemplateSyntaxError("'autoescape' argument should be 'on' or 'off'") | |
case _: | |
raise TemplateSyntaxError("'autoescape' tag requires exactly one argument.") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# django.template.defaulttags.cycle rewritten using Python 3.10's match/case statement | |
@register.tag | |
def cycle(parser, token): | |
""" | |
Cycle among the given strings each time this tag is encountered. | |
Within a loop, cycles among the given strings each time through | |
the loop:: | |
{% for o in some_list %} | |
<tr class="{% cycle 'row1' 'row2' %}"> | |
... | |
</tr> | |
{% endfor %} | |
Outside of a loop, give the values a unique name the first time you call | |
it, then use that name each successive time through:: | |
<tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr> | |
<tr class="{% cycle rowcolors %}">...</tr> | |
<tr class="{% cycle rowcolors %}">...</tr> | |
You can use any number of values, separated by spaces. Commas can also | |
be used to separate values; if a comma is used, the cycle values are | |
interpreted as literal strings. | |
The optional flag "silent" can be used to prevent the cycle declaration | |
from returning any value:: | |
{% for o in some_list %} | |
{% cycle 'row1' 'row2' as rowcolors silent %} | |
<tr class="{{ rowcolors }}">{% include "subtemplate.html " %}</tr> | |
{% endfor %} | |
""" | |
# Note: This returns the exact same node on each {% cycle name %} call; | |
# that is, the node object returned from {% cycle a b c as name %} and the | |
# one returned from {% cycle name %} are the exact same object. This | |
# shouldn't cause problems (heh), but if it does, now you know. | |
# | |
# Ugly hack warning: This stuffs the named template dict into parser so | |
# that names are only unique within each template (as opposed to using | |
# a global variable, which would make cycle names have to be unique across | |
# *all* templates. | |
# | |
# It keeps the last node in the parser to be able to reset it with | |
# {% resetcycle %}. | |
match token.split_contents(): | |
case [_]: | |
raise TemplateSyntaxError("'cycle' tag requires at least two arguments") | |
# {% cycle foo %} case. | |
case [_, name]: | |
if not hasattr(parser, '_named_cycle_nodes'): | |
raise TemplateSyntaxError(f"No named cycles in template. '{name}' is not defined") | |
if name not in parser._named_cycle_nodes: | |
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name) | |
return parser._named_cycle_nodes[name] | |
# {% cycle ... as foo [silent] %} case. | |
case [_, *args, "as", name, flag]: | |
raise TemplateSyntaxError(f"Only 'silent' flag is allowed after cycle's name, not '{flag}'.") | |
case [_, *args, "as", name]: | |
as_form = True | |
silent = False | |
case [_, *args, "as", name, "silent"]: | |
as_form = True | |
silent = True | |
# {% cycle foo bar ... %} case. | |
case [_, *args]: | |
as_form = False | |
if as_form: | |
values = [parser.compile_filter(arg) for arg in args] | |
node = CycleNode(values, name, silent=silent) | |
if not hasattr(parser, '_named_cycle_nodes'): | |
parser._named_cycle_nodes = {} | |
parser._named_cycle_nodes[name] = node | |
else: | |
values = [parser.compile_filter(arg) for arg in args] | |
node = CycleNode(values) | |
parser._last_cycle_node = node | |
return node |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# django.templatetags.i18n.do_get_language_info rewritten using Python 3.10's match/case statement | |
@register.tag("get_language_info") | |
def do_get_language_info(parser, token): | |
""" | |
Store the language information dictionary for the given language code in a | |
context variable. | |
Usage:: | |
{% get_language_info for LANGUAGE_CODE as l %} | |
{{ l.code }} | |
{{ l.name }} | |
{{ l.name_translated }} | |
{{ l.name_local }} | |
{{ l.bidi|yesno:"bi-directional,uni-directional" }} | |
""" | |
match token.split_contents(): | |
case [name, "for", code "as" info]: | |
return GetLanguageInfoNode(parser.compile_filter(code), info) | |
case [name, *rest]: | |
raise TemplateSyntaxError(f"'{name}' requires 'for string as variable' (got {rest!r})") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# django.utils.formats.localize rewritten using Python 3.10's match/case statement | |
def localize(value, use_l10n=None): | |
""" | |
Check if value is a localizable type (date, number...) and return it | |
formatted as a string using current locale format. | |
If use_l10n is provided and is not None, it forces the value to | |
be localized (or not), overriding the value of settings.USE_L10N. | |
""" | |
match value: | |
case str(): # Handle strings first for performance reasons. | |
return value | |
case bool(): # Make sure booleans don't get treated as numbers | |
return str(value) | |
case decimal.Decimal() | float() | int(): | |
if use_l10n is False: | |
return str(value) | |
return number_format(value, use_l10n=use_l10n) | |
case datetime.datetime(): | |
return date_format(value, 'DATETIME_FORMAT', use_l10n=use_l10n) | |
case datetime.date(): | |
return date_format(value, use_l10n=use_l10n) | |
case datetime.time(): | |
return time_format(value, 'TIME_FORMAT', use_l10n=use_l10n) | |
case _: | |
return value |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment