diff --git a/CHANGELOG.md b/CHANGELOG.md index a259f485..7c0dbff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) ### Deprecated ### Removed +- Removed redundant dependency on six ([#781](https://github.com/opensearch-project/opensearch-py/pull/781)) ### 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)) ### Updated APIs diff --git a/noxfile.py b/noxfile.py index cdbc8a6d..b727b60a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -90,7 +90,6 @@ def lint(session: Any) -> None: "isort", "pylint", "types-requests", - "types-six", "types-simplejson", "types-python-dateutil", "types-PyYAML", diff --git a/opensearchpy/_async/helpers/document.py b/opensearchpy/_async/helpers/document.py index 09549068..dc7c5ff3 100644 --- a/opensearchpy/_async/helpers/document.py +++ b/opensearchpy/_async/helpers/document.py @@ -11,8 +11,6 @@ from fnmatch import fnmatch from typing import Any, Optional, Tuple, Type -from six import add_metaclass - from opensearchpy._async.client import AsyncOpenSearch from opensearchpy._async.helpers.index import AsyncIndex from opensearchpy._async.helpers.search import AsyncSearch @@ -38,7 +36,7 @@ def __new__( bases: Tuple[Type[ObjectBase]], attrs: Any, ) -> Any: - new_cls = super(AsyncIndexMeta, cls).__new__(cls, name, bases, attrs) + new_cls = super().__new__(cls, name, bases, attrs) if cls._document_initialized: index_opts = attrs.pop("Index", None) index = cls.construct_index(index_opts, bases) @@ -67,8 +65,7 @@ def construct_index(cls, opts: Any, bases: Any) -> Any: return i -@add_metaclass(AsyncIndexMeta) -class AsyncDocument(ObjectBase): +class AsyncDocument(ObjectBase, metaclass=AsyncIndexMeta): """ Model-like class for persisting documents in opensearch. """ @@ -297,7 +294,7 @@ def to_dict( # type: ignore ``[]``, ``{}``) to be left on the document. Those values will be 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: return d diff --git a/opensearchpy/_async/helpers/faceted_search.py b/opensearchpy/_async/helpers/faceted_search.py index 2b0501d9..e1949b16 100644 --- a/opensearchpy/_async/helpers/faceted_search.py +++ b/opensearchpy/_async/helpers/faceted_search.py @@ -10,14 +10,12 @@ from typing import Any -from six import iteritems, itervalues - from opensearchpy._async.helpers.search import AsyncSearch from opensearchpy.helpers.faceted_search import FacetedResponse from opensearchpy.helpers.query import MatchAll -class AsyncFacetedSearch(object): +class AsyncFacetedSearch: """ Abstraction for creating faceted navigation searches that takes care of composing the queries, aggregations and filters as needed as well as @@ -75,7 +73,7 @@ def __init__(self, query: Any = None, filters: Any = {}, sort: Any = ()) -> None self._filters: Any = {} self._sort = sort self.filter_values: Any = {} - for name, value in iteritems(filters): + for name, value in filters.items(): self.add_filter(name, value) self._s = self.build_search() @@ -140,10 +138,10 @@ def aggregate(self, search: Any) -> Any: Add aggregations representing the facets selected, including potential filters. """ - for f, facet in iteritems(self.facets): + for f, facet in self.facets.items(): agg = facet.get_aggregation() agg_filter = MatchAll() - for field, filter in iteritems(self._filters): + for field, filter in self._filters.items(): if f == field: continue agg_filter &= filter @@ -160,7 +158,7 @@ def filter(self, search: Any) -> Any: return search post_filter = MatchAll() - for f in itervalues(self._filters): + for f in self._filters.values(): post_filter &= f return search.post_filter(post_filter) diff --git a/opensearchpy/_async/helpers/mapping.py b/opensearchpy/_async/helpers/mapping.py index 93f04f05..d345a0dc 100644 --- a/opensearchpy/_async/helpers/mapping.py +++ b/opensearchpy/_async/helpers/mapping.py @@ -11,14 +11,12 @@ from itertools import chain from typing import Any -from six import iteritems - from opensearchpy.connection.async_connections import get_connection from opensearchpy.helpers.field import Nested, Text from opensearchpy.helpers.mapping import META_FIELDS, Properties -class AsyncMapping(object): +class AsyncMapping: _meta: Any properties: Properties @@ -104,11 +102,11 @@ async def update_from_opensearch(self, index: Any, using: str = "default") -> No self._update_from_dict(raw["mappings"]) 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) # metadata like _all etc - for name, value in iteritems(raw): + for name, value in raw.items(): if name != "properties": if isinstance(value, collections_abc.Mapping): self.meta(name, **value) diff --git a/opensearchpy/_async/helpers/search.py b/opensearchpy/_async/helpers/search.py index 7f09ba7f..e6a52428 100644 --- a/opensearchpy/_async/helpers/search.py +++ b/opensearchpy/_async/helpers/search.py @@ -10,8 +10,6 @@ import copy from typing import Any, Sequence -from six import iteritems, string_types - from opensearchpy._async.helpers.actions import aiter, async_scan from opensearchpy.connection.async_connections import get_connection from opensearchpy.exceptions import IllegalOperation, TransportError @@ -37,7 +35,7 @@ def __init__(self, **kwargs: Any) -> None: All the parameters supplied (or omitted) at creation type can be later overridden by methods (`using`, `index` and `doc_type` respectively). """ - super(AsyncSearch, self).__init__(**kwargs) + super().__init__(**kwargs) self.aggs = AggsProxy(self) self._sort: Sequence[Any] = [] @@ -119,7 +117,7 @@ def _clone(self) -> Any: of all the underlying objects. Used internally by most state modifying APIs. """ - s = super(AsyncSearch, self)._clone() + s = super()._clone() s._response_class = self._response_class s._sort = self._sort[:] @@ -158,7 +156,7 @@ def update_from_dict(self, d: Any) -> "AsyncSearch": aggs = d.pop("aggs", d.pop("aggregations", {})) if aggs: 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: self._sort = d.pop("sort") @@ -200,7 +198,7 @@ def script_fields(self, **kwargs: Any) -> Any: """ s = self._clone() for name in kwargs: - if isinstance(kwargs[name], string_types): + if isinstance(kwargs[name], str): kwargs[name] = {"script": kwargs[name]} s._script_fields.update(kwargs) return s @@ -276,7 +274,7 @@ def sort(self, *keys: Any) -> Any: s = self._clone() s._sort = [] for k in keys: - if isinstance(k, string_types) and k.startswith("-"): + if isinstance(k, str) and k.startswith("-"): if k[1:] == "_score": raise IllegalOperation("Sorting by `-_score` is not allowed.") k = {k[1:]: {"order": "desc"}} @@ -470,7 +468,7 @@ class AsyncMultiSearch(Request): """ def __init__(self, **kwargs: Any) -> None: - super(AsyncMultiSearch, self).__init__(**kwargs) + super().__init__(**kwargs) self._searches: Any = [] def __getitem__(self, key: Any) -> Any: @@ -480,7 +478,7 @@ def __iter__(self) -> Any: return iter(self._searches) def _clone(self) -> Any: - ms = super(AsyncMultiSearch, self)._clone() + ms = super()._clone() ms._searches = self._searches[:] return ms diff --git a/opensearchpy/connection/async_connections.py b/opensearchpy/connection/async_connections.py index 60ca210b..dfba0101 100644 --- a/opensearchpy/connection/async_connections.py +++ b/opensearchpy/connection/async_connections.py @@ -9,14 +9,12 @@ from typing import Any -from six import string_types - import opensearchpy from opensearchpy._async.helpers.actions import aiter from opensearchpy.serializer import serializer -class AsyncConnections(object): +class AsyncConnections: _conns: Any """ @@ -92,7 +90,7 @@ async def get_connection(self, alias: str = "default") -> Any: """ # do not check isinstance(AsyncOpenSearch) so that people can wrap their # clients - if not isinstance(alias, string_types): + if not isinstance(alias, str): return alias # connection already established diff --git a/opensearchpy/connection/connections.py b/opensearchpy/connection/connections.py index 3f1edc4a..e4869616 100644 --- a/opensearchpy/connection/connections.py +++ b/opensearchpy/connection/connections.py @@ -26,13 +26,11 @@ from typing import Any -from six import string_types - import opensearchpy from opensearchpy.serializer import serializer -class Connections(object): +class Connections: """ Class responsible for holding connections to different clusters. Used as a singleton in this module. @@ -106,7 +104,7 @@ def get_connection(self, alias: str = "default") -> Any: """ # do not check isinstance(OpenSearch) so that people can wrap their # clients - if not isinstance(alias, string_types): + if not isinstance(alias, str): return alias # connection already established diff --git a/opensearchpy/helpers/analysis.py b/opensearchpy/helpers/analysis.py index ff5d46b9..ea05b26a 100644 --- a/opensearchpy/helpers/analysis.py +++ b/opensearchpy/helpers/analysis.py @@ -26,14 +26,12 @@ from typing import Any, Optional -import six - from opensearchpy.connection.connections import get_connection from .utils import AttrDict, DslBase, merge -class AnalysisBase(object): +class AnalysisBase: @classmethod def _type_shortcut( cls: Any, name_or_instance: Any, type: Any = None, **kwargs: Any @@ -51,7 +49,7 @@ def _type_shortcut( ) -class CustomAnalysis(object): +class CustomAnalysis: name: Optional[str] = "custom" def __init__( @@ -59,14 +57,14 @@ def __init__( ) -> None: self._builtin_type = builtin_type self._name = filter_name - super(CustomAnalysis, self).__init__(**kwargs) + super().__init__(**kwargs) def to_dict(self) -> Any: # only name to present in lists return self._name 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["type"] = self._builtin_type return d @@ -106,12 +104,12 @@ def get_analysis_definition(self: Any) -> Any: return out -class BuiltinAnalysis(object): +class BuiltinAnalysis: name: Optional[str] = "builtin" def __init__(self, name: Any) -> None: self._name = name - super(BuiltinAnalysis, self).__init__() + super().__init__() def to_dict(self) -> Any: # only name to present in lists @@ -168,7 +166,7 @@ def simulate( sec_def = definition.get(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) else: body[section] = [ @@ -235,7 +233,7 @@ def get_definition(self) -> Any: # comma delimited string given by user ( fs - if isinstance(fs, six.string_types) + if isinstance(fs, str) else # list of strings or TokenFilter objects ", ".join(f.to_dict() if hasattr(f, "to_dict") else f for f in fs) @@ -251,7 +249,7 @@ def get_analysis_definition(self) -> Any: fs: Any = {} d = {"filter": fs} for filters in self.filters: - if isinstance(filters, six.string_types): + if isinstance(filters, str): continue fs.update( { diff --git a/opensearchpy/helpers/document.py b/opensearchpy/helpers/document.py index f3595bcf..7d3f34fa 100644 --- a/opensearchpy/helpers/document.py +++ b/opensearchpy/helpers/document.py @@ -28,8 +28,6 @@ from fnmatch import fnmatch from typing import Any, Tuple, Type -from six import add_metaclass, iteritems - from opensearchpy.connection.connections import get_connection from opensearchpy.exceptions import NotFoundError, RequestError @@ -41,7 +39,7 @@ from .utils import DOC_META_FIELDS, META_FIELDS, ObjectBase, merge -class MetaField(object): +class MetaField: def __init__(self, *args: Any, **kwargs: Any) -> None: self.args, self.kwargs = args, kwargs @@ -55,7 +53,7 @@ def __new__( ) -> Any: # DocumentMeta filters attrs in place 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): @@ -69,7 +67,7 @@ def __new__( bases: Tuple[Type[ObjectBase]], attrs: Any, ) -> Any: - new_cls = super(IndexMeta, cls).__new__(cls, name, bases, attrs) + new_cls = super().__new__(cls, name, bases, attrs) if cls._document_initialized: index_opts = attrs.pop("Index", None) index = cls.construct_index(index_opts, bases) @@ -96,7 +94,7 @@ def construct_index(cls, opts: Any, bases: Any) -> Any: return i -class DocumentOptions(object): +class DocumentOptions: def __init__( self, name: str, @@ -109,7 +107,7 @@ def __init__( self.mapping = getattr(meta, "mapping", 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): self.mapping.field(name, value) del attrs[name] @@ -130,8 +128,7 @@ def name(self) -> Any: return self.mapping.properties.name -@add_metaclass(DocumentMeta) -class InnerDoc(ObjectBase): +class InnerDoc(ObjectBase, metaclass=DocumentMeta): """ 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: if data_only: data = {"_source": data} - return super(InnerDoc, cls).from_opensearch(data) + return super().from_opensearch(data) -@add_metaclass(IndexMeta) -class Document(ObjectBase): +class Document(ObjectBase, metaclass=IndexMeta): """ Model-like class for persisting documents in opensearch. """ @@ -353,7 +349,7 @@ def to_dict(self, include_meta: bool = False, skip_empty: bool = True) -> Any: ``[]``, ``{}``) to be left on the document. Those values will be 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: return d diff --git a/opensearchpy/helpers/faceted_search.py b/opensearchpy/helpers/faceted_search.py index a97507a3..42c9b751 100644 --- a/opensearchpy/helpers/faceted_search.py +++ b/opensearchpy/helpers/faceted_search.py @@ -26,8 +26,6 @@ from datetime import datetime, timedelta from typing import Any, Optional -from six import iteritems, itervalues - from opensearchpy.helpers.aggs import A from .query import MatchAll, Nested, Range, Terms @@ -45,7 +43,7 @@ ] -class Facet(object): +class Facet: """ 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 @@ -146,7 +144,7 @@ def _range_to_dict(self, range: Any) -> Any: return out 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["keyed"] = False self._ranges = dict(ranges) @@ -217,7 +215,7 @@ class DateHistogramFacet(Facet): def __init__(self, **kwargs: Any) -> None: kwargs.setdefault("min_doc_count", 0) - super(DateHistogramFacet, self).__init__(**kwargs) + super().__init__(**kwargs) def get_value(self, bucket: Any) -> Any: if not isinstance(bucket["key"], datetime): @@ -256,9 +254,7 @@ class NestedFacet(Facet): def __init__(self, path: Any, nested_facet: Any) -> None: self._path = path self._inner = nested_facet - super(NestedFacet, self).__init__( - path=path, aggs={"inner": nested_facet.get_aggregation()} - ) + super().__init__(path=path, aggs={"inner": nested_facet.get_aggregation()}) def get_values(self, data: Any, filter_values: Any) -> Any: return self._inner.get_values(data.inner, filter_values) @@ -278,7 +274,7 @@ def query_string(self) -> Any: def facets(self) -> Any: if not hasattr(self, "_facets"): 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( getattr(getattr(self.aggregations, "_filter_" + name), name), self._faceted_search.filter_values.get(name, ()), @@ -286,7 +282,7 @@ def facets(self) -> Any: return self._facets -class FacetedSearch(object): +class FacetedSearch: """ Abstraction for creating faceted navigation searches that takes care of composing the queries, aggregations and filters as needed as well as @@ -344,7 +340,7 @@ def __init__(self, query: Any = None, filters: Any = {}, sort: Any = ()) -> None self._filters: Any = {} self._sort = sort self.filter_values: Any = {} - for name, value in iteritems(filters): + for name, value in filters.items(): self.add_filter(name, value) self._s = self.build_search() @@ -409,10 +405,10 @@ def aggregate(self, search: Any) -> Any: Add aggregations representing the facets selected, including potential filters. """ - for f, facet in iteritems(self.facets): + for f, facet in self.facets.items(): agg = facet.get_aggregation() agg_filter = MatchAll() - for field, filter in iteritems(self._filters): + for field, filter in self._filters.items(): if f == field: continue agg_filter &= filter @@ -429,7 +425,7 @@ def filter(self, search: Any) -> Any: return search post_filter = MatchAll() - for f in itervalues(self._filters): + for f in self._filters.values(): post_filter &= f return search.post_filter(post_filter) diff --git a/opensearchpy/helpers/field.py b/opensearchpy/helpers/field.py index f46e044d..c2431324 100644 --- a/opensearchpy/helpers/field.py +++ b/opensearchpy/helpers/field.py @@ -32,15 +32,13 @@ from typing import Any, Optional, Type from dateutil import parser, tz -from six import integer_types, iteritems, string_types -from six.moves import map from ..exceptions import ValidationException from .query import Q from .utils import AttrDict, AttrList, DslBase from .wrappers import Range -unicode: Type[str] = type("") +unicode: Type[str] = str def construct_field(name_or_field: Any, **params: Any) -> Any: @@ -91,7 +89,7 @@ def __init__( """ self._multi = multi self._required = required - super(Field, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def __getitem__(self, subfield: Any) -> Any: return self._params.get("fields", {})[subfield] @@ -131,7 +129,7 @@ def clean(self, data: Any) -> Any: return data def to_dict(self) -> Any: - d = super(Field, self).to_dict() + d = super().to_dict() name, value = d.popitem() value["type"] = name return value @@ -145,7 +143,7 @@ def to_dict(self) -> Any: if isinstance(self.builtin_type, Field): return self.builtin_type.to_dict() - d = super(CustomField, self).to_dict() + d = super().to_dict() d["type"] = self.builtin_type return d @@ -183,13 +181,13 @@ def __init__( # no InnerDoc subclass, creating one instead... 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 if dynamic is not None: self._doc_class._doc_type.mapping.meta("dynamic", dynamic) # type: ignore self._mapping = copy.deepcopy(self._doc_class._doc_type.mapping) - super(Object, self).__init__(**kwargs) + super().__init__(**kwargs) def __getitem__(self, name: Any) -> Any: return self._mapping[name] @@ -210,7 +208,7 @@ def empty(self) -> Any: def to_dict(self) -> Any: d = self._mapping.to_dict() - d.update(super(Object, self).to_dict()) + d.update(super().to_dict()) return d def _collect_fields(self) -> Any: @@ -237,7 +235,7 @@ def _serialize(self, data: Any) -> Any: return data.to_dict() def clean(self, data: Any) -> Any: - data = super(Object, self).clean(data) + data = super().clean(data) if data is None: return None if isinstance(data, (list, AttrList)): @@ -260,7 +258,7 @@ class Nested(Object): def __init__(self, *args: Any, **kwargs: Any) -> None: kwargs.setdefault("multi", True) - super(Nested, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class Date(Field): @@ -273,12 +271,12 @@ def __init__(self, default_timezone: Any = None, *args: Any, **kwargs: Any) -> N May be instance of `datetime.tzinfo` or string containing TZ offset """ 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) - super(Date, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _deserialize(self, data: Any) -> Any: - if isinstance(data, string_types): + if isinstance(data, str): try: data = parser.parse(data) except Exception as e: @@ -292,7 +290,7 @@ def _deserialize(self, data: Any) -> Any: return data if isinstance(data, date): return data - if isinstance(data, integer_types): + if isinstance(data, int): # Divide by a float to preserve milliseconds on the datetime. return datetime.utcfromtimestamp(data / 1000.0) @@ -361,7 +359,7 @@ class DenseVector(Float): def __init__(self, dims: Any, **kwargs: Any) -> None: kwargs["multi"] = True - super(DenseVector, self).__init__(dims=dims, **kwargs) + super().__init__(dims=dims, **kwargs) class SparseVector(Field): @@ -376,9 +374,7 @@ class ScaledFloat(Float): name: Optional[str] = "scaled_float" def __init__(self, scaling_factor: Any, *args: Any, **kwargs: Any) -> None: - super(ScaledFloat, self).__init__( - scaling_factor=scaling_factor, *args, **kwargs - ) + super().__init__(scaling_factor=scaling_factor, *args, **kwargs) class Double(Float): @@ -481,7 +477,7 @@ class RangeField(Field): def _deserialize(self, data: Any) -> Any: if isinstance(data, Range): 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) def _serialize(self, data: Any) -> Any: @@ -489,7 +485,7 @@ def _serialize(self, data: Any) -> Any: return None if not isinstance(data, collections_abc.Mapping): 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): diff --git a/opensearchpy/helpers/mapping.py b/opensearchpy/helpers/mapping.py index f75ef19e..3c2f8ab0 100644 --- a/opensearchpy/helpers/mapping.py +++ b/opensearchpy/helpers/mapping.py @@ -28,8 +28,6 @@ from itertools import chain from typing import Any -from six import iteritems, itervalues - from opensearchpy.connection.connections import get_connection from opensearchpy.helpers.field import Nested, Text, construct_field @@ -53,7 +51,7 @@ class Properties(DslBase): _param_defs = {"properties": {"type": "field", "hash": True}} def __init__(self) -> None: - super(Properties, self).__init__() + super().__init__() def __repr__(self) -> str: return "Properties()" @@ -65,7 +63,7 @@ def __contains__(self, name: Any) -> bool: return name in self.properties 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": self.properties[name] = construct_field(*args, **kwargs) @@ -73,16 +71,14 @@ def field(self, name: Any, *args: Any, **kwargs: Any) -> "Properties": def _collect_fields(self) -> Any: """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 # multi fields if hasattr(f, "fields"): - for inner_f in itervalues(f.fields.to_dict()): - yield inner_f + yield from f.fields.to_dict().values() # nested and inner objects if hasattr(f, "_collect_fields"): - for inner_f in f._collect_fields(): - yield inner_f + yield from f._collect_fields() def update(self, other_object: Any) -> None: if not hasattr(other_object, "properties"): @@ -98,7 +94,7 @@ def update(self, other_object: Any) -> None: our[name] = other[name] -class Mapping(object): +class Mapping: def __init__(self) -> None: self.properties = Properties() self._meta: Any = {} @@ -181,11 +177,11 @@ def update_from_opensearch(self, index: Any, using: str = "default") -> None: self._update_from_dict(raw["mappings"]) 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) # metadata like _all etc - for name, value in iteritems(raw): + for name, value in raw.items(): if name != "properties": if isinstance(value, collections_abc.Mapping): self.meta(name, **value) diff --git a/opensearchpy/helpers/search.py b/opensearchpy/helpers/search.py index aa157b10..95d00836 100644 --- a/opensearchpy/helpers/search.py +++ b/opensearchpy/helpers/search.py @@ -28,8 +28,6 @@ import copy from typing import Any -from six import iteritems, string_types - from opensearchpy.connection.connections import get_connection from opensearchpy.exceptions import TransportError from opensearchpy.helpers import scan @@ -41,7 +39,7 @@ from .utils import AttrDict, DslBase, recursive_to_dict -class QueryProxy(object): +class QueryProxy: """ Simple proxy around DSL objects (queries) that can be called (to add query/post_filter) and also allows attribute access which is proxied to @@ -79,7 +77,7 @@ def __setattr__(self, attr_name: Any, value: Any) -> None: if not attr_name.startswith("_"): self._proxied = Q(self._proxied.to_dict()) setattr(self._proxied, attr_name, value) - super(QueryProxy, self).__setattr__(attr_name, value) + super().__setattr__(attr_name, value) def __getstate__(self) -> Any: return self._search, self._proxied, self._attr_name @@ -88,7 +86,7 @@ def __setstate__(self, state: Any) -> None: self._search, self._proxied, self._attr_name = state -class ProxyDescriptor(object): +class ProxyDescriptor: """ Simple descriptor to enable setting of queries and filters as: @@ -117,10 +115,10 @@ def __init__(self, search: Any) -> None: self._params = {"aggs": {}} 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_map: Any @@ -195,7 +193,7 @@ def index(self, *index: Any) -> Any: else: indexes = [] for i in index: - if isinstance(i, string_types): + if isinstance(i, str): indexes.append(i) elif isinstance(i, list): indexes += i @@ -333,7 +331,7 @@ def __init__(self, **kwargs: Any) -> None: All the parameters supplied (or omitted) at creation type can be later overridden by methods (`using`, `index` and `doc_type` respectively). """ - super(Search, self).__init__(**kwargs) + super().__init__(**kwargs) self.aggs = AggsProxy(self) self._sort: Any = [] @@ -422,7 +420,7 @@ def _clone(self) -> Any: of all the underlying objects. Used internally by most state modifying APIs. """ - s = super(Search, self)._clone() + s = super()._clone() s._response_class = self._response_class s._sort = self._sort[:] @@ -462,7 +460,7 @@ def update_from_dict(self, d: Any) -> "Search": aggs = d.pop("aggs", d.pop("aggregations", {})) if aggs: 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: self._sort = d.pop("sort") @@ -504,7 +502,7 @@ def script_fields(self, **kwargs: Any) -> Any: """ s = self._clone() for name in kwargs: - if isinstance(kwargs[name], string_types): + if isinstance(kwargs[name], str): kwargs[name] = {"script": kwargs[name]} s._script_fields.update(kwargs) return s @@ -580,7 +578,7 @@ def sort(self, *keys: Any) -> Any: s = self._clone() s._sort = [] for k in keys: - if isinstance(k, string_types) and k.startswith("-"): + if isinstance(k, str) and k.startswith("-"): if k[1:] == "_score": raise IllegalOperation("Sorting by `-_score` is not allowed.") k = {k[1:]: {"order": "desc"}} @@ -801,7 +799,7 @@ class MultiSearch(Request): """ def __init__(self, **kwargs: Any) -> None: - super(MultiSearch, self).__init__(**kwargs) + super().__init__(**kwargs) self._searches: Any = [] def __getitem__(self, key: Any) -> Any: @@ -811,7 +809,7 @@ def __iter__(self) -> Any: return iter(self._searches) def _clone(self) -> Any: - ms = super(MultiSearch, self)._clone() + ms = super()._clone() ms._searches = self._searches[:] return ms diff --git a/opensearchpy/helpers/utils.py b/opensearchpy/helpers/utils.py index cad415b9..deec1ccc 100644 --- a/opensearchpy/helpers/utils.py +++ b/opensearchpy/helpers/utils.py @@ -24,15 +24,11 @@ # specific language governing permissions and limitations # under the License. -from __future__ import unicode_literals import collections.abc as collections_abc from copy import copy 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 SKIP_VALUES: Tuple[str, None] = ("", None) @@ -66,7 +62,7 @@ def _wrap(val: Any, obj_wrapper: Optional[Callable[..., Any]] = None) -> Any: return val -class AttrList(object): +class AttrList: def __init__( self, p: Any, obj_wrapper: Optional[Callable[..., Any]] = None ) -> None: @@ -118,7 +114,7 @@ def __setstate__(self, state: Any) -> None: self._l_, self._obj_wrapper = state -class AttrDict(object): +class AttrDict: """ Helper class to provide attribute like access (read and write) to 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: # 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: return key in self._d_ @@ -160,7 +156,7 @@ def __getstate__(self) -> Any: return (self._d_,) 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: try: @@ -204,7 +200,7 @@ def __setattr__(self, name: Any, value: Any) -> None: self._d_[name] = value else: # 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: return iter(self._d_) @@ -230,7 +226,7 @@ class DslMeta(type): def __init__(cls: Any, name: str, bases: Any, attrs: Any) -> None: # TODO: why is it calling itself?! - super(DslMeta, cls).__init__(name, bases, attrs) + super().__init__(name, bases, attrs) # skip for DslBase if not hasattr(cls, "_type_shortcut"): return @@ -252,8 +248,7 @@ def get_dsl_type(cls, name: Any) -> Any: raise UnknownDslObject("DSL type %s does not exist." % name) -@add_metaclass(DslMeta) -class DslBase(object): +class DslBase(metaclass=DslMeta): """ Base class for all DSL objects - queries, filters, aggregations etc. Wraps a dictionary representing the object's json. @@ -285,7 +280,7 @@ def get_dsl_class(cls: Any, name: Any, default: Optional[bool] = None) -> Any: def __init__(self, _expand__to_dot: Any = EXPAND__TO_DOT, **params: Any) -> None: self._params = {} - for pname, pvalue in iteritems(params): + for pname, pvalue in params.items(): if "__" in pname and _expand__to_dot: pname = pname.replace("__", ".") self._setattr(pname, pvalue) @@ -294,7 +289,7 @@ def _repr_params(self) -> str: """Produce a repr of all our parameters to be used in __repr__.""" return ", ".join( "{}={!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 if "type" not in self._param_defs.get(n, {}) or v ) @@ -310,7 +305,7 @@ def __ne__(self, other: Any) -> bool: def __setattr__(self, name: str, value: Any) -> None: if name.startswith("_"): - return super(DslBase, self).__setattr__(name, value) + return super().__setattr__(name, value) return self._setattr(name, value) def _setattr(self, name: Any, value: Any) -> None: @@ -327,7 +322,7 @@ def _setattr(self, name: Any, value: Any) -> None: if not isinstance(value, (tuple, list)): value = (value,) 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"): if not isinstance(value, (tuple, list)): @@ -336,7 +331,7 @@ def _setattr(self, name: Any, value: Any) -> None: # dict(name -> DslBase), make sure we pickup all the objs 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 else: @@ -380,7 +375,7 @@ def to_dict(self) -> Any: Serialize the DSL object to plain dict """ d = {} - for pname, value in iteritems(self._params): + for pname, value in self._params.items(): pinfo = self._param_defs.get(pname) # typed param @@ -392,7 +387,7 @@ def to_dict(self) -> Any: # list of dict(name -> DslBase) if pinfo.get("multi") and pinfo.get("hash"): 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 @@ -401,7 +396,7 @@ def to_dict(self) -> Any: # squash all the hash values into one dict 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 else: @@ -427,13 +422,13 @@ def __init__( ) -> None: d = { 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 "type" in d: # make sure we are consistent everywhere in python d["doc_type"] = d.pop("type") - super(HitMeta, self).__init__(d) + super().__init__(d) class ObjectBase(AttrDict): @@ -447,7 +442,7 @@ def __init__(self, meta: Any = None, **kwargs: Any) -> None: super(AttrDict, self).__setattr__("meta", HitMeta(meta)) - super(ObjectBase, self).__init__(kwargs) + super().__init__(kwargs) @classmethod def __list_fields(cls: Any) -> Any: @@ -491,7 +486,7 @@ def from_opensearch(cls: Any, hit: Any) -> Any: return doc def _from_dict(self, data: Any) -> None: - for k, v in iteritems(data): + for k, v in data.items(): f = self.__get_field(k) if f and f._coerce: v = f.deserialize(v) @@ -508,7 +503,7 @@ def __setstate__(self, state: Any) -> None: def __getattr__(self, name: Any) -> Any: try: - return super(ObjectBase, self).__getattr__(name) + return super().__getattr__(name) except AttributeError: f = self.__get_field(name) if hasattr(f, "empty"): @@ -521,7 +516,7 @@ def __getattr__(self, name: Any) -> Any: def to_dict(self, skip_empty: Optional[bool] = True) -> Any: out = {} - for k, v in iteritems(self._d_): + for k, v in self._d_.items(): # if this is a mapped field, f = self.__get_field(k) 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 ( key in data and isinstance(data[key], (AttrDict, collections_abc.Mapping)) diff --git a/opensearchpy/helpers/wrappers.py b/opensearchpy/helpers/wrappers.py index e8af30e9..aa3b2784 100644 --- a/opensearchpy/helpers/wrappers.py +++ b/opensearchpy/helpers/wrappers.py @@ -27,8 +27,6 @@ import operator from typing import Any -from six import iteritems, string_types - from .utils import AttrDict @@ -57,14 +55,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: if "lt" in data and "lte" in data: 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: - 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: - if isinstance(item, string_types): - return super(Range, self).__contains__(item) + if isinstance(item, str): + return super().__contains__(item) for op in self.OPS: if op in self._d_ and not self.OPS[op](item, self._d_[op]): diff --git a/setup.cfg b/setup.cfg index 5bfc6492..3bf5300d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[bdist_wheel] -universal = 1 - [bdist_rpm] requires = python python-urllib3 @@ -17,9 +14,7 @@ profile=black [black] max-line-length = 240 -target-version = 'py33' +target-version = 'py38' [mypy] ignore_missing_imports=True - - diff --git a/setup.py b/setup.py index aad7bdff..9af1488c 100644 --- a/setup.py +++ b/setup.py @@ -57,7 +57,6 @@ 'urllib3>=1.26.18,<1.27 ; python_version < "3.10"', 'urllib3>=1.26.18,!=2.2.0,<3 ; python_version >= "3.10"', "requests>=2.4.0, <3.0.0", - "six", "python-dateutil", "certifi>=2022.12.07", "Events",