<commit_before>from django.conf import settings
from django import template
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
from django.utils.encoding import smart_str, force_unicode

from ella.core.models import Listing, Dependency, Related, Category
from ella.core.box import *
from ella.core.cache.utils import get_cached_object

register = template.Library()

class ListingNode(template.Node):
    def __init__(self, var_name, parameters, parameters_to_resolve):
        self.var_name = var_name
        self.parameters = parameters
        self.parameters_to_resolve = parameters_to_resolve

    def render(self, context):
        for key in self.parameters_to_resolve:
            self.parameters[key] = template.resolve_variable(self.parameters[key], context)
        #if isinstance(self.parameters['category'], basestring):
        #    if  self.parameters['category'].isdigit() -- ID to lookup
        #    else: SLUG to lookup
        context[self.var_name] = Listing.objects.get_listing(**self.parameters)
        return ''

@register.tag
def listing(parser, token):
    """
    Tag that will obtain listing of top (priority-wise) objects for a given category and store them in context under given name.

    Usage::

        {% listing <limit>[ from <offset>][of <app.model>[, <app.model>[, ...]]][ for <category>] as <result> %}

    Parameters:

        ==================================  ================================================
        Option                              Description
        ==================================  ================================================
        ``limit``                           Number of objects to retrieve.
        ``from offset``                     Starting with number (1-based), starts from first
                                            if no offset specified.
        ``of app.model, ...``               List of allowed models, all if omitted.
        ``for category``                    Category of the listing, all categories if not
                                            specified. Can be either string (slug), digit (id)
                                            or variable containing a Category object.
        ``as result``                       Store the resulting list in context under given
                                            name.
        ==================================  ================================================

    Examples::

        {% listing 10 of articles.article for "home_page" as obj_list %}
        {% listing 10 of articles.article for category as obj_list %}
        {% listing 10 from 10 of articles.article as obj_list %}
        {% listing 10 of articles.article, photos.photo for 1 as obj_list %}
    """
    var_name, parameters, parameters_to_resolve = listing_parse(token.split_contents())
    return ListingNode(var_name, parameters, parameters_to_resolve)

def listing_parse(input):
    params={}
    params_to_resolve=[]
    if len(input) < 4:
        raise template.TemplateSyntaxError, "%r tag argument should have at least 4 arguments" % input[0]
    o=1
    # limit
    params['count'] = input[o]
    params_to_resolve.append('count')
    o=2
    # offset
    if input[o] == 'from':
        params['offset'] = input[o+1]
        params_to_resolve.append('offset')
        o=o+2
    # from - models definition
    if input[o] == 'of':
        o=o+1
        if 'for' in input:
            mc = input.index('for')
        elif 'as' in input:
            mc = input.index('as')
        if mc > 0:
            l = []
            for mod in ''.join(input[o:mc]).split(','):
                m = models.get_model(*mod.split('.'))
                if m is None:
                    raise template.TemplateSyntaxError, "%r tag cannot list objects of unknown model %r" % (input[0], mod)
                l.append(m)
            params['mods'] = l
        o=mc
    # for - category definition
    if input[o] == 'for':
        params['category'] = input[o+1]
        params_to_resolve.append('category')
        o=o+2
    # as
    if input[o] == 'as':
        var_name = input[o+1]
    else:
        raise template.TemplateSyntaxError, "%r tag requires 'as' argument" % input[0]

    return var_name, params, params_to_resolve

class EmptyNode(template.Node):
    def render(self, context):
        return u''

class BoxNode(template.Node):
    def __init__(self, box_type, nodelist, model=None, lookup=None, var_name=None):
        self.box_type, self.nodelist, self.var_name, self.lookup, self.model = box_type, nodelist, var_name, lookup, model

    def render(self, context):
        if self.model and self.lookup:
            try:
                lookup_val = template.resolve_variable(self.lookup[1], context)
            except template.VariableDoesNotExist:
                lookup_val = self.lookup[1]

            try:
                obj = get_cached_object(self.model, **{self.lookup[0] : lookup_val})
            except models.ObjectDoesNotExist:
                return ''
            except AssertionError:
                return ''
        else:
            try:
                obj = template.resolve_variable(self.var_name, context)
            except template.VariableDoesNotExist:
                return ''

        if hasattr(obj, 'Box'):
            box = obj.Box(self.box_type, self.nodelist)
        else:
            box = Box(obj, self.box_type, self.nodelist)

        if not box.obj:
            # TODO: log
            return ''

        # push context stack
        context.push()
        # render the box itself
        box.prepare(context)
        # set the name of this box so that its children can pick up the dependencies
        box_key = box.get_cache_key()
        context[BOX_INFO] = (obj, box_key)
        # render the box
        result = box.render()
        # restore the context
        context.pop()

        if BOX_INFO in context:
            # record dependecies
            source, source_key = context[BOX_INFO]
            Dependency.objects.report_dependency(source, source_key, obj, box_key)
        return result

@register.tag('box')
def do_box(parser, token):
    """
    Tag Node representing our idea of a reusable box. It can handle multiple paramters in its body, that can
    contain other django template. The boxing facility keeps track of box dependencies which allows it to invalidate
    the cache of a parent box when the box itself is being invalidated.

    The object is passed in context as ``object`` when rendering the box parameters.

    Usage::

        {% box BOXTYPE for APP_LABEL.MODEL_NAME with FIELD VALUE %}
        {% box BOXTYPE for var_name %}

    Examples::

        {% box home_listing for articles.article with slug "some-slug" %}{% endbox %}

        {% box home_listing for articles.article with pk object_id %}
            template_name : {{object.get_box_template}}
        {% endbox %}

        {% box home_listing for article %}{% endbox %}
    """
    bits = token.split_contents()

    nodelist = parser.parse(('end' + bits[0],))
    parser.delete_first_token()

    # {% box BOXTYPE for var_name %}                {% box BOXTYPE for content.type with PK_FIELD PK_VALUE %}
    if (len(bits) != 4 or bits[2] != 'for') and (len(bits) != 7 or bits[2] != 'for' or bits[4] != 'with'):
        raise template.TemplateSyntaxError, "{% box BOXTYPE for content.type with FIELD VALUE %} or {% box BOXTYPE for var_name %}"

    if len(bits) == 4:
        # var_name
        return BoxNode(bits[1], nodelist, var_name=bits[3])
    else:
        model = models.get_model(*bits[3].split('.'))
        if model is None:
            if settings.DEBUG:
                raise template.TemplateSyntaxError, "Model %r does not exist" % bits[3]
            return EmptyNode()

        return BoxNode(bits[1], nodelist, model=model, lookup=(smart_str(bits[5]), bits[6]))

@register.inclusion_tag('core/box_media.html', takes_context=True)
def box_media(context):
    return {'media' : context.dicts[-1].get(MEDIA_KEY, None)}

class StaticBoxNode(template.Node):
    def __init__(self, box_type, level):
        self.box_type, self.level = box_type, level

    def render(self, context):
        if self.level:
            try:
                level = template.resolve_variable(self.level, context)
            except template.VariableDoesNotExist:
                level = 1
        else:
            level = 1

        context.push()
        context['level'] = level
        context['next_level'] = level + 1
        t = loader.get_template('box/static/%s.html' % self.box_type)
        resp = t.render(context)
        context.pop()
        return resp

@register.tag('staticbox')
def do_static_box(parser, token):
    """
    Include a static box (a simple template) with ``level`` and ``next_level`` variables in context.
    If no ``LEVEL`` paramter is specified, defaults to 1 (2 for ``next_level``).

    Usage::

        {% staticbox BOXTYPE %}
        {% staticbox BOXTYPE LEVEL %}

    Examples::

        {% staticbox home_listing %}

        {% staticbox home_listing 1 %}

        {% staticbox home_listing level %}

    """
    bits = token.split_contents()

    if  2 > len(bits) > 3:
        raise template.TemplateSyntaxError, '{% staticbox BOX_TYPE [LEVEL] %}'

    if len(bits) == 3:
        level = bits[2]
    else:
        level = None

    return StaticBoxNode(bits[1], level)

@register.inclusion_tag('core/box_media.html', takes_context=True)
def box_media(context):
    return {'media' : context.dicts[-1].get(MEDIA_KEY, None)}

@register.filter
def render(object, content_path):
    """
    A markdown filter that handles the rendering of any text containing markdown markup and/or django template tags.
    Only ``{{object}}`` and ``{{MEDIA_URL}}`` are available in the context.

    Usage::

        {{object|render:"property.to.render"}}

    Examples::

        {{article|render:"perex"}}
        {{article|render:"content.content"}}
    """
    path = content_path.split('.')
    content = object
    for step in path:
        try:
            content = getattr(content, step)
        except:
            # TODO: log
            #raise template.TemplateSyntaxError, "Error accessing %r property of object %r" % (content_path, object)
            return ''

    t = render_str(content)
    return t.render(template.Context({'object' : object, 'MEDIA_URL' : settings.MEDIA_URL}))

def render_str(content):
    "Render string with markdown and/or django template tags and return template."

    import markdown
    result = force_unicode(markdown.markdown(smart_str(content)))
    return template.Template(result)

@register.filter
def prefix(string_list, prefix):
    """
    Add prefix to string list (string delimited with spaces).

    Usage::

        {{string_list|prefix:"pre"}}

    Example::
        {{'a b'|prefix:'x'}}

    Output::

        xa xb
    """
    DELIMITER = ' '
    result = force_unicode(DELIMITER.join([ prefix + i for i in string_list.split(DELIMITER) ]))
    t = template.Template(result)
    return t.render(template.Context({'string_list' : string_list,}))

@register.filter
def suffix(string_list, suffix):
    """
    Add suffix to string list (string delimited with spaces).

    Usage::

        {{string_list|suffix:"pre"}}

    Example::
        {{'a b'|suffix:'x'}}

    Output::

        ax bx
    """
    DELIMITER = ' '
    result = force_unicode(DELIMITER.join([ i + suffix for i in string_list.split(DELIMITER) ]))
    t = template.Template(result)
    return t.render(template.Context({'string_list' : string_list,}))

class RelatedNode(template.Node):
    def __init__(self, obj_var, count, var_name, models=[]):
        self.obj_var, self.count, self.var_name, self.models = obj_var, count, var_name, models

    def render(self, context):
        try:
            obj = template.resolve_variable(self.obj_var, context)
        except template.VariableDoesNotExist:
            return ''

        related = []
        count = self.count

        # manually entered dependencies
        for rel in Related.objects.filter(source_ct=ContentType.objects.get_for_model(obj), source_id=obj._get_pk_val()):
            related.append(rel)
            count -= 1
            if count <= 0:
                break

        # related objects vie tags
        if self.models and count > 0:
            from tagging.models import TaggedItem
            for m in self.models:
                to_add = TaggedItem.objects.get_related(self.obj, m, count)
                for rel in to_add:
                    if rel != obj and rel not in related:
                        count -= 1
                        related.append(rel)
                    if count <= 0:
                        break

        # top objects in given category
        if count > 0:
            cat = get_cached_object(Category, pk=obj.category_id)
            listings = Listing.objects.get_listing(category=cat, count=count, mods=self.models)
            related.extend(listing.target for listing in listings if listing.target != obj)

        context[self.var_name] = related
        return ''

@register.tag('related')
def do_related(parser, token):
    """
    {% related N [app_label.Model, ...] for object as var_name %}
    """
    bits = token.split_contents()

    if len(bits) < 6:
        raise template.TemplateSyntaxError, "{% related N [app_label.Model, ...] for object as var_name %}"

    if not bits[1].isdigit():
        raise template.TemplateSyntaxError, "Count must be an integer."

    if bits[-2] != 'as':
        raise template.TemplateSyntaxError, "Tag must end with as var_name "
    if bits[-4] != 'for':
        raise template.TemplateSyntaxError, "Tag must end with for object as var_name "

    mods = []
    for m in bits[2:-5]:
        if m == ',':
            continue
        if ',' in m:
            ms = m.split()
            for msm in ms:
                try:
                    mods.append(models.get_model(*msm.split('.')))
                except:
                    raise template.TemplateSyntaxError, "%r doesn't represent any model." % msm
        else:
            try:
                mods.append(models.get_model(*m.split('.')))
            except:
                raise template.TemplateSyntaxError, "%r doesn't represent any model." % m
    return RelatedNode(bits[-3], int(bits[1]), bits[-1], mods)

CONTAINER_VARS = ('level', 'name', 'css_class',)

class ContainerNode(template.Node):
    def __init__(self, nodelist, parameters):
        self.nodelist = nodelist
        self.params = parameters

    def render(self, context):
        context.push()

        for key in CONTAINER_VARS:
            if key not in self.params:
                context[key] = ''
                continue
            value = self.params[key]
            try:
                context[key] = template.resolve_variable(value, context)
            except template.VariableDoesNotExist:
                context[key] = value

        if 'level' in context:
            try:
                context['next_level'] = int(context['level']) + 1
            except ValueError:
                pass

        content = self.nodelist.render(context)
        context['content'] = content
        t = template.loader.get_template('inclusion_tags/container.html')
        resp = t.render(context)
        context.pop()
        return resp

@register.tag('container')
def do_container(parser, token):
    bits = token.split_contents()
    parameters = bits[1:]

    if len(parameters) % 2 != 0:
        raise template.TemplateSyntaxError, '{%% %s param "value" param2 value2 ... %%}' % bits[0]

    parameters = dict((smart_str(key), value) for key, value in zip(parameters[0::2], parameters[1::2]))

    for name in parameters.keys():
        if name not in CONTAINER_VARS:
            raise template.TemplateSyntaxError, "%s tag does not accept %r parameter" % (bits[0], name)

    nodelist = parser.parse(('end' + bits[0],))
    parser.delete_first_token()

    return ContainerNode(nodelist, parameters)

<commit_msg>Fix for newer markdown. Old works fine too.<commit_after>from django.conf import settings
from django import template
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
from django.utils.encoding import smart_str, force_unicode

from ella.core.models import Listing, Dependency, Related, Category
from ella.core.box import *
from ella.core.cache.utils import get_cached_object

register = template.Library()

class ListingNode(template.Node):
    def __init__(self, var_name, parameters, parameters_to_resolve):
        self.var_name = var_name
        self.parameters = parameters
        self.parameters_to_resolve = parameters_to_resolve

    def render(self, context):
        for key in self.parameters_to_resolve:
            self.parameters[key] = template.resolve_variable(self.parameters[key], context)
        #if isinstance(self.parameters['category'], basestring):
        #    if  self.parameters['category'].isdigit() -- ID to lookup
        #    else: SLUG to lookup
        context[self.var_name] = Listing.objects.get_listing(**self.parameters)
        return ''

@register.tag
def listing(parser, token):
    """
    Tag that will obtain listing of top (priority-wise) objects for a given category and store them in context under given name.

    Usage::

        {% listing <limit>[ from <offset>][of <app.model>[, <app.model>[, ...]]][ for <category>] as <result> %}

    Parameters:

        ==================================  ================================================
        Option                              Description
        ==================================  ================================================
        ``limit``                           Number of objects to retrieve.
        ``from offset``                     Starting with number (1-based), starts from first
                                            if no offset specified.
        ``of app.model, ...``               List of allowed models, all if omitted.
        ``for category``                    Category of the listing, all categories if not
                                            specified. Can be either string (slug), digit (id)
                                            or variable containing a Category object.
        ``as result``                       Store the resulting list in context under given
                                            name.
        ==================================  ================================================

    Examples::

        {% listing 10 of articles.article for "home_page" as obj_list %}
        {% listing 10 of articles.article for category as obj_list %}
        {% listing 10 from 10 of articles.article as obj_list %}
        {% listing 10 of articles.article, photos.photo for 1 as obj_list %}
    """
    var_name, parameters, parameters_to_resolve = listing_parse(token.split_contents())
    return ListingNode(var_name, parameters, parameters_to_resolve)

def listing_parse(input):
    params={}
    params_to_resolve=[]
    if len(input) < 4:
        raise template.TemplateSyntaxError, "%r tag argument should have at least 4 arguments" % input[0]
    o=1
    # limit
    params['count'] = input[o]
    params_to_resolve.append('count')
    o=2
    # offset
    if input[o] == 'from':
        params['offset'] = input[o+1]
        params_to_resolve.append('offset')
        o=o+2
    # from - models definition
    if input[o] == 'of':
        o=o+1
        if 'for' in input:
            mc = input.index('for')
        elif 'as' in input:
            mc = input.index('as')
        if mc > 0:
            l = []
            for mod in ''.join(input[o:mc]).split(','):
                m = models.get_model(*mod.split('.'))
                if m is None:
                    raise template.TemplateSyntaxError, "%r tag cannot list objects of unknown model %r" % (input[0], mod)
                l.append(m)
            params['mods'] = l
        o=mc
    # for - category definition
    if input[o] == 'for':
        params['category'] = input[o+1]
        params_to_resolve.append('category')
        o=o+2
    # as
    if input[o] == 'as':
        var_name = input[o+1]
    else:
        raise template.TemplateSyntaxError, "%r tag requires 'as' argument" % input[0]

    return var_name, params, params_to_resolve

class EmptyNode(template.Node):
    def render(self, context):
        return u''

class BoxNode(template.Node):
    def __init__(self, box_type, nodelist, model=None, lookup=None, var_name=None):
        self.box_type, self.nodelist, self.var_name, self.lookup, self.model = box_type, nodelist, var_name, lookup, model

    def render(self, context):
        if self.model and self.lookup:
            try:
                lookup_val = template.resolve_variable(self.lookup[1], context)
            except template.VariableDoesNotExist:
                lookup_val = self.lookup[1]

            try:
                obj = get_cached_object(self.model, **{self.lookup[0] : lookup_val})
            except models.ObjectDoesNotExist:
                return ''
            except AssertionError:
                return ''
        else:
            try:
                obj = template.resolve_variable(self.var_name, context)
            except template.VariableDoesNotExist:
                return ''

        if hasattr(obj, 'Box'):
            box = obj.Box(self.box_type, self.nodelist)
        else:
            box = Box(obj, self.box_type, self.nodelist)

        if not box.obj:
            # TODO: log
            return ''

        # push context stack
        context.push()
        # render the box itself
        box.prepare(context)
        # set the name of this box so that its children can pick up the dependencies
        box_key = box.get_cache_key()
        context[BOX_INFO] = (obj, box_key)
        # render the box
        result = box.render()
        # restore the context
        context.pop()

        if BOX_INFO in context:
            # record dependecies
            source, source_key = context[BOX_INFO]
            Dependency.objects.report_dependency(source, source_key, obj, box_key)
        return result

@register.tag('box')
def do_box(parser, token):
    """
    Tag Node representing our idea of a reusable box. It can handle multiple paramters in its body, that can
    contain other django template. The boxing facility keeps track of box dependencies which allows it to invalidate
    the cache of a parent box when the box itself is being invalidated.

    The object is passed in context as ``object`` when rendering the box parameters.

    Usage::

        {% box BOXTYPE for APP_LABEL.MODEL_NAME with FIELD VALUE %}
        {% box BOXTYPE for var_name %}

    Examples::

        {% box home_listing for articles.article with slug "some-slug" %}{% endbox %}

        {% box home_listing for articles.article with pk object_id %}
            template_name : {{object.get_box_template}}
        {% endbox %}

        {% box home_listing for article %}{% endbox %}
    """
    bits = token.split_contents()

    nodelist = parser.parse(('end' + bits[0],))
    parser.delete_first_token()

    # {% box BOXTYPE for var_name %}                {% box BOXTYPE for content.type with PK_FIELD PK_VALUE %}
    if (len(bits) != 4 or bits[2] != 'for') and (len(bits) != 7 or bits[2] != 'for' or bits[4] != 'with'):
        raise template.TemplateSyntaxError, "{% box BOXTYPE for content.type with FIELD VALUE %} or {% box BOXTYPE for var_name %}"

    if len(bits) == 4:
        # var_name
        return BoxNode(bits[1], nodelist, var_name=bits[3])
    else:
        model = models.get_model(*bits[3].split('.'))
        if model is None:
            if settings.DEBUG:
                raise template.TemplateSyntaxError, "Model %r does not exist" % bits[3]
            return EmptyNode()

        return BoxNode(bits[1], nodelist, model=model, lookup=(smart_str(bits[5]), bits[6]))

@register.inclusion_tag('core/box_media.html', takes_context=True)
def box_media(context):
    return {'media' : context.dicts[-1].get(MEDIA_KEY, None)}

class StaticBoxNode(template.Node):
    def __init__(self, box_type, level):
        self.box_type, self.level = box_type, level

    def render(self, context):
        if self.level:
            try:
                level = template.resolve_variable(self.level, context)
            except template.VariableDoesNotExist:
                level = 1
        else:
            level = 1

        context.push()
        context['level'] = level
        context['next_level'] = level + 1
        t = loader.get_template('box/static/%s.html' % self.box_type)
        resp = t.render(context)
        context.pop()
        return resp

@register.tag('staticbox')
def do_static_box(parser, token):
    """
    Include a static box (a simple template) with ``level`` and ``next_level`` variables in context.
    If no ``LEVEL`` paramter is specified, defaults to 1 (2 for ``next_level``).

    Usage::

        {% staticbox BOXTYPE %}
        {% staticbox BOXTYPE LEVEL %}

    Examples::

        {% staticbox home_listing %}

        {% staticbox home_listing 1 %}

        {% staticbox home_listing level %}

    """
    bits = token.split_contents()

    if  2 > len(bits) > 3:
        raise template.TemplateSyntaxError, '{% staticbox BOX_TYPE [LEVEL] %}'

    if len(bits) == 3:
        level = bits[2]
    else:
        level = None

    return StaticBoxNode(bits[1], level)

@register.inclusion_tag('core/box_media.html', takes_context=True)
def box_media(context):
    return {'media' : context.dicts[-1].get(MEDIA_KEY, None)}

@register.filter
def render(object, content_path):
    """
    A markdown filter that handles the rendering of any text containing markdown markup and/or django template tags.
    Only ``{{object}}`` and ``{{MEDIA_URL}}`` are available in the context.

    Usage::

        {{object|render:"property.to.render"}}

    Examples::

        {{article|render:"perex"}}
        {{article|render:"content.content"}}
    """
    path = content_path.split('.')
    content = object
    for step in path:
        try:
            content = getattr(content, step)
        except:
            # TODO: log
            #raise template.TemplateSyntaxError, "Error accessing %r property of object %r" % (content_path, object)
            return ''

    t = render_str(content)
    return t.render(template.Context({'object' : object, 'MEDIA_URL' : settings.MEDIA_URL}))

def render_str(content):
    "Render string with markdown and/or django template tags and return template."

    import markdown
    if getattr(markdown, 'version', False) and markdown.version[1]>=6:
        result = force_unicode(markdown.markdown(content))
    else:
        result = force_unicode(markdown.markdown(smart_str(content)))
    return template.Template(result)

@register.filter
def prefix(string_list, prefix):
    """
    Add prefix to string list (string delimited with spaces).

    Usage::

        {{string_list|prefix:"pre"}}

    Example::
        {{'a b'|prefix:'x'}}

    Output::

        xa xb
    """
    DELIMITER = ' '
    result = force_unicode(DELIMITER.join([ prefix + i for i in string_list.split(DELIMITER) ]))
    t = template.Template(result)
    return t.render(template.Context({'string_list' : string_list,}))

@register.filter
def suffix(string_list, suffix):
    """
    Add suffix to string list (string delimited with spaces).

    Usage::

        {{string_list|suffix:"pre"}}

    Example::
        {{'a b'|suffix:'x'}}

    Output::

        ax bx
    """
    DELIMITER = ' '
    result = force_unicode(DELIMITER.join([ i + suffix for i in string_list.split(DELIMITER) ]))
    t = template.Template(result)
    return t.render(template.Context({'string_list' : string_list,}))

class RelatedNode(template.Node):
    def __init__(self, obj_var, count, var_name, models=[]):
        self.obj_var, self.count, self.var_name, self.models = obj_var, count, var_name, models

    def render(self, context):
        try:
            obj = template.resolve_variable(self.obj_var, context)
        except template.VariableDoesNotExist:
            return ''

        related = []
        count = self.count

        # manually entered dependencies
        for rel in Related.objects.filter(source_ct=ContentType.objects.get_for_model(obj), source_id=obj._get_pk_val()):
            related.append(rel)
            count -= 1
            if count <= 0:
                break

        # related objects vie tags
        if self.models and count > 0:
            from tagging.models import TaggedItem
            for m in self.models:
                to_add = TaggedItem.objects.get_related(self.obj, m, count)
                for rel in to_add:
                    if rel != obj and rel not in related:
                        count -= 1
                        related.append(rel)
                    if count <= 0:
                        break

        # top objects in given category
        if count > 0:
            cat = get_cached_object(Category, pk=obj.category_id)
            listings = Listing.objects.get_listing(category=cat, count=count, mods=self.models)
            related.extend(listing.target for listing in listings if listing.target != obj)

        context[self.var_name] = related
        return ''

@register.tag('related')
def do_related(parser, token):
    """
    {% related N [app_label.Model, ...] for object as var_name %}
    """
    bits = token.split_contents()

    if len(bits) < 6:
        raise template.TemplateSyntaxError, "{% related N [app_label.Model, ...] for object as var_name %}"

    if not bits[1].isdigit():
        raise template.TemplateSyntaxError, "Count must be an integer."

    if bits[-2] != 'as':
        raise template.TemplateSyntaxError, "Tag must end with as var_name "
    if bits[-4] != 'for':
        raise template.TemplateSyntaxError, "Tag must end with for object as var_name "

    mods = []
    for m in bits[2:-5]:
        if m == ',':
            continue
        if ',' in m:
            ms = m.split()
            for msm in ms:
                try:
                    mods.append(models.get_model(*msm.split('.')))
                except:
                    raise template.TemplateSyntaxError, "%r doesn't represent any model." % msm
        else:
            try:
                mods.append(models.get_model(*m.split('.')))
            except:
                raise template.TemplateSyntaxError, "%r doesn't represent any model." % m
    return RelatedNode(bits[-3], int(bits[1]), bits[-1], mods)

CONTAINER_VARS = ('level', 'name', 'css_class',)

class ContainerNode(template.Node):
    def __init__(self, nodelist, parameters):
        self.nodelist = nodelist
        self.params = parameters

    def render(self, context):
        context.push()

        for key in CONTAINER_VARS:
            if key not in self.params:
                context[key] = ''
                continue
            value = self.params[key]
            try:
                context[key] = template.resolve_variable(value, context)
            except template.VariableDoesNotExist:
                context[key] = value

        if 'level' in context:
            try:
                context['next_level'] = int(context['level']) + 1
            except ValueError:
                pass

        content = self.nodelist.render(context)
        context['content'] = content
        t = template.loader.get_template('inclusion_tags/container.html')
        resp = t.render(context)
        context.pop()
        return resp

@register.tag('container')
def do_container(parser, token):
    bits = token.split_contents()
    parameters = bits[1:]

    if len(parameters) % 2 != 0:
        raise template.TemplateSyntaxError, '{%% %s param "value" param2 value2 ... %%}' % bits[0]

    parameters = dict((smart_str(key), value) for key, value in zip(parameters[0::2], parameters[1::2]))

    for name in parameters.keys():
        if name not in CONTAINER_VARS:
            raise template.TemplateSyntaxError, "%s tag does not accept %r parameter" % (bits[0], name)

    nodelist = parser.parse(('end' + bits[0],))
    parser.delete_first_token()

    return ContainerNode(nodelist, parameters)

<|endoftext|>


<commit_before><commit_msg>Move test from main to separated test function, add some comments<commit_after><|endoftext|>


<commit_before>"""
sentry_quotas.plugin
~~~~~~~~~~~~~~~~~~~~

:copyright: (c) 2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from django import forms
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from nydus.db import create_cluster
from sentry.plugins import Plugin

import logging
import time
import sentry_quotas

if not getattr(settings, 'SENTRY_QUOTAS', None):
    raise ImproperlyConfigured('You need to configure SENTRY_QUOTAS')

def get_cluster(hosts=None, router='nydus.db.routers.keyvalue.PartitionRouter'):
    hosts = {
        0: {}  # localhost / default
    }

    return create_cluster({
        'engine': 'nydus.db.backends.redis.Redis',
        'router': router,
        'hosts': hosts,
    })

redis = get_cluster(settings.SENTRY_QUOTAS['redis'])

def get_default_events_per_minute():
    # It'd be nice if this were configurable via the sentry web interface (system level)
    return settings.SENTRY_QUOTAS.get('default_events_per_minute')

def get_per_minute_help_text():
    if get_default_events_per_minute():
        return _('The maximum events per minute before dropping data (system default is %s).') % get_default_events_per_minute()
    return _('The maximum events per minute before dropping data.') % get_default_events_per_minute()

class QuotasOptionsForm(forms.Form):
    per_minute = forms.CharField(label=_('Events / Minute'),
        help_text=get_per_minute_help_text())

class QuotasPlugin(Plugin):
    author = 'Sentry Team'
    author_url = 'https://github.com/getsentry/sentry'
    version = sentry_quotas.VERSION
    description = "Integrates quotas."
    resource_links = [
        ('Bug Tracker', 'https://github.com/getsentry/sentry-quotas/issues'),
        ('Source', 'https://github.com/getsentry/sentry-quotas'),
    ]

    slug = 'quotas'
    title = _('Quotas')
    conf_title = title
    conf_key = 'quotas'
    project_conf_form = QuotasOptionsForm

    logger = logging.getLogger('sentry_quotas')

    def get_events_per_minute(self, project):
        proj_setting = self.get_option('per_minute', project)
        if proj_setting is None:
            return get_default_events_per_minute()
        return proj_setting

    def is_configured(self, project, **kwargs):
        return bool(self.get_events_per_minute(project))

    def incr(self, project, client=redis):
        # we store a key per minute
        key = 'sentry_quotas:%s:%s' % (project.id, int(time.time() % 86400))
        with client.map() as conn:
            result = conn.incr(key)
            conn.expire(key, 60)

        return int(result)

    def has_perm(self, user, perm, *objects, **kwargs):
        if perm == 'create_event':
            project = objects[0]
            quota = self.get_events_per_minute(project)
            if not quota:
                return None

            if self.incr(project) >= quota:
                self.logger.info('Project %r was over quota, event not recorded', project.slug)
                return False

        return None
<commit_msg>Working implementation<commit_after>"""
sentry_quotas.plugin
~~~~~~~~~~~~~~~~~~~~

:copyright: (c) 2012 by the Sentry Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""

from django import forms
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from nydus.db import create_cluster
from sentry.plugins import Plugin

import logging
import time
import sentry_quotas

if not getattr(settings, 'SENTRY_QUOTAS', None):
    raise ImproperlyConfigured('You need to configure SENTRY_QUOTAS')

def get_cluster(hosts=None, router='nydus.db.routers.keyvalue.PartitionRouter'):
    hosts = {
        0: {}  # localhost / default
    }

    return create_cluster({
        'engine': 'nydus.db.backends.redis.Redis',
        'router': router,
        'hosts': hosts,
    })

redis = get_cluster(settings.SENTRY_QUOTAS['redis'])

def get_default_events_per_minute():
    # It'd be nice if this were configurable via the sentry web interface (system level)
    return settings.SENTRY_QUOTAS.get('default_events_per_minute')

def get_per_minute_help_text():
    if get_default_events_per_minute():
        return _('The maximum events per minute before dropping data (system default is %s).') % get_default_events_per_minute()
    return _('The maximum events per minute before dropping data.') % get_default_events_per_minute()

class QuotasOptionsForm(forms.Form):
    per_minute = forms.CharField(label=_('Events / Minute'),
        help_text=get_per_minute_help_text())

class QuotasPlugin(Plugin):
    author = 'Sentry Team'
    author_url = 'https://github.com/getsentry/sentry'
    version = sentry_quotas.VERSION
    description = "Integrates quotas."
    resource_links = [
        ('Bug Tracker', 'https://github.com/getsentry/sentry-quotas/issues'),
        ('Source', 'https://github.com/getsentry/sentry-quotas'),
    ]

    slug = 'quotas'
    title = _('Quotas')
    conf_title = title
    conf_key = 'quotas'
    project_conf_form = QuotasOptionsForm

    logger = logging.getLogger('sentry_quotas')

    def get_events_per_minute(self, project):
        proj_setting = self.get_option('per_minute', project)
        if proj_setting is None:
            return int(get_default_events_per_minute())
        return int(proj_setting)

    def is_configured(self, project, **kwargs):
        return bool(self.get_events_per_minute(project))

    def incr(self, project, client=redis):
        # we store a key per minute
        key = 'sentry_quotas:%s:%s' % (project.id, int(time.time() / 60))
        with client.map() as conn:
            result = conn.incr(key)
            conn.expire(key, 60)

        return int(result)

    def has_perm(self, user, perm, *objects, **kwargs):
        if perm == 'create_event':
            project = objects[0]
            quota = self.get_events_per_minute(project)
            if not quota:
                return None

            if self.incr(project) > quota:
                self.logger.info('Project %r was over quota, event not recorded', project.slug)
                return False

        return None
<|endoftext|>


<commit_before>from django.contrib import admin
from django.conf.urls import url

from .models import Problem, Submission, Config
from .views import submissions_download_response, submissions_download_view, \
    submissions_export_view

class ProblemAdmin(admin.ModelAdmin):

    def get_problem_title(self, problem):
        return problem.problem.title
    get_problem_title.short_description = "title"

    def get_problem_statement(self, problem):
        return problem.problem.statement
    get_problem_statement.short_description = "statement"

    list_display = [
        'id',
        'problem_id',
        'get_problem_title',
        'get_problem_statement',
        'max_score'
    ]

    list_display_links = [
        'id',
        'problem_id',
        'get_problem_title',
        'get_problem_statement'
    ]

    search_fields = [
        'id',
        'problem__problem_id',
        'problem__title',
        'problem__statement'
    ]

class SubmissionAdmin(admin.ModelAdmin):

    def get_urls(self):
        urls = super(SubmissionAdmin, self).get_urls()
        testcases_url = [
            url(r'^download/(?P<filename>[a-z\w\.]+)/type=(?P<submission_type>[a-z]+)/$',
                submissions_download_response, name='submissions_download_response'),

            url(r'^download/', submissions_download_view, name='submissions_download_view'),
            url(r'^export/', submissions_export_view, name='submissions_export_view'),
        ]
        return testcases_url + urls

    def get_username(self, submission):
        return submission.user.username
    get_username.short_description = "submitted-by (ID)"

    def get_name(self, submission):
        return (submission.user.first_name + " " + submission.user.last_name)
    get_name.short_description = "submitted-by (Name)"

    def testcase_wise_result(self, submission):
        return submission.testcase_result_verbose()
    testcase_wise_result.short_description = "testcase wise result"

    def get_problem_title(self, submission):
        return submission.problem.title
    get_problem_title.short_description = "problem"

    list_display = [
        'id',
        'get_username',
        'get_name',
        'ip',
        'get_problem_title',
        'score',
        'time',
        'testcase_wise_result',
    ]

    list_display_links = [
        'id',
        'get_username',
        'ip',
        'get_problem_title',
        'score',
        'time',
    ]

    search_fields = [
        'id',
        'problem__title',
        'user__id',
        'user__username',
        'user__first_name',
        'user__last_name',
    ]

    list_per_page = 500

class ConfigAdmin(admin.ModelAdmin):

    list_display = [
        'id',
        'start',
        'end',
    ]

    list_display_links = [
        'id',
        'start',
        'end',
    ]

admin.site.site_header = "Judge Administration Portal"
admin.site.site_title = "Crux Judge Admin"
admin.site.index_title = "Admin - Crux Judge"
admin.site.register(Problem, ProblemAdmin)
admin.site.register(Submission, SubmissionAdmin)
# Improve later
admin.site.register(Config, ConfigAdmin)
<commit_msg>admin: Add UI for Profile model<commit_after>from django.contrib import admin
from django.conf.urls import url

from .models import Problem, Submission, Config, Profile
from .views import submissions_download_response, submissions_download_view, \
    submissions_export_view

class ProblemAdmin(admin.ModelAdmin):

    def get_problem_title(self, problem):
        return problem.problem.title
    get_problem_title.short_description = "title"

    def get_problem_statement(self, problem):
        return problem.problem.statement
    get_problem_statement.short_description = "statement"

    list_display = [
        'id',
        'problem_id',
        'get_problem_title',
        'get_problem_statement',
        'max_score'
    ]

    list_display_links = [
        'id',
        'problem_id',
        'get_problem_title',
        'get_problem_statement'
    ]

    search_fields = [
        'id',
        'problem__problem_id',
        'problem__title',
        'problem__statement'
    ]

class SubmissionAdmin(admin.ModelAdmin):

    def get_urls(self):
        urls = super(SubmissionAdmin, self).get_urls()
        testcases_url = [
            url(r'^download/(?P<filename>[a-z\w\.]+)/type=(?P<submission_type>[a-z]+)/$',
                submissions_download_response, name='submissions_download_response'),

            url(r'^download/', submissions_download_view, name='submissions_download_view'),
            url(r'^export/', submissions_export_view, name='submissions_export_view'),
        ]
        return testcases_url + urls

    def get_username(self, submission):
        return submission.user.username
    get_username.short_description = "submitted-by (ID)"

    def get_name(self, submission):
        return (submission.user.first_name + " " + submission.user.last_name)
    get_name.short_description = "submitted-by (Name)"

    def testcase_wise_result(self, submission):
        return submission.testcase_result_verbose()
    testcase_wise_result.short_description = "testcase wise result"

    def get_problem_title(self, submission):
        return submission.problem.title
    get_problem_title.short_description = "problem"

    list_display = [
        'id',
        'get_username',
        'get_name',
        'ip',
        'get_problem_title',
        'score',
        'time',
        'testcase_wise_result',
    ]

    list_display_links = [
        'id',
        'get_username',
        'ip',
        'get_problem_title',
        'score',
        'time',
    ]

    search_fields = [
        'id',
        'problem__title',
        'user__id',
        'user__username',
        'user__first_name',
        'user__last_name',
    ]

    list_per_page = 500

class ConfigAdmin(admin.ModelAdmin):

    list_display = [
        'id',
        'start',
        'end',
    ]

    list_display_links = [
        'id',
        'start',
        'end',
    ]

class ProfileAdmin(admin.ModelAdmin):

    list_display = [
        'user',
        'logged_in',
    ]

    list_editable = [
        'logged_in',
    ]

admin.site.site_header = "Judge Administration Portal"
admin.site.site_title = "Crux Judge Admin"
admin.site.index_title = "Admin - Crux Judge"
admin.site.register(Problem, ProblemAdmin)
admin.site.register(Submission, SubmissionAdmin)
# Improve later
admin.site.register(Config, ConfigAdmin)
admin.site.register(Profile, ProfileAdmin)
<|endoftext|>


<commit_before>#!/usr/bin/env python
#########################################################################################
#
# Test function for sct_extract_metric script
#
# ---------------------------------------------------------------------------------------
# Copyright (c) 2014 Polytechnique Montreal <www.neuro.polymtl.ca>
# Author: Augustin Roux
# modified: 2014/09/28
#
# About the license: see the file LICENSE.TXT
#########################################################################################

#import sct_utils as sct
import commands

def test(path_data):

    # parameters
    folder_data = ['mt/', 'label/atlas']
    file_data = ['mtr.nii.gz']

    # define command
    cmd = 'sct_extract_metric' \
        ' -i '+path_data+folder_data[0]+file_data[0]+ \
        ' -f '+path_data+folder_data[0]+folder_data[1]+ \
        ' -l 2,17 '+ \
        ' -method wath '+ \
        ' -vert 1:3'+ \
        ' -o quantif_'+file_data[0]+'.txt' \
        ' -v 1'

    # return
    #return sct.run(cmd, 0)
    return commands.getstatusoutput(cmd)

# call to function
if __name__ == "__main__":
    # call main function
    test()
<commit_msg>TEST: update test_sct_extract_metric.py<commit_after>#!/usr/bin/env python
#########################################################################################
#
# Test function for sct_extract_metric script
#
# ---------------------------------------------------------------------------------------
# Copyright (c) 2014 Polytechnique Montreal <www.neuro.polymtl.ca>
# Author: Augustin Roux
# modified: 2014/09/28
#
# About the license: see the file LICENSE.TXT
#########################################################################################

#import sct_utils as sct
import commands

def test(path_data):

    # parameters
    folder_data = ['mt/', 'label/atlas']
    file_data = ['mtr.nii.gz']

    # define command
    cmd = 'sct_extract_metric' \
        ' -i '+path_data+folder_data[0]+file_data[0]+ \
        ' -f '+path_data+folder_data[0]+folder_data[1]+ \
        ' -method wath '+ \
        ' -vert 1:3'+ \
        ' -o quantif_'+file_data[0]+ \
        ' -v 1'

    # return
    #return sct.run(cmd, 0)
    return commands.getstatusoutput(cmd)

# call to function
if __name__ == "__main__":
    # call main function
    test()
<|endoftext|>


<commit_before>#
# Copyright (c) 2009 Testrepository Contributors
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
# license you chose for the specific language governing permissions and
# limitations under that license.

"""Tests for setup.py."""

import doctest
import os
import subprocess
import sys

from testtools import (
    TestCase,
    )
from testtools.matchers import (
    DocTestMatches,
    )

class TestCanSetup(TestCase):

    def test_bdist(self):
        # Single smoke test to make sure we can build a package.
        path = os.path.join(os.path.dirname(__file__), '..', '..', 'setup.py')
        proc = subprocess.Popen([sys.executable, path, 'bdist'],
            stdin=subprocess.PIPE, stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT)
        output, _ = proc.communicate()
        self.assertEqual(0, proc.returncode)
        self.assertThat(output,
            DocTestMatches("...running bdist...", doctest.ELLIPSIS))
<commit_msg>Make setup.py smoke test more specific again as requested in review<commit_after>#
# Copyright (c) 2009 Testrepository Contributors
#
# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
# license you chose for the specific language governing permissions and
# limitations under that license.

"""Tests for setup.py."""

import doctest
import os
import subprocess
import sys

from testtools import (
    TestCase,
    )
from testtools.matchers import (
    DocTestMatches,
    )

class TestCanSetup(TestCase):

    def test_bdist(self):
        # Single smoke test to make sure we can build a package.
        path = os.path.join(os.path.dirname(__file__), '..', '..', 'setup.py')
        proc = subprocess.Popen([sys.executable, path, 'bdist'],
            stdin=subprocess.PIPE, stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT, universal_newlines=True)
        output, _ = proc.communicate()
        self.assertEqual(0, proc.returncode)
        self.assertThat(output, DocTestMatches("""...
running install_scripts
...
adding '...testr'
...""", doctest.ELLIPSIS))
<|endoftext|>


<commit_before>"""Functional pairing tests using the API with a fake AirPlay Apple TV."""

from aiohttp.test_utils import (AioHTTPTestCase, unittest_run_loop)

import pyatv
from pyatv import const
from pyatv.conf import (AirPlayService, AppleTV)
from tests.airplay.fake_airplay_device import (
    FakeAirPlayDevice, AirPlayUseCases, DEVICE_CREDENTIALS, DEVICE_PIN)

class PairFunctionalTest(AioHTTPTestCase):

    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = AirPlayService(
            'airplay_id', credentials=DEVICE_CREDENTIALS,
            port=self.server.port)
        self.conf = AppleTV('127.0.0.1', 'Apple TV')
        self.conf.add_service(self.service)

    async def tearDownAsync(self):
        await self.pairing.close()
        await super().tearDownAsync()

    async def get_application(self, loop=None):
        self.fake_atv = FakeAirPlayDevice(self)
        self.usecase = AirPlayUseCases(self.fake_atv)
        return self.fake_atv.app

    async def initiate_pairing(self):
        self.usecase.airplay_require_authentication()

        options = {}

        self.pairing = await pyatv.pair(
            self.conf, const.PROTOCOL_AIRPLAY, self.loop, **options)

    @unittest_run_loop
    async def test_pairing_with_device(self):
        await self.initiate_pairing()

        self.assertTrue(self.pairing.device_provides_pin)

        await self.pairing.begin()
        self.pairing.pin(DEVICE_PIN)

        self.assertFalse(self.pairing.has_paired)

        await self.pairing.finish()
        self.assertTrue(self.pairing.has_paired)
        self.assertEqual(self.service.credentials, DEVICE_CREDENTIALS)
<commit_msg>Add AirPlay test for new credentials<commit_after>"""Functional pairing tests using the API with a fake AirPlay Apple TV."""

import binascii
from asynctest.mock import patch

from aiohttp.test_utils import (AioHTTPTestCase, unittest_run_loop)

import pyatv
from pyatv import const
from pyatv.conf import (AirPlayService, AppleTV)
from tests.airplay.fake_airplay_device import (
    FakeAirPlayDevice, AirPlayUseCases, DEVICE_CREDENTIALS, DEVICE_PIN,
    DEVICE_IDENTIFIER, DEVICE_AUTH_KEY)

def predetermined_key(num):
    """Return random data corresponding to hardcoded AirPlay keys."""
    if num == 8:
        return binascii.unhexlify(DEVICE_IDENTIFIER)
    return binascii.unhexlify(DEVICE_AUTH_KEY)

class PairFunctionalTest(AioHTTPTestCase):

    def setUp(self):
        AioHTTPTestCase.setUp(self)
        self.pairing = None

        self.service = AirPlayService(
            'airplay_id', port=self.server.port)
        self.conf = AppleTV('127.0.0.1', 'Apple TV')
        self.conf.add_service(self.service)

    async def tearDownAsync(self):
        await self.pairing.close()
        await super().tearDownAsync()

    async def get_application(self, loop=None):
        self.fake_atv = FakeAirPlayDevice(self)
        self.usecase = AirPlayUseCases(self.fake_atv)
        return self.fake_atv.app

    async def do_pairing(self):
        self.usecase.airplay_require_authentication()

        self.pairing = await pyatv.pair(
            self.conf, const.PROTOCOL_AIRPLAY, self.loop)

        self.assertTrue(self.pairing.device_provides_pin)

        await self.pairing.begin()
        self.pairing.pin(DEVICE_PIN)

        self.assertFalse(self.pairing.has_paired)

        await self.pairing.finish()
        self.assertTrue(self.pairing.has_paired)
        self.assertEqual(self.service.credentials, DEVICE_CREDENTIALS)

    @unittest_run_loop
    @patch('os.urandom')
    async def test_pairing_with_device_new_credentials(self, rand_func):
        rand_func.side_effect = predetermined_key
        await self.do_pairing()

    @unittest_run_loop
    async def test_pairing_with_device_existing_credentials(self):
        self.conf.get_service(
            const.PROTOCOL_AIRPLAY).credentials = DEVICE_CREDENTIALS
        await self.do_pairing()
<|endoftext|>


<commit_before>#!/usr/bin/env python

# Author:
#   Dominique Blaze <contact@d0m.tech>
#

'''
Basic OVAL evaluation:

Import an oval file with oscap.oval.definition_model_import_source
and run evalutation of some sample checks with oscap.oval.agent_new_session
and oscap.oval.agent_eval_system using a callback
'''

import os
from import_handler import oscap, result2str, get_path
import time

'''
Functions
'''

def oval_callback(msg, usr):
    print(msg.get_id()+" => "+result2str(msg.eval())) #eval or get_result return the same thing
    print(msg.get_criteria().__repr__())
    return 0  # if you return something else than 0, the current session stops

# eval oval defs oval:[foo_pass|fail]:def:1
def oval_eval_sample(oval_defs):
    states = {'false': 0, 'true': 0, 'err': 0, 'unknown': 0, 'neval': 0,
              'na': 0, 'verbose': True}

    sess = oscap.oval.agent_new_session(oval_defs, "")
    ret = oscap.oval.agent_eval_system(sess, oval_callback, states)

'''
Main test
'''

print("Opening oval file with original C functions ... ")
oval_defs = oscap.oval.definition_model_import_source(
    oscap.common.source_new_from_file(get_path("samples/oval_sample.xml")))

oval_eval_sample(oval_defs)

# TODO: do the same thing with oval_import

print("finish")

<commit_msg>complete oval test (import + eval + criteria details)<commit_after>#!/usr/bin/env python

# Author:
#   Dominique Blaze <contact@d0m.tech>
#

'''
Basic OVAL evaluation:

Import an oval file with oscap.oval.definition_model_import_source
and run evalutation of some sample checks with oscap.oval.agent_new_session
and oscap.oval.agent_eval_system using a callback
'''

import os
import time
from import_handler import oscap, result2str, get_path
from pprint import pprint
import inspect

'''
Intermediate functions
'''

def browse_criteria(crit_node, mode=0):
    '''
    Browse recursively criteria of an oval test and build a representation of it
    First list item is the operator, and the next ones are the tests
    If the item is a list, it's a criteria (else a criterion, or string for an
    extended defintion , or None for OVAL_NODETYPE_UNKNOWN

    Ex: [operator, "extended def", [operator, test_result2, test_result3]]

    Mode : with mode = 0, test_result is the swig object oval_test_result
    with mode = 1, test result is a a tuple like (test_subtype, test_result)
    for instance (oscap.oval.OVAL_LINUX_DPKG_INFO, OVAL_FAMILY_LINUX
    oscap.xccdf.XCCDF_RESULT_PASS)
    '''

    # init the critria list
    rs = list()

    if crit_node.get_type() == oscap.oval.OVAL_NODETYPE_CRITERIA:
        for c in crit_node.get_subnodes():
            rs.append(browse_criteria(c, mode))

    elif crit_node.get_type() == oscap.oval.OVAL_NODETYPE_CRITERION:
        if mode == 0:
            rs.append(crit_node.get_test())
        elif mode == 1:
            rs.append((crit_node.get_test().get_test().get_family(),
                       crit_node.get_test().get_test().get_subtype(),
                       crit_node.get_test().get_result()))
        else:
            raise ValueError("param mode in browse_criteria should be 0 or 1")

    elif crit_node.get_type() == oscal.oval.OVAL_NODETYPE_EXTENDDEF:  # !!! TODO !!!
        rs.append("extended def")

    else:
        rs.append(None)

    return rs

# if you return something in callback else than 0, the current session stops
def oval_sample_callback(ovdef, usr):
    # .eval or .get_result return the same thing
    print(ovdef.get_id()+" => "+result2str(ovdef.get_result()))

    # retrieve the tests tree and replace test_results by [subtype => result]
    tests_tree = browse_criteria(ovdef.get_criteria(), 1)

    '''
    Expected tree for foo_pass: [[(7006, 1)]]
    = [[(OVAL_INDEPENDENT_TEXT_FILE_CONTENT_54, XCCDF_RESULT_PASS)]]
    or [[(OVAL_INDEPENDENT_TEXT_FILE_CONTENT_54, XCCDF_RESULT_PASS)]] for foo_fail
    '''

    expected_trees = {"oval:foo_pass:def:1": [[
                         (oscap.oval.OVAL_FAMILY_INDEPENDENT,
                          oscap.oval.OVAL_INDEPENDENT_TEXT_FILE_CONTENT_54,
                          oscap.oval.XCCDF_RESULT_PASS)]],
                      "oval:foo_fail:def:1": [[
                         (oscap.oval.OVAL_FAMILY_INDEPENDENT,
                          oscap.oval.OVAL_INDEPENDENT_TEXT_FILE_CONTENT_54,
                          oscap.oval.XCCDF_RESULT_FAIL)]]
                      }

    expected_tree = expected_trees.get(ovdef.get_id())

    if expected_tree is None:
        print("Unexpected oval def : {0}. No expected tests tree defined for it"
              .format(ovdef.get_id()))
    elif expected_tree == tests_tree:
        print("Tests tree of {0} is like expected : {1}".format(ovdef.get_id(),
                                                                tests_tree))
    else:
        raise ValueError("Tests tree of {0} doesn't match with the expected tree.\n"
              "Extracted tree: {1}\nExpected tree: {2}"
              .format(ovdef.get_id(), tests_tree, expected_tree))

    return 0

# eval oval defs oval:[foo_pass|fail]:def:1
def oval_eval_sample(oval_defs):
    states = {'false': 0, 'true': 0, 'err': 0, 'unknown': 0, 'neval': 0,
              'na': 0, 'verbose': True}

    sess = oscap.oval.agent_new_session(oval_defs, "")
    ret = oscap.oval.agent_eval_system(sess, oval_sample_callback, states)

'''
Main test
'''

print("Opening oval file with original C functions ... ")
oval_defs = oscap.oval.definition_model_import_source(
    oscap.common.source_new_from_file(get_path("samples/oval_sample.xml")))

oval_eval_sample(oval_defs)

# TODO: do the same thing with oval_import

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals
from pytest import mark

from pypinyin import pinyin_dict
from pypinyin.contrib.tone_convert import (
    tone_to_normal,
    tone_to_tone2,
    tone2_to_tone,
    tone_to_tone3,
    tone3_to_tone,
    tone2_to_normal,
    tone2_to_tone3,
    tone3_to_tone2,
    tone3_to_normal,
    to_normal,
    to_tone,
    to_tone2,
    to_tone3,
    to_initials,
    to_finals,
    to_finals_tone,
    to_finals_tone2,
    to_finals_tone3,
)

@mark.parametrize('pinyin,result', [
    ['zhōng', 'zhong'],
    ['ān', 'an'],
    ['yuè', 'yue'],
    ['er', 'er'],
    ['nǚ', 'nv'],
    ['nv', 'nv'],
    ['ā', 'a'],
    ['a', 'a'],
])
def test_tone_to_normal(pinyin, result):
    assert tone_to_normal(pinyin) == result

    assert to_normal(pinyin) == result
    assert to_normal(result) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['nǚ', False, 'nv'],
    ['nv', False, 'nv'],
    ['nǚ', True, 'nü'],
    ['nv', True, 'nü'],
])
def test_tone_to_normal_with_v_to_u(pinyin, v_to_u, result):
    assert tone_to_normal(pinyin, v_to_u=v_to_u) == result
    assert to_normal(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhōng', 'zho1ng'],
    ['ān', 'a1n'],
    ['yuè', 'yue4'],
    ['er', 'er'],
    ['nǚ', 'nv3'],
    ['nv', 'nv'],
    ['ā', 'a1'],
    ['a', 'a'],
    ['shang', 'shang'],
])
def test_tone_tone2(pinyin, result):
    assert tone_to_tone2(pinyin) == result
    assert to_tone2(pinyin) == result

@mark.parametrize('pinyin,neutral_tone_with_five,result', [
    ['shang', False, 'shang'],
    ['shang', True, 'sha5ng'],
])
def test_tone_tone2_with_neutral_tone_with_five(
        pinyin, neutral_tone_with_five, result):
    assert tone_to_tone2(
        pinyin, neutral_tone_with_five=neutral_tone_with_five) == result
    assert tone_to_tone2(
        pinyin, neutral_tone_with_5=neutral_tone_with_five) == result
    assert to_tone2(pinyin,
                    neutral_tone_with_five=neutral_tone_with_five) == result
    assert to_tone2(pinyin,
                    neutral_tone_with_5=neutral_tone_with_five) == result

    assert tone2_to_tone(result) == pinyin
    assert to_tone(result) == pinyin

@mark.parametrize('pinyin,v_to_u,result', [
    ['nǚ', False, 'nv3'],
    ['nv', False, 'nv'],
    ['nǚ', True, 'nü3'],
    ['nv', True, 'nü'],
])
def test_tone_tone2_with_v_to_u(pinyin, v_to_u, result):
    assert tone_to_tone2(pinyin, v_to_u=v_to_u) == result
    assert to_tone2(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhōng', 'zhong1'],
    ['ān', 'an1'],
    ['yuè', 'yue4'],
    ['er', 'er'],
    ['nǚ', 'nv3'],
    ['nv', 'nv'],
    ['ā', 'a1'],
    ['a', 'a'],
    ['shang', 'shang'],
])
def test_tone_tone3(pinyin, result):
    assert tone_to_tone3(pinyin) == result
    assert to_tone3(pinyin) == result

@mark.parametrize('pinyin,neutral_tone_with_five,result', [
    ['shang', False, 'shang'],
    ['shang', True, 'shang5'],
])
def test_tone_tone3_with_neutral_tone_with_five(
        pinyin, neutral_tone_with_five, result):
    assert tone_to_tone3(
        pinyin, neutral_tone_with_five=neutral_tone_with_five) == result
    assert tone_to_tone3(
        pinyin, neutral_tone_with_5=neutral_tone_with_five) == result
    assert to_tone3(
        pinyin, neutral_tone_with_five=neutral_tone_with_five) == result
    assert to_tone3(
        pinyin, neutral_tone_with_5=neutral_tone_with_five) == result

    assert tone3_to_tone(result) == pinyin
    assert to_tone(result) == pinyin

@mark.parametrize('pinyin,v_to_u,result', [
    ['nǚ', False, 'nv3'],
    ['nǚ', True, 'nü3'],
    ['nv', True, 'nü'],
])
def test_tone_tone3_with_v_to_u(pinyin, v_to_u, result):
    assert tone_to_tone3(pinyin, v_to_u=v_to_u) == result
    assert to_tone3(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zho1ng', 'zhong1'],
    ['a1n', 'an1'],
    ['yue4', 'yue4'],
    ['er', 'er'],
    ['nv3', 'nv3'],
    ['nü3', 'nv3'],
    ['a1', 'a1'],
    ['a', 'a'],
    ['shang', 'shang'],
    ['sha5ng', 'shang5'],
])
def test_tone2_tone3(pinyin, result):
    assert tone2_to_tone3(pinyin) == result
    assert to_tone3(pinyin) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['lüe3', False, 'lve3'],
    ['lüe3', True, 'lüe3'],
])
def test_tone2_tone3_with_v_to_u(pinyin, v_to_u, result):
    assert tone2_to_tone3(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zho1ng', 'zhong'],
    ['a1n', 'an'],
    ['yue4', 'yue'],
    ['er', 'er'],
    ['nv3', 'nv'],
    ['nü3', 'nv'],
    ['a1', 'a'],
    ['a', 'a'],
    ['shang', 'shang'],
    ['sha5ng', 'shang'],
])
def test_tone2_to_normal(pinyin, result):
    assert tone2_to_normal(pinyin) == result

    assert to_normal(pinyin) == result
    assert to_normal(result) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['nv3', False, 'nv'],
    ['nv3', True, 'nü'],
    ['nü3', False, 'nv'],
    ['nü3', True, 'nü'],
])
def test_tone2_to_normal_with_v_to_u(pinyin, v_to_u, result):
    assert tone2_to_normal(pinyin, v_to_u=v_to_u) == result

    assert to_normal(pinyin, v_to_u=v_to_u) == result
    assert to_normal(result, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhong1', 'zhong'],
    ['an1', 'an'],
    ['yue4', 'yue'],
    ['er', 'er'],
    ['nv3', 'nv'],
    ['nü3', 'nv'],
    ['a1', 'a'],
    ['a', 'a'],
    ['shang', 'shang'],
    ['shang5', 'shang'],
])
def test_tone3_to_normal(pinyin, result):
    assert tone3_to_normal(pinyin) == result
    assert to_normal(pinyin) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['nv3', False, 'nv'],
    ['nv3', True, 'nü'],
    ['nü3', False, 'nv'],
    ['nü3', True, 'nü'],
])
def test_tone3_to_normal_with_v_to_u(pinyin, v_to_u, result):
    assert tone3_to_normal(pinyin, v_to_u=v_to_u) == result
    assert to_normal(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhong1', 'zho1ng'],
    ['lüe4', 'lve4'],
])
def test_tone3_to_tone2(pinyin, result):
    assert tone3_to_tone2(pinyin) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['lüe4', False, 'lve4'],
    ['lüe4', True, 'lüe4'],
])
def test_tone3_to_tone2_with_v_to_u(pinyin, v_to_u, result):
    assert tone3_to_tone2(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,strict,result', [
    ['zhōng', True, 'zh'],
    ['zhōng', False, 'zh'],

    ['zho1ng', True, 'zh'],
    ['zho1ng', False, 'zh'],

    ['zhong1', True, 'zh'],
    ['zhong1', False, 'zh'],

    ['zhong', True, 'zh'],
    ['zhong', False, 'zh'],

    ['yu', True, ''],
    ['yu', False, 'y'],
])
def test_to_initials(pinyin, strict, result):
    assert to_initials(pinyin, strict=strict) == result

@mark.parametrize('pinyin,strict,v_to_u,result', [
    ['zhōng', True, False, 'ong'],
    ['zhōng', False, False, 'ong'],

    ['zho1ng', True, False, 'ong'],
    ['zho1ng', False, False, 'ong'],

    ['zhong1', True, False, 'ong'],
    ['zhong1', False, False, 'ong'],

    ['zhong', True, False, 'ong'],
    ['zhong', False, False, 'ong'],

    ['nǚ', True, False, 'v'],
    ['nv', True, False, 'v'],
    ['nü', True, False, 'v'],
    ['nǚ', True, True, 'ü'],
    ['nü', True, True, 'ü'],
    ['nv', True, True, 'ü'],

    ['gui', True, False, 'uei'],
    ['gui', False, False, 'ui'],
])
def test_to_finals(pinyin, strict, v_to_u, result):
    assert to_finals(pinyin, strict=strict, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,strict,result', [
    ['zhōng', True, 'ōng'],
    ['zhōng', False, 'ōng'],
    ['yū', True, 'ǖ'],
    ['yū', False, 'ū'],
])
def test_to_finals_tone(pinyin, strict, result):
    assert to_finals_tone(pinyin, strict=strict) == result

@mark.parametrize('pinyin,strict,v_to_u,neutral_tone_with_five,result', [
    ['zhōng', True, False, False, 'o1ng'],
    ['zhōng', False, False, False, 'o1ng'],
    ['zhong', False, False, True, 'o5ng'],
    ['yū', True, False, False, 'v1'],
    ['yū', True, True, False, 'ü1'],
    ['yū', False, False, False, 'u1'],
    ['yū', False, True, False, 'u1'],
])
def test_to_finals_tone2(pinyin, strict, v_to_u,
                         neutral_tone_with_five, result):
    assert to_finals_tone2(pinyin, strict=strict, v_to_u=v_to_u,
                           neutral_tone_with_five=neutral_tone_with_five
                           ) == result

@mark.parametrize('pinyin,strict,v_to_u,neutral_tone_with_five,result', [
    ['zhōng', True, False, False, 'ong1'],
    ['zhōng', False, False, False, 'ong1'],
    ['zhong', False, False, True, 'ong5'],
    ['yū', True, False, False, 'v1'],
    ['yū', True, True, False, 'ü1'],
    ['yū', False, False, False, 'u1'],
    ['yū', False, True, False, 'u1'],
])
def test_to_finals_tone3(pinyin, strict, v_to_u, neutral_tone_with_five,
                         result):
    assert to_finals_tone3(pinyin, strict=strict, v_to_u=v_to_u,
                           neutral_tone_with_five=neutral_tone_with_five
                           ) == result

# 所有拼音转换为 tone2 或 tone3 风格后，都可以再转换回原始的拼音
def test_tone_to_tone2_tone3_to_tone():
    pinyin_set = set()
    for py in pinyin_dict.pinyin_dict.values():
        pinyin_set.update(py.split(','))

    for py in pinyin_set:
        tone2 = tone_to_tone2(py)
        assert tone2_to_tone(tone2) == py
        assert to_tone(tone2) == py

        tone2_3 = tone2_to_tone3(tone2)
        assert tone3_to_tone(tone2_3) == py
        assert to_tone(tone2_3) == py

        #
        tone3 = tone_to_tone3(py)
        assert tone3_to_tone(tone3) == py
        assert to_tone(tone3) == py

        tone3_2 = tone3_to_tone2(tone3)
        assert tone2_to_tone(tone3_2) == py
        assert to_tone(tone3_2) == py
<commit_msg>add more tests<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals
from pytest import mark

from pypinyin import pinyin_dict
from pypinyin.contrib.tone_convert import (
    tone_to_normal,
    tone_to_tone2,
    tone2_to_tone,
    tone_to_tone3,
    tone3_to_tone,
    tone2_to_normal,
    tone2_to_tone3,
    tone3_to_tone2,
    tone3_to_normal,
    to_normal,
    to_tone,
    to_tone2,
    to_tone3,
    to_initials,
    to_finals,
    to_finals_tone,
    to_finals_tone2,
    to_finals_tone3,
)

@mark.parametrize('pinyin,result', [
    ['zhōng', 'zhong'],
    ['ān', 'an'],
    ['yuè', 'yue'],
    ['er', 'er'],
    ['nǚ', 'nv'],
    ['nv', 'nv'],
    ['ā', 'a'],
    ['a', 'a'],
])
def test_tone_to_normal(pinyin, result):
    assert tone_to_normal(pinyin) == result

    assert to_normal(pinyin) == result
    assert to_normal(result) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['nǚ', False, 'nv'],
    ['nv', False, 'nv'],
    ['nǚ', True, 'nü'],
    ['nv', True, 'nü'],
])
def test_tone_to_normal_with_v_to_u(pinyin, v_to_u, result):
    assert tone_to_normal(pinyin, v_to_u=v_to_u) == result
    assert to_normal(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhōng', 'zho1ng'],
    ['ān', 'a1n'],
    ['yuè', 'yue4'],
    ['er', 'er'],
    ['nǚ', 'nv3'],
    ['nv', 'nv'],
    ['ā', 'a1'],
    ['a', 'a'],
    ['shang', 'shang'],
])
def test_tone_tone2(pinyin, result):
    assert tone_to_tone2(pinyin) == result
    assert to_tone2(pinyin) == result

@mark.parametrize('pinyin,neutral_tone_with_five,result', [
    ['shang', False, 'shang'],
    ['shang', True, 'sha5ng'],
])
def test_tone_tone2_with_neutral_tone_with_five(
        pinyin, neutral_tone_with_five, result):
    assert tone_to_tone2(
        pinyin, neutral_tone_with_five=neutral_tone_with_five) == result
    assert tone_to_tone2(
        pinyin, neutral_tone_with_5=neutral_tone_with_five) == result
    assert to_tone2(pinyin,
                    neutral_tone_with_five=neutral_tone_with_five) == result
    assert to_tone2(pinyin,
                    neutral_tone_with_5=neutral_tone_with_five) == result

    assert tone2_to_tone(result) == pinyin
    assert to_tone(result) == pinyin

@mark.parametrize('pinyin,v_to_u,result', [
    ['nǚ', False, 'nv3'],
    ['nv', False, 'nv'],
    ['nǚ', True, 'nü3'],
    ['nv', True, 'nü'],
])
def test_tone_tone2_with_v_to_u(pinyin, v_to_u, result):
    assert tone_to_tone2(pinyin, v_to_u=v_to_u) == result
    assert to_tone2(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhōng', 'zhong1'],
    ['ān', 'an1'],
    ['yuè', 'yue4'],
    ['er', 'er'],
    ['nǚ', 'nv3'],
    ['nv', 'nv'],
    ['ā', 'a1'],
    ['a', 'a'],
    ['shang', 'shang'],
])
def test_tone_tone3(pinyin, result):
    assert tone_to_tone3(pinyin) == result
    assert to_tone3(pinyin) == result

@mark.parametrize('pinyin,neutral_tone_with_five,result', [
    ['shang', False, 'shang'],
    ['shang', True, 'shang5'],
])
def test_tone_tone3_with_neutral_tone_with_five(
        pinyin, neutral_tone_with_five, result):
    assert tone_to_tone3(
        pinyin, neutral_tone_with_five=neutral_tone_with_five) == result
    assert tone_to_tone3(
        pinyin, neutral_tone_with_5=neutral_tone_with_five) == result
    assert to_tone3(
        pinyin, neutral_tone_with_five=neutral_tone_with_five) == result
    assert to_tone3(
        pinyin, neutral_tone_with_5=neutral_tone_with_five) == result

    assert tone3_to_tone(result) == pinyin
    assert to_tone(result) == pinyin

@mark.parametrize('pinyin,v_to_u,result', [
    ['nǚ', False, 'nv3'],
    ['nǚ', True, 'nü3'],
    ['nv', True, 'nü'],
])
def test_tone_tone3_with_v_to_u(pinyin, v_to_u, result):
    assert tone_to_tone3(pinyin, v_to_u=v_to_u) == result
    assert to_tone3(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zho1ng', 'zhong1'],
    ['a1n', 'an1'],
    ['yue4', 'yue4'],
    ['er', 'er'],
    ['nv3', 'nv3'],
    ['nü3', 'nv3'],
    ['a1', 'a1'],
    ['a', 'a'],
    ['shang', 'shang'],
    ['sha5ng', 'shang5'],
])
def test_tone2_tone3(pinyin, result):
    assert tone2_to_tone3(pinyin) == result
    assert to_tone3(pinyin) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['lüe3', False, 'lve3'],
    ['lüe3', True, 'lüe3'],
])
def test_tone2_tone3_with_v_to_u(pinyin, v_to_u, result):
    assert tone2_to_tone3(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zho1ng', 'zhong'],
    ['a1n', 'an'],
    ['yue4', 'yue'],
    ['er', 'er'],
    ['nv3', 'nv'],
    ['nü3', 'nv'],
    ['a1', 'a'],
    ['a', 'a'],
    ['shang', 'shang'],
    ['sha5ng', 'shang'],
])
def test_tone2_to_normal(pinyin, result):
    assert tone2_to_normal(pinyin) == result

    assert to_normal(pinyin) == result
    assert to_normal(result) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['nv3', False, 'nv'],
    ['nv3', True, 'nü'],
    ['nü3', False, 'nv'],
    ['nü3', True, 'nü'],
])
def test_tone2_to_normal_with_v_to_u(pinyin, v_to_u, result):
    assert tone2_to_normal(pinyin, v_to_u=v_to_u) == result

    assert to_normal(pinyin, v_to_u=v_to_u) == result
    assert to_normal(result, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhong1', 'zhong'],
    ['an1', 'an'],
    ['yue4', 'yue'],
    ['er', 'er'],
    ['nv3', 'nv'],
    ['nü3', 'nv'],
    ['a1', 'a'],
    ['a', 'a'],
    ['shang', 'shang'],
    ['shang5', 'shang'],
])
def test_tone3_to_normal(pinyin, result):
    assert tone3_to_normal(pinyin) == result
    assert to_normal(pinyin) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['nv3', False, 'nv'],
    ['nv3', True, 'nü'],
    ['nü3', False, 'nv'],
    ['nü3', True, 'nü'],
])
def test_tone3_to_normal_with_v_to_u(pinyin, v_to_u, result):
    assert tone3_to_normal(pinyin, v_to_u=v_to_u) == result
    assert to_normal(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,result', [
    ['zhong1', 'zho1ng'],
    ['lüe4', 'lve4'],
])
def test_tone3_to_tone2(pinyin, result):
    assert tone3_to_tone2(pinyin) == result

@mark.parametrize('pinyin,v_to_u,result', [
    ['lüe4', False, 'lve4'],
    ['lüe4', True, 'lüe4'],
])
def test_tone3_to_tone2_with_v_to_u(pinyin, v_to_u, result):
    assert tone3_to_tone2(pinyin, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,strict,result', [
    ['zhōng', True, 'zh'],
    ['zhōng', False, 'zh'],

    ['zho1ng', True, 'zh'],
    ['zho1ng', False, 'zh'],

    ['zhong1', True, 'zh'],
    ['zhong1', False, 'zh'],

    ['zhong', True, 'zh'],
    ['zhong', False, 'zh'],

    ['yu', True, ''],
    ['yu', False, 'y'],
])
def test_to_initials(pinyin, strict, result):
    assert to_initials(pinyin, strict=strict) == result

@mark.parametrize('pinyin,strict,v_to_u,result', [
    ['zhōng', True, False, 'ong'],
    ['zhōng', False, False, 'ong'],

    ['zho1ng', True, False, 'ong'],
    ['zho1ng', False, False, 'ong'],

    ['zhong1', True, False, 'ong'],
    ['zhong1', False, False, 'ong'],

    ['zhong', True, False, 'ong'],
    ['zhong', False, False, 'ong'],

    ['nǚ', True, False, 'v'],
    ['nv', True, False, 'v'],
    ['nü', True, False, 'v'],
    ['nǚ', True, True, 'ü'],
    ['nü', True, True, 'ü'],
    ['nv', True, True, 'ü'],

    ['gui', True, False, 'uei'],
    ['gui', False, False, 'ui'],
])
def test_to_finals(pinyin, strict, v_to_u, result):
    assert to_finals(pinyin, strict=strict, v_to_u=v_to_u) == result

@mark.parametrize('pinyin,strict,result', [
    ['zhōng', True, 'ōng'],
    ['zho1ng', True, 'ōng'],
    ['zhong1', True, 'ōng'],
    ['zhōng', False, 'ōng'],
    ['yū', True, 'ǖ'],
    ['yu1', True, 'ǖ'],
    ['yū', False, 'ū'],
])
def test_to_finals_tone(pinyin, strict, result):
    assert to_finals_tone(pinyin, strict=strict) == result

@mark.parametrize('pinyin,strict,v_to_u,neutral_tone_with_five,result', [
    ['zhōng', True, False, False, 'o1ng'],
    ['zhong1', True, False, False, 'o1ng'],
    ['zho1ng', True, False, False, 'o1ng'],
    ['zhōng', False, False, False, 'o1ng'],
    ['zhong', False, False, True, 'o5ng'],
    ['yū', True, False, False, 'v1'],
    ['yu1', True, False, False, 'v1'],
    ['yū', True, True, False, 'ü1'],
    ['yū', False, False, False, 'u1'],
    ['yū', False, True, False, 'u1'],
])
def test_to_finals_tone2(pinyin, strict, v_to_u,
                         neutral_tone_with_five, result):
    assert to_finals_tone2(pinyin, strict=strict, v_to_u=v_to_u,
                           neutral_tone_with_five=neutral_tone_with_five
                           ) == result

@mark.parametrize('pinyin,strict,v_to_u,neutral_tone_with_five,result', [
    ['zhōng', True, False, False, 'ong1'],
    ['zhong1', True, False, False, 'ong1'],
    ['zho1ng', True, False, False, 'ong1'],
    ['zhōng', False, False, False, 'ong1'],
    ['zhong', False, False, True, 'ong5'],
    ['yū', True, False, False, 'v1'],
    ['yu1', True, False, False, 'v1'],
    ['yū', True, True, False, 'ü1'],
    ['yū', False, False, False, 'u1'],
    ['yū', False, True, False, 'u1'],
])
def test_to_finals_tone3(pinyin, strict, v_to_u, neutral_tone_with_five,
                         result):
    assert to_finals_tone3(pinyin, strict=strict, v_to_u=v_to_u,
                           neutral_tone_with_five=neutral_tone_with_five
                           ) == result

# 所有拼音转换为 tone2 或 tone3 风格后，都可以再转换回原始的拼音
def test_tone_to_tone2_tone3_to_tone():
    pinyin_set = set()
    for py in pinyin_dict.pinyin_dict.values():
        pinyin_set.update(py.split(','))

    for py in pinyin_set:
        tone2 = tone_to_tone2(py)
        assert tone2_to_tone(tone2) == py
        assert to_tone(tone2) == py

        tone2_3 = tone2_to_tone3(tone2)
        assert tone3_to_tone(tone2_3) == py
        assert to_tone(tone2_3) == py

        #
        tone3 = tone_to_tone3(py)
        assert tone3_to_tone(tone3) == py
        assert to_tone(tone3) == py

        tone3_2 = tone3_to_tone2(tone3)
        assert tone2_to_tone(tone3_2) == py
        assert to_tone(tone3_2) == py
<|endoftext|>


<commit_before>from unittest import TestCase

from opencog.atomspace import AtomSpace, TruthValue, Atom, Handle
from opencog.atomspace import types, is_a, get_type, get_type_name
from opencog.scheme_wrapper import load_scm, scheme_eval, scheme_eval_h, __init__

# We are poking atoms into this from the scm files, so we want
# them to still be there, later.
shared_space = AtomSpace()
__init__(shared_space)

class SchemeTest(TestCase):

    def setUp(self):
        global shared_space
        self.space = shared_space

    def tearDown(self):
        pass

    # Load several different scheme files, containing atom type
    # declarations, and utilities. They should load just fine.
    # These don't actually put any atoms into the atomspace.
    def test_a_load_core_types(self):

        # These relative paths are horridly ugly.
        # There must be a better way ...
        status = load_scm(self.space, "opencog/atomspace/core_types.scm")
        self.assertTrue(status)

        status = load_scm(self.space, "opencog/scm/utilities.scm")
        self.assertTrue(status)

    # Load a file that results in atoms placed in the atomspace.
    # Make sure the loaded atom is what we think it is.
    def test_b_load_file(self):

        status = load_scm(self.space, "tests/cython/guile/basic_unify.scm")
        self.assertTrue(status)

        a1 = self.space.add_node(types.ConceptNode, "hello")
        self.assertTrue(a1)

        # Make sure the truth value is what's in the SCM file.
        expected = TruthValue(0.5, 800)
        self.assertEquals(a1.tv, expected)
        # print a1.tv, expected

    # Run some basic evaluation tests
    def test_c_eval(self):
        basic = scheme_eval_h(self.space,
            "(ConceptNode \"whatever\" (stv 0.5 0.5))")

        a1 = self.space.add_node(types.ConceptNode, "whatever")
        self.assertTrue(a1)

        # Make sure the truth value is what's in the SCM file.
        expected = TruthValue(0.5, 800)
        self.assertEquals(a1.tv, expected)

        # Actually, the atoms overall should compare.
        # print "eq", Atom(basic, self.space) == a1
        self.assertEquals(a1, Atom(basic, self.space))

        # Do it again, from a define in the scm file.
        again = scheme_eval_h(self.space, "wobbly")
        a2 = self.space.add_node(types.ConceptNode, "wobbly")
        self.assertTrue(a2)
        self.assertEquals(a2, Atom(again, self.space))

    # Run the pattern-matcher/unifier/query-engine.
    def test_unifier(self):
        h = scheme_eval_h(self.space, "cap-deduce")
        self.assertTrue(h)
        print "\nThe question is:"
        print h
        question = Atom(h, self.space)
        print question

        h = scheme_eval_h(self.space, "(cog-bind cap-deduce)")
        self.assertTrue(h)
        print h
        answer = Atom(h, self.space)
        print "\nThe answer is:"
        print answer
        self.assertEqual(answer.type, types.SetLink)
        self.assertEqual(answer.arity, 2)
<commit_msg>Unit-test bug fixes<commit_after>from unittest import TestCase

from opencog.atomspace import AtomSpace, TruthValue, Atom, Handle
from opencog.atomspace import types, is_a, get_type, get_type_name
from opencog.scheme_wrapper import load_scm, scheme_eval, scheme_eval_h, __init__

# We are poking atoms into this from the scm files, so we want
# them to still be there, later.
shared_space = AtomSpace()
__init__(shared_space)

class SchemeTest(TestCase):

    def setUp(self):
        global shared_space
        self.space = shared_space

    def tearDown(self):
        pass

    # Load several different scheme files, containing atom type
    # declarations, and utilities. They should load just fine.
    # These don't actually put any atoms into the atomspace.
    def test_a_load_core_types(self):

        # These relative paths are horridly ugly.
        # There must be a better way ...
        status = load_scm(self.space, "build/opencog/atomspace/core_types.scm")
        self.assertTrue(status)

        status = load_scm(self.space, "opencog/scm/utilities.scm")
        self.assertTrue(status)

    # Load a file that results in atoms placed in the atomspace.
    # Make sure the loaded atom is what we think it is.
    def test_b_load_file(self):

        status = load_scm(self.space, "tests/cython/guile/basic_unify.scm")
        self.assertTrue(status)

        a1 = self.space.add_node(types.ConceptNode, "hello")
        self.assertTrue(a1)

        # Make sure the truth value is what's in the SCM file.
        expected = TruthValue(0.5, 800)
        self.assertEquals(a1.tv, expected)
        # print a1.tv, expected

    # Run some basic evaluation tests
    def test_c_eval(self):
        basic = scheme_eval_h(self.space,
            "(ConceptNode \"whatever\" (stv 0.5 0.5))")

        a1 = self.space.add_node(types.ConceptNode, "whatever")
        self.assertTrue(a1)

        # Make sure the truth value is what's in the SCM file.
        expected = TruthValue(0.5, 800)
        self.assertEquals(a1.tv, expected)

        # Actually, the atoms overall should compare.
        # print "eq", Atom(basic, self.space) == a1
        self.assertEquals(a1, Atom(basic, self.space))

        # Do it again, from a define in the scm file.
        again = scheme_eval_h(self.space, "wobbly")
        a2 = self.space.add_node(types.ConceptNode, "wobbly")
        self.assertTrue(a2)
        self.assertEquals(a2, Atom(again, self.space))

    # Run the pattern-matcher/unifier/query-engine.
    def test_unifier(self):
        h = scheme_eval_h(self.space, "cap-deduce")
        self.assertTrue(h)
        print "\nThe question is:"
        print h
        question = Atom(h, self.space)
        print question

        h = scheme_eval_h(self.space, "(cog-bind cap-deduce)")
        self.assertTrue(h)
        print h
        answer = Atom(h, self.space)
        print "\nThe answer is:"
        print answer
        self.assertEqual(answer.type, types.SetLink)
        self.assertEqual(answer.arity, 2)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import, print_function

import unittest
from datetime import datetime

from tests import with_mock_client, with_mock_responses, with_client

from predicthq.endpoints.v1.events.schemas import EventResultSet, CalendarResultSet, Count

class EventsTest(unittest.TestCase):

    @with_mock_client()
    def test_search_params_underscores(self, client):
        client.events.search(id="id", q="query", rank_level=[4,5], rank__gt=85, country=["NZ", "AU"],
             within__radius="2km", within__longitude=-71.0432, within__latitude=42.346,
             label=["label1", "label2"], category="category", state='deleted',
             place__scope=["place1", "place2"], place__exact=["place3"],
             start__gte="2016-03-01", start__lt=datetime(2016, 4, 1), start__tz="Pacific/Auckland",
             active__gte="2016-03-01", active__lt=datetime(2016, 4, 1), active__tz="Pacific/Auckland",
             updated__gte="2016-03-01", updated__lt=datetime(2016, 4, 1), updated__tz="Pacific/Auckland",
             signal__id="zVNLr8tHvWQw", signal__explain=datetime(2016, 4, 1))

        client.request.assert_called_once_with('get', '/v1/events/', params={
            'id': 'id', 'rank.gt': 85, 'rank_level': '4,5', 'category': 'category', 'state': 'deleted', 'country': 'NZ,AU',
            'within': '2km@42.346,-71.0432', 'label': 'label1,label2', 'q': 'query',
            'place.scope': 'place1,place2', 'place.exact': 'place3',
            'start.lt': '2016-04-01T00:00:00.000000', 'start.gte': '2016-03-01T00:00:00.000000', 'start.tz': 'Pacific/Auckland',
            'active.lt': '2016-04-01T00:00:00.000000', 'active.gte': '2016-03-01T00:00:00.000000', 'active.tz': 'Pacific/Auckland',
            'updated.lt': '2016-04-01T00:00:00.000000', 'updated.gte': '2016-03-01T00:00:00.000000', 'updated.tz': 'Pacific/Auckland',
            'signal.id': 'zVNLr8tHvWQw', 'signal.explain': '2016-04-01'})

    @with_mock_client()
    def test_search_params_dicts(self, client):
        client.events.search(id="id", q="query", rank_level=[4,5], rank={"gt": 85}, country=["NZ", "AU"],
             within={"radius": "2km", "longitude": -71.0432, "latitude": 42.346},
             label=["label1", "label2"], category="category", state='deleted',
             place={"scope": ["place1", "place2"], "exact": "place3"},
             start={"gte": "2016-03-01", "lt": datetime(2016, 4, 1), "tz": "Pacific/Auckland"},
             active={"gte": "2016-03-01", "lt": datetime(2016, 4, 1), "tz": "Pacific/Auckland"},
             updated={"gte": "2016-03-01", "lt": datetime(2016, 4, 1), "tz": "Pacific/Auckland"},
             signal={"id": "zVNLr8tHvWQw", "explain": datetime(2016, 4, 1)})

        client.request.assert_called_once_with('get', '/v1/events/', params={
            'id': 'id', 'rank.gt': 85, 'rank_level': '4,5', 'category': 'category', 'state': 'deleted', 'country': 'NZ,AU',
            'within': '2km@42.346,-71.0432', 'label': 'label1,label2', 'q': 'query',
            'place.scope': 'place1,place2', 'place.exact': 'place3',
            'start.lt': '2016-04-01T00:00:00.000000', 'start.gte': '2016-03-01T00:00:00.000000', 'start.tz': 'Pacific/Auckland',
            'active.lt': '2016-04-01T00:00:00.000000', 'active.gte': '2016-03-01T00:00:00.000000', 'active.tz': 'Pacific/Auckland',
            'updated.lt': '2016-04-01T00:00:00.000000', 'updated.gte': '2016-03-01T00:00:00.000000', 'updated.tz': 'Pacific/Auckland',
            'signal.id': 'zVNLr8tHvWQw', 'signal.explain': '2016-04-01'})

    @with_mock_client()
    def test_search_for_account(self, client):
        client.events.for_account('account-id').search(q="query")
        client.request.assert_called_once_with('get', '/v1/accounts/account-id/events/', params={'q': 'query'})

    @with_client()
    @with_mock_responses()
    def test_search(self, client, responses):
        result = client.events.search(q="Foo Fighters", country="AU", limit=10)
        self.assertIsInstance(result, EventResultSet)
        self.assertEqual(result.count, len(list(result.iter_all())))
        self.assertEqual(2, len(responses.calls))

    @with_client()
    @with_mock_responses()
    def test_count(self, client, responses):
        result = client.events.count(active__gte="2015-01-01", active__lte="2015-12-31", within="50km@-27.470784,153.030124")
        self.assertIsInstance(result, Count)
        self.assertEqual(result.count, 2501)

    @with_client()
    @with_mock_responses()
    def test_calendar(self, client, responses):
        result = client.events.calendar(active__gte="2015-12-24", active__lte="2015-12-26", country="NZ", top_events__limit=1, top_events__sort=["rank"], active__tz="Pacific/Auckland")
        self.assertIsInstance(result, CalendarResultSet)
        self.assertEqual(result.count, 60)
        self.assertEqual(3, len(list(result.iter_all())))
        self.assertEqual(1, len(responses.calls))
<commit_msg>add end param to event test<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import, print_function

import unittest
from datetime import datetime

from tests import with_mock_client, with_mock_responses, with_client

from predicthq.endpoints.v1.events.schemas import EventResultSet, CalendarResultSet, Count

class EventsTest(unittest.TestCase):

    @with_mock_client()
    def test_search_params_underscores(self, client):
        client.events.search(id="id", q="query", rank_level=[4,5], rank__gt=85, country=["NZ", "AU"],
             within__radius="2km", within__longitude=-71.0432, within__latitude=42.346,
             label=["label1", "label2"], category="category", state='deleted',
             place__scope=["place1", "place2"], place__exact=["place3"],
             start__gte="2016-03-01", start__lt=datetime(2016, 4, 1), start__tz="Pacific/Auckland",
             end__gte="2016-05-01", end__lt=datetime(2016, 6, 1), end__tz="Pacific/Auckland",
             active__gte="2016-03-01", active__lt=datetime(2016, 4, 1), active__tz="Pacific/Auckland",
             updated__gte="2016-03-01", updated__lt=datetime(2016, 4, 1), updated__tz="Pacific/Auckland",
             signal__id="zVNLr8tHvWQw", signal__explain=datetime(2016, 4, 1))

        client.request.assert_called_once_with('get', '/v1/events/', params={
            'id': 'id', 'rank.gt': 85, 'rank_level': '4,5', 'category': 'category', 'state': 'deleted', 'country': 'NZ,AU',
            'within': '2km@42.346,-71.0432', 'label': 'label1,label2', 'q': 'query',
            'place.scope': 'place1,place2', 'place.exact': 'place3',
            'start.lt': '2016-04-01T00:00:00.000000', 'start.gte': '2016-03-01T00:00:00.000000', 'start.tz': 'Pacific/Auckland',
            'end.lt': '2016-06-01T00:00:00.000000', 'end.gte': '2016-05-01T00:00:00.000000', 'end.tz': 'Pacific/Auckland',
            'active.lt': '2016-04-01T00:00:00.000000', 'active.gte': '2016-03-01T00:00:00.000000', 'active.tz': 'Pacific/Auckland',
            'updated.lt': '2016-04-01T00:00:00.000000', 'updated.gte': '2016-03-01T00:00:00.000000', 'updated.tz': 'Pacific/Auckland',
            'signal.id': 'zVNLr8tHvWQw', 'signal.explain': '2016-04-01'})

    @with_mock_client()
    def test_search_params_dicts(self, client):
        client.events.search(id="id", q="query", rank_level=[4,5], rank={"gt": 85}, country=["NZ", "AU"],
             within={"radius": "2km", "longitude": -71.0432, "latitude": 42.346},
             label=["label1", "label2"], category="category", state='deleted',
             place={"scope": ["place1", "place2"], "exact": "place3"},
             start={"gte": "2016-03-01", "lt": datetime(2016, 4, 1), "tz": "Pacific/Auckland"},
             end={"gte": "2016-05-01", "lt": datetime(2016, 6, 1), "tz": "Pacific/Auckland"},
             active={"gte": "2016-03-01", "lt": datetime(2016, 4, 1), "tz": "Pacific/Auckland"},
             updated={"gte": "2016-03-01", "lt": datetime(2016, 4, 1), "tz": "Pacific/Auckland"},
             signal={"id": "zVNLr8tHvWQw", "explain": datetime(2016, 4, 1)})

        client.request.assert_called_once_with('get', '/v1/events/', params={
            'id': 'id', 'rank.gt': 85, 'rank_level': '4,5', 'category': 'category', 'state': 'deleted', 'country': 'NZ,AU',
            'within': '2km@42.346,-71.0432', 'label': 'label1,label2', 'q': 'query',
            'place.scope': 'place1,place2', 'place.exact': 'place3',
            'start.lt': '2016-04-01T00:00:00.000000', 'start.gte': '2016-03-01T00:00:00.000000', 'start.tz': 'Pacific/Auckland',
            'end.lt': '2016-06-01T00:00:00.000000', 'end.gte': '2016-05-01T00:00:00.000000', 'end.tz': 'Pacific/Auckland',
            'active.lt': '2016-04-01T00:00:00.000000', 'active.gte': '2016-03-01T00:00:00.000000', 'active.tz': 'Pacific/Auckland',
            'updated.lt': '2016-04-01T00:00:00.000000', 'updated.gte': '2016-03-01T00:00:00.000000', 'updated.tz': 'Pacific/Auckland',
            'signal.id': 'zVNLr8tHvWQw', 'signal.explain': '2016-04-01'})

    @with_mock_client()
    def test_search_for_account(self, client):
        client.events.for_account('account-id').search(q="query")
        client.request.assert_called_once_with('get', '/v1/accounts/account-id/events/', params={'q': 'query'})

    @with_client()
    @with_mock_responses()
    def test_search(self, client, responses):
        result = client.events.search(q="Foo Fighters", country="AU", limit=10)
        self.assertIsInstance(result, EventResultSet)
        self.assertEqual(result.count, len(list(result.iter_all())))
        self.assertEqual(2, len(responses.calls))

    @with_client()
    @with_mock_responses()
    def test_count(self, client, responses):
        result = client.events.count(active__gte="2015-01-01", active__lte="2015-12-31", within="50km@-27.470784,153.030124")
        self.assertIsInstance(result, Count)
        self.assertEqual(result.count, 2501)

    @with_client()
    @with_mock_responses()
    def test_calendar(self, client, responses):
        result = client.events.calendar(active__gte="2015-12-24", active__lte="2015-12-26", country="NZ", top_events__limit=1, top_events__sort=["rank"], active__tz="Pacific/Auckland")
        self.assertIsInstance(result, CalendarResultSet)
        self.assertEqual(result.count, 60)
        self.assertEqual(3, len(list(result.iter_all())))
        self.assertEqual(1, len(responses.calls))
<|endoftext|>