Esempio n. 1
0
def test_extract_vfolder_from_path():
    """Tests that vfolder is correctly extracted from path, if any."""
    subdir0 = TranslationProject.objects.get(
        language__code="language1",
        project__code="project1",
    ).directory.child_dirs.first()

    # Check that subdir0 pootle_path matches no vfolder.
    path = subdir0.pootle_path

    assert (None, path) == extract_vfolder_from_path(path)

    # Check that vfoldertreeitem pootle_path returns a vfolder and a clean path.
    vfolder_item = {
        'name': 'vfolder0',
        'location': subdir0.pootle_path,
        'priority': 4,
        'is_public': True,
        'filter_rules': subdir0.child_stores.first().name,
    }
    vfolder0 = VirtualFolder(**vfolder_item)
    vfolder0.save()

    path = subdir0.vf_treeitems.first().pootle_path

    assert (vfolder0, subdir0.pootle_path) == extract_vfolder_from_path(path)

    # Check that the right vfolder is matched and returned.
    subdir1_first_store = subdir0.child_dirs.first().child_stores.first()

    vfolder_location = subdir0.parent.pootle_path
    filter_path = subdir1_first_store.pootle_path.replace(vfolder_location, "")

    vfolder_item.update({
        'location': vfolder_location,
        'priority': 2,
        'filter_rules': filter_path,
    })
    vfolder1 = VirtualFolder(**vfolder_item)
    vfolder1.save()

    path = subdir0.vf_treeitems.first().pootle_path

    assert (vfolder0, subdir0.pootle_path) == extract_vfolder_from_path(path)

    # Despite the virtual folders share the same name they have different
    # locations, but the VirtualFolderTreeItem pootle_path is unique, thus only
    # one exists.
    assert 1 == VirtualFolderTreeItem.objects.filter(pootle_path=path).count()
Esempio n. 2
0
File: tp.py Progetto: haf/pootle
def _test_translate_view(tp, request, response, kwargs, settings):
    ctx = response.context
    kwargs["project_code"] = tp.project.code
    kwargs["language_code"] = tp.language.code
    resource_path = "%(dir_path)s%(filename)s" % kwargs
    request_path = "%s%s" % (tp.pootle_path, resource_path)
    vfolder, pootle_path = extract_vfolder_from_path(request_path)
    current_vfolder_pk = vfolder.pk if vfolder else ""
    display_priority = not current_vfolder_pk and (
        VirtualFolderTreeItem.objects.filter(pootle_path__startswith=pootle_path).exists()
    )
    assertions = dict(
        page="translate",
        translation_project=tp,
        language=tp.language,
        project=tp.project,
        is_admin=False,
        profile=request.profile,
        ctx_path=tp.pootle_path,
        pootle_path=request_path,
        resource_path=resource_path,
        resource_path_parts=get_path_parts(resource_path),
        editor_extends="translation_projects/base.html",
        check_categories=get_qualitycheck_schema(),
        previous_url=get_previous_url(request),
        current_vfolder_pk=current_vfolder_pk,
        display_priority=display_priority,
        cantranslate=check_permission("translate", request),
        cansuggest=check_permission("suggest", request),
        canreview=check_permission("review", request),
        search_form=make_search_form(request=request),
        POOTLE_MT_BACKENDS=settings.POOTLE_MT_BACKENDS,
        AMAGAMA_URL=settings.AMAGAMA_URL,
    )
    view_context_test(ctx, **assertions)
Esempio n. 3
0
def _test_translate_view(tp, request, response, kwargs, settings):
    ctx = response.context
    kwargs["project_code"] = tp.project.code
    kwargs["language_code"] = tp.language.code
    resource_path = "%(dir_path)s%(filename)s" % kwargs
    request_path = "%s%s" % (tp.pootle_path, resource_path)
    vfolder, pootle_path = extract_vfolder_from_path(request_path)
    current_vfolder_pk = (vfolder.pk if vfolder else "")
    display_priority = (not current_vfolder_pk and not kwargs['filename']
                        and ctx['object'].has_vfolders)
    assertions = dict(page="translate",
                      translation_project=tp,
                      language=tp.language,
                      project=tp.project,
                      is_admin=check_permission('administrate', request),
                      ctx_path=tp.pootle_path,
                      pootle_path=request_path,
                      resource_path=resource_path,
                      resource_path_parts=get_path_parts(resource_path),
                      editor_extends="translation_projects/base.html",
                      check_categories=get_qualitycheck_schema(),
                      previous_url=get_previous_url(request),
                      current_vfolder_pk=current_vfolder_pk,
                      display_priority=display_priority,
                      cantranslate=check_permission("translate", request),
                      cansuggest=check_permission("suggest", request),
                      canreview=check_permission("review", request),
                      search_form=make_search_form(request=request),
                      POOTLE_MT_BACKENDS=settings.POOTLE_MT_BACKENDS,
                      AMAGAMA_URL=settings.AMAGAMA_URL)
    view_context_test(ctx, **assertions)
Esempio n. 4
0
    def extracted_path(self):
        if 'virtualfolder' not in settings.INSTALLED_APPS:
            return None, self.request_path

        from virtualfolder.helpers import extract_vfolder_from_path
        from virtualfolder.models import VirtualFolderTreeItem
        return extract_vfolder_from_path(
            self.request_path,
            vfti=VirtualFolderTreeItem.objects.select_related(
                "directory", "vfolder"))
Esempio n. 5
0
    def extracted_path(self):
        if 'virtualfolder' not in settings.INSTALLED_APPS:
            return None, self.request_path

        from virtualfolder.helpers import extract_vfolder_from_path
        from virtualfolder.models import VirtualFolderTreeItem
        return extract_vfolder_from_path(
            self.request_path,
            vfti=VirtualFolderTreeItem.objects.select_related(
                "directory", "vfolder"))
Esempio n. 6
0
    def clean(self):
        from .views import ALLOWED_SORTS

        if "checks" in self.errors:
            del self.errors["checks"]
            self.cleaned_data["checks"] = None
        if "user" in self.errors:
            del self.errors["user"]
            self.cleaned_data["user"] = self.request_user
        if self.errors:
            return
        if self.default_count:
            count = (
                self.cleaned_data.get("count", self.default_count)
                or self.default_count)
            user_count = (
                self.cleaned_data["user"].get_unit_rows()
                or self.default_count)
            self.cleaned_data['count'] = min(count, user_count)
        self.cleaned_data["vfolder"] = None
        pootle_path = self.cleaned_data.get("path")
        if 'virtualfolder' in settings.INSTALLED_APPS:
            from virtualfolder.helpers import extract_vfolder_from_path
            from virtualfolder.models import VirtualFolderTreeItem
            vfolder, pootle_path = extract_vfolder_from_path(
                pootle_path,
                vfti=VirtualFolderTreeItem.objects.select_related(
                    "directory", "vfolder"))
            self.cleaned_data["vfolder"] = vfolder
            self.cleaned_data["pootle_path"] = pootle_path
        path_keys = [
            "project_code", "language_code", "dir_path", "filename"]
        try:
            path_kwargs = {
                k: v
                for k, v in resolve(pootle_path).kwargs.items()
                if k in path_keys}
        except Resolver404:
            raise forms.ValidationError('Unrecognised path')
        self.cleaned_data.update(path_kwargs)
        sort_on = "units"
        if "filter" in self.cleaned_data:
            unit_filter = self.cleaned_data["filter"]
            if unit_filter in ('suggestions', 'user-suggestions'):
                sort_on = 'suggestions'
            elif unit_filter in ('user-submissions', ):
                sort_on = 'submissions'
        sort_by_param = self.cleaned_data["sort"]
        self.cleaned_data["sort_by"] = ALLOWED_SORTS[sort_on].get(sort_by_param)
        self.cleaned_data["sort_on"] = sort_on
Esempio n. 7
0
 def clean(self):
     if "checks" in self.errors:
         del self.errors["checks"]
         self.cleaned_data["checks"] = None
     if "user" in self.errors:
         del self.errors["user"]
         self.cleaned_data["user"] = self.request_user
     if self.errors:
         return
     if self.default_count:
         count = (
             self.cleaned_data.get("count", self.default_count)
             or self.default_count)
         user_count = (
             self.cleaned_data["user"].get_unit_rows()
             or self.default_count)
         self.cleaned_data['count'] = min(count, user_count)
     self.cleaned_data["vfolder"] = None
     pootle_path = self.cleaned_data.get("path")
     if 'virtualfolder' in settings.INSTALLED_APPS:
         from virtualfolder.helpers import extract_vfolder_from_path
         from virtualfolder.models import VirtualFolderTreeItem
         vfolder, pootle_path = extract_vfolder_from_path(
             pootle_path,
             vfti=VirtualFolderTreeItem.objects.select_related(
                 "directory", "vfolder"))
         self.cleaned_data["vfolder"] = vfolder
         self.cleaned_data["pootle_path"] = pootle_path
     path_keys = [
         "project_code", "language_code", "dir_path", "filename"]
     try:
         path_kwargs = {
             k: v
             for k, v in resolve(pootle_path).kwargs.items()
             if k in path_keys}
     except Resolver404:
         raise forms.ValidationError('Unrecognised path')
     self.cleaned_data.update(path_kwargs)
     sort_on = "units"
     if "filter" in self.cleaned_data:
         unit_filter = self.cleaned_data["filter"]
         if unit_filter in ('suggestions', 'user-suggestions'):
             sort_on = 'suggestions'
         elif unit_filter in ('user-submissions', ):
             sort_on = 'submissions'
     sort_by_param = self.cleaned_data["sort"]
     self.cleaned_data["sort_by"] = ALLOWED_SORTS[sort_on].get(sort_by_param)
     self.cleaned_data["sort_on"] = sort_on
Esempio n. 8
0
def _test_translate_view(tp, request, response, kwargs, settings):
    ctx = response.context
    kwargs["project_code"] = tp.project.code
    kwargs["language_code"] = tp.language.code
    resource_path = "%(dir_path)s%(filename)s" % kwargs
    request_path = "%s%s" % (tp.pootle_path, resource_path)
    vfolder, pootle_path = extract_vfolder_from_path(request_path)
    current_vfolder_pk = (
        vfolder.pk
        if vfolder
        else "")
    display_priority = (
        not current_vfolder_pk
        and not kwargs['filename'] and ctx['object'].has_vfolders)
    assertions = dict(
        page="translate",
        translation_project=tp,
        language=tp.language,
        project=tp.project,
        has_admin_access=check_permission('administrate', request),
        ctx_path=tp.pootle_path,
        pootle_path=request_path,
        resource_path=resource_path,
        resource_path_parts=get_path_parts(resource_path),
        editor_extends="translation_projects/base.html",
        check_categories=get_qualitycheck_schema(),
        previous_url=get_previous_url(request),
        current_vfolder_pk=current_vfolder_pk,
        display_priority=display_priority,
        cantranslate=check_permission("translate", request),
        cansuggest=check_permission("suggest", request),
        canreview=check_permission("review", request),
        search_form=make_search_form(request=request),
        POOTLE_MT_BACKENDS=settings.POOTLE_MT_BACKENDS,
        AMAGAMA_URL=settings.AMAGAMA_URL)
    view_context_test(ctx, **assertions)
Esempio n. 9
0
 def extracted_path(self):
     return extract_vfolder_from_path(
         self.request_path,
         vfti=VirtualFolderTreeItem.objects.select_related(
             "directory", "vfolder"))
Esempio n. 10
0
def set_resource(request, path_obj, dir_path, filename):
    """Loads :cls:`pootle_app.models.Directory` and
    :cls:`pootle_store.models.Store` models and populates the
    request object.

    :param path_obj: A path-like object object.
    :param dir_path: Path relative to the root of `path_obj`.
    :param filename: Optional filename.
    """
    obj_directory = getattr(path_obj, 'directory', path_obj)
    ctx_path = obj_directory.pootle_path
    resource_path = dir_path
    pootle_path = ctx_path + dir_path

    directory = None
    store = None

    is_404 = False

    # Get a clean pootle path for retrieving the directory or store.
    # A clean pootle path is a pootle path without any virtual folder name on
    # it. For example /af/test_vfolders/browser/chrome/ is the corresponding
    # clean pootle path for /af/test_vfolders/browser/vfolder8/chrome/
    vfolder, clean_pootle_path = extract_vfolder_from_path(pootle_path)

    if filename:
        pootle_path = pootle_path + filename
        clean_pootle_path = clean_pootle_path + filename
        resource_path = resource_path + filename

        try:
            store = Store.objects.live().select_related(
                'translation_project',
                'parent',
            ).get(pootle_path=clean_pootle_path)
            directory = store.parent
        except Store.DoesNotExist:
            is_404 = True

    if directory is None and not is_404:
        if dir_path:
            try:
                directory = Directory.objects.live().get(pootle_path=clean_pootle_path)
            except Directory.DoesNotExist:
                is_404 = True
        else:
            directory = obj_directory

    if is_404:  # Try parent directory
        language_code, project_code, dp, fn = split_pootle_path(clean_pootle_path)
        if not filename:
            dir_path = dir_path[:dir_path[:-1].rfind('/') + 1]

        url = reverse('pootle-tp-browse',
                      args=[language_code, project_code, dir_path])
        request.redirect_url = url

        raise Http404

    request.store = store
    request.directory = directory
    request.pootle_path = pootle_path
    request.current_vfolder = getattr(vfolder, 'pk', '')

    request.resource_obj = store or (directory if dir_path else path_obj)
    request.resource_path = resource_path
    request.ctx_obj = path_obj or request.resource_obj
    request.ctx_path = ctx_path
Esempio n. 11
0
def get_units(request):
    """Gets source and target texts and its metadata.

    :return: A JSON-encoded string containing the source and target texts
        grouped by the store they belong to.

        The optional `count` GET parameter defines the chunk size to
        consider. The user's preference will be used by default.

        When the `initial` GET parameter is present, a sorted list of
        the result set ids will be returned too.
    """
    pootle_path = request.GET.get("path", None)
    if pootle_path is None:
        raise Http400(_("Arguments missing."))

    User = get_user_model()
    request.profile = User.get(request.user)
    limit = request.profile.get_unit_rows()
    vfolder = None

    if "virtualfolder" in settings.INSTALLED_APPS:
        from virtualfolder.helpers import extract_vfolder_from_path

        vfolder, pootle_path = extract_vfolder_from_path(pootle_path)

    units_qs = Unit.objects.get_for_path(pootle_path, request.profile)

    if vfolder is not None:
        units_qs = units_qs.filter(vfolders=vfolder)

    units_qs = units_qs.select_related("store__translation_project__project", "store__translation_project__language")
    step_queryset = get_step_query(request, units_qs)

    is_initial_request = request.GET.get("initial", False)
    chunk_size = request.GET.get("count", limit)
    uids_param = filter(None, request.GET.get("uids", "").split(u","))
    uids = filter(None, map(to_int, uids_param))

    units = []
    unit_groups = []
    uid_list = []

    if is_initial_request:
        sort_by_field = None
        if len(step_queryset.query.order_by) == 1:
            sort_by_field = step_queryset.query.order_by[0]

        sort_on = None
        for key, item in ALLOWED_SORTS.items():
            if sort_by_field in item.values():
                sort_on = key
                break

        if sort_by_field is None or sort_on == "units":
            # Since `extra()` has been used before, it's necessary to explicitly
            # request the `store__pootle_path` field. This is a subtetly in
            # Django's ORM.
            uid_list = [u["id"] for u in step_queryset.values("id", "store__pootle_path")]
        else:
            # Not using `values_list()` here because it doesn't know about all
            # existing relations when `extra()` has been used before in the
            # queryset. This affects annotated names such as those ending in
            # `__max`, where Django thinks we're trying to lookup a field on a
            # relationship field. That's why `sort_by_field` alias for `__max`
            # is used here. This alias must be queried in
            # `values('sort_by_field', 'id')` with `id` otherwise
            # Django looks for `sort_by_field` field in the initial table.
            # https://code.djangoproject.com/ticket/19434
            uid_list = [u["id"] for u in step_queryset.values("id", "sort_by_field", "store__pootle_path")]

        if len(uids) == 1:
            try:
                uid = uids[0]
                index = uid_list.index(uid)
                begin = max(index - chunk_size, 0)
                end = min(index + chunk_size + 1, len(uid_list))
                uids = uid_list[begin:end]
            except ValueError:
                raise Http404  # `uid` not found in `uid_list`
        else:
            count = 2 * chunk_size
            uids = uid_list[:count]

    if not units and uids:
        units = step_queryset.filter(id__in=uids)

    units_by_path = groupby(units, lambda x: x.store.pootle_path)
    for pootle_path, units in units_by_path:
        unit_groups.append(_path_units_with_meta(pootle_path, units))

    response = {"unitGroups": unit_groups}
    if uid_list:
        response["uIds"] = uid_list

    return JsonResponse(response)
Esempio n. 12
0
def calculate_search_results(kwargs, user):
    pootle_path = kwargs["pootle_path"]
    category = kwargs.get("category")
    checks = kwargs.get("checks")
    offset = kwargs.get("offset", 0)
    limit = kwargs.get("count", 9)
    modified_since = kwargs.get("modified-since")
    search = kwargs.get("search")
    sfields = kwargs.get("sfields")
    soptions = kwargs.get("soptions", [])
    sort = kwargs.get("sort", None)
    language_code, project_code, dir_path, filename = (
        split_pootle_path(kwargs["pootle_path"]))
    uids = [
        int(x)
        for x
        in kwargs.get("uids", "").split(",")
        if x]
    unit_filter = kwargs.get("filter")

    if modified_since:
        modified_since = parse_datetime(modified_since)

    vfolder = None
    if 'virtualfolder' in settings.INSTALLED_APPS:
        vfolder, pootle_path = extract_vfolder_from_path(
            pootle_path,
            vfti=VirtualFolderTreeItem.objects.select_related(
                "directory", "vfolder"))
    qs = (
        Unit.objects.get_translatable(user=user, **resolve(pootle_path).kwargs)
                    .order_by("store", "index"))
    if vfolder is not None:
        qs = qs.filter(vfolders=vfolder)
    # if "filter" is present in request vars...
    if unit_filter:
        # filter the results accordingly
        qs = UnitSearchFilter().filter(
            qs,
            unit_filter,
            user=user,
            checks=checks,
            category=get_category_id(category))
        # filter by modified
        if modified_since:
            qs = qs.filter(submitted_on__gt=modified_since).distinct()
        # sort results
        if unit_filter in ["my-suggestions", "user-suggestions"]:
            sort_on = "suggestions"
        elif unit_filter in ["my-submissions", "user-submissions"]:
            sort_on = "submissions"
        else:
            sort_on = "units"
        sort_by = ALLOWED_SORTS[sort_on].get(sort, None)
        if sort_by is not None:
            # filtered sort
            if sort_on in SIMPLY_SORTED:
                qs = qs.order_by(sort_by, "store__pootle_path", "index")
            else:
                if sort_by[0] == '-':
                    max_field = sort_by[1:]
                    sort_order = '-sort_by_field'
                else:
                    max_field = sort_by
                    sort_order = 'sort_by_field'
                qs = (
                    qs.annotate(sort_by_field=Max(max_field))
                      .order_by(sort_order, "store__pootle_path", "index"))
    # text search
    if search and sfields:
        qs = UnitTextSearch(qs).search(
            search,
            [sfields],
            "exact" in soptions)

    find_unit = (
        not offset
        and language_code
        and project_code
        and filename
        and uids)
    start = offset
    total = qs.count()
    if find_unit:
            # find the uid in the Store
        uid_list = list(qs.values_list("pk", flat=True))
        unit_index = uid_list.index(uids[0])
        start = int(unit_index / (2 * limit)) * (2 * limit)
    end = min(start + (2 * limit), total)

    unit_groups = []
    units_by_path = groupby(
        qs.values(*GroupedResults.select_fields)[start:end],
        lambda x: x["store__pootle_path"])
    for pootle_path, units in units_by_path:
        unit_groups.append(
            {pootle_path: StoreResults(units).data})

    total = qs.count()
    return total, start, min(end, total), unit_groups
Esempio n. 13
0
 def extracted_path(self):
     return extract_vfolder_from_path(
         self.request_path,
         vfti=VirtualFolderTreeItem.objects.select_related(
             "directory", "vfolder"))
Esempio n. 14
0
def calculate_search_results(kwargs, user):
    pootle_path = kwargs["pootle_path"]

    category = kwargs.get("category")
    checks = kwargs.get("checks")
    initial = kwargs.get("initial", False)
    limit = kwargs.get("count", 9)
    modified_since = kwargs.get("modified-since")
    search = kwargs.get("search")
    sfields = kwargs.get("sfields")
    soptions = kwargs.get("soptions", [])
    sort = kwargs.get("sort", None)
    uids = [
        int(x)
        for x
        in kwargs.get("uids", "").split(",")
        if x]
    unit_filter = kwargs.get("filter")

    if modified_since:
        modified_since = parse_datetime(modified_since)

    vfolder = None
    if 'virtualfolder' in settings.INSTALLED_APPS:
        vfolder, pootle_path = extract_vfolder_from_path(
            pootle_path,
            vfti=VirtualFolderTreeItem.objects.select_related(
                "directory", "vfolder"))
    qs = (
        Unit.objects.get_translatable(user=user, **resolve(pootle_path).kwargs)
                    .filter(store__pootle_path__startswith=pootle_path)
                    .order_by("store", "index"))
    if vfolder is not None:
        qs = qs.filter(vfolders=vfolder)
    # if "filter" is present in request vars...
    if unit_filter:
        # filter the results accordingly
        qs = UnitSearchFilter().filter(
            qs,
            unit_filter,
            user=user,
            checks=checks,
            category=get_category_id(category))
        # filter by modified
        if modified_since:
            qs = qs.filter(submitted_on__gt=modified_since).distinct()
        # sort results
        if unit_filter in ["my-suggestions", "user-suggestions"]:
            sort_on = "suggestions"
        elif unit_filter in ["my-submissions", "user-submissions"]:
            sort_on = "submissions"
        else:
            sort_on = "units"
        sort_by = ALLOWED_SORTS[sort_on].get(sort, None)
        if sort_by is not None:
            # filtered sort
            if sort_on in SIMPLY_SORTED:
                qs = qs.order_by(sort_by, "store__pootle_path", "index")
            else:
                if sort_by[0] == '-':
                    max_field = sort_by[1:]
                    sort_order = '-sort_by_field'
                else:
                    max_field = sort_by
                    sort_order = 'sort_by_field'
                qs = (
                    qs.annotate(sort_by_field=Max(max_field))
                      .order_by(sort_order, "store__pootle_path", "index"))
    # text search
    if search and sfields:
        qs = UnitTextSearch(qs).search(
            search,
            [sfields],
            "exact" in soptions)
    begin = 0
    end = None
    uid_list = []
    if initial:
        uid_list = list(qs.values_list("pk", flat=True))
        if uids and len(uids) == 1:
            # if uid is set get the index of the uid
            index = uid_list.index(uids[0])
            begin = max(index - limit, 0)
            end = min(index + limit + 1, len(uid_list))
    elif uids:
        qs = qs.filter(id__in=uids)
    if end is None:
        end = 2 * limit
    unit_groups = []
    units_by_path = groupby(
        qs.values(*GroupedResults.select_fields)[begin:end],
        lambda x: x["store__pootle_path"])
    for pootle_path, units in units_by_path:
        unit_groups.append(
            {pootle_path: StoreResults(units).data})
    return uid_list, unit_groups
Esempio n. 15
0
def calculate_search_results(kwargs, user):
    pootle_path = kwargs["pootle_path"]

    category = kwargs.get("category")
    checks = kwargs.get("checks")
    initial = kwargs.get("initial", False)
    limit = kwargs.get("count", 9)
    modified_since = kwargs.get("modified-since")
    search = kwargs.get("search")
    sfields = kwargs.get("sfields")
    soptions = kwargs.get("soptions", [])
    sort = kwargs.get("sort", None)
    uids = [int(x) for x in kwargs.get("uids", "").split(",") if x]
    unit_filter = kwargs.get("filter")

    if modified_since:
        modified_since = parse_datetime(modified_since)

    vfolder = None
    if 'virtualfolder' in settings.INSTALLED_APPS:
        vfolder, pootle_path = extract_vfolder_from_path(
            pootle_path,
            vfti=VirtualFolderTreeItem.objects.select_related(
                "directory", "vfolder"))
    qs = (Unit.objects.get_translatable(
        user=user, **resolve(pootle_path).kwargs).filter(
            store__pootle_path__startswith=pootle_path).order_by(
                "store", "index"))
    if vfolder is not None:
        qs = qs.filter(vfolders=vfolder)
    # if "filter" is present in request vars...
    if unit_filter:
        # filter the results accordingly
        qs = UnitSearchFilter().filter(qs,
                                       unit_filter,
                                       user=user,
                                       checks=checks,
                                       category=get_category_id(category))
        # filter by modified
        if modified_since:
            qs = qs.filter(submitted_on__gt=modified_since).distinct()
        # sort results
        if unit_filter in ["my-suggestions", "user-suggestions"]:
            sort_on = "suggestions"
        elif unit_filter in ["my-submissions", "user-submissions"]:
            sort_on = "submissions"
        else:
            sort_on = "units"
        sort_by = ALLOWED_SORTS[sort_on].get(sort, None)
        if sort_by is not None:
            # filtered sort
            if sort_on in SIMPLY_SORTED:
                qs = qs.order_by(sort_by, "store__pootle_path", "index")
            else:
                if sort_by[0] == '-':
                    max_field = sort_by[1:]
                    sort_order = '-sort_by_field'
                else:
                    max_field = sort_by
                    sort_order = 'sort_by_field'
                qs = (qs.annotate(sort_by_field=Max(max_field)).order_by(
                    sort_order, "store__pootle_path", "index"))
    # text search
    if search and sfields:
        qs = UnitTextSearch(qs).search(search, [sfields], "exact" in soptions)
    begin = 0
    end = None
    uid_list = []
    if initial:
        uid_list = list(qs.values_list("pk", flat=True))
        if uids and len(uids) == 1:
            # if uid is set get the index of the uid
            index = uid_list.index(uids[0])
            begin = max(index - limit, 0)
            end = min(index + limit + 1, len(uid_list))
    elif uids:
        qs = qs.filter(id__in=uids)
    if end is None:
        end = 2 * limit
    unit_groups = []
    units_by_path = groupby(
        qs.values(*GroupedResults.select_fields)[begin:end],
        lambda x: x["store__pootle_path"])
    for pootle_path, units in units_by_path:
        unit_groups.append({pootle_path: StoreResults(units).data})
    return uid_list, unit_groups
Esempio n. 16
0
def calculate_search_results(kwargs, user):
    pootle_path = kwargs["pootle_path"]
    category = kwargs.get("category")
    checks = kwargs.get("checks")
    offset = kwargs.get("offset", 0)
    limit = kwargs.get("count", 9)
    modified_since = kwargs.get("modified-since")
    search = kwargs.get("search")
    sfields = kwargs.get("sfields")
    soptions = kwargs.get("soptions", [])
    sort = kwargs.get("sort", None)
    language_code, project_code, dir_path, filename = split_pootle_path(kwargs["pootle_path"])
    uids = [int(x) for x in kwargs.get("uids", "").split(",") if x]
    unit_filter = kwargs.get("filter")

    if modified_since:
        modified_since = parse_datetime(modified_since)

    vfolder = None
    if "virtualfolder" in settings.INSTALLED_APPS:
        vfolder, pootle_path = extract_vfolder_from_path(
            pootle_path, vfti=VirtualFolderTreeItem.objects.select_related("directory", "vfolder")
        )
    qs = Unit.objects.get_translatable(user=user, **resolve(pootle_path).kwargs).order_by("store", "index")
    if vfolder is not None:
        qs = qs.filter(vfolders=vfolder)
    # if "filter" is present in request vars...
    if unit_filter:
        # filter the results accordingly
        qs = UnitSearchFilter().filter(qs, unit_filter, user=user, checks=checks, category=get_category_id(category))
        # filter by modified
        if modified_since:
            qs = qs.filter(submitted_on__gt=modified_since).distinct()
        # sort results
        if unit_filter in ["my-suggestions", "user-suggestions"]:
            sort_on = "suggestions"
        elif unit_filter in ["my-submissions", "user-submissions"]:
            sort_on = "submissions"
        else:
            sort_on = "units"
        sort_by = ALLOWED_SORTS[sort_on].get(sort, None)
        if sort_by is not None:
            # filtered sort
            if sort_on in SIMPLY_SORTED:
                qs = qs.order_by(sort_by, "store__pootle_path", "index")
            else:
                if sort_by[0] == "-":
                    max_field = sort_by[1:]
                    sort_order = "-sort_by_field"
                else:
                    max_field = sort_by
                    sort_order = "sort_by_field"
                qs = qs.annotate(sort_by_field=Max(max_field)).order_by(sort_order, "store__pootle_path", "index")
    # text search
    if search and sfields:
        qs = UnitTextSearch(qs).search(search, [sfields], "exact" in soptions)

    find_unit = not offset and language_code and project_code and filename and uids
    start = offset
    total = qs.count()
    if find_unit:
        # find the uid in the Store
        uid_list = list(qs.values_list("pk", flat=True))
        unit_index = uid_list.index(uids[0])
        start = int(unit_index / (2 * limit)) * (2 * limit)
    end = min(start + (2 * limit), total)

    unit_groups = []
    units_by_path = groupby(qs.values(*GroupedResults.select_fields)[start:end], lambda x: x["store__pootle_path"])
    for pootle_path, units in units_by_path:
        unit_groups.append({pootle_path: StoreResults(units).data})

    total = qs.count()
    return total, start, min(end, total), unit_groups
Esempio n. 17
0
def get_units(request):
    """Gets source and target texts and its metadata.

    :return: A JSON-encoded string containing the source and target texts
        grouped by the store they belong to.

        The optional `count` GET parameter defines the chunk size to
        consider. The user's preference will be used by default.

        When the `initial` GET parameter is present, a sorted list of
        the result set ids will be returned too.
    """
    pootle_path = request.GET.get('path', None)
    if pootle_path is None:
        raise Http400(_('Arguments missing.'))

    User = get_user_model()
    request.profile = User.get(request.user)
    limit = request.profile.get_unit_rows()
    vfolder = None

    if 'virtualfolder' in settings.INSTALLED_APPS:
        from virtualfolder.helpers import extract_vfolder_from_path

        vfolder, pootle_path = extract_vfolder_from_path(pootle_path)

    units_qs = Unit.objects.get_for_path(pootle_path, request.profile)

    if vfolder is not None:
        units_qs = units_qs.filter(vfolders=vfolder)

    units_qs = units_qs.select_related(
        'store__translation_project__project',
        'store__translation_project__language',
    )
    step_queryset = get_step_query(request, units_qs)

    is_initial_request = request.GET.get('initial', False)
    chunk_size = request.GET.get('count', limit)
    uids_param = filter(None, request.GET.get('uids', '').split(u','))
    uids = filter(None, map(to_int, uids_param))

    units = []
    unit_groups = []
    uid_list = []

    if is_initial_request:
        sort_by_field = None
        if len(step_queryset.query.order_by) == 1:
            sort_by_field = step_queryset.query.order_by[0]

        sort_on = None
        for key, item in ALLOWED_SORTS.items():
            if sort_by_field in item.values():
                sort_on = key
                break

        if sort_by_field is None or sort_on == 'units':
            uid_list = list(step_queryset.values_list('id', flat=True))
        else:
            # Not using `values_list()` here because it doesn't know about all
            # existing relations when `extra()` has been used before in the
            # queryset. This affects annotated names such as those ending in
            # `__max`, where Django thinks we're trying to lookup a field on a
            # relationship field. That's why `sort_by_field` alias for `__max`
            # is used here. This alias must be queried in
            # `values('sort_by_field', 'id')` with `id` otherwise
            # Django looks for `sort_by_field` field in the initial table.
            # https://code.djangoproject.com/ticket/19434
            uid_list = [
                u['id'] for u in step_queryset.values('id', 'sort_by_field')
            ]

        if len(uids) == 1:
            try:
                uid = uids[0]
                index = uid_list.index(uid)
                begin = max(index - chunk_size, 0)
                end = min(index + chunk_size + 1, len(uid_list))
                uids = uid_list[begin:end]
            except ValueError:
                raise Http404  # `uid` not found in `uid_list`
        else:
            count = 2 * chunk_size
            uids = uid_list[:count]

    if not units and uids:
        units = step_queryset.filter(id__in=uids)

    units_by_path = groupby(units, lambda x: x.store.pootle_path)
    for pootle_path, units in units_by_path:
        unit_groups.append(_path_units_with_meta(pootle_path, units))

    response = {
        'unitGroups': unit_groups,
    }
    if uid_list:
        response['uIds'] = uid_list

    return JsonResponse(response)