<commit_before>import datetime
from django.conf.urls import url
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, InvalidPage
from django.db.models import Count
from django.http import Http404
from django.template.loader import render_to_string
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.constants import ALL_WITH_RELATIONS
from tastypie.fields import ToOneField
from tastypie.http import HttpGone
from tastypie.utils import trailing_slash

from core.serialisers import json
from spa.api.v1.ActivityResource import ActivityResource
from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource
from spa.api.v1.CommentResource import CommentResource
from spa.models.genre import Genre
from spa.models.mix import Mix

class MixResource(BackboneCompatibleResource):
    comments = fields.ToManyField('spa.api.v1.CommentResource.CommentResource', 'comments', null=True, full=True)
    favourites = fields.ToManyField('spa.api.v1.UserResource.UserResource', 'favourites',
                                    related_name='favourites', full=False, null=True)

    likes = fields.ToManyField('spa.api.v1.UserResource.UserResource', 'likes',
                               related_name='likes', full=False, null=True)

    class Meta:
        queryset = Mix.objects.filter(is_active=True)
        user = ToOneField('UserResource', 'user')
        always_return_data = True
        detail_uri_name = 'slug'
        excludes = ['is_active', 'local_file', 'waveform-generated']
        post_excludes = ['comments']
        filtering = {
            'comments': ALL_WITH_RELATIONS,
            'favourites': ALL_WITH_RELATIONS,
            'likes': ALL_WITH_RELATIONS,
            'slug': ALL_WITH_RELATIONS,
        }
        authorization = Authorization()

    def _parseGenreList(self, genres):
        #for magic..
        ret = []
        for genre in genres:
            if genre['id'] == genre['text']:
                new_item = Genre(description=genre['text'])
                new_item.save()
                ret.append(new_item)
            else:
                ret.append(Genre.objects.get(pk=genre['id']))

        return ret

    def _unpackGenreList(self, bundle, genres):
        genre_list = self._parseGenreList(genres)
        bundle.obj.genres = genre_list
        bundle.obj.save()

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/search%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('get_search'),
                name="api_get_search"),
            url(r"^(?P<resource_name>%s)/(?P<id>[\d]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'),
                name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/random/$" % self._meta.resource_name, self.wrap_view('dispatch_random'),
                name="api_dispatch_random"),
            url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d-]+)/$" % self._meta.resource_name,
                self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<slug>\w[\w/-]*)/comments%s$" % (
                self._meta.resource_name, trailing_slash()), self.wrap_view('get_comments'), name="api_get_comments"),
            url(r"^(?P<resource_name>%s)/(?P<slug>\w[\w/-]*)/activity%s$" % (
                self._meta.resource_name, trailing_slash()), self.wrap_view('get_activity'), name="api_get_activity"),
        ]

    def dispatch_random(self, request, **kwargs):
        kwargs['pk'] = self._meta.queryset.values_list('pk', flat=True).order_by('?')[0]
        return self.get_detail(request, **kwargs)

    def get_comments(self, request, **kwargs):
        try:
            basic_bundle = self.build_bundle(request=request)
            obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return HttpGone()

        child_resource = CommentResource()
        return child_resource.get_list(request, mix=obj)

    def get_activity(self, request, **kwargs):
        try:
            basic_bundle = self.build_bundle(request=request)
            obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return HttpGone()

        child_resource = ActivityResource()
        return child_resource.get_list(request, mix=obj)

    def obj_create(self, bundle, **kwargs):
        file_name = "mixes/%s.%s" % (bundle.data['upload-hash'], bundle.data['upload-extension'])
        uid = bundle.data['upload-hash']
        if 'is_featured' not in bundle.data:
            bundle.data['is_featured'] = False

        if 'download_allowed' not in bundle.data:
            bundle.data['download_allowed'] = False

        bundle.data['user'] = bundle.request.user.get_profile()
        ret = super(MixResource, self).obj_create(
            bundle,
            user=bundle.request.user.get_profile(),
            local_file=file_name,
            uid=uid)

        self._unpackGenreList(ret, bundle.data['genre-list'])
        #if ret is hunky dory
        return ret

    def obj_update(self, bundle, **kwargs):
        #don't sync the mix_image, this has to be handled separately
        del bundle.data['mix_image']
        ret = super(MixResource, self).obj_update(bundle, bundle.request)

        bundle.obj.update_favourite(bundle.request.user, bundle.data['favourited'])
        bundle.obj.update_liked(bundle.request.user, bundle.data['liked'])

        self._unpackGenreList(ret, bundle.data['genre-list'])
        return ret

    def apply_sorting(self, obj_list, options=None):
        orderby = options.get('order_by', '')
        if orderby == 'latest':
            obj_list = obj_list.order_by('-id')
        elif orderby == 'toprated':
            obj_list = obj_list.annotate(karma=Count('activity_likes')).order_by('-karma')
        elif orderby == 'mostplayed':
            obj_list = obj_list.annotate(karma=Count('activity_plays')).order_by('-karma')
        elif orderby == 'mostactive':
            obj_list = obj_list.annotate(karma=Count('comments')).order_by('-karma')
        elif orderby == 'recommended':
            obj_list = obj_list.annotate(karma=Count('activity_likes')).order_by('-karma')

        return obj_list

    def apply_filters(self, request, applicable_filters):
        semi_filtered = super(MixResource, self) \
            .apply_filters(request, applicable_filters) \
            .filter(waveform_generated=True)

        f_user = request.GET.get('user', None)

        if request.GET.get('stream'):
            semi_filtered = semi_filtered.filter(user__in=request.user.get_profile().following.all())
        if f_user is not None:
            semi_filtered = semi_filtered.filter(user__slug=f_user)
        else:
            semi_filtered = semi_filtered.filter(is_featured=True)

        return semi_filtered

    def hydrate_favourited(self, bundle):
        return bundle

    def dehydrate_mix_image(self, bundle):
        return bundle.obj.get_image_url(size="160x110")

    def dehydrate(self, bundle):
        bundle.data['waveform_url'] = bundle.obj.get_waveform_url()
        bundle.data['user_name'] = bundle.obj.user.get_nice_name()
        bundle.data['user_profile_url'] = bundle.obj.user.get_absolute_url()
        bundle.data['user_profile_image'] = bundle.obj.user.get_small_profile_image()
        bundle.data['item_url'] = '/mix/%s' % bundle.obj.slug

        bundle.data['favourite_count'] = bundle.obj.favourites.count()

        bundle.data['play_count'] = bundle.obj.activity_plays.count()
        bundle.data['download_count'] = bundle.obj.activity_downloads.count()
        bundle.data['like_count'] = bundle.obj.activity_likes.count()

        bundle.data['tooltip'] = render_to_string('inc/player_tooltip.html', {'item': bundle.obj})
        bundle.data['comment_count'] = bundle.obj.comments.count()

        bundle.data['genre-list'] = json.to_ajax(bundle.obj.genres.all(), 'description', 'slug')
        bundle.data['liked'] = bundle.obj.is_liked(bundle.request.user)

        if bundle.request.user.is_authenticated():
            bundle.data['can_edit'] = bundle.request.user.is_staff or bundle.obj.user_id == bundle.request.user.id
        else:
            bundle.data['can_edit'] = False

        if bundle.request.user.is_authenticated():
            bundle.data['favourited'] = bundle.obj.favourites.filter(user=bundle.request.user).count() != 0
        else:
            bundle.data['favourited'] = False

        return bundle

    def get_search(self, request, **kwargs):
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        # Do the query.
        sqs = Mix.objects.filter(title__icontains=request.GET.get('q', ''))
        paginator = Paginator(sqs, 20)

        try:
            page = paginator.page(int(request.GET.get('page', 1)))
        except InvalidPage:
            raise Http404("Sorry, no results on that page.")

        objects = []

        for result in page.object_list:
            bundle = self.build_bundle(obj=result, request=request)
            bundle = self.full_dehydrate(bundle)
            objects.append(bundle)

        object_list = {
            'objects': objects,
        }

        self.log_throttled_access(request)
        return self.create_response(request, object_list)
<commit_msg>Downloads now become active on mixes after 24 hours<commit_after>import datetime
from django.conf.urls import url
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, InvalidPage
from django.db.models import Count
from django.http import Http404
from django.template.loader import render_to_string
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.constants import ALL_WITH_RELATIONS
from tastypie.fields import ToOneField
from tastypie.http import HttpGone
from tastypie.utils import trailing_slash

from core.serialisers import json
from spa.api.v1.ActivityResource import ActivityResource
from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource
from spa.api.v1.CommentResource import CommentResource
from spa.models.genre import Genre
from spa.models.mix import Mix

class MixResource(BackboneCompatibleResource):
    comments = fields.ToManyField('spa.api.v1.CommentResource.CommentResource', 'comments', null=True, full=True)
    favourites = fields.ToManyField('spa.api.v1.UserResource.UserResource', 'favourites',
                                    related_name='favourites', full=False, null=True)

    likes = fields.ToManyField('spa.api.v1.UserResource.UserResource', 'likes',
                               related_name='likes', full=False, null=True)

    class Meta:
        queryset = Mix.objects.filter(is_active=True)
        user = ToOneField('UserResource', 'user')
        always_return_data = True
        detail_uri_name = 'slug'
        excludes = ['is_active', 'local_file', 'waveform-generated']
        post_excludes = ['comments']
        filtering = {
            'comments': ALL_WITH_RELATIONS,
            'favourites': ALL_WITH_RELATIONS,
            'likes': ALL_WITH_RELATIONS,
            'slug': ALL_WITH_RELATIONS,
        }
        authorization = Authorization()

    def _parseGenreList(self, genres):
        #for magic..
        ret = []
        for genre in genres:
            if genre['id'] == genre['text']:
                new_item = Genre(description=genre['text'])
                new_item.save()
                ret.append(new_item)
            else:
                ret.append(Genre.objects.get(pk=genre['id']))

        return ret

    def _unpackGenreList(self, bundle, genres):
        genre_list = self._parseGenreList(genres)
        bundle.obj.genres = genre_list
        bundle.obj.save()

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/search%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('get_search'),
                name="api_get_search"),
            url(r"^(?P<resource_name>%s)/(?P<id>[\d]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'),
                name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/random/$" % self._meta.resource_name, self.wrap_view('dispatch_random'),
                name="api_dispatch_random"),
            url(r"^(?P<resource_name>%s)/(?P<slug>[\w\d-]+)/$" % self._meta.resource_name,
                self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
            url(r"^(?P<resource_name>%s)/(?P<slug>\w[\w/-]*)/comments%s$" % (
                self._meta.resource_name, trailing_slash()), self.wrap_view('get_comments'), name="api_get_comments"),
            url(r"^(?P<resource_name>%s)/(?P<slug>\w[\w/-]*)/activity%s$" % (
                self._meta.resource_name, trailing_slash()), self.wrap_view('get_activity'), name="api_get_activity"),
        ]

    def dispatch_random(self, request, **kwargs):
        kwargs['pk'] = self._meta.queryset.values_list('pk', flat=True).order_by('?')[0]
        return self.get_detail(request, **kwargs)

    def get_comments(self, request, **kwargs):
        try:
            basic_bundle = self.build_bundle(request=request)
            obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return HttpGone()

        child_resource = CommentResource()
        return child_resource.get_list(request, mix=obj)

    def get_activity(self, request, **kwargs):
        try:
            basic_bundle = self.build_bundle(request=request)
            obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs))
        except ObjectDoesNotExist:
            return HttpGone()

        child_resource = ActivityResource()
        return child_resource.get_list(request, mix=obj)

    def obj_create(self, bundle, **kwargs):
        file_name = "mixes/%s.%s" % (bundle.data['upload-hash'], bundle.data['upload-extension'])
        uid = bundle.data['upload-hash']
        if 'is_featured' not in bundle.data:
            bundle.data['is_featured'] = False

        if 'download_allowed' not in bundle.data:
            bundle.data['download_allowed'] = False

        bundle.data['user'] = bundle.request.user.get_profile()
        ret = super(MixResource, self).obj_create(
            bundle,
            user=bundle.request.user.get_profile(),
            local_file=file_name,
            uid=uid)

        self._unpackGenreList(ret, bundle.data['genre-list'])
        #if ret is hunky dory
        return ret

    def obj_update(self, bundle, **kwargs):
        #don't sync the mix_image, this has to be handled separately
        del bundle.data['mix_image']
        ret = super(MixResource, self).obj_update(bundle, bundle.request)

        bundle.obj.update_favourite(bundle.request.user, bundle.data['favourited'])
        bundle.obj.update_liked(bundle.request.user, bundle.data['liked'])

        self._unpackGenreList(ret, bundle.data['genre-list'])
        return ret

    def apply_sorting(self, obj_list, options=None):
        orderby = options.get('order_by', '')
        if orderby == 'latest':
            obj_list = obj_list.order_by('-id')
        elif orderby == 'toprated':
            obj_list = obj_list.annotate(karma=Count('activity_likes')).order_by('-karma')
        elif orderby == 'mostplayed':
            obj_list = obj_list.annotate(karma=Count('activity_plays')).order_by('-karma')
        elif orderby == 'mostactive':
            obj_list = obj_list.annotate(karma=Count('comments')).order_by('-karma')
        elif orderby == 'recommended':
            obj_list = obj_list.annotate(karma=Count('activity_likes')).order_by('-karma')

        return obj_list

    def apply_filters(self, request, applicable_filters):
        semi_filtered = super(MixResource, self) \
            .apply_filters(request, applicable_filters) \
            .filter(waveform_generated=True)

        f_user = request.GET.get('user', None)

        if request.GET.get('stream'):
            semi_filtered = semi_filtered.filter(user__in=request.user.get_profile().following.all())
        if f_user is not None:
            semi_filtered = semi_filtered.filter(user__slug=f_user)
        else:
            semi_filtered = semi_filtered.filter(is_featured=True)

        return semi_filtered

    def hydrate_favourited(self, bundle):
        return bundle

    def dehydrate_mix_image(self, bundle):
        return bundle.obj.get_image_url(size="160x110")

    def dehydrate(self, bundle):
        bundle.data['waveform_url'] = bundle.obj.get_waveform_url()
        bundle.data['user_name'] = bundle.obj.user.get_nice_name()
        bundle.data['user_profile_url'] = bundle.obj.user.get_absolute_url()
        bundle.data['user_profile_image'] = bundle.obj.user.get_small_profile_image()
        bundle.data['item_url'] = '/mix/%s' % bundle.obj.slug
        bundle.data['download_allowed'] = bundle.obj.download_allowed and \
                                          bundle.obj.upload_date < datetime.datetime.now() - datetime.timedelta(days=1)

        bundle.data['favourite_count'] = bundle.obj.favourites.count()

        bundle.data['play_count'] = bundle.obj.activity_plays.count()
        bundle.data['download_count'] = bundle.obj.activity_downloads.count()
        bundle.data['like_count'] = bundle.obj.activity_likes.count()

        bundle.data['tooltip'] = render_to_string('inc/player_tooltip.html', {'item': bundle.obj})
        bundle.data['comment_count'] = bundle.obj.comments.count()

        bundle.data['genre-list'] = json.to_ajax(bundle.obj.genres.all(), 'description', 'slug')
        bundle.data['liked'] = bundle.obj.is_liked(bundle.request.user)

        if bundle.request.user.is_authenticated():
            bundle.data['can_edit'] = bundle.request.user.is_staff or bundle.obj.user_id == bundle.request.user.id
        else:
            bundle.data['can_edit'] = False

        if bundle.request.user.is_authenticated():
            bundle.data['favourited'] = bundle.obj.favourites.filter(user=bundle.request.user).count() != 0
        else:
            bundle.data['favourited'] = False

        return bundle

    def get_search(self, request, **kwargs):
        self.method_check(request, allowed=['get'])
        self.is_authenticated(request)
        self.throttle_check(request)

        # Do the query.
        sqs = Mix.objects.filter(title__icontains=request.GET.get('q', ''))
        paginator = Paginator(sqs, 20)

        try:
            page = paginator.page(int(request.GET.get('page', 1)))
        except InvalidPage:
            raise Http404("Sorry, no results on that page.")

        objects = []

        for result in page.object_list:
            bundle = self.build_bundle(obj=result, request=request)
            bundle = self.full_dehydrate(bundle)
            objects.append(bundle)

        object_list = {
            'objects': objects,
        }

        self.log_throttled_access(request)
        return self.create_response(request, object_list)
<|endoftext|>


<commit_before>from django.template.loader import render_to_string
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.constants import ALL_WITH_RELATIONS
from core.serialisers import json
from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource
from spa.models import Genre

from spa.models.Mix import Mix

class MixResource(BackboneCompatibleResource):
    comments = fields.ToManyField('spa.api.v1.CommentResource.CommentResource', 'comments', 'mix', null=True)

    class Meta:
        queryset = Mix.objects.filter(is_active=True)
        excludes = ['download_url', 'is_active', 'local_file', 'upload_date']
        filtering = {
            'comments': ALL_WITH_RELATIONS
        }
        authorization = Authorization()

    def _parseGenreList(self, genres):
        #for magic..
        ret = []
        for genre in genres:
            if genre['id'] == genre['text']:
                new_item = Genre(description = genre['text'])
                new_item.save()
                ret.append(new_item)
            else:
                ret.append(Genre.objects.get(pk=genre['id']))

        return ret

    def _unpackGenreList(self, bundle, genres):
        genre_list = self._parseGenreList(genres)
        bundle.obj.genres = genre_list
        bundle.obj.save()

    def obj_create(self, bundle, request=None, **kwargs):
        file_name = "mixes/%s.%s" % (bundle.data['upload-hash'], bundle.data['upload-extension'])
        uid = bundle.data['upload-hash']
        if 'is_featured' not in bundle.data:
            bundle.data['is_featured'] = False

        bundle.data['user'] = request.user.get_profile()
        ret = super(MixResource, self).obj_create(bundle, request, user=request.user.get_profile(), local_file=file_name, uid=uid)
        self._unpackGenreList(ret, bundle.data['genre-list'])
        #if ret is hunky dory
        return ret

    def obj_update(self, bundle, request=None, **kwargs):
        ret = super(MixResource, self).obj_update(bundle, request)
        self._unpackGenreList(ret, bundle.data['genre-list'])
        return ret

    def obj_get_list(self, request=None, **kwargs):
        if 'user' in request.GET and request.GET['user']:
            user = request.GET['user']
            return Mix.get_for_username(user)
        elif 'type' in request.GET and request.GET['type']:
            type = request.GET['type']
            return Mix.get_listing(type, request.user)

        return Mix.get_listing('latest', request.user)

    def dehydrate_mix_image(self, bundle):
        return bundle.obj.get_image_url()

    def dehydrate(self, bundle):
        bundle.data['waveform_url'] = bundle.obj.get_waveform_url()
        bundle.data['user_name'] = bundle.obj.user.nice_name()
        bundle.data['item_url'] = 'mix/%s' % bundle.obj.id

        bundle.data['play_count'] = bundle.obj.plays.count()
        bundle.data['download_count'] = bundle.obj.downloadS.COUNT()
        bundle.data['like_count'] = bundle.obj.likes.count()
        bundle.data['mode'] = 'mix'
        bundle.data['tooltip'] = render_to_string('inc/player_tooltip.html', {'item': bundle.obj})
        bundle.data['comment_count'] = bundle.obj.comments.count()

        bundle.data['genre-list'] = json.to_ajax(bundle.obj.genres.all(), 'description', 'slug')
        bundle.data['liked'] = bundle.obj.is_liked(bundle.request.user)
        bundle.data['favourited'] = bundle.obj.is_favourited(bundle.request.user)
        return bundle
<commit_msg>Fixed typo<commit_after>from django.template.loader import render_to_string
from tastypie import fields
from tastypie.authorization import Authorization
from tastypie.constants import ALL_WITH_RELATIONS
from core.serialisers import json
from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource
from spa.models import Genre

from spa.models.Mix import Mix

class MixResource(BackboneCompatibleResource):
    comments = fields.ToManyField('spa.api.v1.CommentResource.CommentResource', 'comments', 'mix', null=True)

    class Meta:
        queryset = Mix.objects.filter(is_active=True)
        excludes = ['download_url', 'is_active', 'local_file', 'upload_date']
        filtering = {
            'comments': ALL_WITH_RELATIONS
        }
        authorization = Authorization()

    def _parseGenreList(self, genres):
        #for magic..
        ret = []
        for genre in genres:
            if genre['id'] == genre['text']:
                new_item = Genre(description = genre['text'])
                new_item.save()
                ret.append(new_item)
            else:
                ret.append(Genre.objects.get(pk=genre['id']))

        return ret

    def _unpackGenreList(self, bundle, genres):
        genre_list = self._parseGenreList(genres)
        bundle.obj.genres = genre_list
        bundle.obj.save()

    def obj_create(self, bundle, request=None, **kwargs):
        file_name = "mixes/%s.%s" % (bundle.data['upload-hash'], bundle.data['upload-extension'])
        uid = bundle.data['upload-hash']
        if 'is_featured' not in bundle.data:
            bundle.data['is_featured'] = False

        bundle.data['user'] = request.user.get_profile()
        ret = super(MixResource, self).obj_create(bundle, request, user=request.user.get_profile(), local_file=file_name, uid=uid)
        self._unpackGenreList(ret, bundle.data['genre-list'])
        #if ret is hunky dory
        return ret

    def obj_update(self, bundle, request=None, **kwargs):
        ret = super(MixResource, self).obj_update(bundle, request)
        self._unpackGenreList(ret, bundle.data['genre-list'])
        return ret

    def obj_get_list(self, request=None, **kwargs):
        if 'user' in request.GET and request.GET['user']:
            user = request.GET['user']
            return Mix.get_for_username(user)
        elif 'type' in request.GET and request.GET['type']:
            type = request.GET['type']
            return Mix.get_listing(type, request.user)

        return Mix.get_listing('latest', request.user)

    def dehydrate_mix_image(self, bundle):
        return bundle.obj.get_image_url()

    def dehydrate(self, bundle):
        bundle.data['waveform_url'] = bundle.obj.get_waveform_url()
        bundle.data['user_name'] = bundle.obj.user.nice_name()
        bundle.data['item_url'] = 'mix/%s' % bundle.obj.id

        bundle.data['play_count'] = bundle.obj.plays.count()
        bundle.data['download_count'] = bundle.obj.download.count()
        bundle.data['like_count'] = bundle.obj.likes.count()
        bundle.data['mode'] = 'mix'
        bundle.data['tooltip'] = render_to_string('inc/player_tooltip.html', {'item': bundle.obj})
        bundle.data['comment_count'] = bundle.obj.comments.count()

        bundle.data['genre-list'] = json.to_ajax(bundle.obj.genres.all(), 'description', 'slug')
        bundle.data['liked'] = bundle.obj.is_liked(bundle.request.user)
        bundle.data['favourited'] = bundle.obj.is_favourited(bundle.request.user)
        return bundle
<|endoftext|>


<commit_before>from typing import Iterator, Sequence, Iterable, Optional, Dict, Callable, List, Tuple
from thinc.api import Model, set_dropout_rate, Optimizer, Config

from .pipe import Pipe
from ..gold import Example
from ..tokens import Doc
from ..vocab import Vocab
from ..language import Language
from ..errors import Errors
from ..util import link_vectors_to_models, minibatch

default_model_config = """
[model]
@architectures = "spacy.HashEmbedCNN.v1"
pretrained_vectors = null
width = 96
depth = 4
embed_size = 2000
window_size = 1
maxout_pieces = 3
subword_features = true
dropout = null
"""
DEFAULT_TOK2VEC_MODEL = Config().from_str(default_model_config)["model"]

@Language.factory(
    "tok2vec", assigns=["doc.tensor"], default_config={"model": DEFAULT_TOK2VEC_MODEL}
)
def make_tok2vec(nlp: Language, name: str, model: Model) -> "Tok2Vec":
    return Tok2Vec(nlp.vocab, model, name)

class Tok2Vec(Pipe):
    def __init__(self, vocab: Vocab, model: Model, name: str = "tok2vec") -> None:
        """Initialize a tok2vec component.

        vocab (Vocab): The shared vocabulary.
        model (thinc.api.Model): The Thinc Model powering the pipeline component.
        name (str): The component instance name.

        DOCS: https://spacy.io/api/tok2vec#init
        """
        self.vocab = vocab
        self.model = model
        self.name = name
        self.listeners = []
        self.cfg = {}

    def add_listener(self, listener: "Tok2VecListener") -> None:
        self.listeners.append(listener)

    def find_listeners(self, model: Model) -> None:
        for node in model.walk():
            if isinstance(node, Tok2VecListener) and node.upstream_name in (
                "*",
                self.name,
            ):
                self.add_listener(node)

    def __call__(self, doc: Doc) -> Doc:
        """Add context-sensitive embeddings to the Doc.tensor attribute.

        docs (Doc): The Doc to preocess.
        RETURNS (Doc): The processed Doc.

        DOCS: https://spacy.io/api/tok2vec#call
        """
        tokvecses = self.predict([doc])
        self.set_annotations([doc], tokvecses)
        return doc

    def pipe(self, stream: Iterator[Doc], *, batch_size: int = 128) -> Iterator[Doc]:
        """Apply the pipe to a stream of documents. This usually happens under
        the hood when the nlp object is called on a text and all components are
        applied to the Doc.

        stream (Iterable[Doc]): A stream of documents.
        batch_size (int): The number of documents to buffer.
        YIELDS (Doc): Processed documents in order.

        DOCS: https://spacy.io/api/tok2vec#pipe
        """
        for docs in minibatch(stream, batch_size):
            docs = list(docs)
            tokvecses = self.predict(docs)
            self.set_annotations(docs, tokvecses)
            yield from docs

    def predict(self, docs: Iterable[Doc]):
        """Apply the pipeline's model to a batch of docs, without modifying them.
        Returns a single tensor for a batch of documents.

        docs (Iterable[Doc]): The documents to predict.
        RETURNS: Vector representations for each token in the documents.

        DOCS: https://spacy.io/api/tok2vec#predict
        """
        tokvecs = self.model.predict(docs)
        batch_id = Tok2VecListener.get_batch_id(docs)
        for listener in self.listeners:
            listener.receive(batch_id, tokvecs, None)
        return tokvecs

    def set_annotations(self, docs: Sequence[Doc], tokvecses) -> None:
        """Modify a batch of documents, using pre-computed scores.

        docs (Iterable[Doc]): The documents to modify.
        tokvecses: The tensors to set, produced by Tok2Vec.predict.

        DOCS: https://spacy.io/api/tok2vec#predict
        """
        for doc, tokvecs in zip(docs, tokvecses):
            assert tokvecs.shape[0] == len(doc)
            doc.tensor = tokvecs

    def update(
        self,
        examples: Iterable[Example],
        *,
        drop: float = 0.0,
        sgd: Optional[Optimizer] = None,
        losses: Optional[Dict[str, float]] = None,
        set_annotations: bool = False,
    ):
        """Learn from a batch of documents and gold-standard information,
        updating the pipe's model.

        examples (Iterable[Example]): A batch of Example objects.
        drop (float): The dropout rate.
        set_annotations (bool): Whether or not to update the Example objects
            with the predictions.
        sgd (thinc.api.Optimizer): The optimizer.
        losses (Dict[str, float]): Optional record of the loss during training.
            Updated using the component name as the key.
        RETURNS (Dict[str, float]): The updated losses dictionary.

        DOCS: https://spacy.io/api/tok2vec#update
        """
        if losses is None:
            losses = {}
        docs = [eg.predicted for eg in examples]
        if isinstance(docs, Doc):
            docs = [docs]
        set_dropout_rate(self.model, drop)
        tokvecs, bp_tokvecs = self.model.begin_update(docs)
        d_tokvecs = [self.model.ops.alloc2f(*t2v.shape) for t2v in tokvecs]
        losses.setdefault(self.name, 0.0)

        def accumulate_gradient(one_d_tokvecs):
            """Accumulate tok2vec loss and gradient. This is passed as a callback
            to all but the last listener. Only the last one does the backprop.
            """
            nonlocal d_tokvecs
            for i in range(len(one_d_tokvecs)):
                d_tokvecs[i] += one_d_tokvecs[i]
                losses[self.name] += float((one_d_tokvecs[i] ** 2).sum())

        def backprop(one_d_tokvecs):
            """Callback to actually do the backprop. Passed to last listener."""
            accumulate_gradient(one_d_tokvecs)
            d_docs = bp_tokvecs(d_tokvecs)
            if sgd is not None:
                self.model.finish_update(sgd)
            return d_docs

        batch_id = Tok2VecListener.get_batch_id(docs)
        for listener in self.listeners[:-1]:
            listener.receive(batch_id, tokvecs, accumulate_gradient)
        self.listeners[-1].receive(batch_id, tokvecs, backprop)
        if set_annotations:
            self.set_annotations(docs, tokvecs)
        return losses

    def get_loss(self, examples, scores) -> None:
        pass

    def begin_training(
        self,
        get_examples: Callable[[], Iterable[Example]] = lambda: [],
        *,
        pipeline: Optional[List[Tuple[str, Callable[[Doc], Doc]]]] = None,
        sgd: Optional[Optimizer] = None,
    ):
        """Initialize the pipe for training, using data examples if available.

        get_examples (Callable[[], Iterable[Example]]): Optional function that
            returns gold-standard Example objects.
        pipeline (List[Tuple[str, Callable]]): Optional list of pipeline
            components that this component is part of. Corresponds to
            nlp.pipeline.
        sgd (thinc.api.Optimizer): Optional optimizer. Will be created with
            create_optimizer if it doesn't exist.
        RETURNS (thinc.api.Optimizer): The optimizer.

        DOCS: https://spacy.io/api/tok2vec#begin_training
        """
        docs = [Doc(Vocab(), words=["hello"])]
        self.model.initialize(X=docs)
        link_vectors_to_models(self.vocab)

class Tok2VecListener(Model):
    """A layer that gets fed its answers from an upstream connection,
    for instance from a component earlier in the pipeline.
    """

    name = "tok2vec-listener"

    def __init__(self, upstream_name: str, width: int) -> None:
        Model.__init__(self, name=self.name, forward=forward, dims={"nO": width})
        self.upstream_name = upstream_name
        self._batch_id = None
        self._outputs = None
        self._backprop = None

    @classmethod
    def get_batch_id(cls, inputs) -> int:
        return sum(sum(token.orth for token in doc) for doc in inputs)

    def receive(self, batch_id: int, outputs, backprop) -> None:
        self._batch_id = batch_id
        self._outputs = outputs
        self._backprop = backprop

    def verify_inputs(self, inputs) -> bool:
        if self._batch_id is None and self._outputs is None:
            raise ValueError(Errors.E954)
        else:
            batch_id = self.get_batch_id(inputs)
            if batch_id != self._batch_id:
                raise ValueError(Errors.E953.format(id1=batch_id, id2=self._batch_id))
            else:
                return True

def forward(model: Tok2VecListener, inputs, is_train: bool):
    if is_train:
        model.verify_inputs(inputs)
        return model._outputs, model._backprop
    else:
        return [doc.tensor for doc in inputs], lambda dX: []
<commit_msg>Fix Tok2Vec begin_training<commit_after>from typing import Iterator, Sequence, Iterable, Optional, Dict, Callable, List, Tuple
from thinc.api import Model, set_dropout_rate, Optimizer, Config

from .pipe import Pipe
from ..gold import Example
from ..tokens import Doc
from ..vocab import Vocab
from ..language import Language
from ..errors import Errors
from ..util import link_vectors_to_models, minibatch

default_model_config = """
[model]
@architectures = "spacy.HashEmbedCNN.v1"
pretrained_vectors = null
width = 96
depth = 4
embed_size = 2000
window_size = 1
maxout_pieces = 3
subword_features = true
dropout = null
"""
DEFAULT_TOK2VEC_MODEL = Config().from_str(default_model_config)["model"]

@Language.factory(
    "tok2vec", assigns=["doc.tensor"], default_config={"model": DEFAULT_TOK2VEC_MODEL}
)
def make_tok2vec(nlp: Language, name: str, model: Model) -> "Tok2Vec":
    return Tok2Vec(nlp.vocab, model, name)

class Tok2Vec(Pipe):
    def __init__(self, vocab: Vocab, model: Model, name: str = "tok2vec") -> None:
        """Initialize a tok2vec component.

        vocab (Vocab): The shared vocabulary.
        model (thinc.api.Model): The Thinc Model powering the pipeline component.
        name (str): The component instance name.

        DOCS: https://spacy.io/api/tok2vec#init
        """
        self.vocab = vocab
        self.model = model
        self.name = name
        self.listeners = []
        self.cfg = {}

    def add_listener(self, listener: "Tok2VecListener") -> None:
        self.listeners.append(listener)

    def find_listeners(self, model: Model) -> None:
        for node in model.walk():
            if isinstance(node, Tok2VecListener) and node.upstream_name in (
                "*",
                self.name,
            ):
                self.add_listener(node)

    def __call__(self, doc: Doc) -> Doc:
        """Add context-sensitive embeddings to the Doc.tensor attribute.

        docs (Doc): The Doc to preocess.
        RETURNS (Doc): The processed Doc.

        DOCS: https://spacy.io/api/tok2vec#call
        """
        tokvecses = self.predict([doc])
        self.set_annotations([doc], tokvecses)
        return doc

    def pipe(self, stream: Iterator[Doc], *, batch_size: int = 128) -> Iterator[Doc]:
        """Apply the pipe to a stream of documents. This usually happens under
        the hood when the nlp object is called on a text and all components are
        applied to the Doc.

        stream (Iterable[Doc]): A stream of documents.
        batch_size (int): The number of documents to buffer.
        YIELDS (Doc): Processed documents in order.

        DOCS: https://spacy.io/api/tok2vec#pipe
        """
        for docs in minibatch(stream, batch_size):
            docs = list(docs)
            tokvecses = self.predict(docs)
            self.set_annotations(docs, tokvecses)
            yield from docs

    def predict(self, docs: Iterable[Doc]):
        """Apply the pipeline's model to a batch of docs, without modifying them.
        Returns a single tensor for a batch of documents.

        docs (Iterable[Doc]): The documents to predict.
        RETURNS: Vector representations for each token in the documents.

        DOCS: https://spacy.io/api/tok2vec#predict
        """
        tokvecs = self.model.predict(docs)
        batch_id = Tok2VecListener.get_batch_id(docs)
        for listener in self.listeners:
            listener.receive(batch_id, tokvecs, None)
        return tokvecs

    def set_annotations(self, docs: Sequence[Doc], tokvecses) -> None:
        """Modify a batch of documents, using pre-computed scores.

        docs (Iterable[Doc]): The documents to modify.
        tokvecses: The tensors to set, produced by Tok2Vec.predict.

        DOCS: https://spacy.io/api/tok2vec#predict
        """
        for doc, tokvecs in zip(docs, tokvecses):
            assert tokvecs.shape[0] == len(doc)
            doc.tensor = tokvecs

    def update(
        self,
        examples: Iterable[Example],
        *,
        drop: float = 0.0,
        sgd: Optional[Optimizer] = None,
        losses: Optional[Dict[str, float]] = None,
        set_annotations: bool = False,
    ):
        """Learn from a batch of documents and gold-standard information,
        updating the pipe's model.

        examples (Iterable[Example]): A batch of Example objects.
        drop (float): The dropout rate.
        set_annotations (bool): Whether or not to update the Example objects
            with the predictions.
        sgd (thinc.api.Optimizer): The optimizer.
        losses (Dict[str, float]): Optional record of the loss during training.
            Updated using the component name as the key.
        RETURNS (Dict[str, float]): The updated losses dictionary.

        DOCS: https://spacy.io/api/tok2vec#update
        """
        if losses is None:
            losses = {}
        docs = [eg.predicted for eg in examples]
        if isinstance(docs, Doc):
            docs = [docs]
        set_dropout_rate(self.model, drop)
        tokvecs, bp_tokvecs = self.model.begin_update(docs)
        d_tokvecs = [self.model.ops.alloc2f(*t2v.shape) for t2v in tokvecs]
        losses.setdefault(self.name, 0.0)

        def accumulate_gradient(one_d_tokvecs):
            """Accumulate tok2vec loss and gradient. This is passed as a callback
            to all but the last listener. Only the last one does the backprop.
            """
            nonlocal d_tokvecs
            for i in range(len(one_d_tokvecs)):
                d_tokvecs[i] += one_d_tokvecs[i]
                losses[self.name] += float((one_d_tokvecs[i] ** 2).sum())

        def backprop(one_d_tokvecs):
            """Callback to actually do the backprop. Passed to last listener."""
            accumulate_gradient(one_d_tokvecs)
            d_docs = bp_tokvecs(d_tokvecs)
            if sgd is not None:
                self.model.finish_update(sgd)
            return d_docs

        batch_id = Tok2VecListener.get_batch_id(docs)
        for listener in self.listeners[:-1]:
            listener.receive(batch_id, tokvecs, accumulate_gradient)
        self.listeners[-1].receive(batch_id, tokvecs, backprop)
        if set_annotations:
            self.set_annotations(docs, tokvecs)
        return losses

    def get_loss(self, examples, scores) -> None:
        pass

    def begin_training(
        self,
        get_examples: Callable[[], Iterable[Example]] = lambda: [],
        *,
        pipeline: Optional[List[Tuple[str, Callable[[Doc], Doc]]]] = None,
        sgd: Optional[Optimizer] = None,
    ):
        """Initialize the pipe for training, using data examples if available.

        get_examples (Callable[[], Iterable[Example]]): Optional function that
            returns gold-standard Example objects.
        pipeline (List[Tuple[str, Callable]]): Optional list of pipeline
            components that this component is part of. Corresponds to
            nlp.pipeline.
        sgd (thinc.api.Optimizer): Optional optimizer. Will be created with
            create_optimizer if it doesn't exist.
        RETURNS (thinc.api.Optimizer): The optimizer.

        DOCS: https://spacy.io/api/tok2vec#begin_training
        """
        docs = [Doc(self.vocab, words=["hello"])]
        self.model.initialize(X=docs)
        link_vectors_to_models(self.vocab)

class Tok2VecListener(Model):
    """A layer that gets fed its answers from an upstream connection,
    for instance from a component earlier in the pipeline.
    """

    name = "tok2vec-listener"

    def __init__(self, upstream_name: str, width: int) -> None:
        Model.__init__(self, name=self.name, forward=forward, dims={"nO": width})
        self.upstream_name = upstream_name
        self._batch_id = None
        self._outputs = None
        self._backprop = None

    @classmethod
    def get_batch_id(cls, inputs) -> int:
        return sum(sum(token.orth for token in doc) for doc in inputs)

    def receive(self, batch_id: int, outputs, backprop) -> None:
        self._batch_id = batch_id
        self._outputs = outputs
        self._backprop = backprop

    def verify_inputs(self, inputs) -> bool:
        if self._batch_id is None and self._outputs is None:
            raise ValueError(Errors.E954)
        else:
            batch_id = self.get_batch_id(inputs)
            if batch_id != self._batch_id:
                raise ValueError(Errors.E953.format(id1=batch_id, id2=self._batch_id))
            else:
                return True

def forward(model: Tok2VecListener, inputs, is_train: bool):
    if is_train:
        model.verify_inputs(inputs)
        return model._outputs, model._backprop
    else:
        return [doc.tensor for doc in inputs], lambda dX: []
<|endoftext|>


<commit_before># coding=utf-8
#
# fysom.py - pYthOn Finite State Machine - this is a port of Jake
#                        Gordon's javascript-state-machine to python
#                        https://github.com/jakesgordon/javascript-state-machine
#
# Copyright (C) 2011 Mansour Behabadi <mansour@oxplot.com>, Jake Gordon
#                                        and other contributors
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
from __future__ import unicode_literals

__author__ = 'Mansour Behabadi'
__copyright__ = 'Copyright 2011, Mansour Behabadi and Jake Gordon'
__credits__ = ['Mansour Behabadi', 'Jake Gordon']
__license__ = 'MIT'
__version__ = '${version}'
__maintainer__ = 'Mansour Behabadi'
__email__ = 'mansour@oxplot.com'

class FysomError(Exception):
    pass

class Fysom(object):

    def __init__(self, cfg):
        self._apply(cfg)

    def isstate(self, state):
        return self.current == state

    def can(self, event):
        return event in self._map and self.current in self._map[event] \
            and not hasattr(self, 'transition')

    def cannot(self, event):
        return not self.can(event)

    def _apply(self, cfg):
        init = cfg['initial'] if 'initial' in cfg else None
        if isinstance(init, basestring):
            init = {'state': init}
        events = cfg['events'] if 'events' in cfg else []
        callbacks = cfg['callbacks'] if 'callbacks' in cfg else {}
        tmap = {}
        self._map = tmap

        def add(e):
            src = [e['src']] if isinstance(e['src'], basestring) else e['src']
            if e['name'] not in tmap:
                tmap[e['name']] = {}
            for s in src:
                tmap[e['name']][s] = e['dst']

        if init:
            if 'event' not in init:
                init['event'] = 'startup'
            add({'name': init['event'], 'src': 'none', 'dst': init['state']})

        for e in events:
            add(e)

        for name in tmap:
            setattr(self, name, self._build_event(name))

        for name in callbacks:
            setattr(self, name, callbacks[name])

        self.current = 'none'

        if init and 'defer' not in init:
            getattr(self, init['event'])()

    def _build_event(self, event):

        def fn(**kwargs):

            if hasattr(self, 'transition'):
                raise FysomError("event %s inappropriate because previous transition did not complete" % event)
            if not self.can(event):
                raise FysomError("event %s inappropriate in current state %s" % (event, self.current))

            src = self.current
            dst = self._map[event][src]

            class _e_obj(object):
                pass
            e = _e_obj()
            e.fsm, e.event, e.src, e.dst = self, event, src, dst
            for k in kwargs:
                setattr(e, k, kwargs[k])

            if self.current != dst:
                if self._before_event(e) is False:
                    return

                def _tran():
                    delattr(self, 'transition')
                    self.current = dst
                    self._enter_state(e)
                    self._change_state(e)
                    self._after_event(e)
                self.transition = _tran

            if self._leave_state(e) is not False:
                if hasattr(self, 'transition'):
                    self.transition()

        return fn

    def _before_event(self, e):
        fnname = 'onbefore' + e.event
        if hasattr(self, fnname):
            return getattr(self, fnname)(e)

    def _after_event(self, e):
        for fnname in ['onafter' + e.event, 'on' + e.event]:
            if hasattr(self, fnname):
                return getattr(self, fnname)(e)

    def _leave_state(self, e):
        fnname = 'onleave' + e.src
        if hasattr(self, fnname):
            return getattr(self, fnname)(e)

    def _enter_state(self, e):
        for fnname in ['onenter' + e.dst, 'on' + e.dst]:
            if hasattr(self, fnname):
                return getattr(self, fnname)(e)

    def _change_state(self, e):
        fnname = 'onchangestate'
        if hasattr(self, fnname):
            return getattr(self, fnname)(e)
<commit_msg>extracting method for basestring compatibility<commit_after># coding=utf-8
#
# fysom.py - pYthOn Finite State Machine - this is a port of Jake
#                        Gordon's javascript-state-machine to python
#                        https://github.com/jakesgordon/javascript-state-machine
#
# Copyright (C) 2011 Mansour Behabadi <mansour@oxplot.com>, Jake Gordon
#                                        and other contributors
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

__author__ = 'Mansour Behabadi'
__copyright__ = 'Copyright 2011, Mansour Behabadi and Jake Gordon'
__credits__ = ['Mansour Behabadi', 'Jake Gordon']
__license__ = 'MIT'
__version__ = '${version}'
__maintainer__ = 'Mansour Behabadi'
__email__ = 'mansour@oxplot.com'

class FysomError(Exception):
    pass

class Fysom(object):

    def __init__(self, cfg):
        self._apply(cfg)

    def isstate(self, state):
        return self.current == state

    def can(self, event):
        return event in self._map and self.current in self._map[event] \
            and not hasattr(self, 'transition')

    def cannot(self, event):
        return not self.can(event)

    def _apply(self, cfg):
        init = cfg['initial'] if 'initial' in cfg else None
        if self._is_base_string(init):
            init = {'state': init}
        events = cfg['events'] if 'events' in cfg else []
        callbacks = cfg['callbacks'] if 'callbacks' in cfg else {}
        tmap = {}
        self._map = tmap

        def add(e):
            src = [e['src']] if self._is_base_string(e['src']) else e['src']
            if e['name'] not in tmap:
                tmap[e['name']] = {}
            for s in src:
                tmap[e['name']][s] = e['dst']

        if init:
            if 'event' not in init:
                init['event'] = 'startup'
            add({'name': init['event'], 'src': 'none', 'dst': init['state']})

        for e in events:
            add(e)

        for name in tmap:
            setattr(self, name, self._build_event(name))

        for name in callbacks:
            setattr(self, name, callbacks[name])

        self.current = 'none'

        if init and 'defer' not in init:
            getattr(self, init['event'])()

    def _build_event(self, event):

        def fn(**kwargs):

            if hasattr(self, 'transition'):
                raise FysomError("event %s inappropriate because previous transition did not complete" % event)
            if not self.can(event):
                raise FysomError("event %s inappropriate in current state %s" % (event, self.current))

            src = self.current
            dst = self._map[event][src]

            class _e_obj(object):
                pass
            e = _e_obj()
            e.fsm, e.event, e.src, e.dst = self, event, src, dst
            for k in kwargs:
                setattr(e, k, kwargs[k])

            if self.current != dst:
                if self._before_event(e) is False:
                    return

                def _tran():
                    delattr(self, 'transition')
                    self.current = dst
                    self._enter_state(e)
                    self._change_state(e)
                    self._after_event(e)
                self.transition = _tran

            if self._leave_state(e) is not False:
                if hasattr(self, 'transition'):
                    self.transition()

        return fn

    def _before_event(self, e):
        fnname = 'onbefore' + e.event
        if hasattr(self, fnname):
            return getattr(self, fnname)(e)

    def _after_event(self, e):
        for fnname in ['onafter' + e.event, 'on' + e.event]:
            if hasattr(self, fnname):
                return getattr(self, fnname)(e)

    def _leave_state(self, e):
        fnname = 'onleave' + e.src
        if hasattr(self, fnname):
            return getattr(self, fnname)(e)

    def _enter_state(self, e):
        for fnname in ['onenter' + e.dst, 'on' + e.dst]:
            if hasattr(self, fnname):
                return getattr(self, fnname)(e)

    def _change_state(self, e):
        fnname = 'onchangestate'
        if hasattr(self, fnname):
            return getattr(self, fnname)(e)

    def _is_base_string(self, object):
        try:
            return isinstance(object, basestring)
        except NameError:
            return isinstance(object, str)
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
import pywikibot
import time

#what should be snapshoted?
mainPageTitle = {
    'en' : u'Main Page',
    'de' : u'Wikipedia:Hauptseite'
}
#will be added at the end of the snapshoted page
archivePageOutro = {
    'en' : u'',
    'de' : u'\n[[Kategorie:Wikipedia:Hauptseite Archiv]]'
}
#where to put the snapshoted page
archiveTitlePrefix = {
    'en' : u'Wikipedia:Main Page history/',
#    'de' : u'Wikipedia:Hauptseite/Archiv/'
    'de' : u'Benutzer:Sitic/'
}
#script will generate pages archiveTitlePrefix + localize(dateformat)
dateformat = {
    'en' : u'{year} {monthName} {day}',
    'de' : u'{day}. {monthName} {year}'
}
#where to update the template
templateTitle = {
    'en' : u'Template:Main Page history',
    'de' : u'Wikipedia:Hauptseite/Archiv/Vorlage'
}
archiveComment = {
    'en' : u'Bot: creating snapshot of the current [[Main Page]]',
    'de' : u'[[WP:Bot|Bot]]: erstelle Abbild der heutigen [[Wikipedia:Hauptseite|Hauptseite]]'
}
newMonthComment = {
    'en' : u'Bot: adding links to next month',
    'de' : u'[[WP:Bot|Bot]]: Vorbereitung für den nächsten Monat'
}

yearsPageIntro = (u'<noinclude>{{Kasten|Diese Seite wird in [[Wikipedia:'
        u'Archiv der Hauptseite]] eingebunden und automatisch von [[Benutzer:'
        u'AsuraBot]] verwaltet.}}</noinclude>\n')

class SnapMain():
    def __init__(self):
        self.site = pywikibot.Site()
        self.site.login()

        self.day = time.localtime().tm_mday
        self.monthName = pywikibot.date.monthName(self.site.language(),
                time.localtime().tm_mon)
        if time.localtime().tm_mon == 12: # end of the year?
            self.nextmonthName = pywikibot.date.monthName(self.site.language(),
                    1)
        else:
            self.nextmonthName = pywikibot.date.monthName(self.site.language(),
                    time.localtime().tm_mon + 1)

        self.year = time.localtime().tm_year
        self.nextyear = time.localtime().tm_year + 1

        self.snap()

        self.maxDays = pywikibot.date.getNumberOfDaysInMonth(
                time.localtime().tm_mon)
        if time.localtime().tm_mday == self.maxDays: #end of the month?
            self.new_month()

        ##debug
        #self.new_month()

    def format_date(self, day, monthName, year):
        """
        return a string with the formated date (e.g. u'31. Dezember 2013')
        """
        l_dateformat = pywikibot.translate(self.site, dateformat,
                fallback=False)
        return l_dateformat.format(day=day, monthName=monthName, year=year)

    def isleapyear(n):
        if n % 400 == 0:
            return True
        if n % 100 == 0:
            return False
        if n % 4 == 0:
            return True
        else:
            return False

    def snap(self):
        pywikibot.output(u'creating snapshot for today: ' +
                self.format_date(self.day, self.monthName, self.year))
        l_mainPageTitle      = pywikibot.translate(self.site, mainPageTitle,
                fallback=False)
        l_archiveTitlePrefix = pywikibot.translate(self.site,
                archiveTitlePrefix, fallback=False)
        l_archivePageOutro   = pywikibot.translate(self.site, archivePageOutro,
                fallback=False)
        l_archiveComment     = pywikibot.translate(self.site, archiveComment,
                fallback=False)

        mainPage = pywikibot.Page(self.site, l_mainPageTitle)
        date = self.format_date(self.day, self.monthName, self.year)
        archivePage = pywikibot.Page(self.site, l_archiveTitlePrefix + date)

        archivePage.text = pywikibot.removeLanguageLinks(mainPage.expand_text())
        archivePage.text = pywikibot.removeCategoryLinks(archivePage.text)
        archivePage.text += l_archivePageOutro

        print archivePage.text
        #archivePage.save(comment=l_archiveComment, botflag=False, minor=False)

    def new_month(self):
        pywikibot.output(u'new month, updating template')
        l_archiveTitlePrefix = pywikibot.translate(self.site,
                archiveTitlePrefix, fallback=False)
        l_templateTitle   = pywikibot.translate(self.site, templateTitle,
                fallback=False)
        l_newMonthComment = pywikibot.translate(self.site, newMonthComment,
                fallback=False)

        templatePage = pywikibot.Page(self.site, l_templateTitle)
        if time.localtime().tm_mon == 12: # end of the year?
            newYearTable = u'\n\n\n{{|\n|+ \'\'\'{year}\'\'\'\n|}}'
            templatePage.text += newYearTable.format(year=self.nextyear)

            self.year = self.nextyear
            maxDays = 31 #January
        else:
            #check for leap year, getNumberOfDaysInMonth() does not do that
            if isleapyear(self.year) and time.localtime().tm_mon == 1:
                maxDays = 29
            else:
                maxDays = pywikibot.date.getNumberOfDaysInMonth(
                    time.localtime().tm_mon + 1)

        templatePage.text = templatePage.text[:-1] + u'-\n| ' + self.nextmonthName

        for i in range(1, maxDays + 1):
            templatePage.text += u'|| [[' + l_archiveTitlePrefix +\
                    self.format_date(i, self.nextmonthName, self.year) +\
                    u'|' + i.__str__() + u']]'

        templatePage.text += u'\n|}'
        print templatePage.text
        #templatePage.save(comment=l_newMonthComment, botflag=False)

if __name__ == "__main__":
    try:
        SnapMain()
    finally:
        pywikibot.stopme()
<commit_msg>Danu: now in production<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
import pywikibot
import time

#what should be snapshoted?
mainPageTitle = {
    'en' : u'Main Page',
    'de' : u'Wikipedia:Hauptseite'
}
#will be added at the top of the snapshoted page
archivePageIntro = {
    'en' : u'',
    'de' : u'{{{{Wikipedia:Hauptseite/Archiv/Vorlage|Tag={day}|Monat={month}|Jahr={year}}}}}\n'
}
#where to put the snapshoted page
archiveTitlePrefix = {
    'en' : u'Wikipedia:Main Page history/',
    'de' : u'Wikipedia:Hauptseite/Archiv/'
}
#script will generate pages archiveTitlePrefix + localize(dateformat)
dateformat = {
    'en' : u'{year} {monthName} {day}',
    'de' : u'{day}. {monthName} {year}'
}
#where to update the template
templateTitle = {
    'en' : u'Template:Main Page history',
    'de' : u'Wikipedia:Hauptseite/Archiv'
}
archiveComment = {
    'en' : u'Bot: creating snapshot of the current [[Main Page]]',
    'de' : u'[[WP:Bot|Bot]]: erstelle Abbild der heutigen [[Wikipedia:Hauptseite|Hauptseite]]'
}
newMonthComment = {
    'en' : u'Bot: adding links to next month',
    'de' : u'[[WP:Bot|Bot]]: Vorbereitung für den nächsten Monat'
}

yearsPageIntro = (u'<noinclude>{{Kasten|Diese Seite wird in [[Wikipedia:'
        u'Archiv der Hauptseite]] eingebunden und automatisch von [[Benutzer:'
        u'AsuraBot]] verwaltet.}}</noinclude>\n')

class SnapMain():
    def __init__(self):
        self.site = pywikibot.Site()
        self.site.login()

        self.day = time.localtime().tm_mday
	self.month = time.localtime().tm_mon
        self.monthName = pywikibot.date.monthName(self.site.language(),
                self.month)
        if self.month == 12: # end of the year?
            self.nextmonthName = pywikibot.date.monthName(self.site.language(),
                    1)
        else:
            self.nextmonthName = pywikibot.date.monthName(self.site.language(),
                    self.month + 1)

        self.year = time.localtime().tm_year
        self.nextyear = time.localtime().tm_year + 1

        self.snap()

        self.maxDays = pywikibot.date.getNumberOfDaysInMonth(
                time.localtime().tm_mon)
        if time.localtime().tm_mday == self.maxDays: #end of the month?
            self.new_month()

    def format_date(self, day, monthName, year):
        """
        return a string with the formated date (e.g. u'31. Dezember 2013')
        """
        l_dateformat = pywikibot.translate(self.site, dateformat,
                fallback=False)
        return l_dateformat.format(day=day, monthName=monthName, year=year)

    def isleapyear(n):
        if n % 400 == 0:
            return True
        if n % 100 == 0:
            return False
        if n % 4 == 0:
            return True
        else:
            return False

    def snap(self):
        pywikibot.output(u'creating snapshot for today: ' +
                self.format_date(self.day, self.monthName, self.year))
        l_mainPageTitle      = pywikibot.translate(self.site, mainPageTitle,
                fallback=False)
        l_archiveTitlePrefix = pywikibot.translate(self.site,
                archiveTitlePrefix, fallback=False)
        l_archivePageIntro   = pywikibot.translate(self.site, archivePageIntro,
                fallback=False)
        l_archiveComment     = pywikibot.translate(self.site, archiveComment,
                fallback=False)

	l_archivePageIntro = l_archivePageIntro.format(day=time.strftime('%d'),
			month=time.strftime('%m'), year=self.year)

        mainPage = pywikibot.Page(self.site, l_mainPageTitle)
        date = self.format_date(self.day, self.monthName, self.year)
        archivePage = pywikibot.Page(self.site, l_archiveTitlePrefix + date)

        archivePage.text = pywikibot.removeLanguageLinks(mainPage.expand_text())
        archivePage.text = pywikibot.removeCategoryLinks(archivePage.text)
        archivePage.text = l_archivePageIntro + archivePage.text

        archivePage.save(comment=l_archiveComment, botflag=False, minor=False)

    def new_month(self):
        pywikibot.output(u'new month, updating template')
        l_archiveTitlePrefix = pywikibot.translate(self.site,
                archiveTitlePrefix, fallback=False)
        l_templateTitle   = pywikibot.translate(self.site, templateTitle,
                fallback=False)
        l_newMonthComment = pywikibot.translate(self.site, newMonthComment,
                fallback=False)

        templatePage = pywikibot.Page(self.site, l_templateTitle)
        if time.localtime().tm_mon == 12: # end of the year?
            newYearTable = u'\n\n\n{{|\n|+ \'\'\'{year}\'\'\'\n|}}'
            templatePage.text += newYearTable.format(year=self.nextyear)

            self.year = self.nextyear
            maxDays = 31 #January
        else:
            #check for leap year, getNumberOfDaysInMonth() does not do that
            if isleapyear(self.year) and time.localtime().tm_mon == 1:
                maxDays = 29
            else:
                maxDays = pywikibot.date.getNumberOfDaysInMonth(
                    time.localtime().tm_mon + 1)

        templatePage.text = templatePage.text[:-1] + u'-\n| ' + self.nextmonthName

        for i in range(1, maxDays + 1):
            templatePage.text += u'|| [[' + l_archiveTitlePrefix +\
                    self.format_date(i, self.nextmonthName, self.year) +\
                    u'|' + i.__str__() + u']]'

        templatePage.text += u'\n|}'
        print templatePage.text
        #templatePage.save(comment=l_newMonthComment, botflag=False)

if __name__ == "__main__":
    try:
        SnapMain()
    finally:
        pywikibot.stopme()
<|endoftext|>


<commit_before>class Node:
    '''By default data will be None unless explicitly set'''
    def __init__(self, data=None, next_node=None):
        self.data = data
        self.next_node = next_node

<commit_msg>Removed Node.py and foled the Node class directly into the LinkedList module<commit_after><|endoftext|>


<commit_before># Copyright (c) 2004-2007 rPath, Inc.
#
# This program is distributed under the terms of the Common Public License,
# version 1.0. A copy of this license should have been distributed with this
# source file in a file called LICENSE. If it is not present, the license
# is always available at http://www.rpath.com/permanent/licenses/CPL-1.0.
#
# This program is distributed in the hope that it will be useful, but
# without any warranty; without even the implied warranty of merchantability
# or fitness for a particular purpose. See the Common Public License for
# full details.
#
# Dependency resolution for the server side

from conary import versions
from conary.deps import deps
from conary.local.deptable import NO_FLAG_MAGIC
from conary.repository import trovesource
from conary.server import schema

class DependencyTables:
    def __init__(self, db):
        self.db = db

    # we need to extract the instanceids for the troves we were passed
    # in, plus the instanceIds of their included troves
    def _setupTroveList(self, cu, troveList):
        if not troveList:
            return
        schema.resetTable(cu, "tmpInstances")
        schema.resetTable(cu, "tmpId")

        cu.executemany("""
        insert into tmpInstances(instanceId)
        select instanceId
        from Instances
        join Items on Instances.itemId = Items.itemId
        JOIN versions on Instances.versionId = Versions.versionId
        join Flavors on Instances.flavorId = Flavors.flavorId
        where Items.item = ? and Versions.version = ? and Flavors.flavor = ?
        """, troveList, start_transaction=False )
        self.db.analyze("tmpInstances")
        # now grab the instanceIds of their included troves, avoiding duplicates
        cu.execute("""
        insert into tmpId(id)
        select distinct tt.includedId
        from tmpInstances as ti
        join TroveTroves as tt using(instanceId)
        """, start_transaction=False)
        # drop the ones we already have
        cu.execute("delete from tmpId where id in "
                   "(select instanceId from tmpInstances)",
                   start_transaction=False)
        # append the remaining instanceIds
        cu.execute("insert into tmpInstances(instanceId) select id from tmpId",
                   start_transaction=False)
        self.db.analyze("tmpInstances")

    # Prepare temporary Dependency lookup tables for execution
    def _setupDepSets(self, cu, depSetList, reset=True):
        if reset:
            schema.resetTable(cu, "tmpDeps")
            schema.resetTable(cu, "tmpDepNum")
        # count how many dep classes are in each depSet
        depNums = []
        for i, depSet in enumerate(depSetList):
            depNum = 0
            for classId, depClass in depSet.getDepClasses().iteritems():
                for dep in depClass.getDeps():
                    for (depName, flags) in zip(dep.getName(), dep.getFlags()):
                        cu.execute("""
                        insert into tmpDeps(idx, depNum, class, name, flag)
                        values (?, ?, ?, ?, ?)""",
                                   (i, depNum, classId, depName, NO_FLAG_MAGIC))
                        if flags:
                            for flag, sense in flags:
                                # assert sense is required
                                cu.execute("""
                                insert into tmpDeps(idx, depNum, class, name, flag)
                                values (?, ?, ?, ?, ?)""",
                                           (i, depNum, classId, depName, flag))
                    cu.execute("""insert into tmpDepNum(idx, depNum, flagCount)
                    values (?, ?, ?)""", (i, depNum, len(flags)+1))
                    depNum += 1
            depNums.append(depNum)
        self.db.analyze("tmpDeps")
        self.db.analyze("tmpDepNum")
        return depNums

    def resolve(self, groupIds, label, depList, troveList=[], leavesOnly = False):
        """ Determine troves that provide the given dependencies,
            restricting by label and limiting to latest version for
            each (name, flavor) pair.
        """
        cu = self.db.cursor()
        # need to make sure that depList does not contain duplicates
        # for efficiency reasons
        requires = {}
        for depStr in depList:
            depSet = deps.ThawDependencySet(depStr)
            requires[depSet] = depStr
        depSetList = requires.keys()
        depNums = self._setupDepSets(cu, depSetList)

        # 1. look up inmstances whose provides fully satisfy all the
        #    flags of every depName within a depSet (flagCount check)
        # 2. out of those instances, only consider the ones that fully
        #    satisfy all the depName deps within a depSet (depCount
        #    check)
        # 3. filter only the instanceIds the user has access to
        query = """
        select distinct
            tmpDepNum.idx as idx, tmpDepNum.depNum as depNum,
            Items.item, flavor, version, Nodes.timeStamps,
            Nodes.finalTimestamp as finalTimestamp
        from tmpDepNum
        join (
            select
                tmpDeps.idx as idx,
                tmpDeps.depNum as depNum,
                Provides.instanceId as instanceid,
                count(*) as flagCount
            from tmpDeps
            join Dependencies using(class, name, flag)
            join Provides using(depId)
            group by tmpDeps.idx, tmpDeps.depNum, Provides.instanceId
        ) as DepSelect using(idx, depNum, flagCount)
        join Instances on
            Instances.instanceId = DepSelect.instanceId
        join Nodes using(itemId, versionId) """

        where = ["ugi.userGroupId in (%s)" % (
            ",".join("%d" % x for x in groupIds),)]
        args = []
        if troveList:
            self._setupTroveList(cu, troveList)
            query += """
            join tmpInstances as ti on ti.instanceId = Instances.instanceId
            join UserGroupInstancesCache as ugi on
                ugi.instanceId = ti.instanceId """
        else:
            if leavesOnly:
                query += """
                join LatestCache as ugi using (itemId, versionId, branchId) """
                where.append("ugi.latestType = %d" % trovesource.TROVE_QUERY_NORMAL)
                where.append("ugi.flavorId = Instances.flavorId")
            else:
                query += """
                join UserGroupInstancesCache as ugi on
                    ugi.instanceId = Instances.instanceId """
            # restrict by label
            if label:
                query += """
                join LabelMap on
                    Instances.itemId = LabelMap.itemId and
                    Nodes.branchId = LabelMap.branchId
                join Labels using (labelId) """
                where.append("Labels.label = ?")
                args.append(label)
        # final joins to allow us to extract the query results as strings
        query += """
        join Items on Instances.itemId = Items.itemId
        join Versions on Instances.versionId = Versions.versionId
        join Flavors on Instances.flavorId = Flavors.flavorId
        where %s
        order by idx, depNum, finalTimestamp desc """ % (
            " and ".join(where))
        cu.execute(query, args)

        ret = {}
        # sqlite version 3.2.2 have trouble sorting correctly the
        # results from the previous query. If we're running on sqlite,
        # we take the hit here and resort the results in Python...
        if self.db.driver == "sqlite":
            # order by idx, depNum, finalTimestamp desc
            retList = sorted(cu, lambda a: (a[0], a[1], -a[6]))
        else:
            retList = cu

        for (depId, depNum, troveName, flavorStr, versionStr, timeStamps, ft) in retList:
            retd = ret.setdefault(depId, [{} for x in xrange(depNums[depId])])
            # remember the first version of each (n,f) tuple for each query
            retd[depNum].setdefault((troveName, flavorStr), (versionStr, timeStamps))
        result = {}
        for depId, depDictList in ret.iteritems():
            key = requires[depSetList[depId]]
            retList = result.setdefault(key, [ [] for x in xrange(len(depDictList)) ])
            for i, depDict in enumerate(depDictList):
                retList[i] = [ (trv[0], versions.strToFrozen(ver[0], ver[1].split(":")),
                                trv[1]) for trv, ver in depDict.iteritems() ]
        return result
<commit_msg>fix typo<commit_after># Copyright (c) 2004-2007 rPath, Inc.
#
# This program is distributed under the terms of the Common Public License,
# version 1.0. A copy of this license should have been distributed with this
# source file in a file called LICENSE. If it is not present, the license
# is always available at http://www.rpath.com/permanent/licenses/CPL-1.0.
#
# This program is distributed in the hope that it will be useful, but
# without any warranty; without even the implied warranty of merchantability
# or fitness for a particular purpose. See the Common Public License for
# full details.
#
# Dependency resolution for the server side

from conary import versions
from conary.deps import deps
from conary.local.deptable import NO_FLAG_MAGIC
from conary.repository import trovesource
from conary.server import schema

class DependencyTables:
    def __init__(self, db):
        self.db = db

    # we need to extract the instanceids for the troves we were passed
    # in, plus the instanceIds of their included troves
    def _setupTroveList(self, cu, troveList):
        if not troveList:
            return
        schema.resetTable(cu, "tmpInstances")
        schema.resetTable(cu, "tmpId")

        cu.executemany("""
        insert into tmpInstances(instanceId)
        select instanceId
        from Instances
        join Items on Instances.itemId = Items.itemId
        JOIN versions on Instances.versionId = Versions.versionId
        join Flavors on Instances.flavorId = Flavors.flavorId
        where Items.item = ? and Versions.version = ? and Flavors.flavor = ?
        """, troveList, start_transaction=False )
        self.db.analyze("tmpInstances")
        # now grab the instanceIds of their included troves, avoiding duplicates
        cu.execute("""
        insert into tmpId(id)
        select distinct tt.includedId
        from tmpInstances as ti
        join TroveTroves as tt using(instanceId)
        """, start_transaction=False)
        # drop the ones we already have
        cu.execute("delete from tmpId where id in "
                   "(select instanceId from tmpInstances)",
                   start_transaction=False)
        # append the remaining instanceIds
        cu.execute("insert into tmpInstances(instanceId) select id from tmpId",
                   start_transaction=False)
        self.db.analyze("tmpInstances")

    # Prepare temporary Dependency lookup tables for execution
    def _setupDepSets(self, cu, depSetList, reset=True):
        if reset:
            schema.resetTable(cu, "tmpDeps")
            schema.resetTable(cu, "tmpDepNum")
        # count how many dep classes are in each depSet
        depNums = []
        for i, depSet in enumerate(depSetList):
            depNum = 0
            for classId, depClass in depSet.getDepClasses().iteritems():
                for dep in depClass.getDeps():
                    for (depName, flags) in zip(dep.getName(), dep.getFlags()):
                        cu.execute("""
                        insert into tmpDeps(idx, depNum, class, name, flag)
                        values (?, ?, ?, ?, ?)""",
                                   (i, depNum, classId, depName, NO_FLAG_MAGIC))
                        if flags:
                            for flag, sense in flags:
                                # assert sense is required
                                cu.execute("""
                                insert into tmpDeps(idx, depNum, class, name, flag)
                                values (?, ?, ?, ?, ?)""",
                                           (i, depNum, classId, depName, flag))
                    cu.execute("""insert into tmpDepNum(idx, depNum, flagCount)
                    values (?, ?, ?)""", (i, depNum, len(flags)+1))
                    depNum += 1
            depNums.append(depNum)
        self.db.analyze("tmpDeps")
        self.db.analyze("tmpDepNum")
        return depNums

    def resolve(self, groupIds, label, depList, troveList=[], leavesOnly = False):
        """ Determine troves that provide the given dependencies,
            restricting by label and limiting to latest version for
            each (name, flavor) pair.
        """
        cu = self.db.cursor()
        # need to make sure that depList does not contain duplicates
        # for efficiency reasons
        requires = {}
        for depStr in depList:
            depSet = deps.ThawDependencySet(depStr)
            requires[depSet] = depStr
        depSetList = requires.keys()
        depNums = self._setupDepSets(cu, depSetList)

        # 1. look up inmstances whose provides fully satisfy all the
        #    flags of every depName within a depSet (flagCount check)
        # 2. out of those instances, only consider the ones that fully
        #    satisfy all the depName deps within a depSet (depCount
        #    check)
        # 3. filter only the instanceIds the user has access to
        query = """
        select distinct
            tmpDepNum.idx as idx, tmpDepNum.depNum as depNum,
            Items.item, flavor, version, Nodes.timeStamps,
            Nodes.finalTimestamp as finalTimestamp
        from tmpDepNum
        join (
            select
                tmpDeps.idx as idx,
                tmpDeps.depNum as depNum,
                Provides.instanceId as instanceid,
                count(*) as flagCount
            from tmpDeps
            join Dependencies using(class, name, flag)
            join Provides using(depId)
            group by tmpDeps.idx, tmpDeps.depNum, Provides.instanceId
        ) as DepSelect using(idx, depNum, flagCount)
        join Instances on
            Instances.instanceId = DepSelect.instanceId
        join Nodes using(itemId, versionId) """

        where = ["ugi.userGroupId in (%s)" % (
            ",".join("%d" % x for x in groupIds),)]
        args = []
        if troveList:
            self._setupTroveList(cu, troveList)
            query += """
            join tmpInstances as ti on ti.instanceId = Instances.instanceId
            join UserGroupInstancesCache as ugi on
                ugi.instanceId = ti.instanceId """
        else:
            if leavesOnly:
                query += """
                join LatestCache as ugi using (itemId, versionId, branchId) """
                where.append("ugi.latestType = %d" % trovesource.TROVE_QUERY_NORMAL)
                where.append("ugi.flavorId = Instances.flavorId")
            else:
                query += """
                join UserGroupInstancesCache as ugi on
                    ugi.instanceId = Instances.instanceId """
            # restrict by label
            if label:
                query += """
                join LabelMap on
                    Instances.itemId = LabelMap.itemId and
                    Nodes.branchId = LabelMap.branchId
                join Labels using (labelId) """
                where.append("Labels.label = ?")
                args.append(label)
        # final joins to allow us to extract the query results as strings
        query += """
        join Items on Instances.itemId = Items.itemId
        join Versions on Instances.versionId = Versions.versionId
        join Flavors on Instances.flavorId = Flavors.flavorId
        where %s
        order by idx, depNum, finalTimestamp desc """ % (
            " and ".join(where))
        cu.execute(query, args)

        ret = {}
        # sqlite version 3.2.2 have trouble sorting correctly the
        # results from the previous query. If we're running on sqlite,
        # we take the hit here and resort the results in Python...
        if self.db.driver == "sqlite":
            # order by idx, depNum, finalTimestamp desc
            retList = sorted(cu, key = lambda a: (a[0], a[1], -a[6]))
        else:
            retList = cu

        for (depId, depNum, troveName, flavorStr, versionStr, timeStamps, ft) in retList:
            retd = ret.setdefault(depId, [{} for x in xrange(depNums[depId])])
            # remember the first version of each (n,f) tuple for each query
            retd[depNum].setdefault((troveName, flavorStr), (versionStr, timeStamps))
        result = {}
        for depId, depDictList in ret.iteritems():
            key = requires[depSetList[depId]]
            retList = result.setdefault(key, [ [] for x in xrange(len(depDictList)) ])
            for i, depDict in enumerate(depDictList):
                retList[i] = [ (trv[0], versions.strToFrozen(ver[0], ver[1].split(":")),
                                trv[1]) for trv, ver in depDict.iteritems() ]
        return result
<|endoftext|>


<commit_before># -*- coding: UTF-8 -*-
# Copyright 2009-2018 Rumma & Ko Ltd
# License: BSD (see file COPYING for details)

# Note that this module may not have a docstring because any
# global variable defined here will override the global
# namespace of lino/__init__.py who includes it with execfile.

# This module is part of the Lino test suite.
# To test only this module:
#
#   $ python setup.py test -s tests.PackagesTests

from __future__ import unicode_literals
import sys

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

install_requires = [
    # 'Sphinx',
    'django',
    'atelier', 'unipath', 'python_dateutil', 'dateparser',
    'etgen',
    'Babel', 'lxml',
    'beautifulsoup4',
    'pisa',
    'jinja2', 'pytidylib', 'PyYAML',
    'clint',  # lino.modlib.checkdata.management.commands
    'django-localflavor',  # lino.modlib.sepa
    # 'django-iban',  # lino.modlib.sepa
    'openpyxl', 'html2text',
    # 'cairocffi',  # 'cairocffi<0.7',
    # 'bleach',
    # 'html5lib',  # version 7x9 (not 9x9) required by bleach
    'schedule',
    'django-wkhtmltopdf',
    'beautifulsoup4']

if PY2:
    install_requires.append('reportlab<2.7')
    # install_requires.append('django<2')
    install_requires.append('weasyprint<0.43')
else:
    # install_requires.append('django')
    install_requires.append('reportlab')
    install_requires.append('weasyprint')

SETUP_INFO = dict(
    name='lino',
    version='18.12.0',
    install_requires=install_requires,
    description="A framework for writing desktop-like web applications "
                "using Django and ExtJS",
    license='BSD License',
    # obsoletes=['djangosite', 'north'],
    author='Luc Saffre',
    author_email='luc@lino-framework.org',
    url="http://www.lino-framework.org",
    # ~ test_suite = 'lino.test_apps',
    test_suite='tests')

SETUP_INFO.update(long_description="""

.. raw:: html

Lino is a high-level framework for writing desktop-like customized
database applications based on `Django <https://www.djangoproject.com/>`_
and `Sencha ExtJS <http://www.sencha.com/products/extjs/>`_.
Lino applications are Django projects
where the application developer does not need to write any
URLconf, HTML nor CSS (`more <http://lino-framework.org/about/what.html>`__).
Examples of Lino applications are
`Lino Welfare <http://welfare.lino-framework.org>`__,
`Lino Così <http://cosi.lino-framework.org>`__
or
`Lino Voga <http://voga.lino-framework.org>`__
(`more <http://lino-framework.org/about/projects.html>`__)

The central project homepage is http://www.lino-framework.org

""")

SETUP_INFO.update(classifiers="""\
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 3
Development Status :: 5 - Production/Stable
Environment :: Web Environment
Framework :: Django
Intended Audience :: Developers
Intended Audience :: System Administrators
License :: OSI Approved :: BSD License
Natural Language :: English
Natural Language :: French
Natural Language :: German
Operating System :: OS Independent
Topic :: Database :: Front-Ends
Topic :: Office/Business
Topic :: Software Development :: Libraries :: Application Frameworks""".splitlines())

SETUP_INFO.update(packages=[str(n) for n in """
lino
lino.api
lino.core
lino.core.auth
lino.fake_migrations
lino.history
lino.mixins
lino.modlib
lino.modlib.about
lino.modlib.awesomeuploader
lino.modlib.blacklist
lino.modlib.bootstrap3
lino.modlib.changes
lino.modlib.comments
lino.modlib.comments.fixtures
lino.modlib.dashboard
lino.modlib.davlink
lino.modlib.dupable
lino.modlib.export_excel
lino.modlib.extjs
lino.modlib.forms
lino.modlib.gfks
lino.modlib.gfks.fixtures
lino.modlib.ipdict
lino.modlib.jinja
lino.modlib.importfilters
lino.modlib.languages
lino.modlib.languages.fixtures
lino.management
lino.management.commands
lino.modlib.odata
lino.modlib.office
lino.modlib.checkdata
lino.modlib.checkdata.fixtures
lino.modlib.checkdata.management
lino.modlib.checkdata.management.commands
lino.modlib.printing
lino.modlib.restful
lino.modlib.smtpd
lino.modlib.smtpd.management
lino.modlib.smtpd.management.commands
lino.modlib.notify
lino.modlib.notify.fixtures
lino.modlib.social_auth
lino.modlib.summaries
lino.modlib.summaries.fixtures
lino.modlib.summaries.management
lino.modlib.summaries.management.commands
lino.modlib.system
lino.modlib.tinymce
lino.modlib.tinymce.fixtures
lino.modlib.uploads
lino.modlib.users
lino.modlib.users.fixtures
lino.modlib.weasyprint
lino.modlib.wkhtmltopdf
lino.projects
lino.projects.std
lino.sphinxcontrib
lino.sphinxcontrib.logo
lino.utils
lino.utils.demonames
lino.utils.mldbc
""".splitlines() if n])

SETUP_INFO.update(message_extractors={
    'lino': [
        ('**/sandbox/**', 'ignore', None),
        ('**/cache/**', 'ignore', None),
        ('**.py', 'python', None),
        ('**/linoweb.js', 'jinja2', None),
        # ~ ('**.js',                'javascript', None),
        ('**/config/**.html', 'jinja2', None),
        # ~ ('**/templates/**.txt',  'genshi', {
        # ~ 'template_class': 'genshi.template:TextTemplate'
        # ~ })
    ],
})

# SETUP_INFO.update(package_data=dict())

SETUP_INFO.update(include_package_data=True)

# def add_package_data(package, *patterns):
#     package = str(package)
#     l = SETUP_INFO['package_data'].setdefault(package, [])
#     l += [str(x) for x in patterns]
#     l.extend(patterns)
#     return l

# add_package_data('lino.modlib.davlink', '*.jnlp')
# add_package_data('lino.utils', '*.ods')
# add_package_data('lino.config', '*.html')
# add_package_data('lino.config', '*.tmpl')
# add_package_data('lino.config', 'about/*.tmpl')
# add_package_data('lino.config', 'makedocs/*.tmpl')
# add_package_data('lino.modlib.bootstrap3', 'config/bootstrap3/*.html')
# add_package_data('lino.modlib.extjs', 'config/extjs/*.html')
# add_package_data('lino.modlib.extjs', 'config/extjs/*.js')
# add_package_data('lino.modlib.languages.fixtures', '*.tab')
# add_package_data('lino.modlib.notify', 'config/notify/*.eml')

# l = add_package_data('lino.locale')
# for lng in 'de es fr et nl pt pt-br'.split():
#     l.append('lino/locale/%s/LC_MESSAGES/*.mo' % lng)
<commit_msg>http://luc.lino-framework.org/blog/2018/1212.html<commit_after># -*- coding: UTF-8 -*-
# Copyright 2009-2018 Rumma & Ko Ltd
# License: BSD (see file COPYING for details)

# Note that this module may not have a docstring because any
# global variable defined here will override the global
# namespace of lino/__init__.py who includes it with execfile.

# This module is part of the Lino test suite.
# To test only this module:
#
#   $ python setup.py test -s tests.PackagesTests

from __future__ import unicode_literals
import sys

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

install_requires = [
    # 'Sphinx',
    'django',
    'atelier', 'unipath', 'python_dateutil', 'dateparser',
    'etgen',
    'Babel', 'lxml',
    'beautifulsoup4',
    'pisa',
    'jinja2', 'pytidylib', 'PyYAML',
    'clint',  # lino.modlib.checkdata.management.commands
    'django-localflavor',  # lino.modlib.sepa
    # 'django-iban',  # lino.modlib.sepa
    'openpyxl', 'html2text',
    # 'cairocffi',  # 'cairocffi<0.7',
    # 'bleach',
    # 'html5lib',  # version 7x9 (not 9x9) required by bleach
    'schedule',
    'django-wkhtmltopdf',
    'beautifulsoup4']

if PY2:
    install_requires.append('reportlab<2.7')
    # install_requires.append('django<2')
    install_requires.append('weasyprint<0.43')
else:
    # install_requires.append('django')
    install_requires.append('reportlab')
    install_requires.append('weasyprint')

SETUP_INFO = dict(
    name='lino',
    version='18.12.1',
    install_requires=install_requires,
    description="A framework for writing desktop-like web applications "
                "using Django and ExtJS",
    license='BSD License',
    # obsoletes=['djangosite', 'north'],
    author='Luc Saffre',
    author_email='luc@lino-framework.org',
    url="http://www.lino-framework.org",
    # ~ test_suite = 'lino.test_apps',
    test_suite='tests')

SETUP_INFO.update(long_description="""

.. raw:: html

Lino is a high-level framework for writing desktop-like customized
database applications based on `Django <https://www.djangoproject.com/>`_
and `Sencha ExtJS <http://www.sencha.com/products/extjs/>`_.
Lino applications are Django projects
where the application developer does not need to write any
URLconf, HTML nor CSS (`more <http://lino-framework.org/about/what.html>`__).
Examples of Lino applications are
`Lino Welfare <http://welfare.lino-framework.org>`__,
`Lino Così <http://cosi.lino-framework.org>`__
or
`Lino Voga <http://voga.lino-framework.org>`__
(`more <http://lino-framework.org/about/projects.html>`__)

The central project homepage is http://www.lino-framework.org

""")

SETUP_INFO.update(classifiers="""\
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 3
Development Status :: 5 - Production/Stable
Environment :: Web Environment
Framework :: Django
Intended Audience :: Developers
Intended Audience :: System Administrators
License :: OSI Approved :: BSD License
Natural Language :: English
Natural Language :: French
Natural Language :: German
Operating System :: OS Independent
Topic :: Database :: Front-Ends
Topic :: Office/Business
Topic :: Software Development :: Libraries :: Application Frameworks""".splitlines())

SETUP_INFO.update(packages=[str(n) for n in """
lino
lino.api
lino.core
lino.core.auth
lino.fake_migrations
lino.history
lino.mixins
lino.modlib
lino.modlib.about
lino.modlib.awesomeuploader
lino.modlib.blacklist
lino.modlib.bootstrap3
lino.modlib.changes
lino.modlib.comments
lino.modlib.comments.fixtures
lino.modlib.dashboard
lino.modlib.davlink
lino.modlib.dupable
lino.modlib.export_excel
lino.modlib.extjs
lino.modlib.forms
lino.modlib.gfks
lino.modlib.gfks.fixtures
lino.modlib.ipdict
lino.modlib.jinja
lino.modlib.importfilters
lino.modlib.languages
lino.modlib.languages.fixtures
lino.management
lino.management.commands
lino.modlib.odata
lino.modlib.office
lino.modlib.checkdata
lino.modlib.checkdata.fixtures
lino.modlib.checkdata.management
lino.modlib.checkdata.management.commands
lino.modlib.printing
lino.modlib.restful
lino.modlib.smtpd
lino.modlib.smtpd.management
lino.modlib.smtpd.management.commands
lino.modlib.notify
lino.modlib.notify.fixtures
lino.modlib.social_auth
lino.modlib.summaries
lino.modlib.summaries.fixtures
lino.modlib.summaries.management
lino.modlib.summaries.management.commands
lino.modlib.system
lino.modlib.tinymce
lino.modlib.tinymce.fixtures
lino.modlib.uploads
lino.modlib.users
lino.modlib.users.fixtures
lino.modlib.weasyprint
lino.modlib.wkhtmltopdf
lino.projects
lino.projects.std
lino.sphinxcontrib
lino.sphinxcontrib.logo
lino.utils
lino.utils.demonames
lino.utils.mldbc
""".splitlines() if n])

SETUP_INFO.update(message_extractors={
    'lino': [
        ('**/sandbox/**', 'ignore', None),
        ('**/cache/**', 'ignore', None),
        ('**.py', 'python', None),
        ('**/linoweb.js', 'jinja2', None),
        # ~ ('**.js',                'javascript', None),
        ('**/config/**.html', 'jinja2', None),
        # ~ ('**/templates/**.txt',  'genshi', {
        # ~ 'template_class': 'genshi.template:TextTemplate'
        # ~ })
    ],
})

# SETUP_INFO.update(package_data=dict())

SETUP_INFO.update(include_package_data=True)

# def add_package_data(package, *patterns):
#     package = str(package)
#     l = SETUP_INFO['package_data'].setdefault(package, [])
#     l += [str(x) for x in patterns]
#     l.extend(patterns)
#     return l

# add_package_data('lino.modlib.davlink', '*.jnlp')
# add_package_data('lino.utils', '*.ods')
# add_package_data('lino.config', '*.html')
# add_package_data('lino.config', '*.tmpl')
# add_package_data('lino.config', 'about/*.tmpl')
# add_package_data('lino.config', 'makedocs/*.tmpl')
# add_package_data('lino.modlib.bootstrap3', 'config/bootstrap3/*.html')
# add_package_data('lino.modlib.extjs', 'config/extjs/*.html')
# add_package_data('lino.modlib.extjs', 'config/extjs/*.js')
# add_package_data('lino.modlib.languages.fixtures', '*.tab')
# add_package_data('lino.modlib.notify', 'config/notify/*.eml')

# l = add_package_data('lino.locale')
# for lng in 'de es fr et nl pt pt-br'.split():
#     l.append('lino/locale/%s/LC_MESSAGES/*.mo' % lng)
<|endoftext|>


<commit_before>import sys
from datetime import datetime
from difflib import unified_diff
from pathlib import Path
from typing import Optional

def format_simplified(import_line: str) -> str:
    import_line = import_line.strip()
    if import_line.startswith("from "):
        import_line = import_line.replace("from ", "")
        import_line = import_line.replace(" import ", ".")
    elif import_line.startswith("import "):
        import_line = import_line.replace("import ", "")

    return import_line

def format_natural(import_line: str) -> str:
    import_line = import_line.strip()
    if not import_line.startswith("from ") and not import_line.startswith("import "):
        if "." not in import_line:
            return "import {0}".format(import_line)
        parts = import_line.split(".")
        end = parts.pop(-1)
        return "from {0} import {1}".format(".".join(parts), end)

    return import_line

def show_unified_diff(*, file_input: str, file_output: str, file_path: Optional[Path]) -> None:
    file_name = '' if file_path is None else str(file_path)
    file_mtime = str(datetime.now() if file_path is None
                     else datetime.fromtimestamp(file_path.stat().st_mtime))

    unified_diff_lines = unified_diff(
        file_input.splitlines(keepends=True),
        file_output.splitlines(keepends=True),
        fromfile=file_name + ':before',
        tofile=file_name + ':after',
        fromfiledate=file_mtime,
        tofiledate=str(datetime.now())
    )
    for line in unified_diff_lines:
        sys.stdout.write(line)

def ask_whether_to_apply_changes_to_file(fpath: str) -> bool:
    answer = None
    while answer not in ('yes', 'y', 'no', 'n', 'quit', 'q'):
        answer = input("Apply suggested changes to '{0}' [y/n/q]? ".format(fpath)).lower()
        if answer in ('no', 'n'):
            return False
        if answer in ('quit', 'q'):
            sys.exit(1)
    return True
<commit_msg>Update format.py<commit_after>import sys
from datetime import datetime
from difflib import unified_diff
from pathlib import Path
from typing import Optional

def format_simplified(import_line: str) -> str:
    import_line = import_line.strip()
    if import_line.startswith("from "):
        import_line = import_line.replace("from ", "")
        import_line = import_line.replace(" import ", ".")
    elif import_line.startswith("import "):
        import_line = import_line.replace("import ", "")

    return import_line

def format_natural(import_line: str) -> str:
    import_line = import_line.strip()
    if not import_line.startswith("from ") and not import_line.startswith("import "):
        if "." not in import_line:
            return "import {0}".format(import_line)
        parts = import_line.split(".")
        end = parts.pop(-1)
        return "from {0} import {1}".format(".".join(parts), end)

    return import_line

def show_unified_diff(*, file_input: str, file_output: str, file_path: Optional[Path]) -> None:
    file_name = '' if file_path is None else str(file_path)
    file_mtime = str(datetime.now() if file_path is None
                     else datetime.fromtimestamp(file_path.stat().st_mtime))

    unified_diff_lines = unified_diff(
        file_input.splitlines(keepends=True),
        file_output.splitlines(keepends=True),
        fromfile=file_name + ':before',
        tofile=file_name + ':after',
        fromfiledate=file_mtime,
        tofiledate=str(datetime.now())
    )
    for line in unified_diff_lines:
        sys.stdout.write(line)

def ask_whether_to_apply_changes_to_file(file_path: str) -> bool:
    answer = None
    while answer not in ('yes', 'y', 'no', 'n', 'quit', 'q'):
        answer = input("Apply suggested changes to '{0}' [y/n/q]? ".format(file_path)).lower()
        if answer in ('no', 'n'):
            return False
        if answer in ('quit', 'q'):
            sys.exit(1)
    return True
<|endoftext|>