<commit_before>import datetime
import os

from django import template
from django.conf import settings
from django.contrib.gis.geos import GEOSGeometry
from django.core.exceptions import FieldDoesNotExist
from django.template import Context
from django.template.exceptions import TemplateDoesNotExist
from django.utils import six
from django.utils.timezone import utc
from django.utils.translation import ugettext, ungettext

from ..helpers import alphabet_enumeration

register = template.Library()


class SmartIncludeNode(template.Node):
    def __init__(self, viewname):
        super(SmartIncludeNode, self).__init__()
        self.viewname = viewname

    def render(self, context):
        apps = [app.split('.')[-1] for app in settings.INSTALLED_APPS]

        # Bring current app to the top of the list
        appname = context.get('appname', apps[0])
        apps.pop(apps.index(appname))
        apps = [appname] + apps

        viewname = self.viewname
        result = ""
        for module in apps:
            try:
                template_name = "%(module)s/%(module)s_%(viewname)s_fragment.html" % {'viewname': viewname,
                                                                                      'module': module}
                t = template.loader.get_template(template_name)
                result += t.render(Context.flatten(context))
            except TemplateDoesNotExist:
                pass
        return result


@register.tag(name="smart_include")
def do_smart_include(parser, token):
    try:
        tag_name, viewname = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires one argument" % token.contents.split()[0])
    if not (viewname[0] == viewname[-1] and viewname[0] in ('"', "'")):
        raise template.TemplateSyntaxError("%r tag's viewname argument should be in quotes" % tag_name)
    return SmartIncludeNode(viewname[1:-1])


@register.filter
def latlngbounds(obj):
    if obj is None or isinstance(obj, six.string_types):
        return 'null'
    if isinstance(obj, GEOSGeometry):
        extent = obj.extent
    else:
        extent = obj.get_map_image_extent()
    return [[extent[1], extent[0]], [extent[3], extent[2]]]


@register.filter(name='verbose')
def field_verbose_name(obj, field):
    """Usage: {{ object|get_object_field }}"""
    try:
        return obj._meta.get_field(field).verbose_name
    except FieldDoesNotExist:
        a = getattr(obj, '%s_verbose_name' % field)
        if a is None:
            raise
        return u"{}".format(a)


@register.simple_tag()
def media_static_fallback(media_file, static_file, *args, **kwarg):
    if os.path.exists(os.path.join(settings.MEDIA_ROOT, media_file)):
        return os.path.join(settings.MEDIA_URL, media_file)
    return os.path.join(settings.STATIC_URL, static_file)


@register.simple_tag()
def media_static_fallback_path(media_file, static_file, *args, **kwarg):
    if os.path.exists(os.path.join(settings.MEDIA_ROOT, media_file)):
        return os.path.join(settings.MEDIA_ROOT, media_file)
    return os.path.join(settings.STATIC_ROOT, static_file)


@register.filter(name='timesince')
def humanize_timesince(date):
    """
    http://djangosnippets.org/snippets/2275/
    Humanized and localized version of built-in timesince template filter.
    Based on <NAME> idea.
    """
    delta = datetime.datetime.utcnow().replace(tzinfo=utc) - date

    num_years = delta.days / 365
    if (num_years > 0):
        return ungettext(u"%d year ago", u"%d years ago", num_years) % num_years

    num_weeks = delta.days / 7
    if (num_weeks > 0):
        return ungettext(u"%d week ago", u"%d weeks ago", num_weeks) % num_weeks

    if (delta.days > 0):
        return ungettext(u"%d day ago", u"%d days ago", delta.days) % delta.days

    num_hours = delta.seconds / 3600
    if (num_hours > 0):
        return ungettext(u"%d hour ago", u"%d hours ago", num_hours) % num_hours

    num_minutes = delta.seconds / 60
    if (num_minutes > 0):
        return ungettext(u"%d minute ago", u"%d minutes ago", num_minutes) % num_minutes

    return ugettext(u"just a few seconds ago")


@register.inclusion_tag('mapentity/_detail_valuelist_fragment.html')
def valuelist(items, field=None, enumeration=False):
    """
    Common template tag to show a list of values in detail pages.

    :param field: Use this attribute on each item instead of their unicode representation
    :param enumeration: Show enumerations, useful to match those shown by ``mapentity/leaflet.enumeration.js``<commit_msg>Fix humanize_timesince template tag<commit_after>import os

from django import template
from django.conf import settings
from django.contrib.gis.geos import GEOSGeometry
from django.core.exceptions import FieldDoesNotExist
from django.template import Context
from django.template.exceptions import TemplateDoesNotExist
from django.utils import six
from django.utils.timezone import now
from django.utils.translation import ugettext, ungettext

from ..helpers import alphabet_enumeration

register = template.Library()


class SmartIncludeNode(template.Node):
    def __init__(self, viewname):
        super(SmartIncludeNode, self).__init__()
        self.viewname = viewname

    def render(self, context):
        apps = [app.split('.')[-1] for app in settings.INSTALLED_APPS]

        # Bring current app to the top of the list
        appname = context.get('appname', apps[0])
        apps.pop(apps.index(appname))
        apps = [appname] + apps

        viewname = self.viewname
        result = ""
        for module in apps:
            try:
                template_name = "%(module)s/%(module)s_%(viewname)s_fragment.html" % {'viewname': viewname,
                                                                                      'module': module}
                t = template.loader.get_template(template_name)
                result += t.render(Context.flatten(context))
            except TemplateDoesNotExist:
                pass
        return result


@register.tag(name="smart_include")
def do_smart_include(parser, token):
    try:
        tag_name, viewname = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires one argument" % token.contents.split()[0])
    if not (viewname[0] == viewname[-1] and viewname[0] in ('"', "'")):
        raise template.TemplateSyntaxError("%r tag's viewname argument should be in quotes" % tag_name)
    return SmartIncludeNode(viewname[1:-1])


@register.filter
def latlngbounds(obj):
    if obj is None or isinstance(obj, six.string_types):
        return 'null'
    if isinstance(obj, GEOSGeometry):
        extent = obj.extent
    else:
        extent = obj.get_map_image_extent()
    return [[extent[1], extent[0]], [extent[3], extent[2]]]


@register.filter(name='verbose')
def field_verbose_name(obj, field):
    """Usage: {{ object|get_object_field }}"""
    try:
        return obj._meta.get_field(field).verbose_name
    except FieldDoesNotExist:
        a = getattr(obj, '%s_verbose_name' % field)
        if a is None:
            raise
        return u"{}".format(a)


@register.simple_tag()
def media_static_fallback(media_file, static_file, *args, **kwarg):
    if os.path.exists(os.path.join(settings.MEDIA_ROOT, media_file)):
        return os.path.join(settings.MEDIA_URL, media_file)
    return os.path.join(settings.STATIC_URL, static_file)


@register.simple_tag()
def media_static_fallback_path(media_file, static_file, *args, **kwarg):
    if os.path.exists(os.path.join(settings.MEDIA_ROOT, media_file)):
        return os.path.join(settings.MEDIA_ROOT, media_file)
    return os.path.join(settings.STATIC_ROOT, static_file)


@register.filter(name='timesince')
def humanize_timesince(date):
    """
    http://djangosnippets.org/snippets/2275/
    Humanized and localized version of built-in timesince template filter.
    Based on <NAME>'s idea.
    """
    if not date:
        return ""

    delta = now() - date

    num_years = delta.days // 365
    if (num_years > 0):
        return ungettext(u"%d year ago", u"%d years ago", num_years) % num_years

    num_weeks = delta.days // 7
    if (num_weeks > 0):
        return ungettext(u"%d week ago", u"%d weeks ago", num_weeks) % num_weeks

    if (delta.days > 0):
        return ungettext(u"%d day ago", u"%d days ago", delta.days) % delta.days

    num_hours = delta.seconds // 3600
    if (num_hours > 0):
        return ungettext(u"%d hour ago", u"%d hours ago", num_hours) % num_hours

    num_minutes = delta.seconds // 60
    if (num_minutes > 0):
        return ungettext(u"%d minute ago", u"%d minutes ago", num_minutes) % num_minutes

    return ugettext(u"just a few seconds ago")


@register.inclusion_tag('mapentity/_detail_valuelist_fragment.html')
def valuelist(items, field=None, enumeration=False):
    """
    Common template tag to show a list of values in detail pages.

    :param field: Use this attribute on each item instead of their unicode representation
    :param enumeration: Show enumerations, useful to match those shown by ``mapentity/leaflet.enumeration.js``
{'fraction_non_alphanumeric': 0.11146322806250683, 'fraction_numerical': 0.0067752158234072775, 'mean_word_length': 3.1281010374379794, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1546952', 'n_tokens_mistral': 2856, 'n_tokens_neox': 2740, 'n_words': 716}