Remove redundant six dependency (#781)
* Don't create universal wheel for Python 3 only Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> * Update Black target version to match min Python supported Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> * Upgrade files using six to Python 3 syntax Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> * Remove redundant six dependency Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> * Format with Black Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> * Add changelog entry Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --------- Signed-off-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
1ef788a55a
commit
de96d28e45
@@ -7,6 +7,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|||||||
- Removed deprecated `numpy.float_` and update NumPy/Pandas imports ([#762](https://github.com/opensearch-project/opensearch-py/pull/762))
|
- Removed deprecated `numpy.float_` and update NumPy/Pandas imports ([#762](https://github.com/opensearch-project/opensearch-py/pull/762))
|
||||||
### Deprecated
|
### Deprecated
|
||||||
### Removed
|
### Removed
|
||||||
|
- Removed redundant dependency on six ([#781](https://github.com/opensearch-project/opensearch-py/pull/781))
|
||||||
### Fixed
|
### Fixed
|
||||||
- Fixed Search helper to ensure proper retention of the _collapse attribute in chained operations. ([#771](https://github.com/opensearch-project/opensearch-py/pull/771))
|
- Fixed Search helper to ensure proper retention of the _collapse attribute in chained operations. ([#771](https://github.com/opensearch-project/opensearch-py/pull/771))
|
||||||
### Updated APIs
|
### Updated APIs
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ def lint(session: Any) -> None:
|
|||||||
"isort",
|
"isort",
|
||||||
"pylint",
|
"pylint",
|
||||||
"types-requests",
|
"types-requests",
|
||||||
"types-six",
|
|
||||||
"types-simplejson",
|
"types-simplejson",
|
||||||
"types-python-dateutil",
|
"types-python-dateutil",
|
||||||
"types-PyYAML",
|
"types-PyYAML",
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import collections.abc as collections_abc
|
|||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from typing import Any, Optional, Tuple, Type
|
from typing import Any, Optional, Tuple, Type
|
||||||
|
|
||||||
from six import add_metaclass
|
|
||||||
|
|
||||||
from opensearchpy._async.client import AsyncOpenSearch
|
from opensearchpy._async.client import AsyncOpenSearch
|
||||||
from opensearchpy._async.helpers.index import AsyncIndex
|
from opensearchpy._async.helpers.index import AsyncIndex
|
||||||
from opensearchpy._async.helpers.search import AsyncSearch
|
from opensearchpy._async.helpers.search import AsyncSearch
|
||||||
@@ -38,7 +36,7 @@ class AsyncIndexMeta(DocumentMeta):
|
|||||||
bases: Tuple[Type[ObjectBase]],
|
bases: Tuple[Type[ObjectBase]],
|
||||||
attrs: Any,
|
attrs: Any,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
new_cls = super(AsyncIndexMeta, cls).__new__(cls, name, bases, attrs)
|
new_cls = super().__new__(cls, name, bases, attrs)
|
||||||
if cls._document_initialized:
|
if cls._document_initialized:
|
||||||
index_opts = attrs.pop("Index", None)
|
index_opts = attrs.pop("Index", None)
|
||||||
index = cls.construct_index(index_opts, bases)
|
index = cls.construct_index(index_opts, bases)
|
||||||
@@ -67,8 +65,7 @@ class AsyncIndexMeta(DocumentMeta):
|
|||||||
return i
|
return i
|
||||||
|
|
||||||
|
|
||||||
@add_metaclass(AsyncIndexMeta)
|
class AsyncDocument(ObjectBase, metaclass=AsyncIndexMeta):
|
||||||
class AsyncDocument(ObjectBase):
|
|
||||||
"""
|
"""
|
||||||
Model-like class for persisting documents in opensearch.
|
Model-like class for persisting documents in opensearch.
|
||||||
"""
|
"""
|
||||||
@@ -297,7 +294,7 @@ class AsyncDocument(ObjectBase):
|
|||||||
``[]``, ``{}``) to be left on the document. Those values will be
|
``[]``, ``{}``) to be left on the document. Those values will be
|
||||||
stripped out otherwise as they make no difference in opensearch.
|
stripped out otherwise as they make no difference in opensearch.
|
||||||
"""
|
"""
|
||||||
d = super(AsyncDocument, self).to_dict(skip_empty)
|
d = super().to_dict(skip_empty)
|
||||||
if not include_meta:
|
if not include_meta:
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,12 @@
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import iteritems, itervalues
|
|
||||||
|
|
||||||
from opensearchpy._async.helpers.search import AsyncSearch
|
from opensearchpy._async.helpers.search import AsyncSearch
|
||||||
from opensearchpy.helpers.faceted_search import FacetedResponse
|
from opensearchpy.helpers.faceted_search import FacetedResponse
|
||||||
from opensearchpy.helpers.query import MatchAll
|
from opensearchpy.helpers.query import MatchAll
|
||||||
|
|
||||||
|
|
||||||
class AsyncFacetedSearch(object):
|
class AsyncFacetedSearch:
|
||||||
"""
|
"""
|
||||||
Abstraction for creating faceted navigation searches that takes care of
|
Abstraction for creating faceted navigation searches that takes care of
|
||||||
composing the queries, aggregations and filters as needed as well as
|
composing the queries, aggregations and filters as needed as well as
|
||||||
@@ -75,7 +73,7 @@ class AsyncFacetedSearch(object):
|
|||||||
self._filters: Any = {}
|
self._filters: Any = {}
|
||||||
self._sort = sort
|
self._sort = sort
|
||||||
self.filter_values: Any = {}
|
self.filter_values: Any = {}
|
||||||
for name, value in iteritems(filters):
|
for name, value in filters.items():
|
||||||
self.add_filter(name, value)
|
self.add_filter(name, value)
|
||||||
|
|
||||||
self._s = self.build_search()
|
self._s = self.build_search()
|
||||||
@@ -140,10 +138,10 @@ class AsyncFacetedSearch(object):
|
|||||||
Add aggregations representing the facets selected, including potential
|
Add aggregations representing the facets selected, including potential
|
||||||
filters.
|
filters.
|
||||||
"""
|
"""
|
||||||
for f, facet in iteritems(self.facets):
|
for f, facet in self.facets.items():
|
||||||
agg = facet.get_aggregation()
|
agg = facet.get_aggregation()
|
||||||
agg_filter = MatchAll()
|
agg_filter = MatchAll()
|
||||||
for field, filter in iteritems(self._filters):
|
for field, filter in self._filters.items():
|
||||||
if f == field:
|
if f == field:
|
||||||
continue
|
continue
|
||||||
agg_filter &= filter
|
agg_filter &= filter
|
||||||
@@ -160,7 +158,7 @@ class AsyncFacetedSearch(object):
|
|||||||
return search
|
return search
|
||||||
|
|
||||||
post_filter = MatchAll()
|
post_filter = MatchAll()
|
||||||
for f in itervalues(self._filters):
|
for f in self._filters.values():
|
||||||
post_filter &= f
|
post_filter &= f
|
||||||
return search.post_filter(post_filter)
|
return search.post_filter(post_filter)
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,12 @@ import collections.abc as collections_abc
|
|||||||
from itertools import chain
|
from itertools import chain
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import iteritems
|
|
||||||
|
|
||||||
from opensearchpy.connection.async_connections import get_connection
|
from opensearchpy.connection.async_connections import get_connection
|
||||||
from opensearchpy.helpers.field import Nested, Text
|
from opensearchpy.helpers.field import Nested, Text
|
||||||
from opensearchpy.helpers.mapping import META_FIELDS, Properties
|
from opensearchpy.helpers.mapping import META_FIELDS, Properties
|
||||||
|
|
||||||
|
|
||||||
class AsyncMapping(object):
|
class AsyncMapping:
|
||||||
_meta: Any
|
_meta: Any
|
||||||
properties: Properties
|
properties: Properties
|
||||||
|
|
||||||
@@ -104,11 +102,11 @@ class AsyncMapping(object):
|
|||||||
self._update_from_dict(raw["mappings"])
|
self._update_from_dict(raw["mappings"])
|
||||||
|
|
||||||
def _update_from_dict(self, raw: Any) -> None:
|
def _update_from_dict(self, raw: Any) -> None:
|
||||||
for name, definition in iteritems(raw.get("properties", {})):
|
for name, definition in raw.get("properties", {}).items():
|
||||||
self.field(name, definition)
|
self.field(name, definition)
|
||||||
|
|
||||||
# metadata like _all etc
|
# metadata like _all etc
|
||||||
for name, value in iteritems(raw):
|
for name, value in raw.items():
|
||||||
if name != "properties":
|
if name != "properties":
|
||||||
if isinstance(value, collections_abc.Mapping):
|
if isinstance(value, collections_abc.Mapping):
|
||||||
self.meta(name, **value)
|
self.meta(name, **value)
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
import copy
|
import copy
|
||||||
from typing import Any, Sequence
|
from typing import Any, Sequence
|
||||||
|
|
||||||
from six import iteritems, string_types
|
|
||||||
|
|
||||||
from opensearchpy._async.helpers.actions import aiter, async_scan
|
from opensearchpy._async.helpers.actions import aiter, async_scan
|
||||||
from opensearchpy.connection.async_connections import get_connection
|
from opensearchpy.connection.async_connections import get_connection
|
||||||
from opensearchpy.exceptions import IllegalOperation, TransportError
|
from opensearchpy.exceptions import IllegalOperation, TransportError
|
||||||
@@ -37,7 +35,7 @@ class AsyncSearch(Request):
|
|||||||
All the parameters supplied (or omitted) at creation type can be later
|
All the parameters supplied (or omitted) at creation type can be later
|
||||||
overridden by methods (`using`, `index` and `doc_type` respectively).
|
overridden by methods (`using`, `index` and `doc_type` respectively).
|
||||||
"""
|
"""
|
||||||
super(AsyncSearch, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.aggs = AggsProxy(self)
|
self.aggs = AggsProxy(self)
|
||||||
self._sort: Sequence[Any] = []
|
self._sort: Sequence[Any] = []
|
||||||
@@ -119,7 +117,7 @@ class AsyncSearch(Request):
|
|||||||
of all the underlying objects. Used internally by most state modifying
|
of all the underlying objects. Used internally by most state modifying
|
||||||
APIs.
|
APIs.
|
||||||
"""
|
"""
|
||||||
s = super(AsyncSearch, self)._clone()
|
s = super()._clone()
|
||||||
|
|
||||||
s._response_class = self._response_class
|
s._response_class = self._response_class
|
||||||
s._sort = self._sort[:]
|
s._sort = self._sort[:]
|
||||||
@@ -158,7 +156,7 @@ class AsyncSearch(Request):
|
|||||||
aggs = d.pop("aggs", d.pop("aggregations", {}))
|
aggs = d.pop("aggs", d.pop("aggregations", {}))
|
||||||
if aggs:
|
if aggs:
|
||||||
self.aggs._params = {
|
self.aggs._params = {
|
||||||
"aggs": {name: A(value) for (name, value) in iteritems(aggs)}
|
"aggs": {name: A(value) for (name, value) in aggs.items()}
|
||||||
}
|
}
|
||||||
if "sort" in d:
|
if "sort" in d:
|
||||||
self._sort = d.pop("sort")
|
self._sort = d.pop("sort")
|
||||||
@@ -200,7 +198,7 @@ class AsyncSearch(Request):
|
|||||||
"""
|
"""
|
||||||
s = self._clone()
|
s = self._clone()
|
||||||
for name in kwargs:
|
for name in kwargs:
|
||||||
if isinstance(kwargs[name], string_types):
|
if isinstance(kwargs[name], str):
|
||||||
kwargs[name] = {"script": kwargs[name]}
|
kwargs[name] = {"script": kwargs[name]}
|
||||||
s._script_fields.update(kwargs)
|
s._script_fields.update(kwargs)
|
||||||
return s
|
return s
|
||||||
@@ -276,7 +274,7 @@ class AsyncSearch(Request):
|
|||||||
s = self._clone()
|
s = self._clone()
|
||||||
s._sort = []
|
s._sort = []
|
||||||
for k in keys:
|
for k in keys:
|
||||||
if isinstance(k, string_types) and k.startswith("-"):
|
if isinstance(k, str) and k.startswith("-"):
|
||||||
if k[1:] == "_score":
|
if k[1:] == "_score":
|
||||||
raise IllegalOperation("Sorting by `-_score` is not allowed.")
|
raise IllegalOperation("Sorting by `-_score` is not allowed.")
|
||||||
k = {k[1:]: {"order": "desc"}}
|
k = {k[1:]: {"order": "desc"}}
|
||||||
@@ -470,7 +468,7 @@ class AsyncMultiSearch(Request):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs: Any) -> None:
|
def __init__(self, **kwargs: Any) -> None:
|
||||||
super(AsyncMultiSearch, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self._searches: Any = []
|
self._searches: Any = []
|
||||||
|
|
||||||
def __getitem__(self, key: Any) -> Any:
|
def __getitem__(self, key: Any) -> Any:
|
||||||
@@ -480,7 +478,7 @@ class AsyncMultiSearch(Request):
|
|||||||
return iter(self._searches)
|
return iter(self._searches)
|
||||||
|
|
||||||
def _clone(self) -> Any:
|
def _clone(self) -> Any:
|
||||||
ms = super(AsyncMultiSearch, self)._clone()
|
ms = super()._clone()
|
||||||
ms._searches = self._searches[:]
|
ms._searches = self._searches[:]
|
||||||
return ms
|
return ms
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,12 @@
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import string_types
|
|
||||||
|
|
||||||
import opensearchpy
|
import opensearchpy
|
||||||
from opensearchpy._async.helpers.actions import aiter
|
from opensearchpy._async.helpers.actions import aiter
|
||||||
from opensearchpy.serializer import serializer
|
from opensearchpy.serializer import serializer
|
||||||
|
|
||||||
|
|
||||||
class AsyncConnections(object):
|
class AsyncConnections:
|
||||||
_conns: Any
|
_conns: Any
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -92,7 +90,7 @@ class AsyncConnections(object):
|
|||||||
"""
|
"""
|
||||||
# do not check isinstance(AsyncOpenSearch) so that people can wrap their
|
# do not check isinstance(AsyncOpenSearch) so that people can wrap their
|
||||||
# clients
|
# clients
|
||||||
if not isinstance(alias, string_types):
|
if not isinstance(alias, str):
|
||||||
return alias
|
return alias
|
||||||
|
|
||||||
# connection already established
|
# connection already established
|
||||||
|
|||||||
@@ -26,13 +26,11 @@
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import string_types
|
|
||||||
|
|
||||||
import opensearchpy
|
import opensearchpy
|
||||||
from opensearchpy.serializer import serializer
|
from opensearchpy.serializer import serializer
|
||||||
|
|
||||||
|
|
||||||
class Connections(object):
|
class Connections:
|
||||||
"""
|
"""
|
||||||
Class responsible for holding connections to different clusters. Used as a
|
Class responsible for holding connections to different clusters. Used as a
|
||||||
singleton in this module.
|
singleton in this module.
|
||||||
@@ -106,7 +104,7 @@ class Connections(object):
|
|||||||
"""
|
"""
|
||||||
# do not check isinstance(OpenSearch) so that people can wrap their
|
# do not check isinstance(OpenSearch) so that people can wrap their
|
||||||
# clients
|
# clients
|
||||||
if not isinstance(alias, string_types):
|
if not isinstance(alias, str):
|
||||||
return alias
|
return alias
|
||||||
|
|
||||||
# connection already established
|
# connection already established
|
||||||
|
|||||||
@@ -26,14 +26,12 @@
|
|||||||
|
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from opensearchpy.connection.connections import get_connection
|
from opensearchpy.connection.connections import get_connection
|
||||||
|
|
||||||
from .utils import AttrDict, DslBase, merge
|
from .utils import AttrDict, DslBase, merge
|
||||||
|
|
||||||
|
|
||||||
class AnalysisBase(object):
|
class AnalysisBase:
|
||||||
@classmethod
|
@classmethod
|
||||||
def _type_shortcut(
|
def _type_shortcut(
|
||||||
cls: Any, name_or_instance: Any, type: Any = None, **kwargs: Any
|
cls: Any, name_or_instance: Any, type: Any = None, **kwargs: Any
|
||||||
@@ -51,7 +49,7 @@ class AnalysisBase(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CustomAnalysis(object):
|
class CustomAnalysis:
|
||||||
name: Optional[str] = "custom"
|
name: Optional[str] = "custom"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -59,14 +57,14 @@ class CustomAnalysis(object):
|
|||||||
) -> None:
|
) -> None:
|
||||||
self._builtin_type = builtin_type
|
self._builtin_type = builtin_type
|
||||||
self._name = filter_name
|
self._name = filter_name
|
||||||
super(CustomAnalysis, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def to_dict(self) -> Any:
|
def to_dict(self) -> Any:
|
||||||
# only name to present in lists
|
# only name to present in lists
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
def get_definition(self) -> Any:
|
def get_definition(self) -> Any:
|
||||||
d = super(CustomAnalysis, self).to_dict() # type: ignore
|
d = super().to_dict() # type: ignore
|
||||||
d = d.pop(self.name)
|
d = d.pop(self.name)
|
||||||
d["type"] = self._builtin_type
|
d["type"] = self._builtin_type
|
||||||
return d
|
return d
|
||||||
@@ -106,12 +104,12 @@ class CustomAnalysisDefinition(CustomAnalysis):
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
class BuiltinAnalysis(object):
|
class BuiltinAnalysis:
|
||||||
name: Optional[str] = "builtin"
|
name: Optional[str] = "builtin"
|
||||||
|
|
||||||
def __init__(self, name: Any) -> None:
|
def __init__(self, name: Any) -> None:
|
||||||
self._name = name
|
self._name = name
|
||||||
super(BuiltinAnalysis, self).__init__()
|
super().__init__()
|
||||||
|
|
||||||
def to_dict(self) -> Any:
|
def to_dict(self) -> Any:
|
||||||
# only name to present in lists
|
# only name to present in lists
|
||||||
@@ -168,7 +166,7 @@ class CustomAnalyzer(CustomAnalysisDefinition, Analyzer):
|
|||||||
sec_def = definition.get(section, {})
|
sec_def = definition.get(section, {})
|
||||||
sec_names = analyzer_def[section]
|
sec_names = analyzer_def[section]
|
||||||
|
|
||||||
if isinstance(sec_names, six.string_types):
|
if isinstance(sec_names, str):
|
||||||
body[section] = sec_def.get(sec_names, sec_names)
|
body[section] = sec_def.get(sec_names, sec_names)
|
||||||
else:
|
else:
|
||||||
body[section] = [
|
body[section] = [
|
||||||
@@ -235,7 +233,7 @@ class MultiplexerTokenFilter(CustomTokenFilter):
|
|||||||
# comma delimited string given by user
|
# comma delimited string given by user
|
||||||
(
|
(
|
||||||
fs
|
fs
|
||||||
if isinstance(fs, six.string_types)
|
if isinstance(fs, str)
|
||||||
else
|
else
|
||||||
# list of strings or TokenFilter objects
|
# list of strings or TokenFilter objects
|
||||||
", ".join(f.to_dict() if hasattr(f, "to_dict") else f for f in fs)
|
", ".join(f.to_dict() if hasattr(f, "to_dict") else f for f in fs)
|
||||||
@@ -251,7 +249,7 @@ class MultiplexerTokenFilter(CustomTokenFilter):
|
|||||||
fs: Any = {}
|
fs: Any = {}
|
||||||
d = {"filter": fs}
|
d = {"filter": fs}
|
||||||
for filters in self.filters:
|
for filters in self.filters:
|
||||||
if isinstance(filters, six.string_types):
|
if isinstance(filters, str):
|
||||||
continue
|
continue
|
||||||
fs.update(
|
fs.update(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import collections.abc as collections_abc
|
|||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from typing import Any, Tuple, Type
|
from typing import Any, Tuple, Type
|
||||||
|
|
||||||
from six import add_metaclass, iteritems
|
|
||||||
|
|
||||||
from opensearchpy.connection.connections import get_connection
|
from opensearchpy.connection.connections import get_connection
|
||||||
from opensearchpy.exceptions import NotFoundError, RequestError
|
from opensearchpy.exceptions import NotFoundError, RequestError
|
||||||
|
|
||||||
@@ -41,7 +39,7 @@ from .search import Search
|
|||||||
from .utils import DOC_META_FIELDS, META_FIELDS, ObjectBase, merge
|
from .utils import DOC_META_FIELDS, META_FIELDS, ObjectBase, merge
|
||||||
|
|
||||||
|
|
||||||
class MetaField(object):
|
class MetaField:
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
self.args, self.kwargs = args, kwargs
|
self.args, self.kwargs = args, kwargs
|
||||||
|
|
||||||
@@ -55,7 +53,7 @@ class DocumentMeta(type):
|
|||||||
) -> Any:
|
) -> Any:
|
||||||
# DocumentMeta filters attrs in place
|
# DocumentMeta filters attrs in place
|
||||||
attrs["_doc_type"] = DocumentOptions(name, bases, attrs)
|
attrs["_doc_type"] = DocumentOptions(name, bases, attrs)
|
||||||
return super(DocumentMeta, cls).__new__(cls, name, bases, attrs)
|
return super().__new__(cls, name, bases, attrs)
|
||||||
|
|
||||||
|
|
||||||
class IndexMeta(DocumentMeta):
|
class IndexMeta(DocumentMeta):
|
||||||
@@ -69,7 +67,7 @@ class IndexMeta(DocumentMeta):
|
|||||||
bases: Tuple[Type[ObjectBase]],
|
bases: Tuple[Type[ObjectBase]],
|
||||||
attrs: Any,
|
attrs: Any,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
new_cls = super(IndexMeta, cls).__new__(cls, name, bases, attrs)
|
new_cls = super().__new__(cls, name, bases, attrs)
|
||||||
if cls._document_initialized:
|
if cls._document_initialized:
|
||||||
index_opts = attrs.pop("Index", None)
|
index_opts = attrs.pop("Index", None)
|
||||||
index = cls.construct_index(index_opts, bases)
|
index = cls.construct_index(index_opts, bases)
|
||||||
@@ -96,7 +94,7 @@ class IndexMeta(DocumentMeta):
|
|||||||
return i
|
return i
|
||||||
|
|
||||||
|
|
||||||
class DocumentOptions(object):
|
class DocumentOptions:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
@@ -109,7 +107,7 @@ class DocumentOptions(object):
|
|||||||
self.mapping = getattr(meta, "mapping", Mapping())
|
self.mapping = getattr(meta, "mapping", Mapping())
|
||||||
|
|
||||||
# register all declared fields into the mapping
|
# register all declared fields into the mapping
|
||||||
for name, value in list(iteritems(attrs)):
|
for name, value in list(attrs.items()):
|
||||||
if isinstance(value, Field):
|
if isinstance(value, Field):
|
||||||
self.mapping.field(name, value)
|
self.mapping.field(name, value)
|
||||||
del attrs[name]
|
del attrs[name]
|
||||||
@@ -130,8 +128,7 @@ class DocumentOptions(object):
|
|||||||
return self.mapping.properties.name
|
return self.mapping.properties.name
|
||||||
|
|
||||||
|
|
||||||
@add_metaclass(DocumentMeta)
|
class InnerDoc(ObjectBase, metaclass=DocumentMeta):
|
||||||
class InnerDoc(ObjectBase):
|
|
||||||
"""
|
"""
|
||||||
Common class for inner documents like Object or Nested
|
Common class for inner documents like Object or Nested
|
||||||
"""
|
"""
|
||||||
@@ -140,11 +137,10 @@ class InnerDoc(ObjectBase):
|
|||||||
def from_opensearch(cls, data: Any, data_only: bool = False) -> Any:
|
def from_opensearch(cls, data: Any, data_only: bool = False) -> Any:
|
||||||
if data_only:
|
if data_only:
|
||||||
data = {"_source": data}
|
data = {"_source": data}
|
||||||
return super(InnerDoc, cls).from_opensearch(data)
|
return super().from_opensearch(data)
|
||||||
|
|
||||||
|
|
||||||
@add_metaclass(IndexMeta)
|
class Document(ObjectBase, metaclass=IndexMeta):
|
||||||
class Document(ObjectBase):
|
|
||||||
"""
|
"""
|
||||||
Model-like class for persisting documents in opensearch.
|
Model-like class for persisting documents in opensearch.
|
||||||
"""
|
"""
|
||||||
@@ -353,7 +349,7 @@ class Document(ObjectBase):
|
|||||||
``[]``, ``{}``) to be left on the document. Those values will be
|
``[]``, ``{}``) to be left on the document. Those values will be
|
||||||
stripped out otherwise as they make no difference in opensearch.
|
stripped out otherwise as they make no difference in opensearch.
|
||||||
"""
|
"""
|
||||||
d = super(Document, self).to_dict(skip_empty=skip_empty)
|
d = super().to_dict(skip_empty=skip_empty)
|
||||||
if not include_meta:
|
if not include_meta:
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,6 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from six import iteritems, itervalues
|
|
||||||
|
|
||||||
from opensearchpy.helpers.aggs import A
|
from opensearchpy.helpers.aggs import A
|
||||||
|
|
||||||
from .query import MatchAll, Nested, Range, Terms
|
from .query import MatchAll, Nested, Range, Terms
|
||||||
@@ -45,7 +43,7 @@ __all__ = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class Facet(object):
|
class Facet:
|
||||||
"""
|
"""
|
||||||
A facet on faceted search. Wraps and aggregation and provides functionality
|
A facet on faceted search. Wraps and aggregation and provides functionality
|
||||||
to create a filter for selected values and return a list of facet values
|
to create a filter for selected values and return a list of facet values
|
||||||
@@ -146,7 +144,7 @@ class RangeFacet(Facet):
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
def __init__(self, ranges: Any, **kwargs: Any) -> None:
|
def __init__(self, ranges: Any, **kwargs: Any) -> None:
|
||||||
super(RangeFacet, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self._params["ranges"] = list(map(self._range_to_dict, ranges))
|
self._params["ranges"] = list(map(self._range_to_dict, ranges))
|
||||||
self._params["keyed"] = False
|
self._params["keyed"] = False
|
||||||
self._ranges = dict(ranges)
|
self._ranges = dict(ranges)
|
||||||
@@ -217,7 +215,7 @@ class DateHistogramFacet(Facet):
|
|||||||
|
|
||||||
def __init__(self, **kwargs: Any) -> None:
|
def __init__(self, **kwargs: Any) -> None:
|
||||||
kwargs.setdefault("min_doc_count", 0)
|
kwargs.setdefault("min_doc_count", 0)
|
||||||
super(DateHistogramFacet, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def get_value(self, bucket: Any) -> Any:
|
def get_value(self, bucket: Any) -> Any:
|
||||||
if not isinstance(bucket["key"], datetime):
|
if not isinstance(bucket["key"], datetime):
|
||||||
@@ -256,9 +254,7 @@ class NestedFacet(Facet):
|
|||||||
def __init__(self, path: Any, nested_facet: Any) -> None:
|
def __init__(self, path: Any, nested_facet: Any) -> None:
|
||||||
self._path = path
|
self._path = path
|
||||||
self._inner = nested_facet
|
self._inner = nested_facet
|
||||||
super(NestedFacet, self).__init__(
|
super().__init__(path=path, aggs={"inner": nested_facet.get_aggregation()})
|
||||||
path=path, aggs={"inner": nested_facet.get_aggregation()}
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_values(self, data: Any, filter_values: Any) -> Any:
|
def get_values(self, data: Any, filter_values: Any) -> Any:
|
||||||
return self._inner.get_values(data.inner, filter_values)
|
return self._inner.get_values(data.inner, filter_values)
|
||||||
@@ -278,7 +274,7 @@ class FacetedResponse(Response):
|
|||||||
def facets(self) -> Any:
|
def facets(self) -> Any:
|
||||||
if not hasattr(self, "_facets"):
|
if not hasattr(self, "_facets"):
|
||||||
super(AttrDict, self).__setattr__("_facets", AttrDict({}))
|
super(AttrDict, self).__setattr__("_facets", AttrDict({}))
|
||||||
for name, facet in iteritems(self._faceted_search.facets):
|
for name, facet in self._faceted_search.facets.items():
|
||||||
self._facets[name] = facet.get_values(
|
self._facets[name] = facet.get_values(
|
||||||
getattr(getattr(self.aggregations, "_filter_" + name), name),
|
getattr(getattr(self.aggregations, "_filter_" + name), name),
|
||||||
self._faceted_search.filter_values.get(name, ()),
|
self._faceted_search.filter_values.get(name, ()),
|
||||||
@@ -286,7 +282,7 @@ class FacetedResponse(Response):
|
|||||||
return self._facets
|
return self._facets
|
||||||
|
|
||||||
|
|
||||||
class FacetedSearch(object):
|
class FacetedSearch:
|
||||||
"""
|
"""
|
||||||
Abstraction for creating faceted navigation searches that takes care of
|
Abstraction for creating faceted navigation searches that takes care of
|
||||||
composing the queries, aggregations and filters as needed as well as
|
composing the queries, aggregations and filters as needed as well as
|
||||||
@@ -344,7 +340,7 @@ class FacetedSearch(object):
|
|||||||
self._filters: Any = {}
|
self._filters: Any = {}
|
||||||
self._sort = sort
|
self._sort = sort
|
||||||
self.filter_values: Any = {}
|
self.filter_values: Any = {}
|
||||||
for name, value in iteritems(filters):
|
for name, value in filters.items():
|
||||||
self.add_filter(name, value)
|
self.add_filter(name, value)
|
||||||
|
|
||||||
self._s = self.build_search()
|
self._s = self.build_search()
|
||||||
@@ -409,10 +405,10 @@ class FacetedSearch(object):
|
|||||||
Add aggregations representing the facets selected, including potential
|
Add aggregations representing the facets selected, including potential
|
||||||
filters.
|
filters.
|
||||||
"""
|
"""
|
||||||
for f, facet in iteritems(self.facets):
|
for f, facet in self.facets.items():
|
||||||
agg = facet.get_aggregation()
|
agg = facet.get_aggregation()
|
||||||
agg_filter = MatchAll()
|
agg_filter = MatchAll()
|
||||||
for field, filter in iteritems(self._filters):
|
for field, filter in self._filters.items():
|
||||||
if f == field:
|
if f == field:
|
||||||
continue
|
continue
|
||||||
agg_filter &= filter
|
agg_filter &= filter
|
||||||
@@ -429,7 +425,7 @@ class FacetedSearch(object):
|
|||||||
return search
|
return search
|
||||||
|
|
||||||
post_filter = MatchAll()
|
post_filter = MatchAll()
|
||||||
for f in itervalues(self._filters):
|
for f in self._filters.values():
|
||||||
post_filter &= f
|
post_filter &= f
|
||||||
return search.post_filter(post_filter)
|
return search.post_filter(post_filter)
|
||||||
|
|
||||||
|
|||||||
@@ -32,15 +32,13 @@ from datetime import date, datetime
|
|||||||
from typing import Any, Optional, Type
|
from typing import Any, Optional, Type
|
||||||
|
|
||||||
from dateutil import parser, tz
|
from dateutil import parser, tz
|
||||||
from six import integer_types, iteritems, string_types
|
|
||||||
from six.moves import map
|
|
||||||
|
|
||||||
from ..exceptions import ValidationException
|
from ..exceptions import ValidationException
|
||||||
from .query import Q
|
from .query import Q
|
||||||
from .utils import AttrDict, AttrList, DslBase
|
from .utils import AttrDict, AttrList, DslBase
|
||||||
from .wrappers import Range
|
from .wrappers import Range
|
||||||
|
|
||||||
unicode: Type[str] = type("")
|
unicode: Type[str] = str
|
||||||
|
|
||||||
|
|
||||||
def construct_field(name_or_field: Any, **params: Any) -> Any:
|
def construct_field(name_or_field: Any, **params: Any) -> Any:
|
||||||
@@ -91,7 +89,7 @@ class Field(DslBase):
|
|||||||
"""
|
"""
|
||||||
self._multi = multi
|
self._multi = multi
|
||||||
self._required = required
|
self._required = required
|
||||||
super(Field, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def __getitem__(self, subfield: Any) -> Any:
|
def __getitem__(self, subfield: Any) -> Any:
|
||||||
return self._params.get("fields", {})[subfield]
|
return self._params.get("fields", {})[subfield]
|
||||||
@@ -131,7 +129,7 @@ class Field(DslBase):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
def to_dict(self) -> Any:
|
def to_dict(self) -> Any:
|
||||||
d = super(Field, self).to_dict()
|
d = super().to_dict()
|
||||||
name, value = d.popitem()
|
name, value = d.popitem()
|
||||||
value["type"] = name
|
value["type"] = name
|
||||||
return value
|
return value
|
||||||
@@ -145,7 +143,7 @@ class CustomField(Field):
|
|||||||
if isinstance(self.builtin_type, Field):
|
if isinstance(self.builtin_type, Field):
|
||||||
return self.builtin_type.to_dict()
|
return self.builtin_type.to_dict()
|
||||||
|
|
||||||
d = super(CustomField, self).to_dict()
|
d = super().to_dict()
|
||||||
d["type"] = self.builtin_type
|
d["type"] = self.builtin_type
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@@ -183,13 +181,13 @@ class Object(Field):
|
|||||||
|
|
||||||
# no InnerDoc subclass, creating one instead...
|
# no InnerDoc subclass, creating one instead...
|
||||||
self._doc_class = type("InnerDoc", (InnerDoc,), {})
|
self._doc_class = type("InnerDoc", (InnerDoc,), {})
|
||||||
for name, field in iteritems(properties or {}):
|
for name, field in (properties or {}).items():
|
||||||
self._doc_class._doc_type.mapping.field(name, field) # type: ignore
|
self._doc_class._doc_type.mapping.field(name, field) # type: ignore
|
||||||
if dynamic is not None:
|
if dynamic is not None:
|
||||||
self._doc_class._doc_type.mapping.meta("dynamic", dynamic) # type: ignore
|
self._doc_class._doc_type.mapping.meta("dynamic", dynamic) # type: ignore
|
||||||
|
|
||||||
self._mapping = copy.deepcopy(self._doc_class._doc_type.mapping)
|
self._mapping = copy.deepcopy(self._doc_class._doc_type.mapping)
|
||||||
super(Object, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def __getitem__(self, name: Any) -> Any:
|
def __getitem__(self, name: Any) -> Any:
|
||||||
return self._mapping[name]
|
return self._mapping[name]
|
||||||
@@ -210,7 +208,7 @@ class Object(Field):
|
|||||||
|
|
||||||
def to_dict(self) -> Any:
|
def to_dict(self) -> Any:
|
||||||
d = self._mapping.to_dict()
|
d = self._mapping.to_dict()
|
||||||
d.update(super(Object, self).to_dict())
|
d.update(super().to_dict())
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _collect_fields(self) -> Any:
|
def _collect_fields(self) -> Any:
|
||||||
@@ -237,7 +235,7 @@ class Object(Field):
|
|||||||
return data.to_dict()
|
return data.to_dict()
|
||||||
|
|
||||||
def clean(self, data: Any) -> Any:
|
def clean(self, data: Any) -> Any:
|
||||||
data = super(Object, self).clean(data)
|
data = super().clean(data)
|
||||||
if data is None:
|
if data is None:
|
||||||
return None
|
return None
|
||||||
if isinstance(data, (list, AttrList)):
|
if isinstance(data, (list, AttrList)):
|
||||||
@@ -260,7 +258,7 @@ class Nested(Object):
|
|||||||
|
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
kwargs.setdefault("multi", True)
|
kwargs.setdefault("multi", True)
|
||||||
super(Nested, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Date(Field):
|
class Date(Field):
|
||||||
@@ -273,12 +271,12 @@ class Date(Field):
|
|||||||
May be instance of `datetime.tzinfo` or string containing TZ offset
|
May be instance of `datetime.tzinfo` or string containing TZ offset
|
||||||
"""
|
"""
|
||||||
self._default_timezone = default_timezone
|
self._default_timezone = default_timezone
|
||||||
if isinstance(self._default_timezone, string_types):
|
if isinstance(self._default_timezone, str):
|
||||||
self._default_timezone = tz.gettz(self._default_timezone)
|
self._default_timezone = tz.gettz(self._default_timezone)
|
||||||
super(Date, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def _deserialize(self, data: Any) -> Any:
|
def _deserialize(self, data: Any) -> Any:
|
||||||
if isinstance(data, string_types):
|
if isinstance(data, str):
|
||||||
try:
|
try:
|
||||||
data = parser.parse(data)
|
data = parser.parse(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -292,7 +290,7 @@ class Date(Field):
|
|||||||
return data
|
return data
|
||||||
if isinstance(data, date):
|
if isinstance(data, date):
|
||||||
return data
|
return data
|
||||||
if isinstance(data, integer_types):
|
if isinstance(data, int):
|
||||||
# Divide by a float to preserve milliseconds on the datetime.
|
# Divide by a float to preserve milliseconds on the datetime.
|
||||||
return datetime.utcfromtimestamp(data / 1000.0)
|
return datetime.utcfromtimestamp(data / 1000.0)
|
||||||
|
|
||||||
@@ -361,7 +359,7 @@ class DenseVector(Float):
|
|||||||
|
|
||||||
def __init__(self, dims: Any, **kwargs: Any) -> None:
|
def __init__(self, dims: Any, **kwargs: Any) -> None:
|
||||||
kwargs["multi"] = True
|
kwargs["multi"] = True
|
||||||
super(DenseVector, self).__init__(dims=dims, **kwargs)
|
super().__init__(dims=dims, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SparseVector(Field):
|
class SparseVector(Field):
|
||||||
@@ -376,9 +374,7 @@ class ScaledFloat(Float):
|
|||||||
name: Optional[str] = "scaled_float"
|
name: Optional[str] = "scaled_float"
|
||||||
|
|
||||||
def __init__(self, scaling_factor: Any, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, scaling_factor: Any, *args: Any, **kwargs: Any) -> None:
|
||||||
super(ScaledFloat, self).__init__(
|
super().__init__(scaling_factor=scaling_factor, *args, **kwargs)
|
||||||
scaling_factor=scaling_factor, *args, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Double(Float):
|
class Double(Float):
|
||||||
@@ -481,7 +477,7 @@ class RangeField(Field):
|
|||||||
def _deserialize(self, data: Any) -> Any:
|
def _deserialize(self, data: Any) -> Any:
|
||||||
if isinstance(data, Range):
|
if isinstance(data, Range):
|
||||||
return data
|
return data
|
||||||
data = dict((k, self._core_field.deserialize(v)) for k, v in iteritems(data))
|
data = {k: self._core_field.deserialize(v) for k, v in data.items()}
|
||||||
return Range(data)
|
return Range(data)
|
||||||
|
|
||||||
def _serialize(self, data: Any) -> Any:
|
def _serialize(self, data: Any) -> Any:
|
||||||
@@ -489,7 +485,7 @@ class RangeField(Field):
|
|||||||
return None
|
return None
|
||||||
if not isinstance(data, collections_abc.Mapping):
|
if not isinstance(data, collections_abc.Mapping):
|
||||||
data = data.to_dict()
|
data = data.to_dict()
|
||||||
return dict((k, self._core_field.serialize(v)) for k, v in iteritems(data))
|
return {k: self._core_field.serialize(v) for k, v in data.items()}
|
||||||
|
|
||||||
|
|
||||||
class IntegerRange(RangeField):
|
class IntegerRange(RangeField):
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import collections.abc as collections_abc
|
|||||||
from itertools import chain
|
from itertools import chain
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import iteritems, itervalues
|
|
||||||
|
|
||||||
from opensearchpy.connection.connections import get_connection
|
from opensearchpy.connection.connections import get_connection
|
||||||
from opensearchpy.helpers.field import Nested, Text, construct_field
|
from opensearchpy.helpers.field import Nested, Text, construct_field
|
||||||
|
|
||||||
@@ -53,7 +51,7 @@ class Properties(DslBase):
|
|||||||
_param_defs = {"properties": {"type": "field", "hash": True}}
|
_param_defs = {"properties": {"type": "field", "hash": True}}
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super(Properties, self).__init__()
|
super().__init__()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "Properties()"
|
return "Properties()"
|
||||||
@@ -65,7 +63,7 @@ class Properties(DslBase):
|
|||||||
return name in self.properties
|
return name in self.properties
|
||||||
|
|
||||||
def to_dict(self) -> Any:
|
def to_dict(self) -> Any:
|
||||||
return super(Properties, self).to_dict()["properties"]
|
return super().to_dict()["properties"]
|
||||||
|
|
||||||
def field(self, name: Any, *args: Any, **kwargs: Any) -> "Properties":
|
def field(self, name: Any, *args: Any, **kwargs: Any) -> "Properties":
|
||||||
self.properties[name] = construct_field(*args, **kwargs)
|
self.properties[name] = construct_field(*args, **kwargs)
|
||||||
@@ -73,16 +71,14 @@ class Properties(DslBase):
|
|||||||
|
|
||||||
def _collect_fields(self) -> Any:
|
def _collect_fields(self) -> Any:
|
||||||
"""Iterate over all Field objects within, including multi fields."""
|
"""Iterate over all Field objects within, including multi fields."""
|
||||||
for f in itervalues(self.properties.to_dict()):
|
for f in self.properties.to_dict().values():
|
||||||
yield f
|
yield f
|
||||||
# multi fields
|
# multi fields
|
||||||
if hasattr(f, "fields"):
|
if hasattr(f, "fields"):
|
||||||
for inner_f in itervalues(f.fields.to_dict()):
|
yield from f.fields.to_dict().values()
|
||||||
yield inner_f
|
|
||||||
# nested and inner objects
|
# nested and inner objects
|
||||||
if hasattr(f, "_collect_fields"):
|
if hasattr(f, "_collect_fields"):
|
||||||
for inner_f in f._collect_fields():
|
yield from f._collect_fields()
|
||||||
yield inner_f
|
|
||||||
|
|
||||||
def update(self, other_object: Any) -> None:
|
def update(self, other_object: Any) -> None:
|
||||||
if not hasattr(other_object, "properties"):
|
if not hasattr(other_object, "properties"):
|
||||||
@@ -98,7 +94,7 @@ class Properties(DslBase):
|
|||||||
our[name] = other[name]
|
our[name] = other[name]
|
||||||
|
|
||||||
|
|
||||||
class Mapping(object):
|
class Mapping:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.properties = Properties()
|
self.properties = Properties()
|
||||||
self._meta: Any = {}
|
self._meta: Any = {}
|
||||||
@@ -181,11 +177,11 @@ class Mapping(object):
|
|||||||
self._update_from_dict(raw["mappings"])
|
self._update_from_dict(raw["mappings"])
|
||||||
|
|
||||||
def _update_from_dict(self, raw: Any) -> None:
|
def _update_from_dict(self, raw: Any) -> None:
|
||||||
for name, definition in iteritems(raw.get("properties", {})):
|
for name, definition in raw.get("properties", {}).items():
|
||||||
self.field(name, definition)
|
self.field(name, definition)
|
||||||
|
|
||||||
# metadata like _all etc
|
# metadata like _all etc
|
||||||
for name, value in iteritems(raw):
|
for name, value in raw.items():
|
||||||
if name != "properties":
|
if name != "properties":
|
||||||
if isinstance(value, collections_abc.Mapping):
|
if isinstance(value, collections_abc.Mapping):
|
||||||
self.meta(name, **value)
|
self.meta(name, **value)
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import collections.abc as collections_abc
|
|||||||
import copy
|
import copy
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import iteritems, string_types
|
|
||||||
|
|
||||||
from opensearchpy.connection.connections import get_connection
|
from opensearchpy.connection.connections import get_connection
|
||||||
from opensearchpy.exceptions import TransportError
|
from opensearchpy.exceptions import TransportError
|
||||||
from opensearchpy.helpers import scan
|
from opensearchpy.helpers import scan
|
||||||
@@ -41,7 +39,7 @@ from .response import Hit, Response
|
|||||||
from .utils import AttrDict, DslBase, recursive_to_dict
|
from .utils import AttrDict, DslBase, recursive_to_dict
|
||||||
|
|
||||||
|
|
||||||
class QueryProxy(object):
|
class QueryProxy:
|
||||||
"""
|
"""
|
||||||
Simple proxy around DSL objects (queries) that can be called
|
Simple proxy around DSL objects (queries) that can be called
|
||||||
(to add query/post_filter) and also allows attribute access which is proxied to
|
(to add query/post_filter) and also allows attribute access which is proxied to
|
||||||
@@ -79,7 +77,7 @@ class QueryProxy(object):
|
|||||||
if not attr_name.startswith("_"):
|
if not attr_name.startswith("_"):
|
||||||
self._proxied = Q(self._proxied.to_dict())
|
self._proxied = Q(self._proxied.to_dict())
|
||||||
setattr(self._proxied, attr_name, value)
|
setattr(self._proxied, attr_name, value)
|
||||||
super(QueryProxy, self).__setattr__(attr_name, value)
|
super().__setattr__(attr_name, value)
|
||||||
|
|
||||||
def __getstate__(self) -> Any:
|
def __getstate__(self) -> Any:
|
||||||
return self._search, self._proxied, self._attr_name
|
return self._search, self._proxied, self._attr_name
|
||||||
@@ -88,7 +86,7 @@ class QueryProxy(object):
|
|||||||
self._search, self._proxied, self._attr_name = state
|
self._search, self._proxied, self._attr_name = state
|
||||||
|
|
||||||
|
|
||||||
class ProxyDescriptor(object):
|
class ProxyDescriptor:
|
||||||
"""
|
"""
|
||||||
Simple descriptor to enable setting of queries and filters as:
|
Simple descriptor to enable setting of queries and filters as:
|
||||||
|
|
||||||
@@ -117,10 +115,10 @@ class AggsProxy(AggBase, DslBase):
|
|||||||
self._params = {"aggs": {}}
|
self._params = {"aggs": {}}
|
||||||
|
|
||||||
def to_dict(self) -> Any:
|
def to_dict(self) -> Any:
|
||||||
return super(AggsProxy, self).to_dict().get("aggs", {})
|
return super().to_dict().get("aggs", {})
|
||||||
|
|
||||||
|
|
||||||
class Request(object):
|
class Request:
|
||||||
_doc_type: Any
|
_doc_type: Any
|
||||||
_doc_type_map: Any
|
_doc_type_map: Any
|
||||||
|
|
||||||
@@ -195,7 +193,7 @@ class Request(object):
|
|||||||
else:
|
else:
|
||||||
indexes = []
|
indexes = []
|
||||||
for i in index:
|
for i in index:
|
||||||
if isinstance(i, string_types):
|
if isinstance(i, str):
|
||||||
indexes.append(i)
|
indexes.append(i)
|
||||||
elif isinstance(i, list):
|
elif isinstance(i, list):
|
||||||
indexes += i
|
indexes += i
|
||||||
@@ -333,7 +331,7 @@ class Search(Request):
|
|||||||
All the parameters supplied (or omitted) at creation type can be later
|
All the parameters supplied (or omitted) at creation type can be later
|
||||||
overridden by methods (`using`, `index` and `doc_type` respectively).
|
overridden by methods (`using`, `index` and `doc_type` respectively).
|
||||||
"""
|
"""
|
||||||
super(Search, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.aggs = AggsProxy(self)
|
self.aggs = AggsProxy(self)
|
||||||
self._sort: Any = []
|
self._sort: Any = []
|
||||||
@@ -422,7 +420,7 @@ class Search(Request):
|
|||||||
of all the underlying objects. Used internally by most state modifying
|
of all the underlying objects. Used internally by most state modifying
|
||||||
APIs.
|
APIs.
|
||||||
"""
|
"""
|
||||||
s = super(Search, self)._clone()
|
s = super()._clone()
|
||||||
|
|
||||||
s._response_class = self._response_class
|
s._response_class = self._response_class
|
||||||
s._sort = self._sort[:]
|
s._sort = self._sort[:]
|
||||||
@@ -462,7 +460,7 @@ class Search(Request):
|
|||||||
aggs = d.pop("aggs", d.pop("aggregations", {}))
|
aggs = d.pop("aggs", d.pop("aggregations", {}))
|
||||||
if aggs:
|
if aggs:
|
||||||
self.aggs._params = {
|
self.aggs._params = {
|
||||||
"aggs": {name: A(value) for (name, value) in iteritems(aggs)}
|
"aggs": {name: A(value) for (name, value) in aggs.items()}
|
||||||
}
|
}
|
||||||
if "sort" in d:
|
if "sort" in d:
|
||||||
self._sort = d.pop("sort")
|
self._sort = d.pop("sort")
|
||||||
@@ -504,7 +502,7 @@ class Search(Request):
|
|||||||
"""
|
"""
|
||||||
s = self._clone()
|
s = self._clone()
|
||||||
for name in kwargs:
|
for name in kwargs:
|
||||||
if isinstance(kwargs[name], string_types):
|
if isinstance(kwargs[name], str):
|
||||||
kwargs[name] = {"script": kwargs[name]}
|
kwargs[name] = {"script": kwargs[name]}
|
||||||
s._script_fields.update(kwargs)
|
s._script_fields.update(kwargs)
|
||||||
return s
|
return s
|
||||||
@@ -580,7 +578,7 @@ class Search(Request):
|
|||||||
s = self._clone()
|
s = self._clone()
|
||||||
s._sort = []
|
s._sort = []
|
||||||
for k in keys:
|
for k in keys:
|
||||||
if isinstance(k, string_types) and k.startswith("-"):
|
if isinstance(k, str) and k.startswith("-"):
|
||||||
if k[1:] == "_score":
|
if k[1:] == "_score":
|
||||||
raise IllegalOperation("Sorting by `-_score` is not allowed.")
|
raise IllegalOperation("Sorting by `-_score` is not allowed.")
|
||||||
k = {k[1:]: {"order": "desc"}}
|
k = {k[1:]: {"order": "desc"}}
|
||||||
@@ -801,7 +799,7 @@ class MultiSearch(Request):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs: Any) -> None:
|
def __init__(self, **kwargs: Any) -> None:
|
||||||
super(MultiSearch, self).__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self._searches: Any = []
|
self._searches: Any = []
|
||||||
|
|
||||||
def __getitem__(self, key: Any) -> Any:
|
def __getitem__(self, key: Any) -> Any:
|
||||||
@@ -811,7 +809,7 @@ class MultiSearch(Request):
|
|||||||
return iter(self._searches)
|
return iter(self._searches)
|
||||||
|
|
||||||
def _clone(self) -> Any:
|
def _clone(self) -> Any:
|
||||||
ms = super(MultiSearch, self)._clone()
|
ms = super()._clone()
|
||||||
ms._searches = self._searches[:]
|
ms._searches = self._searches[:]
|
||||||
return ms
|
return ms
|
||||||
|
|
||||||
|
|||||||
@@ -24,15 +24,11 @@
|
|||||||
# specific language governing permissions and limitations
|
# specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import collections.abc as collections_abc
|
import collections.abc as collections_abc
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from typing import Any, Callable, Dict, Optional, Tuple
|
from typing import Any, Callable, Dict, Optional, Tuple
|
||||||
|
|
||||||
from six import add_metaclass, iteritems
|
|
||||||
from six.moves import map
|
|
||||||
|
|
||||||
from opensearchpy.exceptions import UnknownDslObject, ValidationException
|
from opensearchpy.exceptions import UnknownDslObject, ValidationException
|
||||||
|
|
||||||
SKIP_VALUES: Tuple[str, None] = ("", None)
|
SKIP_VALUES: Tuple[str, None] = ("", None)
|
||||||
@@ -66,7 +62,7 @@ def _wrap(val: Any, obj_wrapper: Optional[Callable[..., Any]] = None) -> Any:
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
class AttrList(object):
|
class AttrList:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, p: Any, obj_wrapper: Optional[Callable[..., Any]] = None
|
self, p: Any, obj_wrapper: Optional[Callable[..., Any]] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -118,7 +114,7 @@ class AttrList(object):
|
|||||||
self._l_, self._obj_wrapper = state
|
self._l_, self._obj_wrapper = state
|
||||||
|
|
||||||
|
|
||||||
class AttrDict(object):
|
class AttrDict:
|
||||||
"""
|
"""
|
||||||
Helper class to provide attribute like access (read and write) to
|
Helper class to provide attribute like access (read and write) to
|
||||||
dictionaries. Used to provide a convenient way to access both results and
|
dictionaries. Used to provide a convenient way to access both results and
|
||||||
@@ -127,7 +123,7 @@ class AttrDict(object):
|
|||||||
|
|
||||||
def __init__(self, d: Any) -> None:
|
def __init__(self, d: Any) -> None:
|
||||||
# assign the inner dict manually to prevent __setattr__ from firing
|
# assign the inner dict manually to prevent __setattr__ from firing
|
||||||
super(AttrDict, self).__setattr__("_d_", d)
|
super().__setattr__("_d_", d)
|
||||||
|
|
||||||
def __contains__(self, key: Any) -> bool:
|
def __contains__(self, key: Any) -> bool:
|
||||||
return key in self._d_
|
return key in self._d_
|
||||||
@@ -160,7 +156,7 @@ class AttrDict(object):
|
|||||||
return (self._d_,)
|
return (self._d_,)
|
||||||
|
|
||||||
def __setstate__(self, state: Any) -> None:
|
def __setstate__(self, state: Any) -> None:
|
||||||
super(AttrDict, self).__setattr__("_d_", state[0])
|
super().__setattr__("_d_", state[0])
|
||||||
|
|
||||||
def __getattr__(self, attr_name: Any) -> Any:
|
def __getattr__(self, attr_name: Any) -> Any:
|
||||||
try:
|
try:
|
||||||
@@ -204,7 +200,7 @@ class AttrDict(object):
|
|||||||
self._d_[name] = value
|
self._d_[name] = value
|
||||||
else:
|
else:
|
||||||
# there is an attribute on the class (could be property, ..) - don't add it as field
|
# there is an attribute on the class (could be property, ..) - don't add it as field
|
||||||
super(AttrDict, self).__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
|
||||||
def __iter__(self) -> Any:
|
def __iter__(self) -> Any:
|
||||||
return iter(self._d_)
|
return iter(self._d_)
|
||||||
@@ -230,7 +226,7 @@ class DslMeta(type):
|
|||||||
|
|
||||||
def __init__(cls: Any, name: str, bases: Any, attrs: Any) -> None:
|
def __init__(cls: Any, name: str, bases: Any, attrs: Any) -> None:
|
||||||
# TODO: why is it calling itself?!
|
# TODO: why is it calling itself?!
|
||||||
super(DslMeta, cls).__init__(name, bases, attrs)
|
super().__init__(name, bases, attrs)
|
||||||
# skip for DslBase
|
# skip for DslBase
|
||||||
if not hasattr(cls, "_type_shortcut"):
|
if not hasattr(cls, "_type_shortcut"):
|
||||||
return
|
return
|
||||||
@@ -252,8 +248,7 @@ class DslMeta(type):
|
|||||||
raise UnknownDslObject("DSL type %s does not exist." % name)
|
raise UnknownDslObject("DSL type %s does not exist." % name)
|
||||||
|
|
||||||
|
|
||||||
@add_metaclass(DslMeta)
|
class DslBase(metaclass=DslMeta):
|
||||||
class DslBase(object):
|
|
||||||
"""
|
"""
|
||||||
Base class for all DSL objects - queries, filters, aggregations etc. Wraps
|
Base class for all DSL objects - queries, filters, aggregations etc. Wraps
|
||||||
a dictionary representing the object's json.
|
a dictionary representing the object's json.
|
||||||
@@ -285,7 +280,7 @@ class DslBase(object):
|
|||||||
|
|
||||||
def __init__(self, _expand__to_dot: Any = EXPAND__TO_DOT, **params: Any) -> None:
|
def __init__(self, _expand__to_dot: Any = EXPAND__TO_DOT, **params: Any) -> None:
|
||||||
self._params = {}
|
self._params = {}
|
||||||
for pname, pvalue in iteritems(params):
|
for pname, pvalue in params.items():
|
||||||
if "__" in pname and _expand__to_dot:
|
if "__" in pname and _expand__to_dot:
|
||||||
pname = pname.replace("__", ".")
|
pname = pname.replace("__", ".")
|
||||||
self._setattr(pname, pvalue)
|
self._setattr(pname, pvalue)
|
||||||
@@ -294,7 +289,7 @@ class DslBase(object):
|
|||||||
"""Produce a repr of all our parameters to be used in __repr__."""
|
"""Produce a repr of all our parameters to be used in __repr__."""
|
||||||
return ", ".join(
|
return ", ".join(
|
||||||
"{}={!r}".format(n.replace(".", "__"), v)
|
"{}={!r}".format(n.replace(".", "__"), v)
|
||||||
for (n, v) in sorted(iteritems(self._params))
|
for (n, v) in sorted(self._params.items())
|
||||||
# make sure we don't include empty typed params
|
# make sure we don't include empty typed params
|
||||||
if "type" not in self._param_defs.get(n, {}) or v
|
if "type" not in self._param_defs.get(n, {}) or v
|
||||||
)
|
)
|
||||||
@@ -310,7 +305,7 @@ class DslBase(object):
|
|||||||
|
|
||||||
def __setattr__(self, name: str, value: Any) -> None:
|
def __setattr__(self, name: str, value: Any) -> None:
|
||||||
if name.startswith("_"):
|
if name.startswith("_"):
|
||||||
return super(DslBase, self).__setattr__(name, value)
|
return super().__setattr__(name, value)
|
||||||
return self._setattr(name, value)
|
return self._setattr(name, value)
|
||||||
|
|
||||||
def _setattr(self, name: Any, value: Any) -> None:
|
def _setattr(self, name: Any, value: Any) -> None:
|
||||||
@@ -327,7 +322,7 @@ class DslBase(object):
|
|||||||
if not isinstance(value, (tuple, list)):
|
if not isinstance(value, (tuple, list)):
|
||||||
value = (value,)
|
value = (value,)
|
||||||
value = list(
|
value = list(
|
||||||
{k: shortcut(v) for (k, v) in iteritems(obj)} for obj in value
|
{k: shortcut(v) for (k, v) in obj.items()} for obj in value
|
||||||
)
|
)
|
||||||
elif pinfo.get("multi"):
|
elif pinfo.get("multi"):
|
||||||
if not isinstance(value, (tuple, list)):
|
if not isinstance(value, (tuple, list)):
|
||||||
@@ -336,7 +331,7 @@ class DslBase(object):
|
|||||||
|
|
||||||
# dict(name -> DslBase), make sure we pickup all the objs
|
# dict(name -> DslBase), make sure we pickup all the objs
|
||||||
elif pinfo.get("hash"):
|
elif pinfo.get("hash"):
|
||||||
value = {k: shortcut(v) for (k, v) in iteritems(value)}
|
value = {k: shortcut(v) for (k, v) in value.items()}
|
||||||
|
|
||||||
# single value object, just convert
|
# single value object, just convert
|
||||||
else:
|
else:
|
||||||
@@ -380,7 +375,7 @@ class DslBase(object):
|
|||||||
Serialize the DSL object to plain dict
|
Serialize the DSL object to plain dict
|
||||||
"""
|
"""
|
||||||
d = {}
|
d = {}
|
||||||
for pname, value in iteritems(self._params):
|
for pname, value in self._params.items():
|
||||||
pinfo = self._param_defs.get(pname)
|
pinfo = self._param_defs.get(pname)
|
||||||
|
|
||||||
# typed param
|
# typed param
|
||||||
@@ -392,7 +387,7 @@ class DslBase(object):
|
|||||||
# list of dict(name -> DslBase)
|
# list of dict(name -> DslBase)
|
||||||
if pinfo.get("multi") and pinfo.get("hash"):
|
if pinfo.get("multi") and pinfo.get("hash"):
|
||||||
value = list(
|
value = list(
|
||||||
{k: v.to_dict() for k, v in iteritems(obj)} for obj in value
|
{k: v.to_dict() for k, v in obj.items()} for obj in value
|
||||||
)
|
)
|
||||||
|
|
||||||
# multi-values are serialized as list of dicts
|
# multi-values are serialized as list of dicts
|
||||||
@@ -401,7 +396,7 @@ class DslBase(object):
|
|||||||
|
|
||||||
# squash all the hash values into one dict
|
# squash all the hash values into one dict
|
||||||
elif pinfo.get("hash"):
|
elif pinfo.get("hash"):
|
||||||
value = {k: v.to_dict() for k, v in iteritems(value)}
|
value = {k: v.to_dict() for k, v in value.items()}
|
||||||
|
|
||||||
# serialize single values
|
# serialize single values
|
||||||
else:
|
else:
|
||||||
@@ -427,13 +422,13 @@ class HitMeta(AttrDict):
|
|||||||
) -> None:
|
) -> None:
|
||||||
d = {
|
d = {
|
||||||
k[1:] if k.startswith("_") else k: v
|
k[1:] if k.startswith("_") else k: v
|
||||||
for (k, v) in iteritems(document)
|
for (k, v) in document.items()
|
||||||
if k not in exclude
|
if k not in exclude
|
||||||
}
|
}
|
||||||
if "type" in d:
|
if "type" in d:
|
||||||
# make sure we are consistent everywhere in python
|
# make sure we are consistent everywhere in python
|
||||||
d["doc_type"] = d.pop("type")
|
d["doc_type"] = d.pop("type")
|
||||||
super(HitMeta, self).__init__(d)
|
super().__init__(d)
|
||||||
|
|
||||||
|
|
||||||
class ObjectBase(AttrDict):
|
class ObjectBase(AttrDict):
|
||||||
@@ -447,7 +442,7 @@ class ObjectBase(AttrDict):
|
|||||||
|
|
||||||
super(AttrDict, self).__setattr__("meta", HitMeta(meta))
|
super(AttrDict, self).__setattr__("meta", HitMeta(meta))
|
||||||
|
|
||||||
super(ObjectBase, self).__init__(kwargs)
|
super().__init__(kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __list_fields(cls: Any) -> Any:
|
def __list_fields(cls: Any) -> Any:
|
||||||
@@ -491,7 +486,7 @@ class ObjectBase(AttrDict):
|
|||||||
return doc
|
return doc
|
||||||
|
|
||||||
def _from_dict(self, data: Any) -> None:
|
def _from_dict(self, data: Any) -> None:
|
||||||
for k, v in iteritems(data):
|
for k, v in data.items():
|
||||||
f = self.__get_field(k)
|
f = self.__get_field(k)
|
||||||
if f and f._coerce:
|
if f and f._coerce:
|
||||||
v = f.deserialize(v)
|
v = f.deserialize(v)
|
||||||
@@ -508,7 +503,7 @@ class ObjectBase(AttrDict):
|
|||||||
|
|
||||||
def __getattr__(self, name: Any) -> Any:
|
def __getattr__(self, name: Any) -> Any:
|
||||||
try:
|
try:
|
||||||
return super(ObjectBase, self).__getattr__(name)
|
return super().__getattr__(name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
f = self.__get_field(name)
|
f = self.__get_field(name)
|
||||||
if hasattr(f, "empty"):
|
if hasattr(f, "empty"):
|
||||||
@@ -521,7 +516,7 @@ class ObjectBase(AttrDict):
|
|||||||
|
|
||||||
def to_dict(self, skip_empty: Optional[bool] = True) -> Any:
|
def to_dict(self, skip_empty: Optional[bool] = True) -> Any:
|
||||||
out = {}
|
out = {}
|
||||||
for k, v in iteritems(self._d_):
|
for k, v in self._d_.items():
|
||||||
# if this is a mapped field,
|
# if this is a mapped field,
|
||||||
f = self.__get_field(k)
|
f = self.__get_field(k)
|
||||||
if f and f._coerce:
|
if f and f._coerce:
|
||||||
@@ -584,7 +579,7 @@ def merge(data: Any, new_data: Any, raise_on_conflict: bool = False) -> None:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for key, value in iteritems(new_data):
|
for key, value in new_data.items():
|
||||||
if (
|
if (
|
||||||
key in data
|
key in data
|
||||||
and isinstance(data[key], (AttrDict, collections_abc.Mapping))
|
and isinstance(data[key], (AttrDict, collections_abc.Mapping))
|
||||||
|
|||||||
@@ -27,8 +27,6 @@
|
|||||||
import operator
|
import operator
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from six import iteritems, string_types
|
|
||||||
|
|
||||||
from .utils import AttrDict
|
from .utils import AttrDict
|
||||||
|
|
||||||
|
|
||||||
@@ -57,14 +55,14 @@ class Range(AttrDict):
|
|||||||
if "lt" in data and "lte" in data:
|
if "lt" in data and "lte" in data:
|
||||||
raise ValueError("You cannot specify both lt and lte for Range.")
|
raise ValueError("You cannot specify both lt and lte for Range.")
|
||||||
|
|
||||||
super(Range, self).__init__(args[0] if args else kwargs)
|
super().__init__(args[0] if args else kwargs)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "Range(%s)" % ", ".join("%s=%r" % op for op in iteritems(self._d_))
|
return "Range(%s)" % ", ".join("%s=%r" % op for op in self._d_.items())
|
||||||
|
|
||||||
def __contains__(self, item: Any) -> bool:
|
def __contains__(self, item: Any) -> bool:
|
||||||
if isinstance(item, string_types):
|
if isinstance(item, str):
|
||||||
return super(Range, self).__contains__(item)
|
return super().__contains__(item)
|
||||||
|
|
||||||
for op in self.OPS:
|
for op in self.OPS:
|
||||||
if op in self._d_ and not self.OPS[op](item, self._d_[op]):
|
if op in self._d_ and not self.OPS[op](item, self._d_[op]):
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
[bdist_wheel]
|
|
||||||
universal = 1
|
|
||||||
|
|
||||||
[bdist_rpm]
|
[bdist_rpm]
|
||||||
requires = python python-urllib3
|
requires = python python-urllib3
|
||||||
|
|
||||||
@@ -17,9 +14,7 @@ profile=black
|
|||||||
|
|
||||||
[black]
|
[black]
|
||||||
max-line-length = 240
|
max-line-length = 240
|
||||||
target-version = 'py33'
|
target-version = 'py38'
|
||||||
|
|
||||||
[mypy]
|
[mypy]
|
||||||
ignore_missing_imports=True
|
ignore_missing_imports=True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ install_requires = [
|
|||||||
'urllib3>=1.26.18,<1.27 ; python_version < "3.10"',
|
'urllib3>=1.26.18,<1.27 ; python_version < "3.10"',
|
||||||
'urllib3>=1.26.18,!=2.2.0,<3 ; python_version >= "3.10"',
|
'urllib3>=1.26.18,!=2.2.0,<3 ; python_version >= "3.10"',
|
||||||
"requests>=2.4.0, <3.0.0",
|
"requests>=2.4.0, <3.0.0",
|
||||||
"six",
|
|
||||||
"python-dateutil",
|
"python-dateutil",
|
||||||
"certifi>=2022.12.07",
|
"certifi>=2022.12.07",
|
||||||
"Events",
|
"Events",
|
||||||
|
|||||||
Reference in New Issue
Block a user