<commit_before># -*- coding: UTF-8 -*-
import datetime
from microblog import models, settings
from tagging import models as taggingModels
from django.contrib.auth import models as authModels

from django.conf import settings as dsettings
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.template.defaultfilters import slugify

from django.core.paginator import Paginator, InvalidPage, EmptyPage

try:
    import json as simplejson
except ImportError:
    import simplejson
from decorator import decorator

def json(f):
    """
    decoratore da applicare ad una vista per serializzare in json il risultato.
    """
    if dsettings.DEBUG:
        ct = 'text/plain'
        j = lambda d: simplejson.dumps(d, indent = 2)
    else:
        ct = 'application/json'
        j = simplejson.dumps
    def wrapper(func, *args, **kw):
        try:
            result = func(*args, **kw)
        except Exception, e:
            result = j(str(e))
            status = 500
        else:
            if isinstance(result, HttpResponse):
                return result
            else:
                result = j(result)
                status = 200
        return HttpResponse(content = result, content_type = ct, status = status)
    return decorator(wrapper, f)

def category(request, category):
    category = get_object_or_404(models.Category, name = category)
    post_list = _posts_list(request, featured=None).filter(category=category)
    post_list_count = post_list.count()
    posts = _paginate_posts(post_list, request)

    return render_to_response(
        'microblog/category.html',
        {
            'category': category,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def post_list_by_year(request, year, month=None):
    post_list = _posts_list(request).filter(date__year=year)
    if month is not None:
        post_list = post_list.filter(date__month=month)
    post_list_count = post_list.count()
    posts = _paginate_posts(post_list, request)

    return render_to_response(
        'microblog/list_by_year.html',
        {
            'year': year,
            'month': month,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def tag(request, tag):
    tag = get_object_or_404(taggingModels.Tag, name = tag)
    post_list = _posts_list(request, featured=None)
    tagged_posts = taggingModels.TaggedItem.objects.get_by_model(post_list, tag)
    post_list_count = tagged_posts.count()
    posts = _paginate_posts(tagged_posts, request)
    return render_to_response(
        'microblog/tag.html',
        {
            'tag': tag,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def author(request, author):
    user = [
        u for u in authModels.User.objects.all()
        if slugify('%s-%s' % (u.first_name, u.last_name)) == author
    ]
    if not user:
        raise Http404()
    else:
        user = user[0]
    post_list = _posts_list(request).filter(author = user)
    post_list_count = post_list.count()
    posts = _paginate_posts(post_list, request)
    return render_to_response(
        'microblog/author.html',
        {
            'author': user,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def post_list(request):
    posts = _posts_list(request)
    posts = _paginate_posts(posts, request)

    return render_to_response(
        'microblog/post_list.html',
        {
            'posts': posts,
            'featured': models.Post.objects.featured(),
        },
        context_instance = RequestContext(request)
    )

def _paginate_posts(post_list, request):
    if settings.MICROBLOG_POST_LIST_PAGINATION:
        paginator = Paginator(post_list, settings.MICROBLOG_POST_PER_PAGE)
        try:
            page = int(request.GET.get("page", "1"))
        except ValueError:
            page = 1

        try:
            posts = paginator.page(page)
        except (EmptyPage, InvalidPage):
            posts = paginator.page(1)
    else:
        paginator = Paginator(post_list, len(post_list) or 1)
        posts = paginator.page(1)

    return posts

def _posts_list(request, featured=False):
    if settings.MICROBLOG_LANGUAGE_FALLBACK_ON_POST_LIST:
        lang = None
    else:
        lang = request.LANGUAGE_CODE

    post_list = models.Post.objects.published(lang=lang, user=request.user)
    if featured is None:
        return post_list
    return models.Post.objects.filterPostsByFeaturedStatus(post_list, featured=featured)

def _post_detail(request, content):
    return render_to_response(
        'microblog/post_detail.html',
        {
            'post': content.post,
            'content': content
        },
        context_instance = RequestContext(request)
    )

def _trackback_ping(request, content):
    def success():
        x = ('<?xml version="1.0" encoding="utf-8"?>\n'
            '<response><error>0</error></response>')
        return HttpResponse(content = x, content_type = 'text/xml')

    def failure(message=''):
        x = ('<?xml version="1.0" encoding="utf-8"?>\n'
            '<response><error>1</error><message>%s</message></response>') % message
        return HttpResponse(content = x, content_type = 'text/xml', status = 400)

    if request.method != 'POST':
        return failure('only POST methos is supported')

    if not request.POST.get('url'):
        return failure('url argument is mandatory')

    t = {
        'url': request.POST['url'],
        'blog_name': request.POST.get('blog_name', ''),
        'title': request.POST.get('title', ''),
        'excerpt': request.POST.get('excerpt', ''),
    }
    content.new_trackback(**t)
    return success()

@json
def _comment_count(request, content):
    post = content.post
    if settings.MICROBLOG_COMMENT == 'comment':
        from django.contrib import comments
        from django.contrib.contenttypes.models import ContentType
        model = comments.get_model()
        q = model.objects.filter(
            content_type = ContentType.objects.get_for_model(post),
            object_pk = post.id,
            is_public = True
        )
        return q.count()
    else:
        import httplib2
        from urllib import quote
        h = httplib2.Http()
        params = {
            'forum_api_key': settings.MICROBLOG_COMMENT_DISQUS_FORUM_KEY,
            'url': content.get_url(),
        }
        args = '&'.join('%s=%s' % (k,quote(v)) for k, v in params.items())
        url = settings.MICROBLOG_COMMENT_DISQUS_API_URL + 'get_thread_by_url?%s' % args

        resp, page = h.request(url)
        if resp.status != 200:
            return -1
        page = simplejson.loads(page)
        if not page['succeeded']:
            return -1
        elif page['message'] is None:
            return 0
        else:
            return page['message']['num_comments']

def _post404(f):
    def wrapper(*args, **kw):
        try:
            return f(*args, **kw)
        except models.PostContent.DoesNotExist:
            raise Http404()
    return wrapper

if settings.MICROBLOG_URL_STYLE == 'date':
    @_post404
    def post_detail(request, year, month, day, slug):
        return _post_detail(
            request,
            content = models.PostContent.objects.getBySlugAndDate(slug, year, month, day)
        )

    @_post404
    def trackback_ping(request, year, month, day, slug):
        return _trackback_ping(
            request,
            content = models.PostContent.objects.getBySlugAndDate(slug, year, month, day)
        )

    @_post404
    def comment_count(request, year, month, day, slug):
        return _comment_count(
            request,
            content = models.PostContent.objects.getBySlugAndDate(slug, year, month, day)
        )
elif settings.MICROBLOG_URL_STYLE == 'category':
    @_post404
    def post_detail(request, category, slug):
        return _post_detail(
            request,
            content = models.PostContent.objects.getBySlugAndCategory(slug, category)
        )

    @_post404
    def trackback_ping(request, category, slug):
        return _trackback_ping(
            request,
            content = models.PostContent.objects.getBySlugAndCategory(slug, category)
        )

    @_post404
    def comment_count(request, category, slug):
        return _comment_count(
            request,
            content = models.PostContent.objects.getBySlugAndCategory(slug, category)
        )
<commit_msg>rilassato il test su featured<commit_after># -*- coding: UTF-8 -*-
import datetime
from microblog import models, settings
from tagging import models as taggingModels
from django.contrib.auth import models as authModels

from django.conf import settings as dsettings
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.template.defaultfilters import slugify

from django.core.paginator import Paginator, InvalidPage, EmptyPage

try:
    import json as simplejson
except ImportError:
    import simplejson
from decorator import decorator

def json(f):
    """
    decoratore da applicare ad una vista per serializzare in json il risultato.
    """
    if dsettings.DEBUG:
        ct = 'text/plain'
        j = lambda d: simplejson.dumps(d, indent = 2)
    else:
        ct = 'application/json'
        j = simplejson.dumps
    def wrapper(func, *args, **kw):
        try:
            result = func(*args, **kw)
        except Exception, e:
            result = j(str(e))
            status = 500
        else:
            if isinstance(result, HttpResponse):
                return result
            else:
                result = j(result)
                status = 200
        return HttpResponse(content = result, content_type = ct, status = status)
    return decorator(wrapper, f)

def category(request, category):
    category = get_object_or_404(models.Category, name = category)
    post_list = _posts_list(request, featured=None).filter(category=category)
    post_list_count = post_list.count()
    posts = _paginate_posts(post_list, request)

    return render_to_response(
        'microblog/category.html',
        {
            'category': category,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def post_list_by_year(request, year, month=None):
    post_list = _posts_list(request).filter(date__year=year)
    if month is not None:
        post_list = post_list.filter(date__month=month)
    post_list_count = post_list.count()
    posts = _paginate_posts(post_list, request)

    return render_to_response(
        'microblog/list_by_year.html',
        {
            'year': year,
            'month': month,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def tag(request, tag):
    tag = get_object_or_404(taggingModels.Tag, name = tag)
    post_list = _posts_list(request, featured=None)
    tagged_posts = taggingModels.TaggedItem.objects.get_by_model(post_list, tag)
    post_list_count = tagged_posts.count()
    posts = _paginate_posts(tagged_posts, request)
    return render_to_response(
        'microblog/tag.html',
        {
            'tag': tag,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def author(request, author):
    user = [
        u for u in authModels.User.objects.all()
        if slugify('%s-%s' % (u.first_name, u.last_name)) == author
    ]
    if not user:
        raise Http404()
    else:
        user = user[0]
    post_list = _posts_list(request).filter(author = user)
    post_list_count = post_list.count()
    posts = _paginate_posts(post_list, request)
    return render_to_response(
        'microblog/author.html',
        {
            'author': user,
            'posts': posts,
            'post_count': post_list_count,
        },
        context_instance = RequestContext(request)
    )

def post_list(request):
    posts = _posts_list(request)
    posts = _paginate_posts(posts, request)

    return render_to_response(
        'microblog/post_list.html',
        {
            'posts': posts,
            'featured': models.Post.objects.featured(),
        },
        context_instance = RequestContext(request)
    )

def _paginate_posts(post_list, request):
    if settings.MICROBLOG_POST_LIST_PAGINATION:
        paginator = Paginator(post_list, settings.MICROBLOG_POST_PER_PAGE)
        try:
            page = int(request.GET.get("page", "1"))
        except ValueError:
            page = 1

        try:
            posts = paginator.page(page)
        except (EmptyPage, InvalidPage):
            posts = paginator.page(1)
    else:
        paginator = Paginator(post_list, len(post_list) or 1)
        posts = paginator.page(1)

    return posts

def _posts_list(request, featured=False):
    if settings.MICROBLOG_LANGUAGE_FALLBACK_ON_POST_LIST:
        lang = None
    else:
        lang = request.LANGUAGE_CODE

    post_list = models.Post.objects.published(lang=lang, user=request.user)
    if not featured:
        return post_list
    return models.Post.objects.filterPostsByFeaturedStatus(post_list, featured=featured)

def _post_detail(request, content):
    return render_to_response(
        'microblog/post_detail.html',
        {
            'post': content.post,
            'content': content
        },
        context_instance = RequestContext(request)
    )

def _trackback_ping(request, content):
    def success():
        x = ('<?xml version="1.0" encoding="utf-8"?>\n'
            '<response><error>0</error></response>')
        return HttpResponse(content = x, content_type = 'text/xml')

    def failure(message=''):
        x = ('<?xml version="1.0" encoding="utf-8"?>\n'
            '<response><error>1</error><message>%s</message></response>') % message
        return HttpResponse(content = x, content_type = 'text/xml', status = 400)

    if request.method != 'POST':
        return failure('only POST methos is supported')

    if not request.POST.get('url'):
        return failure('url argument is mandatory')

    t = {
        'url': request.POST['url'],
        'blog_name': request.POST.get('blog_name', ''),
        'title': request.POST.get('title', ''),
        'excerpt': request.POST.get('excerpt', ''),
    }
    content.new_trackback(**t)
    return success()

@json
def _comment_count(request, content):
    post = content.post
    if settings.MICROBLOG_COMMENT == 'comment':
        from django.contrib import comments
        from django.contrib.contenttypes.models import ContentType
        model = comments.get_model()
        q = model.objects.filter(
            content_type = ContentType.objects.get_for_model(post),
            object_pk = post.id,
            is_public = True
        )
        return q.count()
    else:
        import httplib2
        from urllib import quote
        h = httplib2.Http()
        params = {
            'forum_api_key': settings.MICROBLOG_COMMENT_DISQUS_FORUM_KEY,
            'url': content.get_url(),
        }
        args = '&'.join('%s=%s' % (k,quote(v)) for k, v in params.items())
        url = settings.MICROBLOG_COMMENT_DISQUS_API_URL + 'get_thread_by_url?%s' % args

        resp, page = h.request(url)
        if resp.status != 200:
            return -1
        page = simplejson.loads(page)
        if not page['succeeded']:
            return -1
        elif page['message'] is None:
            return 0
        else:
            return page['message']['num_comments']

def _post404(f):
    def wrapper(*args, **kw):
        try:
            return f(*args, **kw)
        except models.PostContent.DoesNotExist:
            raise Http404()
    return wrapper

if settings.MICROBLOG_URL_STYLE == 'date':
    @_post404
    def post_detail(request, year, month, day, slug):
        return _post_detail(
            request,
            content = models.PostContent.objects.getBySlugAndDate(slug, year, month, day)
        )

    @_post404
    def trackback_ping(request, year, month, day, slug):
        return _trackback_ping(
            request,
            content = models.PostContent.objects.getBySlugAndDate(slug, year, month, day)
        )

    @_post404
    def comment_count(request, year, month, day, slug):
        return _comment_count(
            request,
            content = models.PostContent.objects.getBySlugAndDate(slug, year, month, day)
        )
elif settings.MICROBLOG_URL_STYLE == 'category':
    @_post404
    def post_detail(request, category, slug):
        return _post_detail(
            request,
            content = models.PostContent.objects.getBySlugAndCategory(slug, category)
        )

    @_post404
    def trackback_ping(request, category, slug):
        return _trackback_ping(
            request,
            content = models.PostContent.objects.getBySlugAndCategory(slug, category)
        )

    @_post404
    def comment_count(request, category, slug):
        return _comment_count(
            request,
            content = models.PostContent.objects.getBySlugAndCategory(slug, category)
        )
<|endoftext|>


<commit_before># Copyright 2015 NEC Corporation.  All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from tempest_lib.common import rest_client
from tempest_lib import exceptions as lib_exceptions

from tempest import config
from tempest import exceptions

CONF = config.CONF

class ServiceClient(rest_client.RestClient):

    def __init__(self, auth_provider, service, region,
                 endpoint_type=None, build_interval=None, build_timeout=None,
                 disable_ssl_certificate_validation=None, ca_certs=None,
                 trace_requests=None):

        # TODO(oomichi): This params setting should be removed after all
        # service clients pass these values, and we can make ServiceClient
        # free from CONF values.
        dscv = (disable_ssl_certificate_validation or
                CONF.identity.disable_ssl_certificate_validation)
        params = {
            'disable_ssl_certificate_validation': dscv,
            'ca_certs': ca_certs or CONF.identity.ca_certificates_file,
            'trace_requests': trace_requests or CONF.debug.trace_requests
        }

        if endpoint_type is not None:
            params.update({'endpoint_type': endpoint_type})
        if build_interval is not None:
            params.update({'build_interval': build_interval})
        if build_timeout is not None:
            params.update({'build_timeout': build_timeout})
        super(ServiceClient, self).__init__(auth_provider, service, region,
                                            **params)

    def request(self, method, url, extra_headers=False, headers=None,
                body=None):
        # TODO(oomichi): This translation is just for avoiding a single
        # huge patch to migrate rest_client module to tempest-lib.
        # Ideally(in the future), we need to remove this translation and
        # replace each API tests with tempest-lib's exceptions.
        try:
            return super(ServiceClient, self).request(
                method, url,
                extra_headers=extra_headers,
                headers=headers, body=body)
        except lib_exceptions.Unauthorized as ex:
            raise exceptions.Unauthorized(ex)
        except lib_exceptions.NotFound as ex:
            raise exceptions.NotFound(ex)
        except lib_exceptions.BadRequest as ex:
            raise exceptions.BadRequest(ex)
        except lib_exceptions.Conflict as ex:
            raise exceptions.Conflict(ex)
        except lib_exceptions.OverLimit as ex:
            raise exceptions.OverLimit(ex)
        except lib_exceptions.RateLimitExceeded as ex:
            raise exceptions.RateLimitExceeded(ex)
        except lib_exceptions.InvalidContentType as ex:
            raise exceptions.InvalidContentType(ex)
        except lib_exceptions.UnprocessableEntity as ex:
            raise exceptions.UnprocessableEntity(ex)
        except lib_exceptions.InvalidHTTPResponseBody as ex:
            raise exceptions.InvalidHTTPResponseBody(ex)
        except lib_exceptions.NotImplemented as ex:
            raise exceptions.NotImplemented(ex)
        except lib_exceptions.ServerFault as ex:
            raise exceptions.ServerFault(ex)
        except lib_exceptions.UnexpectedResponseCode as ex:
            raise exceptions.UnexpectedResponseCode(ex)

class ResponseBody(dict):
    """Class that wraps an http response and dict body into a single value.

    Callers that receive this object will normally use it as a dict but
    can extract the response if needed.
    """

    def __init__(self, response, body=None):
        body_data = body or {}
        self.update(body_data)
        self.response = response

    def __str__(self):
        body = super.__str__(self)
        return "response: %s\nBody: %s" % (self.response, body)

class ResponseBodyList(list):
    """Class that wraps an http response and list body into a single value.

    Callers that receive this object will normally use it as a list but
    can extract the response if needed.
    """

    def __init__(self, response, body=None):
        body_data = body or []
        self.extend(body_data)
        self.response = response

    def __str__(self):
        body = super.__str__(self)
        return "response: %s\nBody: %s" % (self.response, body)
<commit_msg>Add Forbidden translation<commit_after># Copyright 2015 NEC Corporation.  All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from tempest_lib.common import rest_client
from tempest_lib import exceptions as lib_exceptions

from tempest import config
from tempest import exceptions

CONF = config.CONF

class ServiceClient(rest_client.RestClient):

    def __init__(self, auth_provider, service, region,
                 endpoint_type=None, build_interval=None, build_timeout=None,
                 disable_ssl_certificate_validation=None, ca_certs=None,
                 trace_requests=None):

        # TODO(oomichi): This params setting should be removed after all
        # service clients pass these values, and we can make ServiceClient
        # free from CONF values.
        dscv = (disable_ssl_certificate_validation or
                CONF.identity.disable_ssl_certificate_validation)
        params = {
            'disable_ssl_certificate_validation': dscv,
            'ca_certs': ca_certs or CONF.identity.ca_certificates_file,
            'trace_requests': trace_requests or CONF.debug.trace_requests
        }

        if endpoint_type is not None:
            params.update({'endpoint_type': endpoint_type})
        if build_interval is not None:
            params.update({'build_interval': build_interval})
        if build_timeout is not None:
            params.update({'build_timeout': build_timeout})
        super(ServiceClient, self).__init__(auth_provider, service, region,
                                            **params)

    def request(self, method, url, extra_headers=False, headers=None,
                body=None):
        # TODO(oomichi): This translation is just for avoiding a single
        # huge patch to migrate rest_client module to tempest-lib.
        # Ideally(in the future), we need to remove this translation and
        # replace each API tests with tempest-lib's exceptions.
        try:
            return super(ServiceClient, self).request(
                method, url,
                extra_headers=extra_headers,
                headers=headers, body=body)
        except lib_exceptions.Unauthorized as ex:
            raise exceptions.Unauthorized(ex)
        except lib_exceptions.NotFound as ex:
            raise exceptions.NotFound(ex)
        except lib_exceptions.BadRequest as ex:
            raise exceptions.BadRequest(ex)
        except lib_exceptions.Conflict as ex:
            raise exceptions.Conflict(ex)
        except lib_exceptions.OverLimit as ex:
            raise exceptions.OverLimit(ex)
        except lib_exceptions.RateLimitExceeded as ex:
            raise exceptions.RateLimitExceeded(ex)
        except lib_exceptions.InvalidContentType as ex:
            raise exceptions.InvalidContentType(ex)
        except lib_exceptions.UnprocessableEntity as ex:
            raise exceptions.UnprocessableEntity(ex)
        except lib_exceptions.InvalidHTTPResponseBody as ex:
            raise exceptions.InvalidHTTPResponseBody(ex)
        except lib_exceptions.NotImplemented as ex:
            raise exceptions.NotImplemented(ex)
        except lib_exceptions.ServerFault as ex:
            raise exceptions.ServerFault(ex)
        except lib_exceptions.UnexpectedResponseCode as ex:
            raise exceptions.UnexpectedResponseCode(ex)
        # TODO(oomichi): This is just a workaround for failing gate tests
        # when separating Forbidden from Unauthorized in tempest-lib.
        # We will need to remove this translation and replace negative tests
        # with lib_exceptions.Forbidden in the future.
        except lib_exceptions.Forbidden as ex:
            raise exceptions.Unauthorized(ex)

class ResponseBody(dict):
    """Class that wraps an http response and dict body into a single value.

    Callers that receive this object will normally use it as a dict but
    can extract the response if needed.
    """

    def __init__(self, response, body=None):
        body_data = body or {}
        self.update(body_data)
        self.response = response

    def __str__(self):
        body = super.__str__(self)
        return "response: %s\nBody: %s" % (self.response, body)

class ResponseBodyList(list):
    """Class that wraps an http response and list body into a single value.

    Callers that receive this object will normally use it as a list but
    can extract the response if needed.
    """

    def __init__(self, response, body=None):
        body_data = body or []
        self.extend(body_data)
        self.response = response

    def __str__(self):
        body = super.__str__(self)
        return "response: %s\nBody: %s" % (self.response, body)
<|endoftext|>


<commit_before>from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from rosetta.conf import settings as rosetta_settings
import hashlib
import time
import six
import django

try:
    from django.core.cache import caches
    cache = caches[rosetta_settings.ROSETTA_CACHE_NAME]
except ImportError:
    from django.core.cache import get_cache
    cache = get_cache(rosetta_settings.ROSETTA_CACHE_NAME)

try:
    import importlib
except ImportError:
    from django.utils import importlib

class BaseRosettaStorage(object):
    def __init__(self, request):
        self.request = request

    def get(self, key, default=None):
        raise NotImplementedError

    def set(self, key, val):
        raise NotImplementedError

    def has(self, key):
        raise NotImplementedError

    def delete(self, key):
        raise NotImplementedError

class DummyRosettaStorage(BaseRosettaStorage):
    def get(self, key, default=None):
        return default

    def set(self, key, val):
        pass

    def has(self, key):
        return False

    def delete(self, key):
        pass

class SessionRosettaStorage(BaseRosettaStorage):
    def __init__(self, request):
        super(SessionRosettaStorage, self).__init__(request)

        if 'signed_cookies' in settings.SESSION_ENGINE and django.VERSION[1] >= 6 and 'pickle' not in settings.SESSION_SERIALIZER.lower():
            raise ImproperlyConfigured("Sorry, but django-rosetta doesn't support the `signed_cookies` SESSION_ENGINE in Django >= 1.6, because rosetta specific session files cannot be serialized.")

    def get(self, key, default=None):
        if key in self.request.session:
            return self.request.session[key]
        return default

    def set(self, key, val):
        self.request.session[key] = val

    def has(self, key):
        return key in self.request.session

    def delete(self, key):
        del(self.request.session[key])

class CacheRosettaStorage(BaseRosettaStorage):
    # unlike the session storage backend, cache is shared among all users
    # so we need to per-user key prefix, which we store in the session
    def __init__(self, request):
        super(CacheRosettaStorage, self).__init__(request)

        if 'rosetta_cache_storage_key_prefix' in self.request.session:
            self._key_prefix = self.request.session['rosetta_cache_storage_key_prefix']
        else:
            self._key_prefix = hashlib.new('sha1', six.text_type(time.time()).encode('utf8')).hexdigest()
            self.request.session['rosetta_cache_storage_key_prefix'] = self._key_prefix

        if self.request.session['rosetta_cache_storage_key_prefix'] != self._key_prefix:
            raise ImproperlyConfigured("You can't use the CacheRosettaStorage because your Django Session storage doesn't seem to be working. The CacheRosettaStorage relies on the Django Session storage to avoid conflicts.")

        # Make sure we're not using DummyCache
        if 'dummycache' in settings.CACHES[rosetta_settings.ROSETTA_CACHE_NAME]['BACKEND'].lower():
            raise ImproperlyConfigured("You can't use the CacheRosettaStorage if your cache isn't correctly set up (you are using the DummyCache cache backend).")

        # Make sure the actually actually works
        try:
            self.set('rosetta_cache_test', 'rosetta')
            if not self.get('rosetta_cache_test') == 'rosetta':
                raise ImproperlyConfigured("You can't use the CacheRosettaStorage if your cache isn't correctly set up, please double check your Django DATABASES setting and that the cache server is responding.")
        finally:
            self.delete('rosetta_cache_test')

    def get(self, key, default=None):
        #print ('get', self._key_prefix + key)
        return cache.get(self._key_prefix + key, default)

    def set(self, key, val):
        #print ('set', self._key_prefix + key)
        cache.set(self._key_prefix + key, val, 86400)

    def has(self, key):
        #print ('has', self._key_prefix + key)
        return (self._key_prefix + key) in cache

    def delete(self, key):
        #print ('del', self._key_prefix + key)
        cache.delete(self._key_prefix + key)

def get_storage(request):
    from rosetta.conf import settings
    storage_module, storage_class = settings.STORAGE_CLASS.rsplit('.', 1)
    storage_module = importlib.import_module(storage_module)
    return getattr(storage_module, storage_class)(request)
<commit_msg>Fixup comment<commit_after>from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from rosetta.conf import settings as rosetta_settings
import hashlib
import time
import six
import django

try:
    from django.core.cache import caches
    cache = caches[rosetta_settings.ROSETTA_CACHE_NAME]
except ImportError:
    from django.core.cache import get_cache
    cache = get_cache(rosetta_settings.ROSETTA_CACHE_NAME)

try:
    import importlib
except ImportError:
    from django.utils import importlib

class BaseRosettaStorage(object):
    def __init__(self, request):
        self.request = request

    def get(self, key, default=None):
        raise NotImplementedError

    def set(self, key, val):
        raise NotImplementedError

    def has(self, key):
        raise NotImplementedError

    def delete(self, key):
        raise NotImplementedError

class DummyRosettaStorage(BaseRosettaStorage):
    def get(self, key, default=None):
        return default

    def set(self, key, val):
        pass

    def has(self, key):
        return False

    def delete(self, key):
        pass

class SessionRosettaStorage(BaseRosettaStorage):
    def __init__(self, request):
        super(SessionRosettaStorage, self).__init__(request)

        if 'signed_cookies' in settings.SESSION_ENGINE and django.VERSION[1] >= 6 and 'pickle' not in settings.SESSION_SERIALIZER.lower():
            raise ImproperlyConfigured("Sorry, but django-rosetta doesn't support the `signed_cookies` SESSION_ENGINE in Django >= 1.6, because rosetta specific session files cannot be serialized.")

    def get(self, key, default=None):
        if key in self.request.session:
            return self.request.session[key]
        return default

    def set(self, key, val):
        self.request.session[key] = val

    def has(self, key):
        return key in self.request.session

    def delete(self, key):
        del(self.request.session[key])

class CacheRosettaStorage(BaseRosettaStorage):
    # unlike the session storage backend, cache is shared among all users
    # so we need to per-user key prefix, which we store in the session
    def __init__(self, request):
        super(CacheRosettaStorage, self).__init__(request)

        if 'rosetta_cache_storage_key_prefix' in self.request.session:
            self._key_prefix = self.request.session['rosetta_cache_storage_key_prefix']
        else:
            self._key_prefix = hashlib.new('sha1', six.text_type(time.time()).encode('utf8')).hexdigest()
            self.request.session['rosetta_cache_storage_key_prefix'] = self._key_prefix

        if self.request.session['rosetta_cache_storage_key_prefix'] != self._key_prefix:
            raise ImproperlyConfigured("You can't use the CacheRosettaStorage because your Django Session storage doesn't seem to be working. The CacheRosettaStorage relies on the Django Session storage to avoid conflicts.")

        # Make sure we're not using DummyCache
        if 'dummycache' in settings.CACHES[rosetta_settings.ROSETTA_CACHE_NAME]['BACKEND'].lower():
            raise ImproperlyConfigured("You can't use the CacheRosettaStorage if your cache isn't correctly set up (you are using the DummyCache cache backend).")

        # Make sure the cache actually works
        try:
            self.set('rosetta_cache_test', 'rosetta')
            if not self.get('rosetta_cache_test') == 'rosetta':
                raise ImproperlyConfigured("You can't use the CacheRosettaStorage if your cache isn't correctly set up, please double check your Django DATABASES setting and that the cache server is responding.")
        finally:
            self.delete('rosetta_cache_test')

    def get(self, key, default=None):
        #print ('get', self._key_prefix + key)
        return cache.get(self._key_prefix + key, default)

    def set(self, key, val):
        #print ('set', self._key_prefix + key)
        cache.set(self._key_prefix + key, val, 86400)

    def has(self, key):
        #print ('has', self._key_prefix + key)
        return (self._key_prefix + key) in cache

    def delete(self, key):
        #print ('del', self._key_prefix + key)
        cache.delete(self._key_prefix + key)

def get_storage(request):
    from rosetta.conf import settings
    storage_module, storage_class = settings.STORAGE_CLASS.rsplit('.', 1)
    storage_module = importlib.import_module(storage_module)
    return getattr(storage_module, storage_class)(request)
<|endoftext|>


<commit_before>from abc import ABCMeta, abstractmethod
from collections import Counter
from . import Request, Disclosure
__author__ = 'TimeWz667'

DefaultScheduler = "PriorityQueue"

class AbsScheduler(metaclass=ABCMeta):
    def __init__(self, location):
        self.Location = location
        self.OwnTime = float('inf')
        self.GloTime = float('inf')
        self.Upcoming = set()
        self.AtomRequests = dict()
        self.Requests = list()
        self.Disclosures = list()
        self.NumAtoms = 0
        self.Counter = Counter()

    def add_atom(self, atom):
        self.join_scheduler(atom)
        atom.set_scheduler(self)
        self.NumAtoms += 1

    def remove_atom(self, atom):
        atom.drop_next()
        atom.detach_scheduler()
        self.leave_scheduler(atom)
        self.pop_from_upcoming(atom)
        self.NumAtoms -= 1

    @abstractmethod
    def join_scheduler(self, atom):
        pass

    @abstractmethod
    def leave_scheduler(self, atom):
        pass

    @abstractmethod
    def pop_from_upcoming(self, atom):
        self.Upcoming.remove(atom)
        if not self.Upcoming:
            self.OwnTime = float('inf')

    @abstractmethod
    def await(self, atom):
        pass

    def add_scheduler_atom(self, atom):
        self.add_atom(atom)
        self.await(atom)

    @abstractmethod
    def reschedule_all(self):
        pass

    @abstractmethod
    def reschedule_waiting(self):
        pass

    @abstractmethod
    def find_upcoming_atoms(self):
        pass

    def extract_current_request(self):
        for atom in self.Upcoming:
            event = atom.Next
            self.AtomRequests[atom] = Request(event, atom.Name, self.Location)

    def check_current_requests(self):
        if self.NumAtoms <= 0:
            return

        if not self.Upcoming or not (self.Upcoming > self.AtomRequests.keys()):
            self.find_upcoming_atoms()
            self.AtomRequests = dict()

        if not self.AtomRequests:
            self.extract_current_request()

    def find_next(self):
        self.reschedule_waiting()
        self.check_current_requests()
        self.Requests = list(self.AtomRequests.values())
        self.GloTime = min(self.OwnTime, self.GloTime)

    def is_executable(self):
        return self.GloTime is self.OwnTime

    def up_scale_requests(self, loc):
        return [req.up_scale(loc) for req in self.Requests]

    def append_lower_schedule(self, lower):
        if not lower.Requests:
            return

        ti = lower.GloTime
        if ti < self.GloTime:
            self.Requests = lower.up_scale_requests(self.Location)
            self.GloTime = ti
        elif ti == self.GloTime:
            self.Requests += lower.up_scale_requests(self.Location)
        else:
            return

    def fetch_requests(self, rs):
        # rs_out = [req for req in self.Requests if req not in rs]
        # for req in rs_out:
        #     req.Event.cancel()
        self.Requests = list(rs)
        self.Counter['Requests'] += len(rs)

    def append_request_from_source(self, event, who):
        # todo validate
        if event.Time < self.Time:
            self.Requests = [Request(event, who, self.Location)]
            self.Time = event.Time
        elif event.Time == self.Time:
            self.Requests.append(Request(event, who, self.Location))
        else:
            return

    def append_disclosure(self, dss: Disclosure):
        """
        Append a disclosure
        :param dss: message to be exposed
        """
        self.Disclosures.append(dss)

    def append_disclosure_from_source(self, msg, who, **kwargs):
        dss = Disclosure(msg, who, self.Location, **kwargs)
        self.append_disclosure(dss)

    def pop_lower_requests(self):
        gp = groupby(self.Requests, lambda x: x.reached())
        lower, current = list(), list()
        for k, g in gp:
            if k:
                current += list(g)
            else:
                lower += [req.down_scale() for req in g]

        if lower:
            pop = {k: [req for _, req in g] for k, g in groupby(lower, lambda x: x[1].Group)}
        else:
            pop = dict()

        self.Requests = current

        return pop

<commit_msg>write scheduler<commit_after>from abc import ABCMeta, abstractmethod
from collections import Counter
from . import Request, Disclosure
__author__ = 'TimeWz667'
__all__ = ['get_scheduler', '']

DefaultScheduler = "PriorityQueue"

def get_scheduler(loc, tp=None):
    tp = tp if tp else DefaultScheduler
    if tp == "PriorityQueue":
        return None
    elif tp == "Looping":
        return None

class AbsScheduler(metaclass=ABCMeta):
    def __init__(self, location):
        self.Location = location
        self.OwnTime = float('inf')
        self.GloTime = float('inf')
        self.Upcoming = set()
        self.AtomRequests = dict()
        self.Requests = list()
        self.Disclosures = list()
        self.NumAtoms = 0
        self.Counter = Counter()

    def __len__(self):
        return len(self.Requests) + len(self.Disclosures)

    def add_atom(self, atom):
        self.join_scheduler(atom)
        atom.set_scheduler(self)
        self.NumAtoms += 1

    def remove_atom(self, atom):
        atom.drop_next()
        atom.detach_scheduler()
        self.leave_scheduler(atom)
        self.pop_from_upcoming(atom)
        self.NumAtoms -= 1

    @abstractmethod
    def join_scheduler(self, atom):
        pass

    @abstractmethod
    def leave_scheduler(self, atom):
        pass

    def pop_from_upcoming(self, atom):
        self.Upcoming.remove(atom)
        if not self.Upcoming:
            self.OwnTime = float('inf')

    @abstractmethod
    def await(self, atom):
        pass

    def add_scheduler_atom(self, atom):
        self.add_atom(atom)
        self.await(atom)

    @abstractmethod
    def reschedule_all(self):
        pass

    @abstractmethod
    def reschedule_waiting(self):
        pass

    @abstractmethod
    def find_upcoming_atoms(self):
        pass

    def extract_current_request(self):
        for atom in self.Upcoming:
            event = atom.Next
            self.AtomRequests[atom] = Request(event, atom.Name, self.Location)

    def check_current_requests(self):
        if self.NumAtoms <= 0:
            return

        if not self.Upcoming or not (self.Upcoming > self.AtomRequests.keys()):
            self.find_upcoming_atoms()
            self.AtomRequests = dict()

        if not self.AtomRequests:
            self.extract_current_request()

    def find_next(self):
        self.reschedule_waiting()
        self.check_current_requests()
        self.Requests = list(self.AtomRequests.values())
        self.GloTime = min(self.OwnTime, self.GloTime)

    def is_executable(self):
        return self.GloTime is self.OwnTime

    def up_scale_requests(self, loc):
        return [req.up_scale(loc) for req in self.Requests]

    def append_lower_schedule(self, lower):
        if not lower.Requests:
            return

        ti = lower.GloTime
        if ti < self.GloTime:
            self.Requests = lower.up_scale_requests(self.Location)
            self.GloTime = ti
        elif ti == self.GloTime:
            self.Requests += lower.up_scale_requests(self.Location)
        else:
            return

    def fetch_requests(self, rs):
        # rs_out = [req for req in self.Requests if req not in rs]
        # for req in rs_out:
        #     req.Event.cancel()
        self.Requests = list(rs)
        self.Counter['Requests'] += len(rs)

    def append_request_from_source(self, event, who):
        # todo validate
        if event.Time < self.GloTime:
            self.Requests = [Request(event, who, self.Location)]
            self.GloTime = event.Time
        elif event.Time == self.GloTime:
            self.Requests.append(Request(event, who, self.Location))
        else:
            return

    def pop_lower_requests(self):
        current = list()
        lower = dict()

        for req in self.Requests:
            if req.reached():
                continue
            try:
                _, req = req.down_scale()
                lower[req.Group].append(req)
            except KeyError:
                lower[req.Group] = [req]

        self.Requests = current

        return lower

    def append_disclosure(self, dss: Disclosure):
        """
        Append a disclosure
        :param dss: message to be exposed
        """
        self.Disclosures.append(dss)

    def append_disclosure_from_source(self, msg, who, **kwargs):
        dss = Disclosure(msg, who, self.Location, **kwargs)
        self.append_disclosure(dss)

    def pop_disclosures(self):
        ds, self.Disclosures = self.Disclosures, list()
        self.Counter['Disclosure'] + len(ds)
        return ds

    def execution_completed(self):
        self.Requests.clear()
        self.AtomRequests = dict()
        self.Upcoming.clear()
        self.OwnTime = float('inf')

    def cycle_completed(self):
        """
        To finish a cycle without erase un-executed requests
        """
        self.Requests.clear()
        self.Disclosures.clear()
        self.GloTime = self.OwnTime

    def __repr__(self):
        return 'Scheduler{Location={}, #Atoms={}, #Requests={}, #Disclosure={}, Time={}'.format(
            self.Location, self.NumAtoms, len(self.Requests), len(self.Disclosures), self.OwnTime
        )

class LoopingScheduler(AbsScheduler):
    def __init__(self, location):
        AbsScheduler.__init__(self, location)
        self.Atoms = list()
        self.Waiting = set()

    def join_scheduler(self, atom):
        self.Atoms.append(atom)
        self.Waiting.add(atom)

    def leave_scheduler(self, atom):
        self.Atoms.remove(atom)
        self.Waiting.remove(atom)

    def await(self, atom):
        self.Waiting.add(atom)
        self.pop_from_upcoming(atom)

    def reschedule_all(self):
        self.Upcoming.clear()
        self.OwnTime = float('inf')
        self.reschedule_set(self.Atoms)
        self.Waiting.clear()

    def reschedule_waiting(self):
        if self.Upcoming:
            self.reschedule_set(self.Waiting)
            self.Waiting.clear()
        else:
            self.reschedule_all()

    def find_upcoming_atoms(self):
        if not self.Upcoming:
            self.reschedule_all()

    def reschedule_set(self, atoms):
        for atom in atoms:
            event = atom.Next
            if event.Time < self.OwnTime:
                self.Upcoming.clear()
                self.Upcoming.add(atom)
                self.OwnTime = event.Time
            elif event.Time == self.OwnTime:
                self.Upcoming.add(atom)

        self.Counter['Requeuing'] += len(atoms)

class PriorityQueueScheduler(AbsScheduler):
    CAP = 10
    def __init__(self, location):
        AbsScheduler.__init__(self, location)

    def leave_scheduler(self, atom):
        pass

    def await(self, atom):
        pass

    def reschedule_all(self):
        pass

    def reschedule_waiting(self):
        pass

    def find_upcoming_atoms(self):
        pass

    def join_scheduler(self, atom):
        pass<|endoftext|>


<commit_before>"Label pages."

from __future__ import print_function

import logging
from collections import OrderedDict as OD

import tornado.web

from . import constants
from . import settings
from . import utils
from .requesthandler import RequestHandler
from .saver import Saver, SaverError
from .account import AccountSaver
from .publication import PublicationSaver

class LabelSaver(Saver):
    doctype = constants.LABEL

    def set_value(self, value):
        self['value'] = value
        self['normalized_value'] = utils.to_ascii(value).lower()

    def check_value(self, value):
        "Value must be unique."
        try:
            label = utils.get_label(self.db, value)
            if label['_id'] == self.doc.get('_id'): return
        except KeyError:
            pass
        else:
            raise ValueError("label '%s' is not unique" % value)

class Label(RequestHandler):
    "Label page."

    def get(self, identifier):
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('home', error=str(msg))
            return
        accounts = self.get_docs('account/label', key=label['value'])
        publications = self.get_docs('publication/label', key=label['value'])
        publications.sort(key=lambda i: i['published'], reverse=True)
        self.render('label.html',
                    label=label,
                    accounts=accounts,
                    publications=publications)

    @tornado.web.authenticated
    def post(self, identifier):
        if self.get_argument('_http_method', None) == 'delete':
            self.delete(identifier)
            return
        raise tornado.web.HTTPError(
            405, reason='Internal problem; POST only allowed for DELETE.')

    @tornado.web.authenticated
    def delete(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        value = label['value']
        self.delete_entity(label)
        for account in self.get_docs('account/label', key=value):
            with AccountSaver(account, rqh=self) as saver:
                labels = set(account['labels'])
                labels.discard(value)
                saver['labels'] = sorted(labels)
        for publication in self.get_docs('publication/label', key=value):
            with PublicationSaver(publication, rqh=self) as saver:
                labels = set(publication['labels'])
                labels.discard(value)
                saver['labels'] = sorted(labels)
        self.see_other('labels')

class LabelJson(Label):
    "Label JSON data."

    def render(self, template, **kwargs):
        self.write(self.get_label_json(kwargs['label'],
                                       full=True,
                                       publications=kwargs['publications'],
                                       accounts=kwargs['accounts']))

class LabelsList(RequestHandler):
    "Labels list page."

    def get(self):
        labels = self.get_docs('label/value')
        self.render('labels.html', labels=labels)

class LabelsTable(RequestHandler):
    "Labels table page."

    def get(self):
        labels = self.get_docs('label/value')
        if self.is_curator():
            accounts = dict([(l['value'], []) for l in labels])
            for account in self.get_docs('account/email'):
                for label in account['labels']:
                    accounts.setdefault(label, []).append(account['email'])
            for label in labels:
                label['accounts'] = sorted(accounts.get(label['value'], []))
        view = self.db.view('publication/label', group=True)
        counts = dict([(r.key, r.value) for r in view])
        for label in labels:
            label['count'] = counts.get(label['value'], 0)
        self.render('labels_table.html', labels=labels)

class LabelsJson(LabelsTable):
    "JSON for labels."

    def render(self, template, **kwargs):
        URL = self.absolute_reverse_url
        labels = kwargs['labels']
        result = OD()
        result['entity'] = 'labels'
        result['timestamp'] = utils.timestamp()
        result['links'] = links = OD()
        links['self'] = {'href': URL('labels_json')}
        links['display'] = {'href': URL('labels')}
        result['labels_count'] = len(labels)
        result['labels'] = [self.get_label_json(l) for l in labels]
        self.write(result)

class LabelAdd(RequestHandler):
    "Label addition page."

    def get(self):
        self.check_admin()
        self.render('label_add.html')

    def post(self):
        self.check_admin()
        try:
            value = self.get_argument('value')
        except tornado.web.MissingArgumentError:
            self.see_other('label_add', error='no label provided')
            return
        try:
            with LabelSaver(rqh=self) as saver:
                saver.set_value(value)
            label = saver.doc
        except ValueError, msg:
            self.set_error_flash(str(msg))
            self.see_other('label_add')
            return
        self.see_other('label', label['value'])

class LabelEdit(RequestHandler):
    "Label edit page."

    def get(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        self.render('label_edit.html', label=label)

    def post(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        old_value = label['value']
        new_value = self.get_argument('value')
        try:
            with LabelSaver(label, rqh=self) as saver:
                saver.check_revision()
                saver.set_value(new_value)
                saver['description'] = self.get_argument('description', None)
        except SaverError:
            self.set_error_flash(utils.REV_ERROR)
            self.see_other('label', label['value'])
            return
        if new_value != old_value:
            for account in self.get_docs('account/label', key=old_value):
                with AccountSaver(account, rqh=self) as saver:
                    labels = set(account['labels'])
                    labels.discard(old_value)
                    labels.add(new_value)
                    saver['labels'] = sorted(labels)
            for publ in self.get_docs('publication/label', key=old_value):
                with PublicationSaver(publ, rqh=self) as saver:
                    labels = set(publ['labels'])
                    labels.discard(old_value)
                    labels.add(new_value)
                    saver['labels'] = sorted(labels)
        self.see_other('label', label['value'])

class LabelMerge(RequestHandler):
    "Merge label into another."

    def get(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        self.render('label_merge.html',
                    label=label,
                    labels=self.get_docs('label/value'))

    def post(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        try:
            merge = self.get_label(self.get_argument('merge'))
        except tornado.web.MissingArgumentError:
            self.set_error_flash('no merge label provided')
            self.see_other('labels')
            return
        except KeyError, msg:
            self.set_error_flash(str(msg))
            self.see_other('labels')
            return
        old_label = label['value']
        new_label = merge['value']
        self.delete_entity(label)
        for account in self.get_docs('account/label', key=old_label):
            with AccountSaver(account, rqh=self) as saver:
                labels = set(account['labels'])
                labels.discard(old_label)
                labels.add(new_label)
                saver['labels'] = sorted(labels)
        for publication in self.get_docs('publication/label', key=old_label):
            with PublicationSaver(publication, rqh=self) as saver:
                labels = set(publication['labels'])
                labels.discard(old_label)
                labels.add(new_label)
                saver['labels'] = sorted(labels)
        self.see_other('label', new_label)
<commit_msg>Fixed label edit issue. Closes #144.<commit_after>"Label pages."

from __future__ import print_function

import logging
from collections import OrderedDict as OD

import tornado.web

from . import constants
from . import settings
from . import utils
from .requesthandler import RequestHandler
from .saver import Saver, SaverError
from .account import AccountSaver
from .publication import PublicationSaver

class LabelSaver(Saver):
    doctype = constants.LABEL

    def set_value(self, value):
        self['value'] = value
        self['normalized_value'] = utils.to_ascii(value).lower()

    def check_value(self, value):
        "Value must be unique."
        try:
            label = utils.get_label(self.db, value)
            if label['_id'] == self.doc.get('_id'): return
        except KeyError:
            pass
        else:
            raise ValueError("label '%s' is not unique" % value)

class Label(RequestHandler):
    "Label page."

    def get(self, identifier):
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('home', error=str(msg))
            return
        accounts = self.get_docs('account/label', key=label['value'])
        publications = self.get_docs('publication/label', key=label['value'])
        publications.sort(key=lambda i: i['published'], reverse=True)
        self.render('label.html',
                    label=label,
                    accounts=accounts,
                    publications=publications)

    @tornado.web.authenticated
    def post(self, identifier):
        if self.get_argument('_http_method', None) == 'delete':
            self.delete(identifier)
            return
        raise tornado.web.HTTPError(
            405, reason='Internal problem; POST only allowed for DELETE.')

    @tornado.web.authenticated
    def delete(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        value = label['value']
        self.delete_entity(label)
        for account in self.get_docs('account/label', key=value):
            with AccountSaver(account, rqh=self) as saver:
                labels = set(account['labels'])
                labels.discard(value)
                saver['labels'] = sorted(labels)
        for publication in self.get_docs('publication/label', key=value):
            with PublicationSaver(publication, rqh=self) as saver:
                labels = set(publication['labels'])
                labels.discard(value)
                saver['labels'] = sorted(labels)
        self.see_other('labels')

class LabelJson(Label):
    "Label JSON data."

    def render(self, template, **kwargs):
        self.write(self.get_label_json(kwargs['label'],
                                       full=True,
                                       publications=kwargs['publications'],
                                       accounts=kwargs['accounts']))

class LabelsList(RequestHandler):
    "Labels list page."

    def get(self):
        labels = self.get_docs('label/value')
        self.render('labels.html', labels=labels)

class LabelsTable(RequestHandler):
    "Labels table page."

    def get(self):
        labels = self.get_docs('label/value')
        if self.is_curator():
            accounts = dict([(l['value'], []) for l in labels])
            for account in self.get_docs('account/email'):
                for label in account['labels']:
                    accounts.setdefault(label, []).append(account['email'])
            for label in labels:
                label['accounts'] = sorted(accounts.get(label['value'], []))
        view = self.db.view('publication/label', group=True)
        counts = dict([(r.key, r.value) for r in view])
        for label in labels:
            label['count'] = counts.get(label['value'], 0)
        self.render('labels_table.html', labels=labels)

class LabelsJson(LabelsTable):
    "JSON for labels."

    def render(self, template, **kwargs):
        URL = self.absolute_reverse_url
        labels = kwargs['labels']
        result = OD()
        result['entity'] = 'labels'
        result['timestamp'] = utils.timestamp()
        result['links'] = links = OD()
        links['self'] = {'href': URL('labels_json')}
        links['display'] = {'href': URL('labels')}
        result['labels_count'] = len(labels)
        result['labels'] = [self.get_label_json(l) for l in labels]
        self.write(result)

class LabelAdd(RequestHandler):
    "Label addition page."

    def get(self):
        self.check_admin()
        self.render('label_add.html')

    def post(self):
        self.check_admin()
        try:
            value = self.get_argument('value')
        except tornado.web.MissingArgumentError:
            self.see_other('label_add', error='no label provided')
            return
        try:
            with LabelSaver(rqh=self) as saver:
                saver.set_value(value)
            label = saver.doc
        except ValueError, msg:
            self.set_error_flash(str(msg))
            self.see_other('label_add')
            return
        self.see_other('label', label['value'])

class LabelEdit(RequestHandler):
    "Label edit page."

    def get(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        self.render('label_edit.html', label=label)

    def post(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        old_value = label['value']
        new_value = self.get_argument('value')
        try:
            with LabelSaver(label, rqh=self) as saver:
                saver.check_revision()
                saver.set_value(new_value)
                saver['description'] = self.get_argument('description', None)
        except SaverError:
            self.set_error_flash(utils.REV_ERROR)
            self.see_other('label', label['value'])
            return
        if new_value != old_value:
            for account in self.get_docs('account/label', key=old_value):
                with AccountSaver(account, rqh=self) as saver:
                    labels = account['labels'].copy()
                    labels.discard(old_value)
                    labels.add(new_value)
                    saver['labels'] = sorted(labels)
            for publ in self.get_docs('publication/label', key=old_value):
                with PublicationSaver(publ, rqh=self) as saver:
                    labels = publ['labels'].copy()
                    labels[new_value] = labels.pop(old_value)
                    saver['labels'] = labels
        self.see_other('label', label['value'])

class LabelMerge(RequestHandler):
    "Merge label into another."

    def get(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        self.render('label_merge.html',
                    label=label,
                    labels=self.get_docs('label/value'))

    def post(self, identifier):
        self.check_admin()
        try:
            label = self.get_label(identifier)
        except KeyError, msg:
            self.see_other('labels', error=str(msg))
            return
        try:
            merge = self.get_label(self.get_argument('merge'))
        except tornado.web.MissingArgumentError:
            self.set_error_flash('no merge label provided')
            self.see_other('labels')
            return
        except KeyError, msg:
            self.set_error_flash(str(msg))
            self.see_other('labels')
            return
        old_label = label['value']
        new_label = merge['value']
        self.delete_entity(label)
        for account in self.get_docs('account/label', key=old_label):
            with AccountSaver(account, rqh=self) as saver:
                labels = set(account['labels'])
                labels.discard(old_label)
                labels.add(new_label)
                saver['labels'] = sorted(labels)
        for publication in self.get_docs('publication/label', key=old_label):
            with PublicationSaver(publication, rqh=self) as saver:
                labels = set(publication['labels'])
                labels.discard(old_label)
                labels.add(new_label)
                saver['labels'] = sorted(labels)
        self.see_other('label', new_label)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Author: Óscar Nájera
# License: 3-clause BSD
"""
Backreferences Generator
========================

Parses example file code in order to keep track of used functions
"""

from __future__ import print_function
import ast
import os

# Try Python 2 first, otherwise load from Python 3
try:
    import cPickle as pickle
except ImportError:
    import pickle
# Try Python 3 first, otherwise load from Python 2
try:
    from html import escape
except ImportError:
    from functools import partial
    from xml.sax.saxutils import escape

    escape = partial(escape, entities={'"': '"'})

class NameFinder(ast.NodeVisitor):
    """Finds the longest form of variable names and their imports in code

    Only retains names from imported modules.
    """

    def __init__(self):
        super(NameFinder, self).__init__()
        self.imported_names = {}
        self.accessed_names = set()

    def visit_Import(self, node, prefix=''):
        for alias in node.names:
            local_name = alias.asname or alias.name
            self.imported_names[local_name] = prefix + alias.name

    def visit_ImportFrom(self, node):
        self.visit_Import(node, node.module + '.')

    def visit_Name(self, node):
        self.accessed_names.add(node.id)

    def visit_Attribute(self, node):
        attrs = []
        while isinstance(node, ast.Attribute):
            attrs.append(node.attr)
            node = node.value

        if isinstance(node, ast.Name):
            # This is a.b, not e.g. a().b
            attrs.append(node.id)
            self.accessed_names.add('.'.join(reversed(attrs)))
        else:
            # need to get a in a().b
            self.visit(node)

    def get_mapping(self):
        for name in self.accessed_names:
            local_name = name.split('.', 1)[0]
            remainder = name[len(local_name):]
            if local_name in self.imported_names:
                # Join import path to relative path
                full_name = self.imported_names[local_name] + remainder
                yield name, full_name

def get_short_module_name(module_name, obj_name):
    """ Get the shortest possible module name """
    parts = module_name.split('.')
    short_name = module_name
    for i in range(len(parts) - 1, 0, -1):
        short_name = '.'.join(parts[:i])
        try:
            exec('from %s import %s' % (short_name, obj_name))
        except Exception:  # libraries can throw all sorts of exceptions...
            # get the last working module name
            short_name = '.'.join(parts[:(i + 1)])
            break
    return short_name

def identify_names(code):
    """Builds a codeobj summary by identifying and resolving used names

    >>> code = '''
    ... from a.b import c
    ... import d as e
    ... print(c)
    ... e.HelloWorld().f.g
    ... '''
    >>> for name, o in sorted(identify_names(code).items()):
    ...     print(name, o['name'], o['module'], o['module_short'])
    c c a.b a.b
    e.HelloWorld HelloWorld d d
    """
    finder = NameFinder()
    try:
        finder.visit(ast.parse(code))
    except SyntaxError:
        return {}

    example_code_obj = {}
    for name, full_name in finder.get_mapping():
        # name is as written in file (e.g. np.asarray)
        # full_name includes resolved import path (e.g. numpy.asarray)
        splitted = full_name.rsplit('.', 1)
        if len(splitted) == 1:
            # module without attribute. This is not useful for
            # backreferences
            continue

        module, attribute = splitted
        # get shortened module name
        module_short = get_short_module_name(module, attribute)
        cobj = {'name': attribute, 'module': module,
                'module_short': module_short}
        example_code_obj[name] = cobj
    return example_code_obj

def scan_used_functions(example_file, gallery_conf):
    """save variables so we can later add links to the documentation"""
    example_code_obj = identify_names(open(example_file).read())
    if example_code_obj:
        codeobj_fname = example_file[:-3] + '_codeobj.pickle'
        with open(codeobj_fname, 'wb') as fid:
            pickle.dump(example_code_obj, fid, pickle.HIGHEST_PROTOCOL)

    backrefs = set('{module_short}.{name}'.format(**entry)
                   for entry in example_code_obj.values()
                   if entry['module'].startswith(gallery_conf['doc_module']))

    return backrefs

THUMBNAIL_TEMPLATE = """
.. raw:: html

.. only:: html

    .. figure:: /{thumbnail}

        :ref:`sphx_glr_{ref_name}`

.. raw:: html

"""

BACKREF_THUMBNAIL_TEMPLATE = THUMBNAIL_TEMPLATE + """
.. only:: not html

    * :ref:`sphx_glr_{ref_name}`
"""

def _thumbnail_div(full_dir, fname, snippet, is_backref=False):
    """Generates RST to place a thumbnail in a gallery"""
    thumb = os.path.join(full_dir, 'images', 'thumb',
                         'sphx_glr_%s_thumb.png' % fname[:-3])

    # Inside rst files forward slash defines paths
    thumb = thumb.replace(os.sep, "/")

    ref_name = os.path.join(full_dir, fname).replace(os.path.sep, '_')

    template = BACKREF_THUMBNAIL_TEMPLATE if is_backref else THUMBNAIL_TEMPLATE
    return template.format(snippet=escape(snippet),
                           thumbnail=thumb, ref_name=ref_name)

def write_backreferences(seen_backrefs, gallery_conf,
                         target_dir, fname, snippet):
    """Writes down back reference files, which include a thumbnail list
    of examples using a certain module"""
    if gallery_conf['backreferences_dir'] is None:
        return

    example_file = os.path.join(target_dir, fname)
    build_target_dir = os.path.relpath(target_dir, gallery_conf['src_dir'])
    backrefs = scan_used_functions(example_file, gallery_conf)
    for backref in backrefs:
        include_path = os.path.join(gallery_conf['src_dir'],
                                    gallery_conf['backreferences_dir'],
                                    '%s.examples' % backref)
        seen = backref in seen_backrefs
        with open(include_path, 'a' if seen else 'w') as ex_file:
            if not seen:
                heading = '\n\nExamples using ``%s``' % backref
                ex_file.write(heading + '\n')
                ex_file.write('^' * len(heading) + '\n')
            ex_file.write(_thumbnail_div(build_target_dir, fname, snippet,
                                         is_backref=True))
            seen_backrefs.add(backref)
<commit_msg>Enforce UTF8 encoding in backreferences<commit_after># -*- coding: utf-8 -*-
# Author: Óscar Nájera
# License: 3-clause BSD
"""
Backreferences Generator
========================

Parses example file code in order to keep track of used functions
"""

from __future__ import print_function
import ast
import os
import codecs

# Try Python 2 first, otherwise load from Python 3
try:
    import cPickle as pickle
except ImportError:
    import pickle
# Try Python 3 first, otherwise load from Python 2
try:
    from html import escape
except ImportError:
    from functools import partial
    from xml.sax.saxutils import escape

    escape = partial(escape, entities={'"': '"'})

class NameFinder(ast.NodeVisitor):
    """Finds the longest form of variable names and their imports in code

    Only retains names from imported modules.
    """

    def __init__(self):
        super(NameFinder, self).__init__()
        self.imported_names = {}
        self.accessed_names = set()

    def visit_Import(self, node, prefix=''):
        for alias in node.names:
            local_name = alias.asname or alias.name
            self.imported_names[local_name] = prefix + alias.name

    def visit_ImportFrom(self, node):
        self.visit_Import(node, node.module + '.')

    def visit_Name(self, node):
        self.accessed_names.add(node.id)

    def visit_Attribute(self, node):
        attrs = []
        while isinstance(node, ast.Attribute):
            attrs.append(node.attr)
            node = node.value

        if isinstance(node, ast.Name):
            # This is a.b, not e.g. a().b
            attrs.append(node.id)
            self.accessed_names.add('.'.join(reversed(attrs)))
        else:
            # need to get a in a().b
            self.visit(node)

    def get_mapping(self):
        for name in self.accessed_names:
            local_name = name.split('.', 1)[0]
            remainder = name[len(local_name):]
            if local_name in self.imported_names:
                # Join import path to relative path
                full_name = self.imported_names[local_name] + remainder
                yield name, full_name

def get_short_module_name(module_name, obj_name):
    """ Get the shortest possible module name """
    parts = module_name.split('.')
    short_name = module_name
    for i in range(len(parts) - 1, 0, -1):
        short_name = '.'.join(parts[:i])
        try:
            exec('from %s import %s' % (short_name, obj_name))
        except Exception:  # libraries can throw all sorts of exceptions...
            # get the last working module name
            short_name = '.'.join(parts[:(i + 1)])
            break
    return short_name

def identify_names(code):
    """Builds a codeobj summary by identifying and resolving used names

    >>> code = '''
    ... from a.b import c
    ... import d as e
    ... print(c)
    ... e.HelloWorld().f.g
    ... '''
    >>> for name, o in sorted(identify_names(code).items()):
    ...     print(name, o['name'], o['module'], o['module_short'])
    c c a.b a.b
    e.HelloWorld HelloWorld d d
    """
    finder = NameFinder()
    try:
        finder.visit(ast.parse(code))
    except SyntaxError:
        return {}

    example_code_obj = {}
    for name, full_name in finder.get_mapping():
        # name is as written in file (e.g. np.asarray)
        # full_name includes resolved import path (e.g. numpy.asarray)
        splitted = full_name.rsplit('.', 1)
        if len(splitted) == 1:
            # module without attribute. This is not useful for
            # backreferences
            continue

        module, attribute = splitted
        # get shortened module name
        module_short = get_short_module_name(module, attribute)
        cobj = {'name': attribute, 'module': module,
                'module_short': module_short}
        example_code_obj[name] = cobj
    return example_code_obj

def scan_used_functions(example_file, gallery_conf):
    """save variables so we can later add links to the documentation"""
    example_code_obj = identify_names(
        codecs.open(example_file, encoding='utf-8').read())
    if example_code_obj:
        codeobj_fname = example_file[:-3] + '_codeobj.pickle'
        with open(codeobj_fname, 'wb') as fid:
            pickle.dump(example_code_obj, fid, pickle.HIGHEST_PROTOCOL)

    backrefs = set('{module_short}.{name}'.format(**entry)
                   for entry in example_code_obj.values()
                   if entry['module'].startswith(gallery_conf['doc_module']))

    return backrefs

THUMBNAIL_TEMPLATE = """
.. raw:: html

.. only:: html

    .. figure:: /{thumbnail}

        :ref:`sphx_glr_{ref_name}`

.. raw:: html

"""

BACKREF_THUMBNAIL_TEMPLATE = THUMBNAIL_TEMPLATE + """
.. only:: not html

    * :ref:`sphx_glr_{ref_name}`
"""

def _thumbnail_div(full_dir, fname, snippet, is_backref=False):
    """Generates RST to place a thumbnail in a gallery"""
    thumb = os.path.join(full_dir, 'images', 'thumb',
                         'sphx_glr_%s_thumb.png' % fname[:-3])

    # Inside rst files forward slash defines paths
    thumb = thumb.replace(os.sep, "/")

    ref_name = os.path.join(full_dir, fname).replace(os.path.sep, '_')

    template = BACKREF_THUMBNAIL_TEMPLATE if is_backref else THUMBNAIL_TEMPLATE
    return template.format(snippet=escape(snippet),
                           thumbnail=thumb, ref_name=ref_name)

def write_backreferences(seen_backrefs, gallery_conf,
                         target_dir, fname, snippet):
    """Writes down back reference files, which include a thumbnail list
    of examples using a certain module"""
    if gallery_conf['backreferences_dir'] is None:
        return

    example_file = os.path.join(target_dir, fname)
    build_target_dir = os.path.relpath(target_dir, gallery_conf['src_dir'])
    backrefs = scan_used_functions(example_file, gallery_conf)
    for backref in backrefs:
        include_path = os.path.join(gallery_conf['src_dir'],
                                    gallery_conf['backreferences_dir'],
                                    '%s.examples' % backref)
        seen = backref in seen_backrefs
        with open(include_path, 'a' if seen else 'w') as ex_file:
            if not seen:
                heading = '\n\nExamples using ``%s``' % backref
                ex_file.write(heading + '\n')
                ex_file.write('^' * len(heading) + '\n')
            ex_file.write(_thumbnail_div(build_target_dir, fname, snippet,
                                         is_backref=True))
            seen_backrefs.add(backref)
<|endoftext|>