Exemple #1
0
def invalidate_language_list_cache(**kwargs):
    instance = kwargs["instance"]
    # XXX: maybe use custom signals or simple function calls?
    if instance.__class__.__name__ not in ['Language', 'TranslationProject']:
        return

    key = make_method_key('LiveLanguageManager', 'cached_dict', '*')
    cache.delete_pattern(key)

    key = make_method_key('LiveLanguageManager', 'all_cached_dict', '*')
    cache.delete_pattern(key)
Exemple #2
0
    def cached_dict(self, locale_code='en-us', show_all=False):
        """Retrieves a sorted list of live language codes and names.

        By default only returns live languages for enabled projects, but it can
        also return live languages for disabled projects if specified.

        :param locale_code: the UI locale for which language full names need to
            be localized.
        :param show_all: tells whether to return all live languages (both for
            disabled and enabled projects) or only live languages for enabled
            projects.
        :return: an `OrderedDict`
        """
        key_prefix = 'all_cached_dict' if show_all else 'cached_dict'
        key = make_method_key(self, key_prefix, locale_code)
        languages = cache.get(key, None)
        if languages is None:
            qs = self.get_all_queryset() if show_all else self.get_queryset()
            languages = OrderedDict(
                sorted([(lang[0], tr_lang(lang[1]))
                        for lang in qs.values_list('code', 'fullname')],
                       cmp=locale.strcoll,
                       key=lambda x: x[1]))
            cache.set(key, languages, CACHE_TIMEOUT)

        return languages
Exemple #3
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)

        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        logging.debug(u'Cache miss for %s', cache_key)

        resources_path = ''.join(['/%/', self.code, '/%'])

        sql_query = '''
        SELECT pootle_path
        FROM pootle_store_store
        WHERE pootle_path LIKE %s
          UNION
        SELECT pootle_path
        FROM pootle_app_directory
        WHERE pootle_path LIKE %s;
        '''
        cursor = connection.cursor()
        cursor.execute(sql_query, [resources_path, resources_path])
        results = cursor.fetchall()

        # Calculate TP-relative paths and sort them
        resources = sorted({to_tp_relative_path(result[0]) for result in results},
                           key=get_path_sortkey)

        cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)

        return resources
Exemple #4
0
    def cached_dict(self, user):
        """Return a cached ordered dictionary of projects tuples for `user`.

        - Admins always get all projects.
        - Regular users only get enabled projects accessible to them.

        :param user: The user for whom projects need to be retrieved for.
        :return: An ordered dictionary of project tuples including
          (`fullname`, `disabled`) and `code` is a key in the dictionary.
        """
        if not user.is_superuser:
            cache_params = {'username': user.username}
        else:
            cache_params = {'is_admin': user.is_superuser}
        cache_key = make_method_key('Project', 'cached_dict', cache_params)
        projects = cache.get(cache_key)
        if not projects:
            logging.debug('Cache miss for %s', cache_key)
            projects_dict = self.for_user(user).order_by('fullname') \
                                               .values('code', 'fullname',
                                                       'disabled')

            projects = OrderedDict(
                (project.pop('code'), project) for project in projects_dict
            )
            cache.set(cache_key, projects, settings.POOTLE_CACHE_TIMEOUT)

        return projects
Exemple #5
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        from virtualfolder.models import VirtualFolderTreeItem

        cache_key = make_method_key(self, 'resources', self.code)
        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        stores = Store.objects.live().order_by().filter(
            translation_project__project__pk=self.pk)
        dirs = Directory.objects.live().order_by().filter(
            pootle_path__regex=r"^/[^/]*/%s/" % self.code)
        vftis = (VirtualFolderTreeItem.objects.filter(
            vfolder__is_public=True,
            pootle_path__regex=r"^/[^/]*/%s/" %
            self.code) if 'virtualfolder' in settings.INSTALLED_APPS else [])
        resources = sorted(
            {
                to_tp_relative_path(pootle_path)
                for pootle_path in (
                    set(stores.values_list("pootle_path", flat=True))
                    | set(dirs.values_list("pootle_path", flat=True))
                    | set(
                        vftis.values_list("pootle_path", flat=True
                                          ) if vftis else []))
            },
            key=get_path_sortkey)
        cache.set(cache_key, resources, settings.POOTLE_CACHE_TIMEOUT)
        return resources
Exemple #6
0
def invalidate_language_list_cache(sender, instance, **kwargs):
    # XXX: maybe use custom signals or simple function calls?
    if instance.__class__.__name__ not in ["Language", "TranslationProject"]:
        return

    key = make_method_key("LiveLanguageManager", "cached_dict", "*")
    cache.delete_pattern(key)
Exemple #7
0
def invalidate_accessible_projects_cache(sender, instance, **kwargs):
    # XXX: maybe use custom signals or simple function calls?
    if (instance.__class__.__name__ not in
        ['Project', 'TranslationProject', 'PermissionSet']):
        return

    # FIXME: use Redis directly to clear these caches effectively

    cache.delete_many([
        make_method_key('Project', 'cached_dict', {'is_admin': False}),
        make_method_key('Project', 'cached_dict', {'is_admin': True}),
    ])

    User = get_user_model()
    users_list = User.objects.values_list('username', flat=True)
    cache.delete_many(map(lambda x: 'projects:accessible:%s' % x, users_list))
Exemple #8
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        from virtualfolder.models import VirtualFolderTreeItem

        cache_key = make_method_key(self, 'resources', self.code)
        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        stores = Store.objects.live().order_by().filter(
            translation_project__project__pk=self.pk)
        dirs = Directory.objects.live().order_by().filter(
            pootle_path__regex=r"^/[^/]*/%s/" % self.code)
        vftis = (
            VirtualFolderTreeItem.objects.filter(
                vfolder__is_public=True,
                pootle_path__regex=r"^/[^/]*/%s/" % self.code)
            if 'virtualfolder' in settings.INSTALLED_APPS
            else [])
        resources = sorted(
            {to_tp_relative_path(pootle_path)
             for pootle_path
             in (set(stores.values_list("pootle_path", flat=True))
                 | set(dirs.values_list("pootle_path", flat=True))
                 | set(vftis.values_list("pootle_path", flat=True)
                       if vftis
                       else []))},
            key=get_path_sortkey)
        cache.set(cache_key, resources, settings.POOTLE_CACHE_TIMEOUT)
        return resources
Exemple #9
0
    def cached_dict(self, user):
        """Return a cached ordered dictionary of projects tuples for `user`.

        - Admins always get all projects.
        - Regular users only get enabled projects accessible to them.

        :param user: The user for whom projects need to be retrieved for.
        :return: An ordered dictionary of project tuples including
          (`fullname`, `disabled`) and `code` is a key in the dictionary.
        """
        if not user.is_superuser:
            cache_params = {"username": user.username}
        else:
            cache_params = {"is_admin": user.is_superuser}
        cache_key = make_method_key("Project", "cached_dict", cache_params)
        projects = cache.get(cache_key)
        if not projects:
            logging.debug("Cache miss for %s", cache_key)
            projects_dict = (
                self.for_user(user)
                .order_by("fullname")
                .values("code", "fullname", "disabled")
            )

            projects = OrderedDict(
                (project.pop("code"), project) for project in projects_dict
            )
            cache.set(cache_key, projects, CACHE_TIMEOUT)

        return projects
Exemple #10
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, "resources", self.code)
        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        stores = (
            Store.objects.live()
            .order_by()
            .filter(translation_project__project__pk=self.pk)
        )
        dirs = (
            Directory.objects.live()
            .order_by()
            .filter(pootle_path__regex=r"^/[^/]*/%s/" % self.code)
        )
        resources = sorted(
            {
                to_tp_relative_path(pootle_path)
                for pootle_path in (
                    set(stores.values_list("pootle_path", flat=True))
                    | set(dirs.values_list("pootle_path", flat=True))
                )
            },
            key=get_path_sortkey,
        )
        cache.set(cache_key, resources, CACHE_TIMEOUT)
        return resources
Exemple #11
0
def invalidate_accessible_projects_cache(sender, instance, **kwargs):
    # XXX: maybe use custom signals or simple function calls?
    if (instance.__class__.__name__
            not in ['Project', 'TranslationProject', 'PermissionSet']):
        return

    # FIXME: use Redis directly to clear these caches effectively

    cache.delete_many([
        make_method_key('Project', 'cached_dict', {'is_admin': False}),
        make_method_key('Project', 'cached_dict', {'is_admin': True}),
    ])

    User = get_user_model()
    users_list = User.objects.values_list('username', flat=True)
    cache.delete_many(map(lambda x: 'projects:accessible:%s' % x, users_list))
Exemple #12
0
    def cached_dict(self, locale_code='en-us', show_all=False):
        """Retrieves a sorted list of live language codes and names.

        By default only returns live languages for enabled projects, but it can
        also return live languages for disabled projects if specified.

        :param locale_code: the UI locale for which language full names need to
            be localized.
        :param show_all: tells whether to return all live languages (both for
            disabled and enabled projects) or only live languages for enabled
            projects.
        :return: an `OrderedDict`
        """
        key_prefix = 'all_cached_dict' if show_all else 'cached_dict'
        key = make_method_key(self, key_prefix, locale_code)
        languages = cache.get(key, None)
        if languages is None:
            qs = self.get_all_queryset() if show_all else self.get_queryset()
            languages = OrderedDict(
                sorted([(lang[0], tr_lang(lang[1]))
                        for lang in qs.values_list('code', 'fullname')],
                       cmp=locale.strcoll,
                       key=lambda x: x[1])
            )
            cache.set(key, languages, settings.POOTLE_CACHE_TIMEOUT)

        return languages
Exemple #13
0
    def top_scorers(cls, days=30, language=None, project=None, limit=5):
        """Returns users with the top scores.

        :param days: period of days to account for scores.
        :param language: limit results to the given language code.
        :param project: limit results to the given project code.
        :param limit: limit results to this number of users. Values other
            than positive numbers will return the entire result set.
        """
        cache_kwargs = {
            'days': days,
            'language': language,
            'project': project,
            'limit': limit,
        }
        cache_key = make_method_key(cls, 'top_scorers', cache_kwargs)

        top_scorers = cache.get(cache_key, None)
        if top_scorers is not None:
            return top_scorers

        now = timezone.now()
        past = now + datetime.timedelta(-days)

        lookup_kwargs = {
            'creation_time__range': [past, now],
        }

        if language is not None:
            lookup_kwargs.update({
                'submission__translation_project__language__code':
                language,
            })

        if project is not None:
            lookup_kwargs.update({
                'submission__translation_project__project__code':
                project,
            })

        meta_user_ids = cls.objects.meta_users().values_list('id', flat=True)
        top_scores = ScoreLog.objects.values("user").filter(
            **lookup_kwargs).exclude(user__pk__in=meta_user_ids, ).annotate(
                total_score=Sum('score_delta'), ).order_by('-total_score')

        if isinstance(limit, (int, long)) and limit > 0:
            top_scores = top_scores[:limit]

        users = dict((user.id, user) for user in cls.objects.filter(
            pk__in=[item['user'] for item in top_scores]))

        top_scorers = []
        for item in top_scores:
            user = users[item['user']]
            user.total_score = item['total_score']
            top_scorers.append(user)

        cache.set(cache_key, list(top_scorers), 60)
        return top_scorers
Exemple #14
0
def invalidate_accessible_projects_cache(sender, instance, **kwargs):
    # XXX: maybe use custom signals or simple function calls?
    if (instance.__class__.__name__ not in
        ['Project', 'TranslationProject', 'PermissionSet']):
        return

    cache.delete_pattern(make_method_key('Project', 'cached_dict', '*'))
    cache.delete('projects:all')
    cache.delete_pattern('projects:accessible:*')
Exemple #15
0
def invalidate_resources_cache(sender, instance, **kwargs):
    if instance.__class__.__name__ not in ['Directory', 'Store']:
        return

    # Don't invalidate if the save didn't create new objects
    if (('created' in kwargs and 'raw' in kwargs) and
        (not kwargs['created'] or kwargs['raw'])):
        return

    lang, proj, dir, fn = split_pootle_path(instance.pootle_path)
    if proj is not None:
        cache.delete(make_method_key(Project, 'resources', proj))
Exemple #16
0
def invalidate_accessible_projects_cache(**kwargs):
    instance = kwargs["instance"]
    # XXX: maybe use custom signals or simple function calls?
    if instance.__class__.__name__ not in [
        "Project",
        "TranslationProject",
        "PermissionSet",
    ]:
        return

    cache.delete_pattern(make_method_key("Project", "cached_dict", "*"))
    cache.delete("projects:all")
    cache.delete_pattern("projects:accessible:*")
Exemple #17
0
def invalidate_resources_cache(**kwargs):
    instance = kwargs["instance"]
    if instance.__class__.__name__ not in ['Directory', 'Store']:
        return

    # Don't invalidate if the save didn't create new objects
    if (('created' in kwargs and 'raw' in kwargs) and
        (not kwargs['created'] or kwargs['raw'])):
        return

    proj_code = split_pootle_path(instance.pootle_path)[1]
    if proj_code is not None:
        cache.delete(make_method_key(Project, 'resources', proj_code))
Exemple #18
0
    def top_scorers(cls, days=30, language=None, project=None, limit=5):
        """Returns users with the top scores.

        :param days: period of days to account for scores.
        :param language: limit results to the given language code.
        :param project: limit results to the given project code.
        :param limit: limit results to this number of users. Values other
            than positive numbers will return the entire result set.
        """
        cache_kwargs = {
            'days': days,
            'language': language,
            'project': project,
            'limit': limit,
        }
        cache_key = make_method_key(cls, 'top_scorers', cache_kwargs)

        top_scorers = cache.get(cache_key, None)
        if top_scorers is not None:
            return top_scorers

        now = timezone.now()
        past = now + datetime.timedelta(-days)

        lookup_kwargs = {
            'scorelog__creation_time__range': [past, now],
        }

        if language is not None:
            lookup_kwargs.update({
                'scorelog__submission__translation_project__language__code':
                    language,
            })

        if project is not None:
            lookup_kwargs.update({
                'scorelog__submission__translation_project__project__code':
                    project,
            })

        top_scorers = cls.objects.hide_meta().filter(
            **lookup_kwargs
        ).annotate(
            total_score=Sum('scorelog__score_delta'),
        ).order_by('-total_score')

        if isinstance(limit, (int, long)) and limit > 0:
            top_scorers = top_scorers[:limit]

        cache.set(cache_key, list(top_scorers), 60)
        return top_scorers
Exemple #19
0
    def top_scorers(cls, days=30, language=None, project=None, limit=5):
        """Returns users with the top scores.

        :param days: period of days to account for scores.
        :param language: limit results to the given language code.
        :param project: limit results to the given project code.
        :param limit: limit results to this number of users. Values other
            than positive numbers will return the entire result set.
        """
        cache_kwargs = {
            'days': days,
            'language': language,
            'project': project,
            'limit': limit,
        }
        cache_key = make_method_key(cls, 'top_scorers', cache_kwargs)

        top_scorers = cache.get(cache_key, None)
        if top_scorers is not None:
            return top_scorers

        now = timezone.now()
        past = now + datetime.timedelta(-days)

        lookup_kwargs = {
            'scorelog__creation_time__range': [past, now],
        }

        if language is not None:
            lookup_kwargs.update({
                'scorelog__submission__translation_project__language__code':
                    language,
            })

        if project is not None:
            lookup_kwargs.update({
                'scorelog__submission__translation_project__project__code':
                    project,
            })

        top_scorers = cls.objects.hide_meta().filter(
            **lookup_kwargs
        ).annotate(
            total_score=Sum('scorelog__score_delta'),
        ).order_by('-total_score')

        if isinstance(limit, (int, long)) and limit > 0:
            top_scorers = top_scorers[:limit]

        cache.set(cache_key, list(top_scorers), 60)
        return top_scorers
Exemple #20
0
def invalidate_resources_cache(**kwargs):
    instance = kwargs["instance"]
    if instance.__class__.__name__ not in ['Directory', 'Store']:
        return

    # Don't invalidate if the save didn't create new objects
    no_new_objects = (('created' in kwargs and 'raw' in kwargs)
                      and (not kwargs['created'] or kwargs['raw']))

    if no_new_objects and instance.parent.get_children():
        return

    proj_code = split_pootle_path(instance.pootle_path)[1]
    if proj_code is not None:
        cache.delete(make_method_key(Project, 'resources', proj_code))
Exemple #21
0
    def invalidate_resources_cache_for_vfolders(sender, instance, **kwargs):
        if instance.__class__.__name__ == 'VirtualFolder':
            try:
                # In case this is vfolder_post_save.
                affected_projects = kwargs['projects']
            except KeyError:
                # In case this is pre_delete.
                affected_projects = Project.objects.filter(
                    translationproject__stores__unit__vfolders=instance
                ).distinct().values_list('code', flat=True)

            cache.delete_many([
                make_method_key('Project', 'resources', proj)
                for proj in affected_projects
            ])
Exemple #22
0
    def invalidate_resources_cache_for_vfolders(sender, instance, **kwargs):
        if instance.__class__.__name__ == 'VirtualFolder':
            try:
                # In case this is vfolder_post_save.
                affected_projects = kwargs['projects']
            except KeyError:
                # In case this is pre_delete.
                affected_projects = Project.objects.filter(
                    translationproject__stores__unit__vfolders=instance
                ).distinct().values_list('code', flat=True)

            cache.delete_many([
                make_method_key('Project', 'resources', proj)
                for proj in affected_projects
            ])
Exemple #23
0
def invalidate_resources_cache(**kwargs):
    instance = kwargs["instance"]
    if instance.__class__.__name__ not in ["Directory", "Store"]:
        return

    # Don't invalidate if the save didn't create new objects
    no_new_objects = ("created" in kwargs and "raw"
                      in kwargs) and (not kwargs["created"] or kwargs["raw"])

    if no_new_objects and instance.parent.get_children():
        return

    proj_code = split_pootle_path(instance.pootle_path)[1]
    if proj_code is not None:
        cache.delete(make_method_key(Project, "resources", proj_code))
Exemple #24
0
    def cached_dict(self, user):
        """Return a cached list of projects tuples for `user`.

        :param user: The user for whom projects need to be retrieved for.
        :return: A list of project tuples including (code, fullname)
        """
        cache_key = make_method_key('Project', 'cached_dict',
                                    {'is_admin': user.is_superuser})
        projects = cache.get(cache_key)
        if not projects:
            logging.debug('Cache miss for %s', cache_key)
            projects = OrderedDict(
                self.for_user(user).order_by('fullname').values_list(
                    'code', 'fullname'))
            cache.set(cache_key, projects, settings.OBJECT_CACHE_TIMEOUT)

        return projects
Exemple #25
0
    def cached_dict(self, locale_code='en-us'):
        """Retrieves a sorted list of live language codes and names.

        :param locale_code: the UI locale for which language full names need to
            be localized.
        :return: an `OrderedDict`
        """
        key = make_method_key(self, 'cached_dict', locale_code)
        languages = cache.get(key, None)
        if languages is None:
            languages = OrderedDict(
                sorted([(lang[0], tr_lang(lang[1]))
                        for lang in self.values_list('code', 'fullname')],
                       cmp=locale.strcoll,
                       key=lambda x: x[1]))
            cache.set(key, languages, settings.POOTLE_CACHE_TIMEOUT)

        return languages
Exemple #26
0
    def cached_dict(self, user):
        """Return a cached list of projects tuples for `user`.

        :param user: The user for whom projects need to be retrieved for.
        :return: A list of project tuples including (code, fullname)
        """
        cache_key = make_method_key('Project', 'cached_dict',
                                    {'is_admin': user.is_superuser})
        projects = cache.get(cache_key)
        if not projects:
            logging.debug('Cache miss for %s', cache_key)
            projects = OrderedDict(
                self.for_user(user).order_by('fullname')
                                   .values_list('code', 'fullname')
            )
            cache.set(cache_key, projects, settings.OBJECT_CACHE_TIMEOUT)

        return projects
Exemple #27
0
    def cached_dict(self, locale_code='en-us'):
        """Retrieves a sorted list of live language codes and names.

        :param locale_code: the UI locale for which language full names need to
            be localized.
        :return: an `OrderedDict`
        """
        key = make_method_key(self, 'cached_dict', locale_code)
        languages = cache.get(key, None)
        if languages is None:
            languages = OrderedDict(
                sorted([(lang[0], tr_lang(lang[1]))
                        for lang in self.values_list('code', 'fullname')],
                        cmp=locale.strcoll,
                        key=lambda x: x[1])
            )
            cache.set(key, languages, settings.OBJECT_CACHE_TIMEOUT)

        return languages
Exemple #28
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)

        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        logging.debug(u'Cache miss for %s', cache_key)

        resources_path = ''.join(['/%/', self.code, '/%'])

        sql_query = '''
        SELECT DISTINCT
            REPLACE(pootle_path,
                    CONCAT(SUBSTRING_INDEX(pootle_path, '/', 3), '/'),
                    '')
        FROM (
            SELECT pootle_path
            FROM pootle_store_store
            WHERE pootle_path LIKE %s
          UNION
            SELECT pootle_path FROM pootle_app_directory
            WHERE pootle_path LIKE %s
        ) AS t;
        '''
        cursor = connection.cursor()
        cursor.execute(sql_query, [resources_path, resources_path])

        results = cursor.fetchall()

        # Flatten tuple and sort in a list
        resources = list(reduce(lambda x,y: x+y, results))
        resources.sort(key=get_path_sortkey)

        cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)

        return resources
Exemple #29
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)
        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        stores = Store.objects.live().order_by().filter(
            translation_project__project_id=self.pk)
        dirs = Directory.objects.live().order_by().filter(tp__project_id=self.pk)
        resources = sorted(
            {tp_path[1:]
             for tp_path
             in (set(stores.values_list("tp_path", flat=True))
                 | set(dirs.values_list("tp_path", flat=True)))},
            key=get_path_sortkey)
        cache.set(cache_key, resources, settings.POOTLE_CACHE_TIMEOUT)
        return resources
Exemple #30
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)
        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        stores = Store.objects.live().order_by().filter(
            translation_project__project_id=self.pk)
        dirs = Directory.objects.live().order_by().filter(tp__project_id=self.pk)
        resources = sorted(
            {tp_path[1:]
             for tp_path
             in (set(stores.values_list("tp_path", flat=True))
                 | set(dirs.values_list("tp_path", flat=True)))},
            key=get_path_sortkey)
        cache.set(cache_key, resources, settings.POOTLE_CACHE_TIMEOUT)
        return resources
Exemple #31
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)

        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        logging.debug(u'Cache miss for %s', cache_key)

        resources_path = ''.join(['/%/', self.code, '/%'])

        sql_query = '''
        SELECT pootle_path
        FROM pootle_store_store
        WHERE pootle_path LIKE %s
          UNION
        SELECT pootle_path
        FROM pootle_app_directory
        WHERE pootle_path LIKE %s;
        '''
        cursor = connection.cursor()
        cursor.execute(sql_query, [resources_path, resources_path])
        results = cursor.fetchall()

        # Calculate TP-relative paths and sort them
        resources = sorted(
            {to_tp_relative_path(result[0])
             for result in results},
            key=get_path_sortkey)

        cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)

        return resources
Exemple #32
0
    def top_scorers(cls, days=30, language=None, project=None, limit=5):
        """Returns users with the top scores.

        :param days: period of days to account for scores.
        :param language: limit results to the given language code.
        :param project: limit results to the given project code.
        :param limit: limit results to this number of users. Values other
            than positive numbers will return the entire result set.
        """
        cache_kwargs = {
            'days': days,
            'language': language,
            'project': project,
            'limit': limit,
        }
        cache_key = make_method_key(cls, 'top_scorers', cache_kwargs)

        top_scorers = cache.get(cache_key, None)
        if top_scorers is not None:
            return top_scorers

        now = timezone.now()
        past = now + datetime.timedelta(-days)

        lookup_kwargs = {
            'creation_time__range': [past, now],
        }

        if language is not None:
            lookup_kwargs.update({
                'submission__translation_project__language__code':
                    language,
            })

        if project is not None:
            lookup_kwargs.update({
                'submission__translation_project__project__code':
                    project,
            })

        meta_user_ids = cls.objects.meta_users().values_list('id', flat=True)
        top_scores = ScoreLog.objects.values("user").filter(
            **lookup_kwargs
        ).exclude(
            user__pk__in=meta_user_ids,
        ).annotate(
            total_score=Sum('score_delta'),
        ).order_by('-total_score')

        if isinstance(limit, (int, long)) and limit > 0:
            top_scores = top_scores[:limit]

        users = dict(
            (user.id, user)
            for user in cls.objects.filter(
                pk__in=[item['user'] for item in top_scores]
            )
        )

        top_scorers = []
        for item in top_scores:
            user = users[item['user']]
            user.total_score = item['total_score']
            top_scorers.append(user)

        cache.set(cache_key, list(top_scorers), 60)
        return top_scorers
Exemple #33
0
def clear_language_list_cache():
    key = make_method_key("LiveLanguageManager", "cached_dict", "*")
    cache.delete_pattern(key)

    key_all = make_method_key("LiveLanguageManager", "all_cached_dict", "*")
    cache.delete_pattern(key_all)
Exemple #34
0
def clear_language_list_cache():
    key = make_method_key('LiveLanguageManager', 'cached_dict', '*')
    cache.delete_pattern(key)
Exemple #35
0
    def top_scorers(cls, days=30, language=None, project=None, limit=5,
                    offset=0):
        """Returns users with the top scores.

        :param days: period of days to account for scores.
        :param language: limit results to the given language code.
        :param project: limit results to the given project code.
        :param limit: limit results to this number of users. Values other
            than positive numbers will return the entire result set.
        """
        cache_kwargs = {
            'days': days,
            'language': language,
            'project': project,
            'limit': limit,
            'offset': offset,
        }
        cache_key = make_method_key(cls, 'top_scorers', cache_kwargs)

        top_scorers = cache.get(cache_key, None)
        if top_scorers is not None:
            return top_scorers

        now = timezone.now()
        past = now + datetime.timedelta(-days)

        lookup_kwargs = {
            'creation_time__range': [past, now],
        }

        if language is not None:
            lookup_kwargs.update({
                'submission__translation_project__language__code':
                    language,
            })

        if project is not None:
            lookup_kwargs.update({
                'submission__translation_project__project__code':
                    project,
            })

        meta_user_ids = cls.objects.meta_users().values_list('id', flat=True)
        top_scores = ScoreLog.objects.values("user").filter(
            **lookup_kwargs
        ).exclude(
            user__pk__in=meta_user_ids,
        ).annotate(
            total_score=Sum('score_delta'),
            suggested=Sum(
                Case(
                    When(
                        action_code=TranslationActionCodes.SUGG_ADDED,
                        then='wordcount'
                    ),
                    default=0,
                    output_field=models.IntegerField()
                )
            ),
            translated=Sum(
                Case(
                    When(
                        translated_wordcount__isnull=False,
                        then='translated_wordcount'
                    ),
                    default=0,
                    output_field=models.IntegerField()
                )
            ),
            reviewed=Sum(
                Case(
                    When(
                        action_code__in=[
                            TranslationActionCodes.SUGG_REVIEWED_ACCEPTED,
                            TranslationActionCodes.REVIEWED,
                            TranslationActionCodes.EDITED,
                        ],
                        translated_wordcount__isnull=True,
                        then='wordcount',
                    ),
                    default=0,
                    output_field=models.IntegerField()
                )
            ),
        ).order_by('-total_score')[offset:]

        if isinstance(limit, (int, long)) and limit > 0:
            top_scores = top_scores[:limit]

        users = dict(
            (user.id, user)
            for user in cls.objects.filter(
                pk__in=[item['user'] for item in top_scores]
            )
        )

        top_scorers = []
        for item in top_scores:
            item['user'] = users[item['user']]
            item['public_total_score'] = formatter.number(
                round(item['total_score']))
            top_scorers.append(item)

        cache.set(cache_key, top_scorers, 60)
        return top_scorers
Exemple #36
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)

        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        logging.debug(u'Cache miss for %s', cache_key)

        resources_path = ''.join(['/%/', self.code, '/%'])

        if connection.vendor == 'mysql':
            sql_query = '''
            SELECT DISTINCT
                REPLACE(pootle_path,
                        CONCAT(SUBSTRING_INDEX(pootle_path, '/', 3), '/'),
                        '')
            FROM (
                SELECT pootle_path
                FROM pootle_store_store
                WHERE pootle_path LIKE %s
              UNION
                SELECT pootle_path FROM pootle_app_directory
                WHERE pootle_path LIKE %s
            ) AS t;
            '''
        elif connection.vendor == 'postgresql':
            sql_query = '''
            SELECT DISTINCT
                REPLACE(pootle_path,
                        ARRAY_TO_STRING((
                                         STRING_TO_ARRAY(pootle_path,'/')
                                        )[1:3], '/')
                        || '/',
                        '')
            FROM (
                SELECT pootle_path
                FROM pootle_store_store
                WHERE pootle_path LIKE %s
              UNION
                SELECT pootle_path FROM pootle_app_directory
                WHERE pootle_path LIKE %s
            ) AS t;
            '''
        elif connection.vendor == 'sqlite':
            # Due to the limitations of SQLite there is no way to do this just
            # using raw SQL.
            from pootle_store.models import Store

            store_objs = Store.objects.extra(
                where=[
                    'pootle_store_store.pootle_path LIKE %s',
                    'pootle_store_store.pootle_path NOT LIKE %s',
                ],
                params=[resources_path,
                        '/templates/%']).select_related('parent').distinct()

            # Populate with stores and their parent directories, avoiding any
            # duplicates
            resources = []
            for store in store_objs.iterator():
                directory = store.parent
                if (not directory.is_translationproject()
                        and all(directory.path != path for path in resources)):
                    resources.append(directory.path)

                if all(store.path != path for path in resources):
                    resources.append(store.path)

            resources.sort(key=get_path_sortkey)

            cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)
            return resources

        cursor = connection.cursor()
        cursor.execute(sql_query, [resources_path, resources_path])

        results = cursor.fetchall()

        # Flatten tuple and sort in a list
        resources = list(reduce(lambda x, y: x + y, results))
        resources.sort(key=get_path_sortkey)

        cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)

        return resources
Exemple #37
0
    def resources(self):
        """Returns a list of :cls:`~pootle_app.models.Directory` and
        :cls:`~pootle_store.models.Store` resource paths available for
        this :cls:`~pootle_project.models.Project` across all languages.
        """
        cache_key = make_method_key(self, 'resources', self.code)

        resources = cache.get(cache_key, None)
        if resources is not None:
            return resources

        logging.debug(u'Cache miss for %s', cache_key)

        resources_path = ''.join(['/%/', self.code, '/%'])

        if connection.vendor == 'mysql':
            sql_query = '''
            SELECT DISTINCT
                REPLACE(pootle_path,
                        CONCAT(SUBSTRING_INDEX(pootle_path, '/', 3), '/'),
                        '')
            FROM (
                SELECT pootle_path
                FROM pootle_store_store
                WHERE pootle_path LIKE %s
              UNION
                SELECT pootle_path FROM pootle_app_directory
                WHERE pootle_path LIKE %s
            ) AS t;
            '''
        elif connection.vendor == 'postgresql':
            sql_query = '''
            SELECT DISTINCT
                REPLACE(pootle_path,
                        ARRAY_TO_STRING((
                                         STRING_TO_ARRAY(pootle_path,'/')
                                        )[1:3], '/')
                        || '/',
                        '')
            FROM (
                SELECT pootle_path
                FROM pootle_store_store
                WHERE pootle_path LIKE %s
              UNION
                SELECT pootle_path FROM pootle_app_directory
                WHERE pootle_path LIKE %s
            ) AS t;
            '''
        elif connection.vendor == 'sqlite':
            # Due to the limitations of SQLite there is no way to do this just
            # using raw SQL.
            from pootle_store.models import Store

            store_objs = Store.objects.extra(
                where=[
                    'pootle_store_store.pootle_path LIKE %s',
                    'pootle_store_store.pootle_path NOT LIKE %s',
                ], params=[resources_path, '/templates/%']
            ).select_related('parent').distinct()

            # Populate with stores and their parent directories, avoiding any
            # duplicates
            resources = []
            for store in store_objs.iterator():
                directory = store.parent
                if (not directory.is_translationproject() and
                    all(directory.path != path for path in resources)):
                    resources.append(directory.path)

                if all(store.path != path for path in resources):
                    resources.append(store.path)

            resources.sort(key=get_path_sortkey)

            cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)
            return resources

        cursor = connection.cursor()
        cursor.execute(sql_query, [resources_path, resources_path])

        results = cursor.fetchall()

        # Flatten tuple and sort in a list
        resources = list(reduce(lambda x,y: x+y, results))
        resources.sort(key=get_path_sortkey)

        cache.set(cache_key, resources, settings.OBJECT_CACHE_TIMEOUT)

        return resources
Exemple #38
0
    def top_scorers(cls,
                    days=30,
                    language=None,
                    project=None,
                    limit=5,
                    offset=0):
        """Returns users with the top scores.

        :param days: period of days to account for scores.
        :param language: limit results to the given language code.
        :param project: limit results to the given project code.
        :param limit: limit results to this number of users. Values other
            than positive numbers will return the entire result set.
        """
        cache_kwargs = {
            'days': days,
            'language': language,
            'project': project,
            'limit': limit,
            'offset': offset,
        }
        cache_key = make_method_key(cls, 'top_scorers', cache_kwargs)

        top_scorers = cache.get(cache_key, None)
        if top_scorers is not None:
            return top_scorers

        now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
        past = now + datetime.timedelta(-days)

        lookup_kwargs = {
            'creation_time__range': [past, now],
        }

        if language is not None:
            lookup_kwargs.update({
                'submission__translation_project__language__code':
                language,
            })

        if project is not None:
            lookup_kwargs.update({
                'submission__translation_project__project__code':
                project,
            })

        meta_user_ids = cls.objects.meta_users().values_list('id', flat=True)
        top_scores = ScoreLog.objects.values("user").filter(
            **lookup_kwargs).exclude(user__pk__in=meta_user_ids, ).annotate(
                total_score=Sum('score_delta'),
                suggested=Sum(
                    Case(When(action_code=TranslationActionCodes.SUGG_ADDED,
                              then='wordcount'),
                         default=0,
                         output_field=models.IntegerField())),
                translated=Sum(
                    Case(When(translated_wordcount__isnull=False,
                              then='translated_wordcount'),
                         default=0,
                         output_field=models.IntegerField())),
                reviewed=Sum(
                    Case(When(
                        action_code__in=[
                            TranslationActionCodes.SUGG_REVIEWED_ACCEPTED,
                            TranslationActionCodes.REVIEWED,
                            TranslationActionCodes.EDITED,
                        ],
                        translated_wordcount__isnull=True,
                        then='wordcount',
                    ),
                         default=0,
                         output_field=models.IntegerField())),
            ).order_by('-total_score')[offset:]

        if isinstance(limit, (int, long)) and limit > 0:
            top_scores = top_scores[:limit]

        users = dict((user.id, user) for user in cls.objects.filter(
            pk__in=[item['user'] for item in top_scores]))

        top_scorers = []
        for item in top_scores:
            item['user'] = users[item['user']]
            item['public_total_score'] = _humanize_score(item['total_score'])
            top_scorers.append(item)

        cache.set(cache_key, top_scorers, 60)
        return top_scorers