Skip to content

Commit

Permalink
Move common types to superdesk.core.types
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkLark86 committed Sep 3, 2024
1 parent 4690675 commit 0229807
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 78 deletions.
2 changes: 1 addition & 1 deletion superdesk/core/elastic/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from elasticsearch.exceptions import NotFoundError, TransportError, RequestError
from elasticsearch.helpers import async_bulk

from ..resources.cursor import SearchRequest
from superdesk.core.types import SearchRequest
from .base_client import BaseElasticResourceClient, ElasticCursor, InvalidSearchString


Expand Down
15 changes: 9 additions & 6 deletions superdesk/core/elastic/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

from typing import Dict, Any, Optional, Iterator, List, Tuple, Union, TypedDict
from typing import Dict, Any, Optional, Iterator, List, Tuple, Union, TypedDict, Literal
import ast

import simplejson as json
from eve.io.mongo.parser import parse

from superdesk.errors import SuperdeskApiError
from ..resources.cursor import ProjectedFieldArg, SearchRequest
from superdesk.core.types import ProjectedFieldArg, SearchRequest, SortParam
from .common import ElasticClientConfig, ElasticResourceConfig


Expand Down Expand Up @@ -172,8 +172,7 @@ def _get_find_args(

if "sort" not in query:
if req.sort:
sort = ast.literal_eval(req.sort)
_set_sort(query, sort)
_set_sort(query, req.sort)
elif self.resource_config.default_sort:
_set_sort(query, self.resource_config.default_sort)

Expand Down Expand Up @@ -282,9 +281,13 @@ def _format_doc(self, hit: Dict[str, Any]):
return doc


def _set_sort(query, sort):
def _set_sort(query: dict, sort: SortParam | None) -> None:
if sort is None:
return

query["sort"] = []
for key, sortdir in sort:
sort_list = ast.literal_eval(sort) if isinstance(sort, str) else sort
for key, sortdir in sort_list:
sort_dict = dict([(key, "asc" if sortdir > 0 else "desc")])
query["sort"].append(sort_dict)

Expand Down
2 changes: 1 addition & 1 deletion superdesk/core/elastic/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from uuid import uuid4

from ..config import ConfigModel
from ..resources.cursor import SearchRequest
from superdesk.core.types import SearchRequest


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion superdesk/core/elastic/sync_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from elasticsearch.exceptions import NotFoundError, TransportError, RequestError
from elasticsearch.helpers import bulk

from ..resources.cursor import SearchRequest
from superdesk.core.types import SearchRequest
from .base_client import BaseElasticResourceClient, ElasticCursor, InvalidSearchString


Expand Down
67 changes: 1 addition & 66 deletions superdesk/core/resources/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,76 +8,11 @@
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

from typing import Dict, Any, Generic, TypeVar, Type, Optional, List, Union, Literal
from typing_extensions import TypedDict
from typing import Dict, Any, Generic, TypeVar, Type, Optional, List

from pydantic import BaseModel, ConfigDict
from motor.motor_asyncio import AsyncIOMotorCollection, AsyncIOMotorCursor


#: The data type for projections, either a list of field names, or a dictionary containing
#: the field and enable/disable state
ProjectedFieldArg = Union[List[str], Dict[str, Literal[0]], Dict[str, Literal[1]]]


class SearchArgs(TypedDict, total=False):
"""Dictionary containing Elasticsearch search arguments
This is for use with the `.find` methods in elastic clients
"""

#: A JSON string containing an elasticsearch query
source: str

#: A query string
q: str

#: Default field, for use with the query string
df: str

#: Default operator, for use with the query string (defaults to "AND")
default_operator: str

#: A JSON string containing bool query filters, to be applied to the elastic query
filter: str

#: A list of dictionaries containing bool query filters, to be applied to the elastic query
filters: List[Dict[str, Any]]

#: A JSON string containing the field projections to filter out the returned fields
projections: str


class SearchRequest(BaseModel):
"""Dataclass containing Elasticsearch request arguments"""

model_config = ConfigDict(extra="allow")

#: Argument for the search filters
args: Optional[SearchArgs] = None

#: Sorting to be used
sort: Optional[str] = None

#: Maximum number of documents to be returned
max_results: int = 25

#: The page number to be returned
page: int = 1

#: A JSON string containing an Elasticsearch where query
where: Optional[Union[str, Dict]] = None

#: If `True`, will include aggregations with the result
aggregations: bool = False

#: If `True`, will include highlights with the result
highlight: bool = False

#: The field projections to be applied
projection: Optional[ProjectedFieldArg] = None


ResourceModelType = TypeVar("ResourceModelType", bound="ResourceModel")


Expand Down
82 changes: 82 additions & 0 deletions superdesk/core/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2024 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

from typing import Dict, Any, Optional, List, Union, Literal
from typing_extensions import TypedDict

from pydantic import BaseModel, ConfigDict, NonNegativeInt


#: The data type for projections, either a list of field names, or a dictionary containing
#: the field and enable/disable state
ProjectedFieldArg = Union[List[str], Dict[str, Literal[0]], Dict[str, Literal[1]]]
SortListParam = list[tuple[str, Literal[1, -1]]]
SortParam = str | SortListParam
VersionParam = Literal["all"] | NonNegativeInt


class SearchArgs(TypedDict, total=False):
"""Dictionary containing Elasticsearch search arguments
This is for use with the `.find` methods in elastic clients
"""

#: A JSON string containing an elasticsearch query
source: str

#: A query string
q: str

#: Default field, for use with the query string
df: str

#: Default operator, for use with the query string (defaults to "AND")
default_operator: str

#: A JSON string containing bool query filters, to be applied to the elastic query
filter: str

#: A list of dictionaries containing bool query filters, to be applied to the elastic query
filters: List[Dict[str, Any]]

#: A JSON string containing the field projections to filter out the returned fields
projections: str

version: VersionParam | None


class SearchRequest(BaseModel):
"""Dataclass containing Elasticsearch request arguments"""

model_config = ConfigDict(extra="allow")

#: Argument for the search filters
args: Optional[SearchArgs] = None

#: Sorting to be used
sort: SortParam | None = None

#: Maximum number of documents to be returned
max_results: int = 25

#: The page number to be returned
page: int = 1

#: A JSON string contianing an Elasticsearch where query
where: str | dict | None = None

#: If `True`, will include aggregations with the result
aggregations: bool = False

#: If `True`, will include highlights with the result
highlight: bool = False

#: The field projections to be applied
projection: Optional[ProjectedFieldArg] = None
2 changes: 1 addition & 1 deletion tests/core/elastic_async_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import simplejson as json

from superdesk.tests import AsyncTestCase
from superdesk.core.resources.cursor import SearchRequest
from superdesk.core.types import SearchRequest

from .modules.users import User
from .fixtures.users import john_doe
Expand Down
2 changes: 1 addition & 1 deletion tests/core/elastic_sync_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import simplejson as json

from superdesk.tests import AsyncTestCase
from superdesk.core.resources.cursor import SearchRequest
from superdesk.core.types import SearchRequest

from .modules.users import User
from .fixtures.users import john_doe
Expand Down
2 changes: 1 addition & 1 deletion tests/core/resource_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import simplejson as json
from bson import ObjectId

from superdesk.core.resources.cursor import SearchRequest
from superdesk.core.types import SearchRequest
from superdesk.utc import utcnow
from superdesk.utils import format_time

Expand Down

0 comments on commit 0229807

Please sign in to comment.