From f2055848f350d70b57dd268d6f7155e399d91d83 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:08:31 +0200 Subject: [PATCH 01/46] Use wraps decorator and remove manually wrapping properties --- zds/utils/templatetags/append_to_get.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index f7f2682b34..390be9dfb5 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -1,4 +1,5 @@ from django import template +from functools import wraps register = template.Library() @@ -9,13 +10,13 @@ def easy_tag(func): """deal with the repetitive parts of parsing template tags""" + + @wraps(func) def inner(parser, token): try: return func(*token.split_contents()) except TypeError: raise template.TemplateSyntaxError('Bad arguments for tag "%s"' % token.split_contents()[0]) - inner.__name__ = func.__name__ - inner.__doc__ = inner.__doc__ return inner From 1ee9fabe38d5bfc5683f0e0313ad28b12a72bcff Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:10:06 +0200 Subject: [PATCH 02/46] Rename parameter hiding build in type --- zds/utils/templatetags/append_to_get.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 390be9dfb5..22f70fa204 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -22,9 +22,9 @@ def inner(parser, token): class AppendGetNode(template.Node): - def __init__(self, dict): + def __init__(self, dictionary): self.dict_pairs = {} - for pair in dict.split(','): + for pair in dictionary.split(','): pair = pair.split('=') self.dict_pairs[pair[0]] = template.Variable(pair[1]) @@ -46,5 +46,5 @@ def render(self, context): @register.tag() @easy_tag -def append_to_get(_tag_name, dict): - return AppendGetNode(dict) +def append_to_get(_tag_name, dictionary): + return AppendGetNode(dictionary) From f6ef86bb90a9b981e1cea2baea7e3ae3f884fa8c Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:13:00 +0200 Subject: [PATCH 03/46] Avoid crash if dictionary is not correctly formatted --- zds/utils/templatetags/append_to_get.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 22f70fa204..1fee72831d 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -26,7 +26,8 @@ def __init__(self, dictionary): self.dict_pairs = {} for pair in dictionary.split(','): pair = pair.split('=') - self.dict_pairs[pair[0]] = template.Variable(pair[1]) + if len(pair) > 1: + self.dict_pairs[pair[0]] = template.Variable(pair[1]) def render(self, context): get = context['request'].GET.copy() From d9c5e139daa8e5b7b70d48c3d2ec0578ce411c75 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:33:26 +0200 Subject: [PATCH 04/46] Simplify argument list rendering --- zds/utils/templatetags/append_to_get.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 1fee72831d..1a8f813365 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -36,11 +36,9 @@ def render(self, context): for key in self.dict_pairs: get[key] = self.dict_pairs[key].resolve(context) - if len(get): - path += "?" - for (key, v) in get.items(): - for value in get.getlist(key): - path += u"&{0}={1}".format(key, value) + if len(get) > 0: + list_arg = ["{0}={1}".format(key, value) for key in get.keys() for value in get.getlist(key)] + path += "?" + "&".join(list_arg) return path From 713dff2a9d308375596f9e85560fff9e4c45e660 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:53:14 +0200 Subject: [PATCH 05/46] Adding doc string --- zds/utils/templatetags/append_to_get.py | 50 +++++++++++++++++++++---- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 1a8f813365..0dcdf0180a 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -4,12 +4,21 @@ register = template.Library() """ -Decorator to facilitate template tag creation +Decorator to facilitate template tag creation. """ def easy_tag(func): - """deal with the repetitive parts of parsing template tags""" + """ + Deal with the repetitive parts of parsing template tags : + + - Wraps functions attributes; + - Raise `TemplateSyntaxError` if arguments are not well formated. + + :rtype: function + :param func: Function to wraps. + :type func: function + """ @wraps(func) def inner(parser, token): @@ -21,15 +30,34 @@ def inner(parser, token): class AppendGetNode(template.Node): + """ + Template node allowing to render an URL appending argument to current GET address. + + Parse a string like `key1=var1,key2=var2` and generate a new URL with the provided parameters appended to current + parameters. + """ + + def __init__(self, arg_list): + """ + Create a template node which append `arg_list` to GET URL. + + :param str arg_list: the argument list to append. + """ - def __init__(self, dictionary): self.dict_pairs = {} - for pair in dictionary.split(','): + for pair in arg_list.split(','): pair = pair.split('=') if len(pair) > 1: self.dict_pairs[pair[0]] = template.Variable(pair[1]) def render(self, context): + """ + Render the new URL according to the current context. + + :param context: Current context. + :return: New URL with arguments appended. + :rtype: str + """ get = context['request'].GET.copy() path = context['request'].META['PATH_INFO'] @@ -37,13 +65,19 @@ def render(self, context): get[key] = self.dict_pairs[key].resolve(context) if len(get) > 0: - list_arg = ["{0}={1}".format(key, value) for key in get.keys() for value in get.getlist(key)] - path += "?" + "&".join(list_arg) + list_arg = [u"{0}={1}".format(key, value) for key in get.keys() for value in get.getlist(key)] + path += u"?" + u"&".join(list_arg) return path @register.tag() @easy_tag -def append_to_get(_tag_name, dictionary): - return AppendGetNode(dictionary) +def append_to_get(_, arg_list): + """Render an URL appending argument to current GET address. + + :param _: Tag name (not used) + :param arg_list: Argument list like `key1=var1,key2=var2` + :return: Template node. + """ + return AppendGetNode(arg_list) From 85e6c5895cbff72e281d97e54f4ab3cca5e056b7 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:54:18 +0200 Subject: [PATCH 06/46] Add double underscore to private member. --- zds/utils/templatetags/append_to_get.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 0dcdf0180a..912780df50 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -44,11 +44,11 @@ def __init__(self, arg_list): :param str arg_list: the argument list to append. """ - self.dict_pairs = {} + self.__dict_pairs = {} for pair in arg_list.split(','): pair = pair.split('=') if len(pair) > 1: - self.dict_pairs[pair[0]] = template.Variable(pair[1]) + self.__dict_pairs[pair[0]] = template.Variable(pair[1]) def render(self, context): """ @@ -61,8 +61,8 @@ def render(self, context): get = context['request'].GET.copy() path = context['request'].META['PATH_INFO'] - for key in self.dict_pairs: - get[key] = self.dict_pairs[key].resolve(context) + for key in self.__dict_pairs: + get[key] = self.__dict_pairs[key].resolve(context) if len(get) > 0: list_arg = [u"{0}={1}".format(key, value) for key in get.keys() for value in get.getlist(key)] From e4cf402c7b9f7f949e494a34808fb3cdbef02668 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 11:59:43 +0200 Subject: [PATCH 07/46] Rewrite argument list parsing handling bad formatted argument list --- zds/utils/templatetags/append_to_get.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 912780df50..f663e8b669 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -46,9 +46,12 @@ def __init__(self, arg_list): self.__dict_pairs = {} for pair in arg_list.split(','): - pair = pair.split('=') - if len(pair) > 1: - self.__dict_pairs[pair[0]] = template.Variable(pair[1]) + try: + key, val = pair.split('=') + self.__dict_pairs[key] = template.Variable(val) + except ValueError: + raise template.TemplateSyntaxError( + "Bad argument format. '{}' must use the format 'key1=var1,key2=var2'".format(arg_list)) def render(self, context): """ From 181a83e96ce3a06b9259f3d0863e740e6bf75933 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:03:15 +0200 Subject: [PATCH 08/46] Change formatting from old style to new one --- zds/utils/templatetags/append_to_get.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index f663e8b669..66e96b194c 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -25,7 +25,7 @@ def inner(parser, token): try: return func(*token.split_contents()) except TypeError: - raise template.TemplateSyntaxError('Bad arguments for tag "%s"' % token.split_contents()[0]) + raise template.TemplateSyntaxError('Bad arguments for tag "{}"'.format(token.split_contents()[0])) return inner From 087f43919b70fdfd2966f2f7cfa20e1baa88ac08 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:13:39 +0200 Subject: [PATCH 09/46] Improve error message More detailed messages. --- zds/utils/templatetags/append_to_get.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 66e96b194c..9cd001d81a 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -22,10 +22,20 @@ def easy_tag(func): @wraps(func) def inner(parser, token): + splitted_arg = token.split_contents() try: - return func(*token.split_contents()) + return func(*splitted_arg) except TypeError: - raise template.TemplateSyntaxError('Bad arguments for tag "{}"'.format(token.split_contents()[0])) + import inspect + args = inspect.getargspec(func).args[1:] + + err_msg = 'Bad arguments for tag "{0}".\nThe tag "{0}" take {1} arguments ({2}).\n {3} were provided ({4}).' + fstring = err_msg.format(splitted_arg[0], + len(args), + ", ".join(args), + len(splitted_arg), + ", ".join(splitted_arg)) + raise template.TemplateSyntaxError(fstring) return inner From 5d5526d28c03f32e1c9e9c0ea5c57b10715f8eb2 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:15:50 +0200 Subject: [PATCH 10/46] not used parameter --- zds/utils/templatetags/append_to_get.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 9cd001d81a..c1b853c389 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -21,7 +21,7 @@ def easy_tag(func): """ @wraps(func) - def inner(parser, token): + def inner(_, token): splitted_arg = token.split_contents() try: return func(*splitted_arg) From 4361f201d95746bc390e6d6080c2ffd667c50f89 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:18:35 +0200 Subject: [PATCH 11/46] Small correction --- zds/utils/templatetags/append_to_get.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index c1b853c389..b81995a5a1 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -22,19 +22,19 @@ def easy_tag(func): @wraps(func) def inner(_, token): - splitted_arg = token.split_contents() + split_arg = token.split_contents() try: - return func(*splitted_arg) + return func(*split_arg) except TypeError: import inspect args = inspect.getargspec(func).args[1:] err_msg = 'Bad arguments for tag "{0}".\nThe tag "{0}" take {1} arguments ({2}).\n {3} were provided ({4}).' - fstring = err_msg.format(splitted_arg[0], + fstring = err_msg.format(split_arg[0], len(args), ", ".join(args), - len(splitted_arg), - ", ".join(splitted_arg)) + len(split_arg), + ", ".join(split_arg)) raise template.TemplateSyntaxError(fstring) return inner From 31b5b2622be48f34b1a1f689c91dcecf9c34b3d4 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:19:01 +0200 Subject: [PATCH 12/46] Typo --- zds/utils/templatetags/append_to_get.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index b81995a5a1..1636971d01 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -13,7 +13,7 @@ def easy_tag(func): Deal with the repetitive parts of parsing template tags : - Wraps functions attributes; - - Raise `TemplateSyntaxError` if arguments are not well formated. + - Raise `TemplateSyntaxError` if arguments are not well formatted. :rtype: function :param func: Function to wraps. From 46831443ad4cb0e58a7bbbfe11fb32f7b70b1867 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:21:24 +0200 Subject: [PATCH 13/46] Use Djando/Tag template function. --- zds/utils/templatetags/captureas.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zds/utils/templatetags/captureas.py b/zds/utils/templatetags/captureas.py index 5a95cea55e..dd2b42905d 100644 --- a/zds/utils/templatetags/captureas.py +++ b/zds/utils/templatetags/captureas.py @@ -6,11 +6,13 @@ @register.tag(name='captureas') def do_captureas(parser, token): try: - tag_name, args = token.contents.split(None, 1) + tag_name, args = token.split_contents() except ValueError: raise template.TemplateSyntaxError("'captureas' node requires a variable name.") + nodelist = parser.parse(('endcaptureas',)) parser.delete_first_token() + return CaptureasNode(nodelist, args) From c0eb22bba49c454fe9af00fd2201c5c7e9dedcb1 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:23:53 +0200 Subject: [PATCH 14/46] Rename variable and members --- zds/utils/templatetags/captureas.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zds/utils/templatetags/captureas.py b/zds/utils/templatetags/captureas.py index dd2b42905d..1188963871 100644 --- a/zds/utils/templatetags/captureas.py +++ b/zds/utils/templatetags/captureas.py @@ -6,23 +6,23 @@ @register.tag(name='captureas') def do_captureas(parser, token): try: - tag_name, args = token.split_contents() + tag_name, variable_name = token.split_contents() except ValueError: raise template.TemplateSyntaxError("'captureas' node requires a variable name.") nodelist = parser.parse(('endcaptureas',)) parser.delete_first_token() - return CaptureasNode(nodelist, args) + return CaptureasNode(nodelist, variable_name) class CaptureasNode(template.Node): - def __init__(self, nodelist, varname): - self.nodelist = nodelist - self.varname = varname + def __init__(self, nodelist, variable_name): + self.__node_list = nodelist + self.__variable_name = variable_name def render(self, context): - output = self.nodelist.render(context) - context[self.varname] = output.strip(' \t\n\r') + output = self.__node_list.render(context) + context[self.__variable_name] = output.strip(' \t\n\r') return '' From e80bfe3d462462ca34a6a60512aa62de8ac81792 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:27:13 +0200 Subject: [PATCH 15/46] Remove useless args --- zds/utils/templatetags/captureas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/captureas.py b/zds/utils/templatetags/captureas.py index 1188963871..8ca7bb8e3e 100644 --- a/zds/utils/templatetags/captureas.py +++ b/zds/utils/templatetags/captureas.py @@ -24,5 +24,5 @@ def __init__(self, nodelist, variable_name): def render(self, context): output = self.__node_list.render(context) - context[self.__variable_name] = output.strip(' \t\n\r') + context[self.__variable_name] = output.strip() return '' From 658cbb54163d5e6f77b4d39c09c71aef6fa86169 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:37:23 +0200 Subject: [PATCH 16/46] Add doc string --- zds/utils/templatetags/captureas.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/zds/utils/templatetags/captureas.py b/zds/utils/templatetags/captureas.py index 8ca7bb8e3e..504bf24e95 100644 --- a/zds/utils/templatetags/captureas.py +++ b/zds/utils/templatetags/captureas.py @@ -2,9 +2,21 @@ register = template.Library() +""" +Define a tag allowing to capture template content as a variable. +""" + @register.tag(name='captureas') def do_captureas(parser, token): + """ + Define a tag allowing to capture template content as a variable. + + :param parser: The django template parser + :param token: tag token (tag_name + variable_name) + :return: Template node. + """ + try: tag_name, variable_name = token.split_contents() except ValueError: @@ -17,12 +29,28 @@ def do_captureas(parser, token): class CaptureasNode(template.Node): + """ + Capture end render node content to a variable name. + """ def __init__(self, nodelist, variable_name): + """ + Create a template node which render `nodelist` to `variable_name`. + + :param nodelist: The node list to capture. + :param variable_name: The variable name which will gain the rendered content. + """ self.__node_list = nodelist self.__variable_name = variable_name def render(self, context): + """ + Render the node list to the variable name. + + :param context: Current context. + :return: Empty string + :rtype: str + """ output = self.__node_list.render(context) context[self.__variable_name] = output.strip() return '' From ee6a8d7098feacb5332459f92c3d971540a5f0c8 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:37:54 +0200 Subject: [PATCH 17/46] Rename unused variable. --- zds/utils/templatetags/captureas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/captureas.py b/zds/utils/templatetags/captureas.py index 504bf24e95..b9eea07638 100644 --- a/zds/utils/templatetags/captureas.py +++ b/zds/utils/templatetags/captureas.py @@ -18,7 +18,7 @@ def do_captureas(parser, token): """ try: - tag_name, variable_name = token.split_contents() + _, variable_name = token.split_contents() except ValueError: raise template.TemplateSyntaxError("'captureas' node requires a variable name.") From 37275f16e65c692c1d4a503236e6c2a80dc29b24 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:43:14 +0200 Subject: [PATCH 18/46] Factorize error catch --- zds/utils/templatetags/date.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 15499f8c3a..fb39df8b09 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -16,9 +16,7 @@ def date_formatter(value, tooltip, small): try: value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) - except AttributeError: - return value - except ValueError: + except (AttributeError, ValueError): return value if getattr(value, 'tzinfo', None): From 4e8fc91788fe5f62d15e0e99f81eb90b80eaa8ab Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:47:09 +0200 Subject: [PATCH 19/46] Set all base string formatting on the module beginning --- zds/utils/templatetags/date.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index fb39df8b09..abea83cf9e 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -12,6 +12,10 @@ register = template.Library() +__DATE_FMT_FUTUR = "Dans le futur" +__ABS_DATE_FMT_SMALL = 'd/m/y à H\hi' +__ABS_DATE_FMT_NORMAL = 'l d F Y à H\hi' + def date_formatter(value, tooltip, small): try: value = datetime(value.year, value.month, value.day, @@ -25,7 +29,7 @@ def date_formatter(value, tooltip, small): now = datetime.now() now = now - timedelta(0, 0, now.microsecond) if value > now: - return "Dans le futur" + return __DATE_FMT_FUTUR else: delta = now - value # Natural time for today, absolute date after. @@ -33,9 +37,9 @@ def date_formatter(value, tooltip, small): if (delta.days == 0) != tooltip: return naturaltime(value) elif small: - return date(value, 'd/m/y à H\hi') + return date(value, __ABS_DATE_FMT_SMALL) else: - return date(value, 'l d F Y à H\hi') + return date(value, __ABS_DATE_FMT_NORMAL) @register.filter From 9d32c3d99fa22868110b82588aad8e8dd25cb452 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:48:09 +0200 Subject: [PATCH 20/46] Use named argument for boolean parameters --- zds/utils/templatetags/date.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index abea83cf9e..17b81fde97 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -16,6 +16,7 @@ __ABS_DATE_FMT_SMALL = 'd/m/y à H\hi' __ABS_DATE_FMT_NORMAL = 'l d F Y à H\hi' + def date_formatter(value, tooltip, small): try: value = datetime(value.year, value.month, value.day, @@ -44,9 +45,9 @@ def date_formatter(value, tooltip, small): @register.filter def format_date(value, small=False): - return date_formatter(value, False, small) + return date_formatter(value, tooltip=False, small=small) @register.filter def tooltip_date(value): - return date_formatter(value, True, False) + return date_formatter(value, tooltip=True, small=False) From 1d690980135be81e490d10877db378fe6f83e516 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:49:28 +0200 Subject: [PATCH 21/46] factorize standard output call. --- zds/utils/templatetags/date.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 17b81fde97..361a250f17 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -29,6 +29,7 @@ def date_formatter(value, tooltip, small): else: now = datetime.now() now = now - timedelta(0, 0, now.microsecond) + if value > now: return __DATE_FMT_FUTUR else: @@ -37,10 +38,8 @@ def date_formatter(value, tooltip, small): # Reverse if in tooltip if (delta.days == 0) != tooltip: return naturaltime(value) - elif small: - return date(value, __ABS_DATE_FMT_SMALL) else: - return date(value, __ABS_DATE_FMT_NORMAL) + return date(value, __ABS_DATE_FMT_SMALL if small else __ABS_DATE_FMT_NORMAL) @register.filter From 19d434e10ef5599b7425e2837455ee65553ecbed Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:51:53 +0200 Subject: [PATCH 22/46] Fix encoding --- zds/utils/templatetags/append_to_get.py | 2 ++ zds/utils/templatetags/captureas.py | 2 ++ zds/utils/templatetags/date.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 1636971d01..5b78b8face 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + from django import template from functools import wraps diff --git a/zds/utils/templatetags/captureas.py b/zds/utils/templatetags/captureas.py index b9eea07638..d9d0aa14f3 100644 --- a/zds/utils/templatetags/captureas.py +++ b/zds/utils/templatetags/captureas.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + from django import template register = template.Library() diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 361a250f17..243351c142 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -1,4 +1,4 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- from datetime import timedelta From 5029bbd63593c5bdc07a48d987c2f1b73487377f Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 13:58:30 +0200 Subject: [PATCH 23/46] Doc string --- zds/utils/templatetags/date.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 243351c142..2be83fc684 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -8,16 +8,28 @@ from django.utils.datetime_safe import datetime from django.utils.tzinfo import LocalTimezone - register = template.Library() +""" +Define a filter to format date. +""" + +# Date formating constants __DATE_FMT_FUTUR = "Dans le futur" -__ABS_DATE_FMT_SMALL = 'd/m/y à H\hi' -__ABS_DATE_FMT_NORMAL = 'l d F Y à H\hi' +__ABS_DATE_FMT_SMALL = 'd/m/y à H\hi' # Small format +__ABS_DATE_FMT_NORMAL = 'l d F Y à H\hi' # Normal format def date_formatter(value, tooltip, small): + """ + Format a date to an human readable string. + + :param value: Date to format. + :param bool tooltip: if `True`, format date to a tooltip label. + :param bool small: if `True`, create a shorter string. + :return: + """ try: value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) @@ -44,9 +56,11 @@ def date_formatter(value, tooltip, small): @register.filter def format_date(value, small=False): + """Format a date to an human readable string.""" return date_formatter(value, tooltip=False, small=small) @register.filter def tooltip_date(value): + """Format a date to an human readable string. To be used in tooltip.""" return date_formatter(value, tooltip=True, small=False) From 26e918a8e9a92239bf98afa8c0f7aaff177fa3ac Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 14:15:15 +0200 Subject: [PATCH 24/46] remove useless filter argument. --- zds/utils/templatetags/emarkdown.py | 31 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index e2c4763451..e04aeeb8d9 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -6,19 +6,29 @@ import re import markdown - from markdown.extensions.zds import ZdsExtension from zds.utils.templatetags.smileysDef import smileys -# Markdowns customs extensions : -def get_markdown_instance(Inline=False): - zdsext = ZdsExtension({"inline": Inline, "emoticons": smileys}) +""" +Markdown related filters. +""" + + +def get_markdown_instance(inline=False): + """ + Provide a pre-configured markdown parser. + + :param bool inline: If `True`, configure parser to parse only inline content. + :return: A ZMarkdown parser. + """ + zdsext = ZdsExtension({"inline": inline, "emoticons": smileys}) # Generate parser md = markdown.Markdown(extensions=(zdsext,), safe_mode = 'escape', - inline = Inline, # Protect use of html by escape it + inline = inline, + # Parse only inline content. enable_attributes = False, # Disable the conversion of attributes. # This could potentially allow an @@ -27,7 +37,8 @@ def get_markdown_instance(Inline=False): tab_length = 4, # Length of tabs in the source. # This is the default value - output_format = 'html5', # html5 output + output_format = 'html5', + # html5 output # This is the default value smart_emphasis = True, # Enable smart emphasis for underscore syntax @@ -40,7 +51,7 @@ def get_markdown_instance(Inline=False): @register.filter('humane_time') -def humane_time(t, conf={}): +def humane_time(t): tp = time.localtime(t) return time.strftime("%d %b %Y, %H:%M:%S", tp) @@ -49,8 +60,8 @@ def humane_time(t, conf={}): def emarkdown(text): try: return mark_safe( - get_markdown_instance( - Inline=False).convert(text).encode('utf-8')) + get_markdown_instance(inline=False).convert(text).encode('utf-8')) + except: return mark_safe( u'

Une erreur est survenue ' @@ -61,7 +72,7 @@ def emarkdown(text): def emarkdown_inline(text): return mark_safe( get_markdown_instance( - Inline=True).convert(text).encode('utf-8').strip()) + inline=True).convert(text).encode('utf-8').strip()) def sub_hd1(g): From 26c120d337ff9704ffcda0944d020da6ec2628da Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 14:19:14 +0200 Subject: [PATCH 25/46] Move humane_time filter to date module (not related to markdown) --- templates/article/member/history.html | 2 +- templates/tutorial/tutorial/history.html | 2 +- zds/utils/templatetags/date.py | 8 ++++++++ zds/utils/templatetags/emarkdown.py | 5 ----- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/templates/article/member/history.html b/templates/article/member/history.html index cc368a5290..0efb16a7a9 100644 --- a/templates/article/member/history.html +++ b/templates/article/member/history.html @@ -1,8 +1,8 @@ {% extends "article/base_content.html" %} -{% load emarkdown %} {% load profile %} {% load date %} {% load thumbnail %} +{% load date %} {% block title %} diff --git a/templates/tutorial/tutorial/history.html b/templates/tutorial/tutorial/history.html index 09cfe41c57..36f4a80e93 100644 --- a/templates/tutorial/tutorial/history.html +++ b/templates/tutorial/tutorial/history.html @@ -1,7 +1,7 @@ {% extends "tutorial/base.html" %} -{% load emarkdown %} {% load profile %} {% load thumbnail %} +{% load date %} {% block title %} diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 2be83fc684..19776b4253 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from datetime import timedelta +import time from django import template from django.contrib.humanize.templatetags.humanize import naturaltime @@ -64,3 +65,10 @@ def format_date(value, small=False): def tooltip_date(value): """Format a date to an human readable string. To be used in tooltip.""" return date_formatter(value, tooltip=True, small=False) + + +@register.filter('humane_time') +def humane_time(t): + tp = time.localtime(t) + return time.strftime("%d %b %Y, %H:%M:%S", tp) + diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index e04aeeb8d9..11e17614b1 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -2,7 +2,6 @@ from django import template from django.utils.safestring import mark_safe -import time import re import markdown @@ -50,10 +49,6 @@ def get_markdown_instance(inline=False): register = template.Library() -@register.filter('humane_time') -def humane_time(t): - tp = time.localtime(t) - return time.strftime("%d %b %Y, %H:%M:%S", tp) @register.filter(needs_autoescape=False) From da0a2f437c57809e37ebb20fbeb83817d47b4663 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 14:45:53 +0200 Subject: [PATCH 26/46] Factorise markdown header shift "decale_header" --- zds/utils/templatetags/emarkdown.py | 56 +++++++---------------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 11e17614b1..31dee2f3ff 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -1,19 +1,21 @@ # coding: utf-8 +from functools import partial +import re + from django import template from django.utils.safestring import mark_safe -import re import markdown from markdown.extensions.zds import ZdsExtension from zds.utils.templatetags.smileysDef import smileys +register = template.Library() """ Markdown related filters. """ - def get_markdown_instance(inline=False): """ Provide a pre-configured markdown parser. @@ -46,10 +48,6 @@ def get_markdown_instance(inline=False): ) return md -register = template.Library() - - - @register.filter(needs_autoescape=False) def emarkdown(text): @@ -70,49 +68,21 @@ def emarkdown_inline(text): inline=True).convert(text).encode('utf-8').strip()) -def sub_hd1(g): - lvl = g.group('level') - hd = g.group('header') - next = "#" + lvl + hd - - return next - +def decale_header(text, count): -def sub_hd2(g): - lvl = g.group('level') - hd = g.group('header') - next = "#" + lvl + hd + def sub_hd(match): + lvl = match.group('level') + hd = match.group('header') - return next + new_content = "#" * count + lvl + hd + return new_content -def sub_hd3(g): - lvl = g.group('level') - hd = g.group('header') - next = "###" + lvl + hd - - return next - - -@register.filter('decale_header_1') -def decale_header_1(text): return re.sub( r'(^|\n)(?P#{1,4})(?P

.*?)#*(\n|$)', - sub_hd1, + sub_hd, text.encode("utf-8")) -@register.filter('decale_header_2') -def decale_header_2(text): - return re.sub( - r'(^|\n)(?P#{1,4})(?P
.*?)#*(\n|$)', - sub_hd2, - text.encode("utf-8")) - - -@register.filter('decale_header_3') -def decale_header_3(text): - return re.sub( - r'(^|\n)(?P#{1,4})(?P
.*?)#*(\n|$)', - sub_hd3, - text.encode("utf-8")) +for i in range(4): + register.filter('decale_header_{}'.format(i))(partial(decale_header, count=i)) From 86588e72a276241ec8484da118eafd0e3ba8f4c4 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 14:54:23 +0200 Subject: [PATCH 27/46] Factorize markdown render + docstring --- zds/utils/templatetags/emarkdown.py | 47 +++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 31dee2f3ff..62b77f43ed 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -16,6 +16,11 @@ Markdown related filters. """ +# Constant strings +__MD_ERROR_PARSING = u"Une erreur est survenue dans la génération de texte Markdown. " \ + u"Veuillez rapporter le bug." + + def get_markdown_instance(inline=False): """ Provide a pre-configured markdown parser. @@ -49,23 +54,47 @@ def get_markdown_instance(inline=False): return md +def render_markdown(text, inline=False): + """ + Render a markdown text to html. + + :param str text: Text to render. + :param bool inline: If `True`, parse only inline content. + :return: Equivalent html string. + :rtype: str + """ + return get_markdown_instance(inline=False).convert(text).encode('utf-8').strip() + + @register.filter(needs_autoescape=False) def emarkdown(text): - try: - return mark_safe( - get_markdown_instance(inline=False).convert(text).encode('utf-8')) + """ + Filter markdown text and render it to html. + :param str text: Text to render. + :return: Equivalent html string. + :rtype: str + """ + try: + return mark_safe(render_markdown(text, inline=False)) except: - return mark_safe( - u'

Une erreur est survenue ' - u'dans la génération de texte Markdown. Veuillez rapporter le bug

') + return mark_safe(u'

{}

'.format(__MD_ERROR_PARSING)) @register.filter(needs_autoescape=False) def emarkdown_inline(text): - return mark_safe( - get_markdown_instance( - inline=True).convert(text).encode('utf-8').strip()) + """ + Filter markdown text and render it to html. Only inline elements will be parsed. + + :param str text: Text to render. + :return: Equivalent html string. + :rtype: str + """ + + try: + return mark_safe(render_markdown(text, inline=True)) + except: + return mark_safe(u'

{}

'.format(__MD_ERROR_PARSING)) def decale_header(text, count): From 4c555498aca6ac10424cdce656b7f7f1cb00b914 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 15:00:08 +0200 Subject: [PATCH 28/46] Docstring + comments --- zds/utils/templatetags/emarkdown.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 62b77f43ed..1f0e5526e4 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -98,8 +98,18 @@ def emarkdown_inline(text): def decale_header(text, count): + """ + Shift header in markdown document. + + :param str text: Text to filter. + :param int count: + :return: Filtered text. + :rtype: str + """ def sub_hd(match): + """Replace header shifted.""" + lvl = match.group('level') hd = match.group('header') @@ -113,5 +123,6 @@ def sub_hd(match): text.encode("utf-8")) -for i in range(4): +# Register 3 filter. +for i in range(1, 4): register.filter('decale_header_{}'.format(i))(partial(decale_header, count=i)) From 2bbb1429fb077adafb6c861145f0a6ae15faa267 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 15:14:03 +0200 Subject: [PATCH 29/46] Docstring + comments --- zds/utils/templatetags/date.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 19776b4253..5e78b88f1d 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -35,6 +35,7 @@ def date_formatter(value, tooltip, small): value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) except (AttributeError, ValueError): + # Check why not raise template.TemplateSyntaxError() return value if getattr(value, 'tzinfo', None): @@ -69,6 +70,7 @@ def tooltip_date(value): @register.filter('humane_time') def humane_time(t): + """Render time to an human readable string""" tp = time.localtime(t) return time.strftime("%d %b %Y, %H:%M:%S", tp) From 43c66c5d4837a07838deabd01c4f16e0af811dab Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 15:25:59 +0200 Subject: [PATCH 30/46] Add test directory --- zds/utils/templatetags/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 zds/utils/templatetags/tests/__init__.py diff --git a/zds/utils/templatetags/tests/__init__.py b/zds/utils/templatetags/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From f2e45ef38ec12b4d7464d2ec1f8594f2ce7a2f9c Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 16:26:42 +0200 Subject: [PATCH 31/46] Fix: Django do not like partial :( --- zds/utils/templatetags/emarkdown.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 1f0e5526e4..22026accab 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -1,6 +1,5 @@ # coding: utf-8 -from functools import partial import re from django import template @@ -125,4 +124,5 @@ def sub_hd(match): # Register 3 filter. for i in range(1, 4): - register.filter('decale_header_{}'.format(i))(partial(decale_header, count=i)) + register.filter('decale_header_{}'.format(i))(lambda t: decale_header(t, count=i)) + From 11a47d9aafa88a3b3fbbf4b3a504b36b376f9376 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 16:47:05 +0200 Subject: [PATCH 32/46] Fix: allowing empty list in AppendGetNode --- zds/utils/templatetags/append_to_get.py | 13 ++-- .../templatetags/tests/tests_append_to_get.py | 70 +++++++++++++++++++ 2 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 zds/utils/templatetags/tests/tests_append_to_get.py diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index 5b78b8face..ddc753a456 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -58,12 +58,13 @@ def __init__(self, arg_list): self.__dict_pairs = {} for pair in arg_list.split(','): - try: - key, val = pair.split('=') - self.__dict_pairs[key] = template.Variable(val) - except ValueError: - raise template.TemplateSyntaxError( - "Bad argument format. '{}' must use the format 'key1=var1,key2=var2'".format(arg_list)) + if pair: + try: + key, val = pair.split('=') + self.__dict_pairs[key] = template.Variable(val) + except ValueError: + raise template.TemplateSyntaxError( + "Bad argument format. '{}' must use the format 'key1=var1,key2=var2'".format(arg_list)) def render(self, context): """ diff --git a/zds/utils/templatetags/tests/tests_append_to_get.py b/zds/utils/templatetags/tests/tests_append_to_get.py new file mode 100644 index 0000000000..715091840b --- /dev/null +++ b/zds/utils/templatetags/tests/tests_append_to_get.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + + +from django.test import TestCase, RequestFactory +from django.template import TemplateSyntaxError, Token, TOKEN_TEXT, Context + +from zds.utils.templatetags.append_to_get import easy_tag, AppendGetNode + + +class EasyTagTest(TestCase): + def setUp(self): + def my_function(a, b, c): + """My doc string.""" + return a, b, c + + self.simple_function = my_function + self.wrapped_function = easy_tag(self.simple_function) + + def test_valid_call(self): + + # Call tag without parser and three elements + ret = self.wrapped_function(None, Token(TOKEN_TEXT, "elem1 elem2 elem3")) + + # Check arguments have been split + self.assertEqual(3, len(ret)) + self.assertEqual("elem1", ret[0]) + self.assertEqual("elem2", ret[1]) + self.assertEqual("elem3", ret[2]) + + # Check functions wrapping + self.assertEqual(self.simple_function.__name__, self.wrapped_function.__name__) + self.assertEqual(self.simple_function.__doc__, self.wrapped_function.__doc__) + + def test_invalid_call(self): + + # Check raising TemplateSyntaxError if call with too few arguments + self.assertRaises(TemplateSyntaxError, self.wrapped_function, None, Token(TOKEN_TEXT,"elem1 elem2")) + + # Check raising TemplateSyntaxError if call with too many arguments + self.assertRaises(TemplateSyntaxError, self.wrapped_function, None, Token(TOKEN_TEXT,"elem1 elem2 elem3 elem4")) + + +class AppendGetNodeTest(TestCase): + def setUp(self): + # Every test needs access to the request factory. + factory = RequestFactory() + self.argl1 = "key1=var1" + + self.argl2 = "key1=var1,key2=var2" + self.context = Context({'request': factory.get('/data/test'), 'var1': 1, 'var2': 2}) + + def test_valid_call(self): + + # Test normal call + agn = AppendGetNode(self.argl2) + tr = agn.render(self.context) + self.assertTrue(tr == "/data/test?key1=1&key2=2" or tr == "/data/test?key2=2&key1=1") + + # Test call with one argument + agn = AppendGetNode(self.argl1) + tr = agn.render(self.context) + self.assertEqual(tr, "/data/test?key1=1") + + + # Test call without arguments + agn = AppendGetNode("") + tr = agn.render(self.context) + self.assertEqual(tr, "/data/test") + + From 14d72eff69b2dc6a0cb9b95d6ec56f7008d75cb7 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 17:18:13 +0200 Subject: [PATCH 33/46] Fix: Check value not empty in AppendGetNode --- zds/utils/templatetags/append_to_get.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zds/utils/templatetags/append_to_get.py b/zds/utils/templatetags/append_to_get.py index ddc753a456..a6cfacf37e 100644 --- a/zds/utils/templatetags/append_to_get.py +++ b/zds/utils/templatetags/append_to_get.py @@ -61,10 +61,13 @@ def __init__(self, arg_list): if pair: try: key, val = pair.split('=') + if not val: + raise template.TemplateSyntaxError( + "Bad argument format. Empty value for key '{}".format(key)) self.__dict_pairs[key] = template.Variable(val) except ValueError: raise template.TemplateSyntaxError( - "Bad argument format. '{}' must use the format 'key1=var1,key2=var2'".format(arg_list)) + "Bad argument format.\n'{}' must use the format 'key1=var1,key2=var2'".format(arg_list)) def render(self, context): """ From 584a6dd1f1ae605c2e3eedeace932e9a827baec7 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 17:31:40 +0200 Subject: [PATCH 34/46] Add Test for "append_to_get" module --- .../templatetags/tests/tests_append_to_get.py | 59 +++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/zds/utils/templatetags/tests/tests_append_to_get.py b/zds/utils/templatetags/tests/tests_append_to_get.py index 715091840b..a416f1b376 100644 --- a/zds/utils/templatetags/tests/tests_append_to_get.py +++ b/zds/utils/templatetags/tests/tests_append_to_get.py @@ -2,7 +2,7 @@ from django.test import TestCase, RequestFactory -from django.template import TemplateSyntaxError, Token, TOKEN_TEXT, Context +from django.template import TemplateSyntaxError, Token, TOKEN_TEXT, Context, VariableDoesNotExist, Template from zds.utils.templatetags.append_to_get import easy_tag, AppendGetNode @@ -44,20 +44,18 @@ class AppendGetNodeTest(TestCase): def setUp(self): # Every test needs access to the request factory. factory = RequestFactory() - self.argl1 = "key1=var1" - self.argl2 = "key1=var1,key2=var2" self.context = Context({'request': factory.get('/data/test'), 'var1': 1, 'var2': 2}) def test_valid_call(self): # Test normal call - agn = AppendGetNode(self.argl2) + agn = AppendGetNode("key1=var1,key2=var2") tr = agn.render(self.context) self.assertTrue(tr == "/data/test?key1=1&key2=2" or tr == "/data/test?key2=2&key1=1") # Test call with one argument - agn = AppendGetNode(self.argl1) + agn = AppendGetNode("key1=var1") tr = agn.render(self.context) self.assertEqual(tr, "/data/test?key1=1") @@ -67,4 +65,55 @@ def test_valid_call(self): tr = agn.render(self.context) self.assertEqual(tr, "/data/test") + def test_invalid_call(self): + + # Test invalid format + + # Space separators args : + self.assertRaises(TemplateSyntaxError, AppendGetNode, "key1=var1 key2=var2") + # No values : + self.assertRaises(TemplateSyntaxError, AppendGetNode, "key1=,key2=var2") + self.assertRaises(TemplateSyntaxError, AppendGetNode, "key1,key2=var2") + # Not resolvable variable + agn = AppendGetNode("key1=var3,key2=var2") + self.assertRaises(VariableDoesNotExist, agn.render, self.context) + + def test_valid_templatetag(self): + + # Test normal call + tr = Template("{% load append_to_get %}" + "{% append_to_get key1=var1,key2=var2 %}" + ).render(self.context) + self.assertTrue(tr == "/data/test?key1=1&key2=2" or tr == "/data/test?key2=2&key1=1") + + # Test call with one argument + tr = Template("{% load append_to_get %}" + "{% append_to_get key1=var1 %}" + ).render(self.context) + self.assertEqual(tr, "/data/test?key1=1") + + def test_invalid_templatetag(self): + # Test invalid format + + # Space separators args : + str_tp = ("{% load append_to_get %}" + "{% append_to_get key1=var1 key2=var2 %}") + self.assertRaises(TemplateSyntaxError, Template, str_tp) + + # No values : + str_tp = ("{% load append_to_get %}" + "{% append_to_get key1=,key2=var2 %}") + self.assertRaises(TemplateSyntaxError, Template, str_tp) + str_tp = ("{% load append_to_get %}" + "{% append_to_get key1,key2=var2 %}") + self.assertRaises(TemplateSyntaxError, Template, str_tp) + + # Not resolvable variable + tr = Template("{% load append_to_get %}" + "{% append_to_get key1=var3,key2=var2 %}" + ) + self.assertRaises(VariableDoesNotExist, tr.render, self.context) + + + From 7e0eaf4f9bce895a46ba93b12b63467db09629ad Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Thu, 11 Sep 2014 18:02:35 +0200 Subject: [PATCH 35/46] Add Test for "captureas" module --- .../templatetags/tests/tests_captureas.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 zds/utils/templatetags/tests/tests_captureas.py diff --git a/zds/utils/templatetags/tests/tests_captureas.py b/zds/utils/templatetags/tests/tests_captureas.py new file mode 100644 index 0000000000..42045b15b2 --- /dev/null +++ b/zds/utils/templatetags/tests/tests_captureas.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +from django.test import TestCase +from django.template import Context, Template, TemplateSyntaxError + + +class CaptureasNodeTest(TestCase): + def setUp(self): + self.context = Context() + + def test_valid_templatetag(self): + + # Test empty element + self.assertFalse("var1" in self.context) + tr = Template("{% load captureas %}" + "{% captureas var1%}" + "{% endcaptureas %}" + ).render(self.context) + self.assertTrue("var1" in self.context) + + self.assertEqual(tr, "") + self.assertEqual(self.context["var1"], "") + + # Test simple content + self.assertFalse("var2" in self.context) + tr = Template("{% load captureas %}" + "{% captureas var2%}" + "{% for i in 'xxxxxxxxxx' %}" + "{{forloop.counter0}}" + "{% endfor %}" + "{% endcaptureas %}" + ).render(self.context) + self.assertTrue("var2" in self.context) + + self.assertEqual(tr, "") + self.assertEqual(self.context["var2"], "0123456789") + + def test_invalid_templatetag(self): + # No var name + tp = ("{% load captureas %}" + "{% captureas%}" + "{% endcaptureas %}" + ) + self.assertRaises(TemplateSyntaxError, Template, tp) + + # Too many var name + tp = ("{% load captureas %}" + "{% captureas v1 v2%}" + "{% endcaptureas %}" + ) + self.assertRaises(TemplateSyntaxError, Template, tp) From dc731cf01569c7c34f0aa0b2eb0331a0b0cddddb Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 11:58:57 +0200 Subject: [PATCH 36/46] move const string on top of the module --- zds/utils/templatetags/date.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 5e78b88f1d..91660cfa42 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -15,11 +15,12 @@ Define a filter to format date. """ -# Date formating constants +# Date formatting constants __DATE_FMT_FUTUR = "Dans le futur" __ABS_DATE_FMT_SMALL = 'd/m/y à H\hi' # Small format __ABS_DATE_FMT_NORMAL = 'l d F Y à H\hi' # Normal format +__ABS_HUMAN_TIME_FMT = "%d %b %Y, %H:%M:%S" def date_formatter(value, tooltip, small): @@ -72,5 +73,5 @@ def tooltip_date(value): def humane_time(t): """Render time to an human readable string""" tp = time.localtime(t) - return time.strftime("%d %b %Y, %H:%M:%S", tp) + return time.strftime(__ABS_HUMAN_TIME_FMT, tp) From 481b314005b25189b6a20f86b21e590c3401a589 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 13:28:27 +0200 Subject: [PATCH 37/46] Better timedelta argument passing --- zds/utils/templatetags/date.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 91660cfa42..568ecf4bd5 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -36,14 +36,14 @@ def date_formatter(value, tooltip, small): value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second) except (AttributeError, ValueError): - # Check why not raise template.TemplateSyntaxError() + # todo : Check why not raise template.TemplateSyntaxError() ? return value if getattr(value, 'tzinfo', None): now = datetime.now(LocalTimezone(value)) else: now = datetime.now() - now = now - timedelta(0, 0, now.microsecond) + now = now - timedelta(microseconds=now.microsecond) if value > now: return __DATE_FMT_FUTUR From 528c3d2d6392f9a930e6cf8c5a2457d274d7b0e5 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 14:12:46 +0200 Subject: [PATCH 38/46] Add tests to "date" templatetags module --- zds/utils/templatetags/tests/tests_date.py | 117 +++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 zds/utils/templatetags/tests/tests_date.py diff --git a/zds/utils/templatetags/tests/tests_date.py b/zds/utils/templatetags/tests/tests_date.py new file mode 100644 index 0000000000..cac8a92a40 --- /dev/null +++ b/zds/utils/templatetags/tests/tests_date.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime, timedelta + +from django.test import TestCase +from django.template import Context, Template + + +class DateFormatterTest(TestCase): + # todo: Add test with localization parameters + + def setUp(self): + + now = datetime.now() + date_previous_in_day = now - timedelta(hours=1) + date_previous_abs = datetime(2013, 9, 12, hour=11, minute=10, second=42, microsecond=10) + date_future_in_day = now + timedelta(hours=1) + + self.context = Context({"date_previous_in_day": date_previous_in_day, + "date_previous_abs": date_previous_abs, + "date_future_in_day": date_future_in_day, + "date_epoch": 42, + "NoneVal": None}) + + def test_format_date(self): + # Default behaviour + tr = Template("{% load date %}" + "{{ date_previous_in_day | format_date}}" + ).render(self.context) + self.assertEqual(u"il y a une heure", tr) + + tr = Template("{% load date %}" + "{{ date_future_in_day | format_date}}" + ).render(self.context) + self.assertEqual(u"Dans le futur", tr) + + tr = Template("{% load date %}" + "{{ date_previous_abs | format_date}}" + ).render(self.context) + + self.assertEqual(u"jeudi 12 septembre 2013 à 11h10", tr) + + # small == False :=> Same behaviour + tr = Template("{% load date %}" + "{{ date_previous_in_day | format_date:False}}" + ).render(self.context) + self.assertEqual(u"il y a une heure", tr) + + tr = Template("{% load date %}" + "{{ date_future_in_day | format_date:False}}" + ).render(self.context) + self.assertEqual(u"Dans le futur", tr) + + tr = Template("{% load date %}" + "{{ date_previous_abs | format_date:False}}" + ).render(self.context) + + self.assertEqual(u"jeudi 12 septembre 2013 à 11h10", tr) + + # small == True :=> absolute date change + tr = Template("{% load date %}" + "{{ date_previous_in_day | format_date:True}}" + ).render(self.context) + self.assertEqual(u"il y a une heure", tr) + + tr = Template("{% load date %}" + "{{ date_future_in_day | format_date:True}}" + ).render(self.context) + self.assertEqual(u"Dans le futur", tr) + + tr = Template("{% load date %}" + "{{ date_previous_abs | format_date:True}}" + ).render(self.context) + + self.assertEqual(u"12/09/13 à 11h10", tr) + + # Bad format + tr = Template("{% load date %}" + "{{ NoneVal | format_date}}" + ).render(self.context) + + self.assertEqual(u"None", tr) + + def test_tooltip_date(self): + # Default behaviour + + # Todo: Add test to step time less than one day with tooltip + # Todo: I don't know how to test this without hugly hack on datetime.now() + + tr = Template("{% load date %}" + "{{ date_future_in_day | tooltip_date}}" + ).render(self.context) + self.assertEqual(u"Dans le futur", tr) + + tr = Template("{% load date %}" + "{{ date_previous_abs | tooltip_date}}" + ).render(self.context) + + self.assertEqual(u"il y a 1\xa0année", tr) + + # Bad format + tr = Template("{% load date %}" + "{{ NoneVal | tooltip_date}}" + ).render(self.context) + + self.assertEqual(u"None", tr) + + def test_humane_time(self): + + # Default behaviour + tr = Template("{% load date %}" + "{{ date_epoch | humane_time}}" + ).render(self.context) + self.assertEqual(u"01 Jan 1970, 01:00:42", tr) + + + From f267126ae74a8bb08c205b58ce77b75c452373a0 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 14:38:38 +0200 Subject: [PATCH 39/46] Fix: Markdown inline not propagated --- zds/utils/templatetags/emarkdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 22026accab..632745eacd 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -62,7 +62,7 @@ def render_markdown(text, inline=False): :return: Equivalent html string. :rtype: str """ - return get_markdown_instance(inline=False).convert(text).encode('utf-8').strip() + return get_markdown_instance(inline=inline).convert(text).encode('utf-8').strip() @register.filter(needs_autoescape=False) From e96b3b657f40660c56c51657a3bfc6eba96c0ea3 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 14:43:48 +0200 Subject: [PATCH 40/46] Fix: Only add complete match from all --- zds/utils/templatetags/emarkdown.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 632745eacd..4a9b5093e2 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -112,7 +112,7 @@ def sub_hd(match): lvl = match.group('level') hd = match.group('header') - new_content = "#" * count + lvl + hd + new_content = "#" * count + match.group(0) return new_content From f41ef8e8482f3fc88f7c82cce36810bb5d774b36 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 15:11:24 +0200 Subject: [PATCH 41/46] Fix: shift header --- zds/utils/templatetags/emarkdown.py | 40 ++++++++++++++++++----------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index 4a9b5093e2..cb3027f328 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -96,6 +96,18 @@ def emarkdown_inline(text): return mark_safe(u'

{}

'.format(__MD_ERROR_PARSING)) +def sub_hd(match, count): + """Replace header shifted.""" + st = match.group(1) + lvl = match.group('level') + hd = match.group('header') + end = match.group(4) + + new_content = st + "#" * count + lvl + hd + end + + return new_content + + def decale_header(text, count): """ Shift header in markdown document. @@ -105,24 +117,22 @@ def decale_header(text, count): :return: Filtered text. :rtype: str """ - - def sub_hd(match): - """Replace header shifted.""" - - lvl = match.group('level') - hd = match.group('header') - - new_content = "#" * count + match.group(0) - - return new_content - return re.sub( r'(^|\n)(?P#{1,4})(?P
.*?)#*(\n|$)', - sub_hd, + lambda t: sub_hd(t, count), text.encode("utf-8")) -# Register 3 filter. -for i in range(1, 4): - register.filter('decale_header_{}'.format(i))(lambda t: decale_header(t, count=i)) +@register.filter('decale_header_1') +def decale_header_1(text): + return decale_header(text, 1) + + +@register.filter('decale_header_2') +def decale_header_2(text): + return decale_header(text, 2) + +@register.filter('decale_header_3') +def decale_header_3(text): + return decale_header(text, 3) \ No newline at end of file From 32a677d4369c8dd1b1292b38638bff68037164bb Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 15:41:17 +0200 Subject: [PATCH 42/46] Add test to "emarkdown" template tags --- .../templatetags/tests/test_emarkdown.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 zds/utils/templatetags/tests/test_emarkdown.py diff --git a/zds/utils/templatetags/tests/test_emarkdown.py b/zds/utils/templatetags/tests/test_emarkdown.py new file mode 100644 index 0000000000..97153fb8bd --- /dev/null +++ b/zds/utils/templatetags/tests/test_emarkdown.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +from django.test import TestCase +from django.template import Context, Template + + +class EMarkdownTest(TestCase): + def setUp(self): + content = u"# Titre 1\n\n## Titre **2**\n\n### Titre 3\n\n> test" + self.context = Context({"content": content}) + + def test_emarkdown(self): + # The goal is not to test zmarkdown but test that template tag correctly call it + + tr = Template("{% load emarkdown %}{{ content | emarkdown}}").render(self.context) + + self.assertEqual(u"

Titre 1

\n" + "

Titre 2

\n" + "
Titre 3
\n" + "
\n" + "

test

\n" + "
", tr) + + # Todo: Found a way to force parsing crash or simulate it. + + def test_emarkdown_inline(self): + # The goal is not to test zmarkdown but test that template tag correctly call it + + tr = Template("{% load emarkdown %}{{ content | emarkdown_inline}}").render(self.context) + + self.assertEqual(u"

# Titre 1\n\n" + "## Titre 2\n\n" + "### Titre 3\n\n" + "> test\n" + "

", tr) + + # Todo: Found a way to force parsing crash or simulate it. + + def test_decale_header(self): + tr = Template("{% load emarkdown %}{{ content | decale_header_1}}").render(self.context) + self.assertEqual(u"## Titre 1\n\n" + "### Titre **2**\n\n" + "#### Titre 3\n\n" + "> test", tr) + + tr = Template("{% load emarkdown %}{{ content | decale_header_2}}").render(self.context) + self.assertEqual(u"### Titre 1\n\n" + "#### Titre **2**\n\n" + "##### Titre 3\n\n" + "> test", tr) + + tr = Template("{% load emarkdown %}{{ content | decale_header_3}}").render(self.context) + self.assertEqual(u"#### Titre 1\n\n" + "##### Titre **2**\n\n" + "###### Titre 3\n\n" + "> test", tr) \ No newline at end of file From 13230e7cd31a9a6b83e84f47dd8129d0776cd21d Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 15:41:50 +0200 Subject: [PATCH 43/46] Fix doc string comment --- zds/utils/templatetags/date.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 568ecf4bd5..3608f59822 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -71,7 +71,7 @@ def tooltip_date(value): @register.filter('humane_time') def humane_time(t): - """Render time to an human readable string""" + """Render time (number of second from epoch) to an human readable string""" tp = time.localtime(t) return time.strftime(__ABS_HUMAN_TIME_FMT, tp) From 613f557c0e341745b470d07873cb088923d89047 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 16:42:34 +0200 Subject: [PATCH 44/46] Complete doc --- doc/sphinx/source/index.rst | 7 +- doc/sphinx/source/install/install-linux.rst | 14 +-- doc/sphinx/source/install/install-os-x.rst | 14 +-- doc/sphinx/source/install/install-windows.rst | 42 ++++---- doc/sphinx/source/utils/templatetags.rst | 102 ++++++++++++++++++ doc/sphinx/source/utils/utils.rst | 10 ++ 6 files changed, 152 insertions(+), 37 deletions(-) create mode 100644 doc/sphinx/source/utils/templatetags.rst create mode 100644 doc/sphinx/source/utils/utils.rst diff --git a/doc/sphinx/source/index.rst b/doc/sphinx/source/index.rst index edd080e6c7..e72fd750da 100644 --- a/doc/sphinx/source/index.rst +++ b/doc/sphinx/source/index.rst @@ -2,7 +2,7 @@ sphinx-quickstart le Samedi 30 Août 2014 à 12:10:30. Documentation de Zeste De Savoir -=========================================== +================================ Sommaire: @@ -15,12 +15,13 @@ Sommaire: forum/forum.rst gallery/gallery.rst article/article.rst - + utils/utils.rst + Index et tableaux -================== +================= * :ref:`genindex` * :ref:`modindex` diff --git a/doc/sphinx/source/install/install-linux.rst b/doc/sphinx/source/install/install-linux.rst index 66d5af3efc..d2679ad414 100644 --- a/doc/sphinx/source/install/install-linux.rst +++ b/doc/sphinx/source/install/install-linux.rst @@ -1,6 +1,6 @@ -======================== +======================= Installation sous Linux -======================== +======================= Pour installer une version locale de ZdS sur GNU/Linux, veuillez suivre les instructions suivantes. Si une commande ne passe pas, essayez de savoir pourquoi avant de continuer. @@ -31,7 +31,7 @@ Ou, en une ligne, easy_install pip Instalation et configuration de `virtualenv` -=========================================== +============================================ (cette étape n'est pas obligatoire, mais fortement conseillée) @@ -48,20 +48,22 @@ Instalation et configuration de `virtualenv` source zdsenv/bin/activate +Pour sortir de votre environnement : ``deactive`` + Une documentation plus complète de cet outil [est disponible ici](http://docs.python-guide.org/en/latest/dev/virtualenvs/). Front ou Back ? =============== Si vous ne comptez qu'au back-end du site, téléchargez le zip des ressources `ici `_ -Il faudra l'extraire dans le dossier `dist/` à la racine de votre projet. +Il faudra l'extraire dans le dossier ``dist/`` à la racine de votre projet. Si vous comptez contribuer au front-end, rendez-vous sur [la documentation dédiée](gulp.md). Lancer ZdS -=============== +========== -Une fois dans votre environnement python (`source ../bin/activate` si vous utilisez virtualenv, très fortement conseillé), lancez l'installation complète : +Une fois dans votre environnement python (``source ../bin/activate`` si vous utilisez virtualenv, très fortement conseillé), lancez l'installation complète : .. sourcecode:: bash diff --git a/doc/sphinx/source/install/install-os-x.rst b/doc/sphinx/source/install/install-os-x.rst index 98ae0a5213..f8b55c9bdb 100644 --- a/doc/sphinx/source/install/install-os-x.rst +++ b/doc/sphinx/source/install/install-os-x.rst @@ -1,6 +1,6 @@ -======================== +====================== Installation sous OS X -======================== +====================== Pour installer une version locale de ZdS sur OS X, veuillez suivre les instructions suivantes. Si une commande ne passe pas, essayez de savoir pourquoi avant de continuer. @@ -28,7 +28,7 @@ Installation de virtualenv Création de votre environnement -========================== +=============================== .. sourcecode:: bash @@ -56,7 +56,7 @@ Front ou Back ? =============== Si vous ne comptez qu'au back-end du site, téléchargez le zip des ressources `ici `_ -Il faudra l'extraire dans le dossier `dist/` à la racine de votre projet. +Il faudra l'extraire dans le dossier ``dist/`` à la racine de votre projet. Si vous comptez contribuer au front-end, rendez-vous sur la documentation dédiée. @@ -70,11 +70,11 @@ Installation de toutes les dépendances gulp build -Pour relancer votre environnement : `source ~/.virtualenvs/zdsenv/bin/activate` -Pour sortir de votre environnement : `deactive` +Pour relancer votre environnement : ``source ~/.virtualenvs/zdsenv/bin/activate`` +Pour sortir de votre environnement : ``deactive`` Aller plus loin -================ +=============== Pour faire fonctionner ZdS dans son ensemble vous devez installer les outils LateX et Pandoc. diff --git a/doc/sphinx/source/install/install-windows.rst b/doc/sphinx/source/install/install-windows.rst index 79fae3041e..0dfcd8aafd 100644 --- a/doc/sphinx/source/install/install-windows.rst +++ b/doc/sphinx/source/install/install-windows.rst @@ -1,6 +1,6 @@ -========================================= +========================================== Installation sous **Windows 7, 8** et plus -========================================= +========================================== Pour installer une version locale de ZdS sur Windows, veuillez suivre les instructions suivantes. Si une commande ne passe pas, essayez de savoir pourquoi avant de continuer. @@ -12,38 +12,38 @@ Prérequis - `PowerShell 3.0+ `_ - `Git `_ (Git pour Eclipse ne suffit pas ; associez les .sh) - [Téléchargez et installez Python 2.7](https://www.python.org/download/releases/2.7/) -- Installez setuptools : Démarrez `Powershell `_ **en mode administrateur** et lancez la commande suivante : `(Invoke-WebRequest https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py).Content | python -` +- Installez setuptools : Démarrez `Powershell `_ **en mode administrateur** et lancez la commande suivante : ``(Invoke-WebRequest https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py).Content | python -`` - Redémarrez Powershell -- Installez pip : `easy_install pip` -- Désactivez la sécurité sur les script powershell `Set-ExecutionPolicy RemoteSigned` +- Installez pip : ``easy_install pip`` +- Désactivez la sécurité sur les script powershell ``Set-ExecutionPolicy RemoteSigned`` - Installez Virtualenv avec les commandes suivante : - - `pip install virtualenv` - - `pip install virtualenvwrapper-powershell` + - ``pip install virtualenv`` + - ``pip install virtualenvwrapper-powershell`` - Créez votre workspace dédié à ZdS - - `set $env:WORKON_HOME` - - `mkdir '~\.virtualenvs'` - - `Import-Module virtualenvwrapper` - - `New-VirtualEnvironment zdsenv --no-site-packages` -- Cloner le dépot git *via la console git* (et pas via powershell) windows: `git clone https://github.com/zestedesavoir/zds-site.git` + - ``set $env:WORKON_HOME`` + - ``mkdir '~\.virtualenvs'`` + - ``Import-Module virtualenvwrapper`` + - ``New-VirtualEnvironment zdsenv --no-site-packages`` +- Cloner le dépot git *via la console git* (et pas via powershell) windows: ``git clone https://github.com/zestedesavoir/zds-site.git`` Front ou Back ? -========= +=============== Si vous ne comptez qu'au back-end du site, téléchargez le zip des ressources `ici `_ -Il faudra l'extraire dans le dossier `dist/` à la racine de votre projet. +Il faudra l'extraire dans le dossier ``dist/`` à la racine de votre projet. Si vous comptez contribuer au front-end, rendez-vous sur [la documentation dédiée](gulp.md). Suite de l'installation -========= +======================= - Dans la console PowerShell via l'environnement zdsenv installez les dépendances. - - `easy_install lxml` - - `pip install -r requirements.txt` - - `python manage.py syncdb` - - `python manage.py migrate` - - `python manage.py runserver` -- Pour redémarrer virtualenv les fois suivantes : `~\.virtualenvs\zdsenv\Scripts\activate.ps1` + - ``easy_install lxml`` + - ``pip install -r requirements.txt`` + - ``python manage.py syncdb`` + - ``python manage.py migrate`` + - ``python manage.py runserver`` +- Pour redémarrer virtualenv les fois suivantes : ``~\.virtualenvs\zdsenv\Scripts\activate.ps1`` Pour faire fonctionner ZdS dans son ensemble vous devez installer les outils LateX et Pandoc. diff --git a/doc/sphinx/source/utils/templatetags.rst b/doc/sphinx/source/utils/templatetags.rst new file mode 100644 index 0000000000..eebc1042b0 --- /dev/null +++ b/doc/sphinx/source/utils/templatetags.rst @@ -0,0 +1,102 @@ + +Elements de templates personnalisés +=================================== + +Le package ``zds/utils/templatetags`` contient un ensemble de tags et filtres personnalisés pouvant être utilisés +dans les templates rendues par Django. + +La majorité de ces modules proposent aussi des fonctions proposant les même fonctionnalités depuis le reste du code +Python. + +append_to_get +------------- + +L'élément ``append_to_get`` permet de rajouter des paramètres à la requête ``GET`` courante. Par exemple, sur une page +``module/toto``, le code de template suivant :: + + {% load append_to_get %} + Mon lien + +produira le code suivant :: + + Mon lien + +si le contenu de ``var1`` est ``1`` et le contenu de ``var2`` est ``2`` + +captureas +--------- + +L'élément ``captureas`` permet de demander d'effectuer le rendu d'un bloc de template et de stocker son contenu dans +une variable. Ainsi le code suivant :: + + {% load captureas %} + {% captureas var2 %} + {% for i in 'xxxxxxxxxx' %} + {{forloop.counter0}} + {% endfor %} + {% endcaptureas %} + +ne produit rien en sortie mais affecte le résultat du bloc entre les éléments ``{% captureas var2 %}`` et +``{% endcaptureas %}``, soit ``0123456789``, dans la variable de template ``var2`` + +date +---- + +Plusieurs filtres sont disponible dans ce module. + +format_date ++++++++++++ + +Ce filtre formate une date au format ``DateTime`` destiné à être affiché sur le site:: + + {% load date %} + {{ date | format_date}} + +tooltip_date +++++++++++++ + +Ce filtre effectue la même chose que ``format_date`` mais à destination des ``tooltip``. + +humane_time ++++++++++++ + +Formate une date au format *Nombre de seconde depuis Epoch* en un élément lisible. Ainsi :: + + {% load date %} + {{ date_epoch | humane_time}} + +sera rendu :: + + 01 Jan 1970, 01:00:42 + +Si le contenu de ``date_epoch`` etait de ``42``. + +emarkdown +--------- + +Markdown vers HTML +++++++++++++++++++ + +Permet de rendre un texte markdown en HTML : + +- ``emarkdown`` : Transforamtion classique +- ``emarkdown_inline`` : Transforamtion uniquement des éléments *inline* et donc pas de blocs. Utilisés pour les + signatures des membres. + + +Markdown vers Markdown +++++++++++++++++++++++ + +Ces élements sont utilisés dans le cadre de la transformation du markdown avant d'être traité par ``Pandoc`` lors de la +génération des fichiers PDF et EPUB des tutos : + +- ``decale_header_1`` : Décale les titres de 1 niveau (un titre de niveau 1 devient un titre de niveau 2, etc.) +- ``decale_header_2`` : Décale les titres de 2 niveaux (un titre de niveau 1 devient un titre de niveau 3, etc.) +- ``decale_header_3`` : Décale les titres de 3 niveaux (un titre de niveau 1 devient un titre de niveau 4, etc.) + + + +autres +------ + +**TODO** \ No newline at end of file diff --git a/doc/sphinx/source/utils/utils.rst b/doc/sphinx/source/utils/utils.rst new file mode 100644 index 0000000000..9422b32f8c --- /dev/null +++ b/doc/sphinx/source/utils/utils.rst @@ -0,0 +1,10 @@ +============= +Autres outils +============= + +Le package ``zds/utils`` contient un certains nombres d'outils transverses. + +.. toctree:: + :maxdepth: 2 + + templatetags \ No newline at end of file From b214115658657fe6a0763fcb7e2c92e42bb73933 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Fri, 12 Sep 2014 17:15:59 +0200 Subject: [PATCH 45/46] Remove redundant module loading --- templates/article/member/history.html | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/article/member/history.html b/templates/article/member/history.html index 0efb16a7a9..6857cb2e02 100644 --- a/templates/article/member/history.html +++ b/templates/article/member/history.html @@ -2,7 +2,6 @@ {% load profile %} {% load date %} {% load thumbnail %} -{% load date %} {% block title %} From a9837de713511bc9247904db5b995827e1a72df4 Mon Sep 17 00:00:00 2001 From: Christophe Gabard Date: Tue, 16 Sep 2014 17:32:08 +0200 Subject: [PATCH 46/46] pep-8 correction --- zds/utils/templatetags/date.py | 1 - zds/utils/templatetags/emarkdown.py | 2 +- zds/utils/templatetags/tests/test_emarkdown.py | 2 +- zds/utils/templatetags/tests/tests_append_to_get.py | 10 +++------- zds/utils/templatetags/tests/tests_date.py | 5 +---- 5 files changed, 6 insertions(+), 14 deletions(-) diff --git a/zds/utils/templatetags/date.py b/zds/utils/templatetags/date.py index 3608f59822..751fc5bd16 100644 --- a/zds/utils/templatetags/date.py +++ b/zds/utils/templatetags/date.py @@ -74,4 +74,3 @@ def humane_time(t): """Render time (number of second from epoch) to an human readable string""" tp = time.localtime(t) return time.strftime(__ABS_HUMAN_TIME_FMT, tp) - diff --git a/zds/utils/templatetags/emarkdown.py b/zds/utils/templatetags/emarkdown.py index cb3027f328..0273941cee 100644 --- a/zds/utils/templatetags/emarkdown.py +++ b/zds/utils/templatetags/emarkdown.py @@ -135,4 +135,4 @@ def decale_header_2(text): @register.filter('decale_header_3') def decale_header_3(text): - return decale_header(text, 3) \ No newline at end of file + return decale_header(text, 3) diff --git a/zds/utils/templatetags/tests/test_emarkdown.py b/zds/utils/templatetags/tests/test_emarkdown.py index 97153fb8bd..1673379ef6 100644 --- a/zds/utils/templatetags/tests/test_emarkdown.py +++ b/zds/utils/templatetags/tests/test_emarkdown.py @@ -53,4 +53,4 @@ def test_decale_header(self): self.assertEqual(u"#### Titre 1\n\n" "##### Titre **2**\n\n" "###### Titre 3\n\n" - "> test", tr) \ No newline at end of file + "> test", tr) diff --git a/zds/utils/templatetags/tests/tests_append_to_get.py b/zds/utils/templatetags/tests/tests_append_to_get.py index a416f1b376..565ad15e5f 100644 --- a/zds/utils/templatetags/tests/tests_append_to_get.py +++ b/zds/utils/templatetags/tests/tests_append_to_get.py @@ -33,11 +33,12 @@ def test_valid_call(self): def test_invalid_call(self): + wf = self.wrapped_function # Check raising TemplateSyntaxError if call with too few arguments - self.assertRaises(TemplateSyntaxError, self.wrapped_function, None, Token(TOKEN_TEXT,"elem1 elem2")) + self.assertRaises(TemplateSyntaxError, wf, None, Token(TOKEN_TEXT, "elem1 elem2")) # Check raising TemplateSyntaxError if call with too many arguments - self.assertRaises(TemplateSyntaxError, self.wrapped_function, None, Token(TOKEN_TEXT,"elem1 elem2 elem3 elem4")) + self.assertRaises(TemplateSyntaxError, wf, None, Token(TOKEN_TEXT, "elem1 elem2 elem3 elem4")) class AppendGetNodeTest(TestCase): @@ -59,7 +60,6 @@ def test_valid_call(self): tr = agn.render(self.context) self.assertEqual(tr, "/data/test?key1=1") - # Test call without arguments agn = AppendGetNode("") tr = agn.render(self.context) @@ -113,7 +113,3 @@ def test_invalid_templatetag(self): "{% append_to_get key1=var3,key2=var2 %}" ) self.assertRaises(VariableDoesNotExist, tr.render, self.context) - - - - diff --git a/zds/utils/templatetags/tests/tests_date.py b/zds/utils/templatetags/tests/tests_date.py index cac8a92a40..e7ed653b93 100644 --- a/zds/utils/templatetags/tests/tests_date.py +++ b/zds/utils/templatetags/tests/tests_date.py @@ -110,8 +110,5 @@ def test_humane_time(self): # Default behaviour tr = Template("{% load date %}" "{{ date_epoch | humane_time}}" - ).render(self.context) + ).render(self.context) self.assertEqual(u"01 Jan 1970, 01:00:42", tr) - - -