From 8165e106a9d6e5e31f55097fdebfac534aca41b9 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Tue, 3 Sep 2024 18:57:12 +0100 Subject: [PATCH] more code generator cleanup --- elasticsearch_dsl/interfaces.py | 677 ++++++++++++++---------------- elasticsearch_dsl/query.py | 152 +++---- utils/generator.py | 305 +++++++++----- utils/templates/interfaces.py.tpl | 41 +- utils/templates/query.py.tpl | 33 +- 5 files changed, 622 insertions(+), 586 deletions(-) diff --git a/elasticsearch_dsl/interfaces.py b/elasticsearch_dsl/interfaces.py index dd7817de..3bf11bf8 100644 --- a/elasticsearch_dsl/interfaces.py +++ b/elasticsearch_dsl/interfaces.py @@ -60,7 +60,7 @@ class CommonTermsQuery(QueryBase): :arg high_freq_operator: No documentation available. :arg low_freq_operator: No documentation available. :arg minimum_should_match: No documentation available. - :arg query: (required)No documentation available. + :arg query: (required) No documentation available. """ analyzer: Union[str, "NotSet"] @@ -96,52 +96,6 @@ def __init__( super().__init__(**kwargs) -class DistanceFeatureQueryBase(QueryBase): - """ - :arg origin: (required)Date or point of origin used to calculate - distances. If the `field` value is a `date` or `date_nanos` field, - the `origin` value must be a date. Date Math, such as `now-1h`, is - supported. If the field value is a `geo_point` field, the `origin` - value must be a geopoint. - :arg pivot: (required)Distance from the `origin` at which relevance - scores receive half of the `boost` value. If the `field` value is - a `date` or `date_nanos` field, the `pivot` value must be a time - unit, such as `1h` or `10d`. If the `field` value is a `geo_point` - field, the `pivot` value must be a distance unit, such as `1km` or - `12m`. - :arg field: (required)Name of the field used to calculate distances. - This field must meet the following criteria: be a `date`, - `date_nanos` or `geo_point` field; have an `index` mapping - parameter value of `true`, which is the default; have an - `doc_values` mapping parameter value of `true`, which is the - default. - """ - - origin: Any - pivot: Any - field: Union[str, "InstrumentedField", "NotSet"] - - def __init__( - self, - *, - origin: Any = NOT_SET, - pivot: Any = NOT_SET, - field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, - **kwargs: Any, - ): - if not isinstance(origin, NotSet): - kwargs["origin"] = origin - if not isinstance(pivot, NotSet): - kwargs["pivot"] = pivot - if not isinstance(field, NotSet): - kwargs["field"] = str(field) - super().__init__(**kwargs) - - -class DateDistanceFeatureQuery(DistanceFeatureQueryBase): - pass - - class FunctionScoreContainer(AttrDict[Any]): """ :arg exp: Function that scores a document with a exponential decay, @@ -218,7 +172,7 @@ class FuzzyQuery(QueryBase): :arg transpositions: Indicates whether edits include transpositions of two adjacent characters (for example `ab` to `ba`). :arg fuzziness: Maximum edit distance allowed for matching. - :arg value: (required)Term you wish to find in the provided field. + :arg value: (required) Term you wish to find in the provided field. """ max_expansions: Union[int, "NotSet"] @@ -254,10 +208,6 @@ def __init__( super().__init__(**kwargs) -class GeoDistanceFeatureQuery(DistanceFeatureQueryBase): - pass - - class InnerHits(AttrDict[Any]): """ :arg name: The name for the particular inner hit definition in the @@ -515,7 +465,7 @@ class MatchBoolPrefixQuery(QueryBase): :arg prefix_length: Number of beginning characters left unchanged for fuzzy matching. Can be applied to the term subqueries constructed for all terms but the final term. - :arg query: (required)Terms you wish to find in the provided field. + :arg query: (required) Terms you wish to find in the provided field. The last term is used in a prefix query. """ @@ -570,7 +520,7 @@ class MatchPhrasePrefixQuery(QueryBase): tokens. :arg max_expansions: Maximum number of terms to which the last provided term of the query value will expand. - :arg query: (required)Text you wish to find in the provided field. + :arg query: (required) Text you wish to find in the provided field. :arg slop: Maximum number of positions allowed between matching tokens. :arg zero_terms_query: Indicates whether no documents are returned if @@ -611,7 +561,7 @@ class MatchPhraseQuery(QueryBase): """ :arg analyzer: Analyzer used to convert the text in the query value into tokens. - :arg query: (required)Query terms that are analyzed and turned into a + :arg query: (required) Query terms that are analyzed and turned into a phrase query. :arg slop: Maximum number of positions allowed between matching tokens. @@ -667,7 +617,7 @@ class MatchQuery(QueryBase): value. :arg prefix_length: Number of beginning characters left unchanged for fuzzy matching. - :arg query: (required)Text, number, boolean value or date you wish to + :arg query: (required) Text, number, boolean value or date you wish to find in the provided field. :arg zero_terms_query: Indicates whether no documents are returned if the `analyzer` removes all tokens, such as when using a `stop` @@ -739,8 +689,8 @@ def __init__( class PinnedDoc(AttrDict[Any]): """ - :arg _id: (required)The unique document ID. - :arg _index: (required)The index that contains the document. + :arg _id: (required) The unique document ID. + :arg _index: (required) The index that contains the document. """ _id: Union[str, "NotSet"] @@ -763,7 +713,7 @@ def __init__( class PrefixQuery(QueryBase): """ :arg rewrite: Method used to rewrite the query. - :arg value: (required)Beginning characters of terms you wish to find + :arg value: (required) Beginning characters of terms you wish to find in the provided field. :arg case_insensitive: Allows ASCII case insensitive matching of the value with the indexed field values when set to `true`. Default is @@ -820,7 +770,7 @@ class RankFeatureFunctionLinear(RankFeatureFunction): class RankFeatureFunctionLogarithm(RankFeatureFunction): """ - :arg scaling_factor: (required)Configurable scaling factor. + :arg scaling_factor: (required) Configurable scaling factor. """ scaling_factor: Union[float, "NotSet"] @@ -849,9 +799,9 @@ def __init__(self, *, pivot: Union[float, "NotSet"] = NOT_SET, **kwargs: Any): class RankFeatureFunctionSigmoid(RankFeatureFunction): """ - :arg pivot: (required)Configurable pivot value so that the result will - be less than 0.5. - :arg exponent: (required)Configurable Exponent. + :arg pivot: (required) Configurable pivot value so that the result + will be less than 0.5. + :arg exponent: (required) Configurable Exponent. """ pivot: Union[float, "NotSet"] @@ -881,8 +831,8 @@ class RegexpQuery(QueryBase): :arg max_determinized_states: Maximum number of automaton states required for the query. :arg rewrite: Method used to rewrite the query. - :arg value: (required)Regular expression for terms you wish to find in - the provided field. + :arg value: (required) Regular expression for terms you wish to find + in the provided field. """ case_insensitive: Union[bool, "NotSet"] @@ -1046,7 +996,7 @@ def __init__( class SpanTermQuery(QueryBase): """ - :arg value: (required)No documentation available. + :arg value: (required) No documentation available. """ value: Union[str, "NotSet"] @@ -1059,7 +1009,7 @@ def __init__(self, *, value: Union[str, "NotSet"] = NOT_SET, **kwargs: Any): class TermQuery(QueryBase): """ - :arg value: (required)Term you wish to find in the provided field. + :arg value: (required) Term you wish to find in the provided field. :arg case_insensitive: Allows ASCII case insensitive matching of the value with the indexed field values when set to `true`. When `false`, the case sensitivity of matching depends on the @@ -1089,7 +1039,7 @@ class TermsSetQuery(QueryBase): of matching terms required to return a document. :arg minimum_should_match_script: Custom script containing the number of matching terms required to return a document. - :arg terms: (required)Array of terms you wish to find in the provided + :arg terms: (required) Array of terms you wish to find in the provided field. """ @@ -1118,8 +1068,8 @@ def __init__( class TextExpansionQuery(QueryBase): """ - :arg model_id: (required)The text expansion NLP model to use - :arg model_text: (required)The query text + :arg model_id: (required) The text expansion NLP model to use + :arg model_text: (required) The query text :arg pruning_config: Token pruning configurations """ @@ -1178,13 +1128,9 @@ def __init__( super().__init__(kwargs) -class UntypedDistanceFeatureQuery(DistanceFeatureQueryBase): - pass - - class WeightedTokensQuery(QueryBase): """ - :arg tokens: (required)The tokens representing this query + :arg tokens: (required) The tokens representing this query :arg pruning_config: Token pruning configurations """ @@ -1245,33 +1191,10 @@ def __init__( super().__init__(**kwargs) -class ScriptField(AttrDict[Any]): - """ - :arg script: (required)No documentation available. - :arg ignore_failure: No documentation available. - """ - - script: Union["i.Script", Dict[str, Any], "NotSet"] - ignore_failure: Union[bool, "NotSet"] - - def __init__( - self, - *, - script: Union["i.Script", Dict[str, Any], "NotSet"] = NOT_SET, - ignore_failure: Union[bool, "NotSet"] = NOT_SET, - **kwargs: Any, - ): - if not isinstance(script, NotSet): - kwargs["script"] = script - if not isinstance(ignore_failure, NotSet): - kwargs["ignore_failure"] = ignore_failure - super().__init__(kwargs) - - class FieldAndFormat(AttrDict[Any]): """ - :arg field: (required)Wildcard pattern. The request returns values for - field names matching this pattern. + :arg field: (required) Wildcard pattern. The request returns values + for field names matching this pattern. :arg format: Format in which the values are returned. :arg include_unmapped: No documentation available. """ @@ -1297,36 +1220,39 @@ def __init__( super().__init__(kwargs) -class SortOptions(AttrDict[Any]): +class FieldCollapse(AttrDict[Any]): """ - :arg _score: No documentation available. - :arg _doc: No documentation available. - :arg _geo_distance: No documentation available. - :arg _script: No documentation available. + :arg field: (required) The field to collapse the result set on + :arg inner_hits: The number of inner hits and their sort order + :arg max_concurrent_group_searches: The number of concurrent requests + allowed to retrieve the inner_hits per group + :arg collapse: No documentation available. """ - _score: Union["i.ScoreSort", Dict[str, Any], "NotSet"] - _doc: Union["i.ScoreSort", Dict[str, Any], "NotSet"] - _geo_distance: Union["i.GeoDistanceSort", Dict[str, Any], "NotSet"] - _script: Union["i.ScriptSort", Dict[str, Any], "NotSet"] + field: Union[str, "InstrumentedField", "NotSet"] + inner_hits: Union["i.InnerHits", List["i.InnerHits"], Dict[str, Any], "NotSet"] + max_concurrent_group_searches: Union[int, "NotSet"] + collapse: Union["i.FieldCollapse", Dict[str, Any], "NotSet"] def __init__( self, *, - _score: Union["i.ScoreSort", Dict[str, Any], "NotSet"] = NOT_SET, - _doc: Union["i.ScoreSort", Dict[str, Any], "NotSet"] = NOT_SET, - _geo_distance: Union["i.GeoDistanceSort", Dict[str, Any], "NotSet"] = NOT_SET, - _script: Union["i.ScriptSort", Dict[str, Any], "NotSet"] = NOT_SET, + field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, + inner_hits: Union[ + "i.InnerHits", List["i.InnerHits"], Dict[str, Any], "NotSet" + ] = NOT_SET, + max_concurrent_group_searches: Union[int, "NotSet"] = NOT_SET, + collapse: Union["i.FieldCollapse", Dict[str, Any], "NotSet"] = NOT_SET, **kwargs: Any, ): - if not isinstance(_score, NotSet): - kwargs["_score"] = _score - if not isinstance(_doc, NotSet): - kwargs["_doc"] = _doc - if not isinstance(_geo_distance, NotSet): - kwargs["_geo_distance"] = _geo_distance - if not isinstance(_script, NotSet): - kwargs["_script"] = _script + if not isinstance(field, NotSet): + kwargs["field"] = str(field) + if not isinstance(inner_hits, NotSet): + kwargs["inner_hits"] = inner_hits + if not isinstance(max_concurrent_group_searches, NotSet): + kwargs["max_concurrent_group_searches"] = max_concurrent_group_searches + if not isinstance(collapse, NotSet): + kwargs["collapse"] = collapse super().__init__(kwargs) @@ -1491,7 +1417,7 @@ def __init__( class Highlight(HighlightBase): """ :arg encoder: No documentation available. - :arg fields: (required)No documentation available. + :arg fields: (required) No documentation available. """ encoder: Union[Literal["default", "html"], "NotSet"] @@ -1519,39 +1445,59 @@ def __init__( super().__init__(**kwargs) -class FieldCollapse(AttrDict[Any]): +class ScriptField(AttrDict[Any]): """ - :arg field: (required)The field to collapse the result set on - :arg inner_hits: The number of inner hits and their sort order - :arg max_concurrent_group_searches: The number of concurrent requests - allowed to retrieve the inner_hits per group - :arg collapse: No documentation available. + :arg script: (required) No documentation available. + :arg ignore_failure: No documentation available. """ - field: Union[str, "InstrumentedField", "NotSet"] - inner_hits: Union["i.InnerHits", List["i.InnerHits"], Dict[str, Any], "NotSet"] - max_concurrent_group_searches: Union[int, "NotSet"] - collapse: Union["i.FieldCollapse", Dict[str, Any], "NotSet"] + script: Union["i.Script", Dict[str, Any], "NotSet"] + ignore_failure: Union[bool, "NotSet"] def __init__( self, *, - field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, - inner_hits: Union[ - "i.InnerHits", List["i.InnerHits"], Dict[str, Any], "NotSet" - ] = NOT_SET, - max_concurrent_group_searches: Union[int, "NotSet"] = NOT_SET, - collapse: Union["i.FieldCollapse", Dict[str, Any], "NotSet"] = NOT_SET, + script: Union["i.Script", Dict[str, Any], "NotSet"] = NOT_SET, + ignore_failure: Union[bool, "NotSet"] = NOT_SET, **kwargs: Any, ): - if not isinstance(field, NotSet): - kwargs["field"] = str(field) - if not isinstance(inner_hits, NotSet): - kwargs["inner_hits"] = inner_hits - if not isinstance(max_concurrent_group_searches, NotSet): - kwargs["max_concurrent_group_searches"] = max_concurrent_group_searches - if not isinstance(collapse, NotSet): - kwargs["collapse"] = collapse + if not isinstance(script, NotSet): + kwargs["script"] = script + if not isinstance(ignore_failure, NotSet): + kwargs["ignore_failure"] = ignore_failure + super().__init__(kwargs) + + +class SortOptions(AttrDict[Any]): + """ + :arg _score: No documentation available. + :arg _doc: No documentation available. + :arg _geo_distance: No documentation available. + :arg _script: No documentation available. + """ + + _score: Union["i.ScoreSort", Dict[str, Any], "NotSet"] + _doc: Union["i.ScoreSort", Dict[str, Any], "NotSet"] + _geo_distance: Union["i.GeoDistanceSort", Dict[str, Any], "NotSet"] + _script: Union["i.ScriptSort", Dict[str, Any], "NotSet"] + + def __init__( + self, + *, + _score: Union["i.ScoreSort", Dict[str, Any], "NotSet"] = NOT_SET, + _doc: Union["i.ScoreSort", Dict[str, Any], "NotSet"] = NOT_SET, + _geo_distance: Union["i.GeoDistanceSort", Dict[str, Any], "NotSet"] = NOT_SET, + _script: Union["i.ScriptSort", Dict[str, Any], "NotSet"] = NOT_SET, + **kwargs: Any, + ): + if not isinstance(_score, NotSet): + kwargs["_score"] = _score + if not isinstance(_doc, NotSet): + kwargs["_doc"] = _doc + if not isinstance(_geo_distance, NotSet): + kwargs["_geo_distance"] = _geo_distance + if not isinstance(_script, NotSet): + kwargs["_script"] = _script super().__init__(kwargs) @@ -1590,45 +1536,22 @@ def __init__( super().__init__(kwargs) -class IntervalsPrefix(AttrDict[Any]): - """ - :arg analyzer: Analyzer used to analyze the `prefix`. - :arg prefix: (required)Beginning characters of terms you wish to find - in the top-level field. - :arg use_field: If specified, match intervals from this field rather - than the top-level field. The `prefix` is normalized using the - search analyzer from this field, unless `analyzer` is specified - separately. - """ - - analyzer: Union[str, "NotSet"] - prefix: Union[str, "NotSet"] - use_field: Union[str, "InstrumentedField", "NotSet"] - - def __init__( - self, - *, - analyzer: Union[str, "NotSet"] = NOT_SET, - prefix: Union[str, "NotSet"] = NOT_SET, - use_field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, - **kwargs: Any, - ): - if not isinstance(analyzer, NotSet): - kwargs["analyzer"] = analyzer - if not isinstance(prefix, NotSet): - kwargs["prefix"] = prefix - if not isinstance(use_field, NotSet): - kwargs["use_field"] = str(use_field) - super().__init__(kwargs) - - -class IntervalsAnyOf(AttrDict[Any]): +class IntervalsAllOf(AttrDict[Any]): """ - :arg intervals: (required)An array of rules to match. + :arg intervals: (required) An array of rules to combine. All rules + must produce a match in a document for the overall source to + match. + :arg max_gaps: Maximum number of positions between the matching terms. + Intervals produced by the rules further apart than this are not + considered matches. + :arg ordered: If `true`, intervals produced by the rules should appear + in the order in which they are specified. :arg filter: Rule used to filter returned intervals. """ intervals: Union[List["i.IntervalsContainer"], Dict[str, Any], "NotSet"] + max_gaps: Union[int, "NotSet"] + ordered: Union[bool, "NotSet"] filter: Union["i.IntervalsFilter", Dict[str, Any], "NotSet"] def __init__( @@ -1637,31 +1560,29 @@ def __init__( intervals: Union[ List["i.IntervalsContainer"], Dict[str, Any], "NotSet" ] = NOT_SET, + max_gaps: Union[int, "NotSet"] = NOT_SET, + ordered: Union[bool, "NotSet"] = NOT_SET, filter: Union["i.IntervalsFilter", Dict[str, Any], "NotSet"] = NOT_SET, **kwargs: Any, ): if not isinstance(intervals, NotSet): kwargs["intervals"] = intervals + if not isinstance(max_gaps, NotSet): + kwargs["max_gaps"] = max_gaps + if not isinstance(ordered, NotSet): + kwargs["ordered"] = ordered if not isinstance(filter, NotSet): kwargs["filter"] = filter super().__init__(kwargs) -class IntervalsAllOf(AttrDict[Any]): +class IntervalsAnyOf(AttrDict[Any]): """ - :arg intervals: (required)An array of rules to combine. All rules must - produce a match in a document for the overall source to match. - :arg max_gaps: Maximum number of positions between the matching terms. - Intervals produced by the rules further apart than this are not - considered matches. - :arg ordered: If `true`, intervals produced by the rules should appear - in the order in which they are specified. + :arg intervals: (required) An array of rules to match. :arg filter: Rule used to filter returned intervals. """ intervals: Union[List["i.IntervalsContainer"], Dict[str, Any], "NotSet"] - max_gaps: Union[int, "NotSet"] - ordered: Union[bool, "NotSet"] filter: Union["i.IntervalsFilter", Dict[str, Any], "NotSet"] def __init__( @@ -1670,17 +1591,11 @@ def __init__( intervals: Union[ List["i.IntervalsContainer"], Dict[str, Any], "NotSet" ] = NOT_SET, - max_gaps: Union[int, "NotSet"] = NOT_SET, - ordered: Union[bool, "NotSet"] = NOT_SET, filter: Union["i.IntervalsFilter", Dict[str, Any], "NotSet"] = NOT_SET, **kwargs: Any, ): if not isinstance(intervals, NotSet): kwargs["intervals"] = intervals - if not isinstance(max_gaps, NotSet): - kwargs["max_gaps"] = max_gaps - if not isinstance(ordered, NotSet): - kwargs["ordered"] = ordered if not isinstance(filter, NotSet): kwargs["filter"] = filter super().__init__(kwargs) @@ -1692,7 +1607,7 @@ class IntervalsFuzzy(AttrDict[Any]): :arg fuzziness: Maximum edit distance allowed for matching. :arg prefix_length: Number of beginning characters left unchanged when creating expansions. - :arg term: (required)The term to match. + :arg term: (required) The term to match. :arg transpositions: Indicates whether edits include transpositions of two adjacent characters (for example, `ab` to `ba`). :arg use_field: If specified, match intervals from this field rather @@ -1734,38 +1649,6 @@ def __init__( super().__init__(kwargs) -class IntervalsWildcard(AttrDict[Any]): - """ - :arg analyzer: Analyzer used to analyze the `pattern`. Defaults to the - top-level field's analyzer. - :arg pattern: (required)Wildcard pattern used to find matching terms. - :arg use_field: If specified, match intervals from this field rather - than the top-level field. The `pattern` is normalized using the - search analyzer from this field, unless `analyzer` is specified - separately. - """ - - analyzer: Union[str, "NotSet"] - pattern: Union[str, "NotSet"] - use_field: Union[str, "InstrumentedField", "NotSet"] - - def __init__( - self, - *, - analyzer: Union[str, "NotSet"] = NOT_SET, - pattern: Union[str, "NotSet"] = NOT_SET, - use_field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, - **kwargs: Any, - ): - if not isinstance(analyzer, NotSet): - kwargs["analyzer"] = analyzer - if not isinstance(pattern, NotSet): - kwargs["pattern"] = pattern - if not isinstance(use_field, NotSet): - kwargs["use_field"] = str(use_field) - super().__init__(kwargs) - - class IntervalsMatch(AttrDict[Any]): """ :arg analyzer: Analyzer used to analyze terms in the query. @@ -1773,7 +1656,7 @@ class IntervalsMatch(AttrDict[Any]): Terms further apart than this are not considered matches. :arg ordered: If `true`, matching terms must appear in their specified order. - :arg query: (required)Text you wish to find in the provided field. + :arg query: (required) Text you wish to find in the provided field. :arg use_field: If specified, match intervals from this field rather than the top-level field. The `term` is normalized using the search analyzer from this field, unless `analyzer` is specified @@ -1814,58 +1697,98 @@ def __init__( super().__init__(kwargs) -class TextEmbedding(AttrDict[Any]): - """ - :arg model_id: (required)No documentation available. - :arg model_text: (required)No documentation available. +class IntervalsPrefix(AttrDict[Any]): + """ + :arg analyzer: Analyzer used to analyze the `prefix`. + :arg prefix: (required) Beginning characters of terms you wish to find + in the top-level field. + :arg use_field: If specified, match intervals from this field rather + than the top-level field. The `prefix` is normalized using the + search analyzer from this field, unless `analyzer` is specified + separately. """ - model_id: Union[str, "NotSet"] - model_text: Union[str, "NotSet"] + analyzer: Union[str, "NotSet"] + prefix: Union[str, "NotSet"] + use_field: Union[str, "InstrumentedField", "NotSet"] def __init__( self, *, - model_id: Union[str, "NotSet"] = NOT_SET, - model_text: Union[str, "NotSet"] = NOT_SET, + analyzer: Union[str, "NotSet"] = NOT_SET, + prefix: Union[str, "NotSet"] = NOT_SET, + use_field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, **kwargs: Any, ): - if not isinstance(model_id, NotSet): - kwargs["model_id"] = model_id - if not isinstance(model_text, NotSet): - kwargs["model_text"] = model_text + if not isinstance(analyzer, NotSet): + kwargs["analyzer"] = analyzer + if not isinstance(prefix, NotSet): + kwargs["prefix"] = prefix + if not isinstance(use_field, NotSet): + kwargs["use_field"] = str(use_field) super().__init__(kwargs) -class SpanFirstQuery(QueryBase): +class IntervalsWildcard(AttrDict[Any]): """ - :arg end: (required)Controls the maximum end position permitted in a - match. - :arg match: (required)Can be any other span type query. + :arg analyzer: Analyzer used to analyze the `pattern`. Defaults to the + top-level field's analyzer. + :arg pattern: (required) Wildcard pattern used to find matching terms. + :arg use_field: If specified, match intervals from this field rather + than the top-level field. The `pattern` is normalized using the + search analyzer from this field, unless `analyzer` is specified + separately. """ - end: Union[int, "NotSet"] - match: Union["i.SpanQuery", Dict[str, Any], "NotSet"] + analyzer: Union[str, "NotSet"] + pattern: Union[str, "NotSet"] + use_field: Union[str, "InstrumentedField", "NotSet"] def __init__( self, *, - end: Union[int, "NotSet"] = NOT_SET, - match: Union["i.SpanQuery", Dict[str, Any], "NotSet"] = NOT_SET, + analyzer: Union[str, "NotSet"] = NOT_SET, + pattern: Union[str, "NotSet"] = NOT_SET, + use_field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, **kwargs: Any, ): - if not isinstance(end, NotSet): - kwargs["end"] = end - if not isinstance(match, NotSet): - kwargs["match"] = match - super().__init__(**kwargs) + if not isinstance(analyzer, NotSet): + kwargs["analyzer"] = analyzer + if not isinstance(pattern, NotSet): + kwargs["pattern"] = pattern + if not isinstance(use_field, NotSet): + kwargs["use_field"] = str(use_field) + super().__init__(kwargs) + + +class TextEmbedding(AttrDict[Any]): + """ + :arg model_id: (required) No documentation available. + :arg model_text: (required) No documentation available. + """ + + model_id: Union[str, "NotSet"] + model_text: Union[str, "NotSet"] + + def __init__( + self, + *, + model_id: Union[str, "NotSet"] = NOT_SET, + model_text: Union[str, "NotSet"] = NOT_SET, + **kwargs: Any, + ): + if not isinstance(model_id, NotSet): + kwargs["model_id"] = model_id + if not isinstance(model_text, NotSet): + kwargs["model_text"] = model_text + super().__init__(kwargs) class SpanContainingQuery(QueryBase): """ - :arg big: (required)Can be any span query. Matching spans from `big` + :arg big: (required) Can be any span query. Matching spans from `big` that contain matches from `little` are returned. - :arg little: (required)Can be any span query. Matching spans from + :arg little: (required) Can be any span query. Matching spans from `big` that contain matches from `little` are returned. """ @@ -1888,8 +1811,8 @@ def __init__( class SpanFieldMaskingQuery(QueryBase): """ - :arg field: (required)No documentation available. - :arg query: (required)No documentation available. + :arg field: (required) No documentation available. + :arg query: (required) No documentation available. """ field: Union[str, "InstrumentedField", "NotSet"] @@ -1909,10 +1832,34 @@ def __init__( super().__init__(**kwargs) +class SpanFirstQuery(QueryBase): + """ + :arg end: (required) Controls the maximum end position permitted in a + match. + :arg match: (required) Can be any other span type query. + """ + + end: Union[int, "NotSet"] + match: Union["i.SpanQuery", Dict[str, Any], "NotSet"] + + def __init__( + self, + *, + end: Union[int, "NotSet"] = NOT_SET, + match: Union["i.SpanQuery", Dict[str, Any], "NotSet"] = NOT_SET, + **kwargs: Any, + ): + if not isinstance(end, NotSet): + kwargs["end"] = end + if not isinstance(match, NotSet): + kwargs["match"] = match + super().__init__(**kwargs) + + class SpanMultiTermQuery(QueryBase): """ - :arg match: (required)Should be a multi term query (one of `wildcard`, - `fuzzy`, `prefix`, `range`, or `regexp` query). + :arg match: (required) Should be a multi term query (one of + `wildcard`, `fuzzy`, `prefix`, `range`, or `regexp` query). """ match: Union[Query, "NotSet"] @@ -1925,7 +1872,7 @@ def __init__(self, *, match: Union[Query, "NotSet"] = NOT_SET, **kwargs: Any): class SpanNearQuery(QueryBase): """ - :arg clauses: (required)Array of one or more other span type queries. + :arg clauses: (required) Array of one or more other span type queries. :arg in_order: Controls whether matches are required to be in-order. :arg slop: Controls the maximum number of intervening unmatched positions permitted. @@ -1952,57 +1899,14 @@ def __init__( super().__init__(**kwargs) -class SpanWithinQuery(QueryBase): - """ - :arg big: (required)Can be any span query. Matching spans from - `little` that are enclosed within `big` are returned. - :arg little: (required)Can be any span query. Matching spans from - `little` that are enclosed within `big` are returned. - """ - - big: Union["i.SpanQuery", Dict[str, Any], "NotSet"] - little: Union["i.SpanQuery", Dict[str, Any], "NotSet"] - - def __init__( - self, - *, - big: Union["i.SpanQuery", Dict[str, Any], "NotSet"] = NOT_SET, - little: Union["i.SpanQuery", Dict[str, Any], "NotSet"] = NOT_SET, - **kwargs: Any, - ): - if not isinstance(big, NotSet): - kwargs["big"] = big - if not isinstance(little, NotSet): - kwargs["little"] = little - super().__init__(**kwargs) - - -class SpanOrQuery(QueryBase): - """ - :arg clauses: (required)Array of one or more other span type queries. - """ - - clauses: Union[List["i.SpanQuery"], Dict[str, Any], "NotSet"] - - def __init__( - self, - *, - clauses: Union[List["i.SpanQuery"], Dict[str, Any], "NotSet"] = NOT_SET, - **kwargs: Any, - ): - if not isinstance(clauses, NotSet): - kwargs["clauses"] = clauses - super().__init__(**kwargs) - - class SpanNotQuery(QueryBase): """ :arg dist: The number of tokens from within the include span that can’t have overlap with the exclude span. Equivalent to setting both `pre` and `post`. - :arg exclude: (required)Span query whose matches must not overlap + :arg exclude: (required) Span query whose matches must not overlap those returned. - :arg include: (required)Span query whose matches are filtered. + :arg include: (required) Span query whose matches are filtered. :arg post: The number of tokens after the include span that can’t have overlap with the exclude span. :arg pre: The number of tokens before the include span that can’t have @@ -2038,57 +1942,81 @@ def __init__( super().__init__(**kwargs) -class ScriptSort(AttrDict[Any]): +class SpanOrQuery(QueryBase): """ - :arg order: No documentation available. - :arg script: (required)No documentation available. - :arg type: No documentation available. - :arg mode: No documentation available. - :arg nested: No documentation available. + :arg clauses: (required) Array of one or more other span type queries. """ - order: Union[Literal["asc", "desc"], "NotSet"] - script: Union["i.Script", Dict[str, Any], "NotSet"] - type: Union[Literal["string", "number", "version"], "NotSet"] - mode: Union[Literal["min", "max", "sum", "avg", "median"], "NotSet"] - nested: Union["i.NestedSortValue", Dict[str, Any], "NotSet"] + clauses: Union[List["i.SpanQuery"], Dict[str, Any], "NotSet"] def __init__( self, *, - order: Union[Literal["asc", "desc"], "NotSet"] = NOT_SET, - script: Union["i.Script", Dict[str, Any], "NotSet"] = NOT_SET, - type: Union[Literal["string", "number", "version"], "NotSet"] = NOT_SET, - mode: Union[Literal["min", "max", "sum", "avg", "median"], "NotSet"] = NOT_SET, - nested: Union["i.NestedSortValue", Dict[str, Any], "NotSet"] = NOT_SET, + clauses: Union[List["i.SpanQuery"], Dict[str, Any], "NotSet"] = NOT_SET, **kwargs: Any, ): - if not isinstance(order, NotSet): - kwargs["order"] = order - if not isinstance(script, NotSet): - kwargs["script"] = script - if not isinstance(type, NotSet): - kwargs["type"] = type - if not isinstance(mode, NotSet): - kwargs["mode"] = mode - if not isinstance(nested, NotSet): - kwargs["nested"] = nested - super().__init__(kwargs) + if not isinstance(clauses, NotSet): + kwargs["clauses"] = clauses + super().__init__(**kwargs) -class ScoreSort(AttrDict[Any]): +class SpanWithinQuery(QueryBase): """ - :arg order: No documentation available. + :arg big: (required) Can be any span query. Matching spans from + `little` that are enclosed within `big` are returned. + :arg little: (required) Can be any span query. Matching spans from + `little` that are enclosed within `big` are returned. """ - order: Union[Literal["asc", "desc"], "NotSet"] + big: Union["i.SpanQuery", Dict[str, Any], "NotSet"] + little: Union["i.SpanQuery", Dict[str, Any], "NotSet"] def __init__( - self, *, order: Union[Literal["asc", "desc"], "NotSet"] = NOT_SET, **kwargs: Any + self, + *, + big: Union["i.SpanQuery", Dict[str, Any], "NotSet"] = NOT_SET, + little: Union["i.SpanQuery", Dict[str, Any], "NotSet"] = NOT_SET, + **kwargs: Any, ): - if not isinstance(order, NotSet): - kwargs["order"] = order - super().__init__(kwargs) + if not isinstance(big, NotSet): + kwargs["big"] = big + if not isinstance(little, NotSet): + kwargs["little"] = little + super().__init__(**kwargs) + + +class HighlightField(HighlightBase): + """ + :arg fragment_offset: No documentation available. + :arg matched_fields: No documentation available. + :arg analyzer: No documentation available. + """ + + fragment_offset: Union[int, "NotSet"] + matched_fields: Union[ + Union[str, "InstrumentedField"], List[Union[str, "InstrumentedField"]], "NotSet" + ] + analyzer: Union[str, Dict[str, Any], "NotSet"] + + def __init__( + self, + *, + fragment_offset: Union[int, "NotSet"] = NOT_SET, + matched_fields: Union[ + Union[str, "InstrumentedField"], + List[Union[str, "InstrumentedField"]], + "NotSet", + ] = NOT_SET, + analyzer: Union[str, Dict[str, Any], "NotSet"] = NOT_SET, + **kwargs: Any, + ): + if not isinstance(fragment_offset, NotSet): + kwargs["fragment_offset"] = fragment_offset + if not isinstance(matched_fields, NotSet): + kwargs["matched_fields"] = str(matched_fields) + if not isinstance(analyzer, NotSet): + kwargs["analyzer"] = analyzer + super().__init__(**kwargs) class GeoDistanceSort(AttrDict[Any]): @@ -2136,38 +2064,57 @@ def __init__( super().__init__(kwargs) -class HighlightField(HighlightBase): +class ScoreSort(AttrDict[Any]): """ - :arg fragment_offset: No documentation available. - :arg matched_fields: No documentation available. - :arg analyzer: No documentation available. + :arg order: No documentation available. """ - fragment_offset: Union[int, "NotSet"] - matched_fields: Union[ - Union[str, "InstrumentedField"], List[Union[str, "InstrumentedField"]], "NotSet" - ] - analyzer: Union[str, "NotSet"] + order: Union[Literal["asc", "desc"], "NotSet"] + + def __init__( + self, *, order: Union[Literal["asc", "desc"], "NotSet"] = NOT_SET, **kwargs: Any + ): + if not isinstance(order, NotSet): + kwargs["order"] = order + super().__init__(kwargs) + + +class ScriptSort(AttrDict[Any]): + """ + :arg order: No documentation available. + :arg script: (required) No documentation available. + :arg type: No documentation available. + :arg mode: No documentation available. + :arg nested: No documentation available. + """ + + order: Union[Literal["asc", "desc"], "NotSet"] + script: Union["i.Script", Dict[str, Any], "NotSet"] + type: Union[Literal["string", "number", "version"], "NotSet"] + mode: Union[Literal["min", "max", "sum", "avg", "median"], "NotSet"] + nested: Union["i.NestedSortValue", Dict[str, Any], "NotSet"] def __init__( self, *, - fragment_offset: Union[int, "NotSet"] = NOT_SET, - matched_fields: Union[ - Union[str, "InstrumentedField"], - List[Union[str, "InstrumentedField"]], - "NotSet", - ] = NOT_SET, - analyzer: Union[str, "NotSet"] = NOT_SET, + order: Union[Literal["asc", "desc"], "NotSet"] = NOT_SET, + script: Union["i.Script", Dict[str, Any], "NotSet"] = NOT_SET, + type: Union[Literal["string", "number", "version"], "NotSet"] = NOT_SET, + mode: Union[Literal["min", "max", "sum", "avg", "median"], "NotSet"] = NOT_SET, + nested: Union["i.NestedSortValue", Dict[str, Any], "NotSet"] = NOT_SET, **kwargs: Any, ): - if not isinstance(fragment_offset, NotSet): - kwargs["fragment_offset"] = fragment_offset - if not isinstance(matched_fields, NotSet): - kwargs["matched_fields"] = str(matched_fields) - if not isinstance(analyzer, NotSet): - kwargs["analyzer"] = analyzer - super().__init__(**kwargs) + if not isinstance(order, NotSet): + kwargs["order"] = order + if not isinstance(script, NotSet): + kwargs["script"] = script + if not isinstance(type, NotSet): + kwargs["type"] = type + if not isinstance(mode, NotSet): + kwargs["mode"] = mode + if not isinstance(nested, NotSet): + kwargs["nested"] = nested + super().__init__(kwargs) class IntervalsContainer(AttrDict[Any]): @@ -2292,7 +2239,7 @@ class NestedSortValue(AttrDict[Any]): :arg filter: No documentation available. :arg max_children: No documentation available. :arg nested: No documentation available. - :arg path: (required)No documentation available. + :arg path: (required) No documentation available. """ filter: Union[Query, "NotSet"] diff --git a/elasticsearch_dsl/query.py b/elasticsearch_dsl/query.py index 3ec14537..1aa7c058 100644 --- a/elasticsearch_dsl/query.py +++ b/elasticsearch_dsl/query.py @@ -302,12 +302,13 @@ class Boosting(Query): Returns documents matching a `positive` query while reducing the relevance score of documents that also match a `negative` query. - :arg negative: (required)Query used to decrease the relevance score of - matching documents. - :arg positive: (required)Any returned documents must match this query. - :arg negative_boost: (required)Floating point number between 0 and 1.0 - used to decrease the relevance scores of documents matching the - `negative` query. + :arg negative: (required) Query used to decrease the relevance score + of matching documents. + :arg positive: (required) Any returned documents must match this + query. + :arg negative_boost: (required) Floating point number between 0 and + 1.0 used to decrease the relevance scores of documents matching + the `negative` query. """ name = "boosting" @@ -358,10 +359,10 @@ class CombinedFields(Query): The `combined_fields` query supports searching multiple text fields as if their contents had been indexed into one combined field. - :arg query: (required)Text to search for in the provided `fields`. The - `combined_fields` query analyzes the provided text before + :arg query: (required) Text to search for in the provided `fields`. + The `combined_fields` query analyzes the provided text before performing a search. - :arg fields: (required)List of fields to search. Field wildcard + :arg fields: (required) List of fields to search. Field wildcard patterns are allowed. Only `text` fields are supported, and they must all have the same search `analyzer`. :arg auto_generate_synonyms_phrase_query: If true, match phrase @@ -404,7 +405,7 @@ class ConstantScore(Query): Wraps a filter query and returns every matching document with a relevance score equal to the `boost` parameter value. - :arg filter: (required)Filter query you wish to run. Any returned + :arg filter: (required) Filter query you wish to run. Any returned documents must match this query. Filter queries do not calculate relevance scores. To speed up performance, Elasticsearch automatically caches frequently used filter queries. @@ -427,7 +428,7 @@ class DisMax(Query): relevance score from any matching clause, plus a tie breaking increment for any additional matching subqueries. - :arg queries: (required)One or more query clauses. Returned documents + :arg queries: (required) One or more query clauses. Returned documents must match one or more of these queries. If a document matches multiple queries, Elasticsearch uses the highest relevance score. :arg tie_breaker: Floating point number between 0 and 1.0 used to @@ -456,9 +457,23 @@ class DistanceFeature(Query): date or point. For example, you can use this query to give more weight to documents closer to a certain date or location. - :arg untyped: An instance of ``UntypedDistanceFeatureQuery``. - :arg geo: An instance of ``GeoDistanceFeatureQuery``. - :arg date: An instance of ``DateDistanceFeatureQuery``. + :arg pivot: (required) Distance from the `origin` at which relevance + scores receive half of the `boost` value. If the `field` value is + a `date` or `date_nanos` field, the `pivot` value must be a time + unit, such as `1h` or `10d`. If the `field` value is a `geo_point` + field, the `pivot` value must be a distance unit, such as `1km` or + `12m`. + :arg field: (required) Name of the field used to calculate distances. + This field must meet the following criteria: be a `date`, + `date_nanos` or `geo_point` field; have an `index` mapping + parameter value of `true`, which is the default; have an + `doc_values` mapping parameter value of `true`, which is the + default. + :arg origin: (required) Date or point of origin used to calculate + distances. If the `field` value is a `date` or `date_nanos` field, + the `origin` value must be a date. Date Math, such as `now-1h`, is + supported. If the field value is a `geo_point` field, the `origin` + value must be a geopoint. """ name = "distance_feature" @@ -466,32 +481,19 @@ class DistanceFeature(Query): def __init__( self, *, - untyped: Union["i.UntypedDistanceFeatureQuery", "NotSet"] = NOT_SET, - geo: Union["i.GeoDistanceFeatureQuery", "NotSet"] = NOT_SET, - date: Union["i.DateDistanceFeatureQuery", "NotSet"] = NOT_SET, + pivot: Any = NOT_SET, + field: Union[str, "InstrumentedField", "NotSet"] = NOT_SET, + origin: Any = NOT_SET, **kwargs: Any, ): - if not isinstance(untyped, NotSet): - kwargs = cast( - Dict[str, Any], - untyped.to_dict() if hasattr(untyped, "to_dict") else untyped, - ) - elif not isinstance(geo, NotSet): - kwargs = cast( - Dict[str, Any], geo.to_dict() if hasattr(geo, "to_dict") else geo - ) - elif not isinstance(date, NotSet): - kwargs = cast( - Dict[str, Any], date.to_dict() if hasattr(date, "to_dict") else date - ) - super().__init__(**kwargs) + super().__init__(pivot=pivot, field=field, origin=origin, **kwargs) class Exists(Query): """ Returns documents that contain an indexed value for a field. - :arg field: (required)Name of the field you wish to search. + :arg field: (required) Name of the field you wish to search. """ name = "exists" @@ -623,7 +625,7 @@ class GeoDistance(Query): Matches `geo_point` and `geo_shape` values within a given distance of a geopoint. - :arg distance: (required)The radius of the circle centred on the + :arg distance: (required) The radius of the circle centred on the specified location. Points which fall into this circle are considered to be matches. :arg distance_type: How to compute the distance. Set to `plane` for a @@ -708,10 +710,10 @@ class HasChild(Query): Returns parent documents whose joined child documents match a provided query. - :arg query: (required)Query you wish to run on child documents of the + :arg query: (required) Query you wish to run on child documents of the `type` field. If a child document matches the search, the query returns the parent document. - :arg type: (required)Name of the child relationship mapped for the + :arg type: (required) Name of the child relationship mapped for the `join` field. :arg ignore_unmapped: Indicates whether to ignore an unmapped `type` and not return any documents instead of an error. @@ -764,11 +766,11 @@ class HasParent(Query): Returns child documents whose joined parent document matches a provided query. - :arg parent_type: (required)Name of the parent relationship mapped for - the `join` field. - :arg query: (required)Query you wish to run on parent documents of the - `parent_type` field. If a parent document matches the search, the - query returns its child documents. + :arg parent_type: (required) Name of the parent relationship mapped + for the `join` field. + :arg query: (required) Query you wish to run on parent documents of + the `parent_type` field. If a parent document matches the search, + the query returns its child documents. :arg ignore_unmapped: Indicates whether to ignore an unmapped `parent_type` and not return any documents instead of an error. You can use this parameter to query multiple indices that may not @@ -846,7 +848,7 @@ class Knn(Query): similarity metric. knn query finds nearest vectors through approximate search on indexed dense_vectors. - :arg field: (required)The name of the vector field to search against + :arg field: (required) The name of the vector field to search against :arg query_vector: The query vector :arg query_vector_builder: The query vector builder. You must provide a query_vector_builder or query_vector, but not both. @@ -1033,7 +1035,7 @@ class MoreLikeThis(Query): """ Returns documents that are "like" a given set of documents. - :arg like: (required)Specifies free form text and/or a single or + :arg like: (required) Specifies free form text and/or a single or multiple documents for which you want to find similar documents. :arg analyzer: The analyzer that is used to analyze the free form text. Defaults to the analyzer associated with the first field in @@ -1139,7 +1141,7 @@ class MultiMatch(Query): value across multiple fields. The provided text is analyzed before matching. - :arg query: (required)Text, number, boolean value or date you wish to + :arg query: (required) Text, number, boolean value or date you wish to find in the provided field. :arg analyzer: Analyzer used to convert the text in the query value into tokens. @@ -1240,8 +1242,8 @@ class Nested(Query): Wraps another query to search nested fields. If an object matches the search, the nested query returns the root parent document. - :arg path: (required)Path to the nested object you wish to search. - :arg query: (required)Query you wish to run on nested objects in the + :arg path: (required) Path to the nested object you wish to search. + :arg query: (required) Query you wish to run on nested objects in the path. :arg ignore_unmapped: Indicates whether to ignore an unmapped path and not return any documents instead of an error. @@ -1304,7 +1306,7 @@ class Percolate(Query): """ Matches queries stored in an index. - :arg field: (required)Field that holds the indexed queries. The field + :arg field: (required) Field that holds the indexed queries. The field must use the `percolator` mapping type. :arg document: The source of the document being percolated. :arg documents: An array of sources of the documents being percolated. @@ -1352,7 +1354,7 @@ class Pinned(Query): Promotes selected documents to rank higher than those matching a given query. - :arg organic: (required)Any choice of query used to rank documents + :arg organic: (required) Any choice of query used to rank documents which will be ranked below the "pinned" documents. :arg ids: Document IDs listed in the order they are to appear in results. Required if `docs` is not specified. @@ -1402,7 +1404,7 @@ class QueryString(Query): Returns documents based on a provided query string, using a parser with a strict syntax. - :arg query: (required)Query string you wish to parse and use for + :arg query: (required) Query string you wish to parse and use for search. :arg allow_leading_wildcard: If `true`, the wildcard characters `*` and `?` are allowed as the first character of the query string. @@ -1551,7 +1553,7 @@ class RankFeature(Query): Boosts the relevance score of documents based on the numeric value of a `rank_feature` or `rank_features` field. - :arg field: (required)`rank_feature` or `rank_features` field used to + :arg field: (required) `rank_feature` or `rank_features` field used to boost relevance scores. :arg saturation: Saturation function used to boost relevance scores based on the value of the rank feature `field`. @@ -1618,9 +1620,9 @@ class Rule(Query): """ No documentation available. - :arg ruleset_ids: (required)No documentation available. - :arg match_criteria: (required)No documentation available. - :arg organic: (required)No documentation available. + :arg ruleset_ids: (required) No documentation available. + :arg match_criteria: (required) No documentation available. + :arg organic: (required) No documentation available. """ name = "rule" @@ -1649,7 +1651,7 @@ class Script(Query): Filters documents based on a provided script. The script query is typically used in a filter context. - :arg script: (required)Contains a script to run as a query. This + :arg script: (required) Contains a script to run as a query. This script must return a boolean value, `true` or `false`. """ @@ -1668,8 +1670,8 @@ class ScriptScore(Query): """ Uses a script to provide a custom score for returned documents. - :arg query: (required)Query used to return documents. - :arg script: (required)Script used to compute the score of documents + :arg query: (required) Query used to return documents. + :arg script: (required) Script used to compute the score of documents returned by the query. Important: final relevance scores from the `script_score` query cannot be negative. :arg min_score: Documents with a score lower than this floating point @@ -1696,8 +1698,8 @@ class Semantic(Query): """ A semantic query to semantic_text field types - :arg query: (required)The query text - :arg field: (required)The field to query, which must be a + :arg query: (required) The query text + :arg field: (required) The field to query, which must be a semantic_text field type """ @@ -1734,7 +1736,7 @@ class SimpleQueryString(Query): Returns documents based on a provided query string, using a parser with a limited but fault-tolerant syntax. - :arg query: (required)Query string in the simple query string syntax + :arg query: (required) Query string in the simple query string syntax you wish to parse and use for search. :arg analyzer: Analyzer used to convert text in the query string into tokens. @@ -1808,9 +1810,9 @@ class SpanContaining(Query): """ Returns matches which enclose another span query. - :arg little: (required)Can be any span query. Matching spans from + :arg little: (required) Can be any span query. Matching spans from `big` that contain matches from `little` are returned. - :arg big: (required)Can be any span query. Matching spans from `big` + :arg big: (required) Can be any span query. Matching spans from `big` that contain matches from `little` are returned. """ @@ -1831,8 +1833,8 @@ class SpanFieldMasking(Query): Wrapper to allow span queries to participate in composite single-field span queries by _lying_ about their search field. - :arg query: (required)No documentation available. - :arg field: (required)No documentation available. + :arg query: (required) No documentation available. + :arg field: (required) No documentation available. """ name = "span_field_masking" @@ -1851,8 +1853,8 @@ class SpanFirst(Query): """ Matches spans near the beginning of a field. - :arg match: (required)Can be any other span type query. - :arg end: (required)Controls the maximum end position permitted in a + :arg match: (required) Can be any other span type query. + :arg end: (required) Controls the maximum end position permitted in a match. """ @@ -1874,8 +1876,8 @@ class SpanMulti(Query): `prefix`, `range`, or `regexp` query) as a `span` query, so it can be nested. - :arg match: (required)Should be a multi term query (one of `wildcard`, - `fuzzy`, `prefix`, `range`, or `regexp` query). + :arg match: (required) Should be a multi term query (one of + `wildcard`, `fuzzy`, `prefix`, `range`, or `regexp` query). """ name = "span_multi" @@ -1893,7 +1895,7 @@ class SpanNear(Query): maximum number of intervening unmatched positions, as well as whether matches are required to be in-order. - :arg clauses: (required)Array of one or more other span type queries. + :arg clauses: (required) Array of one or more other span type queries. :arg in_order: Controls whether matches are required to be in-order. :arg slop: Controls the maximum number of intervening unmatched positions permitted. @@ -1918,9 +1920,9 @@ class SpanNot(Query): within x tokens before (controlled by the parameter `pre`) or y tokens after (controlled by the parameter `post`) another span query. - :arg exclude: (required)Span query whose matches must not overlap + :arg exclude: (required) Span query whose matches must not overlap those returned. - :arg include: (required)Span query whose matches are filtered. + :arg include: (required) Span query whose matches are filtered. :arg dist: The number of tokens from within the include span that can’t have overlap with the exclude span. Equivalent to setting both `pre` and `post`. @@ -1951,7 +1953,7 @@ class SpanOr(Query): """ Matches the union of its span clauses. - :arg clauses: (required)Array of one or more other span type queries. + :arg clauses: (required) Array of one or more other span type queries. """ name = "span_or" @@ -1990,9 +1992,9 @@ class SpanWithin(Query): """ Returns matches which are enclosed inside another span query. - :arg little: (required)Can be any span query. Matching spans from + :arg little: (required) Can be any span query. Matching spans from `little` that are enclosed within `big` are returned. - :arg big: (required)Can be any span query. Matching spans from + :arg big: (required) Can be any span query. Matching spans from `little` that are enclosed within `big` are returned. """ @@ -2014,7 +2016,7 @@ class SparseVector(Query): convert a query into a list of token-weight pairs, queries against a sparse vector field. - :arg field: (required)The name of the field that contains the token- + :arg field: (required) The name of the field that contains the token- weight pairs to be searched against. This field must be a mapped sparse_vector field. :arg query_vector: Dictionary of precomputed sparse vectors and their @@ -2198,7 +2200,7 @@ class Wrapper(Query): """ A query that accepts any other query as base64 encoded string. - :arg query: (required)A base64 encoded query. The binary data format + :arg query: (required) A base64 encoded query. The binary data format can be any of JSON, YAML, CBOR or SMILE encodings """ @@ -2212,7 +2214,7 @@ class Type(Query): """ No documentation available. - :arg value: (required)No documentation available. + :arg value: (required) No documentation available. """ name = "type" diff --git a/utils/generator.py b/utils/generator.py index b871409a..458acbc2 100644 --- a/utils/generator.py +++ b/utils/generator.py @@ -33,7 +33,14 @@ query_py = jinja_env.get_template("query.py.tpl") interfaces_py = jinja_env.get_template("interfaces.py.tpl") -RESERVED = {"from": "from_"} +# map with name replacements for Elasticsearch attributes +PROP_REPLACEMENTS = {"from": "from_"} + +# map with Elasticsearch type replacements +# keys and values are in given in "{namespace}:{name}" format +TYPE_REPLACEMENTS = { + "_types.query_dsl:DistanceFeatureQuery": "_types.query_dsl:DistanceFeatureQueryBase", +} def wrapped_doc(text, width=70, initial_indent="", subsequent_indent=""): @@ -65,6 +72,8 @@ def add_not_set(type_): class ElasticsearchSchema: + """Operations related to the Elasticsearch schema.""" + def __init__(self): response = None for branch in [f"{VERSION[0]}.{VERSION[1]}", "main"]: @@ -78,6 +87,10 @@ def __init__(self): if not response: raise RuntimeError("Could not download Elasticsearch schema") self.schema = json.loads(response.read()) + + # Interfaces collects interfaces that are seen while traversing the schema. + # Any interfaces collected here are then rendered as Python in the + # interfaces.py module. self.interfaces = set() def find_type(self, name, namespace=None): @@ -91,6 +104,13 @@ def reset_interfaces(self): self.interfaces = set() def get_python_type(self, schema_type): + """Obtain Python typing details for a given schema type + + This method returns a tuple. The first element is a string with the + Python type hint. The second element is a dictionary with Python DSL + specific typing details to be stored in the DslBase._param_defs + attribute (or None if the type does not need to be in _param_defs). + """ if schema_type["kind"] == "instance_of": type_name = schema_type["type"] if type_name["namespace"] in ["_types", "internal", "_builtins"]: @@ -109,6 +129,7 @@ def get_python_type(self, schema_type): elif type_name["name"] == "Field": return 'Union[str, "InstrumentedField"]', None else: + # not an instance of a native type, so we get the type and try again return self.get_python_type( self.find_type(type_name["name"], type_name["namespace"]) ) @@ -116,22 +137,25 @@ def get_python_type(self, schema_type): type_name["namespace"] == "_types.query_dsl" and type_name["name"] == "QueryContainer" ): + # QueryContainer maps to the DSL's Query class return "Query", {"type": "query"} else: + # for any other instances we get the type and recurse type_ = self.find_type(type_name["name"], type_name["namespace"]) if type_: return self.get_python_type(type_) elif schema_type["kind"] == "type_alias": + # for an alias, we use the aliased type return self.get_python_type(schema_type["type"]) elif schema_type["kind"] == "array_of": + # for arrays we use List[element_type] type_, param = self.get_python_type(schema_type["value"]) - if type_.startswith("Union["): - types = type_[6:-1].split(",") return f"List[{type_}]", {**param, "multi": True} if param else None elif schema_type["kind"] == "dictionary_of": + # for dicts we use Mapping[key_type, value_type] key_type, key_param = self.get_python_type(schema_type["key"]) value_type, value_param = self.get_python_type(schema_type["value"]) return f"Mapping[{key_type}, {value_type}]", None @@ -143,6 +167,7 @@ def get_python_type(self, schema_type): and schema_type["items"][1]["kind"] == "array_of" and schema_type["items"][0] == schema_type["items"][1]["value"] ): + # special kind of unions in the form Union[type, List[type]] type_, param = self.get_python_type(schema_type["items"][0]) return ( f"Union[{type_}, List[{type_}]]", @@ -154,18 +179,23 @@ def get_python_type(self, schema_type): and schema_type["items"][1]["kind"] == "instance_of" and schema_type["items"][0]["type"] == {"name": "T", "namespace": "_spec_utils.PipeSeparatedFlags"} + and schema_type["items"][1]["type"] + == {"name": "string", "namespace": "_builtins"} ): + # for now we treat PipeSeparatedFlags as a special case self.interfaces.add("PipeSeparatedFlags") return '"i.PipeSeparatedFlags"', None else: + # generic union type types = list( - dict.fromkeys( + dict.fromkeys( # eliminate duplicates [self.get_python_type(t) for t in schema_type["items"]] ) ) return "Union[" + ", ".join([type_ for type_, _ in types]) + "]", None elif schema_type["kind"] == "enum": + # enums are mapped to Literal[member, ...] return ( "Literal[" + ", ".join( @@ -177,12 +207,14 @@ def get_python_type(self, schema_type): elif schema_type["kind"] == "interface": if schema_type["name"]["namespace"] == "_types.query_dsl": + # handle specific DSL classes explicitly to map to existing + # Python DSL classes if schema_type["name"]["name"].endswith("RangeQuery"): return '"wrappers.Range[Any]"', None elif schema_type["name"]["name"].endswith("ScoreFunction"): name = schema_type["name"]["name"][:-8] if name == "FieldValueFactorScore": - name = "FieldValueFactor" # naming exception + name = "FieldValueFactor" # Python DSL uses different name return f'"f.{name}"', None elif schema_type["name"]["name"].endswith("DecayFunction"): return '"f.DecayFunction"', None @@ -191,15 +223,28 @@ def get_python_type(self, schema_type): elif schema_type["name"]["namespace"] == "_types.analysis" and schema_type[ "name" ]["name"].endswith("Analyzer"): - return "str", None + # not expanding analyzers at this time, maybe in the future + return "str, Dict[str, Any]", None + + # to handle other interfaces we generate a type of the same name + # and add the interface to the interfaces.py module self.interfaces.add(schema_type["name"]["name"]) return f"\"i.{schema_type['name']['name']}\"", None elif schema_type["kind"] == "user_defined_value": + # user_defined_value maps to Python's Any type return "Any", None raise RuntimeError(f"Cannot find Python type for {schema_type}") - def argument_to_python_type(self, arg): + def get_attribute_data(self, arg): + """Return the template definitions for a class attribute. + + This method returns a tuple. The first element is a dict with the + information to render the attribute. The second element is a dictionary + with Python DSL specific typing details to be stored in the + DslBase._param_defs attribute (or None if the type does not need to be + in _param_defs). + """ try: type_, param = schema.get_python_type(arg["type"]) except RuntimeError: @@ -207,125 +252,157 @@ def argument_to_python_type(self, arg): param = None if type_ != "Any": if "i." in type_: - type_ = add_dict_type(type_) + type_ = add_dict_type(type_) # interfaces can be given as dicts type_ = add_not_set(type_) - required = "(required)" if arg["required"] else "" + required = "(required) " if arg["required"] else "" doc = wrapped_doc( f":arg {arg['name']}: {required}{arg.get('description', 'No documentation available.')}", subsequent_indent=" ", ) - kwarg = { - "name": RESERVED.get(arg["name"], arg["name"]), + arg = { + "name": PROP_REPLACEMENTS.get(arg["name"], arg["name"]), "type": type_, "doc": doc, "required": arg["required"], } if param is not None: param = {"name": arg["name"], "param": param} - return kwarg, param + return arg, param - def instance_of_to_python_class(self, p, k): - instance = schema.find_type( - p["type"]["type"]["name"], p["type"]["type"]["namespace"] - ) - if instance["kind"] == "interface": - k["kwargs"] = [] - k["params"] = [] - for p in instance["properties"]: - kwarg, param = self.argument_to_python_type(p) - if kwarg["required"]: - i = 0 - for i in range(len(k["kwargs"])): - if k["kwargs"][i]["required"] is False: - break - k["kwargs"].insert(i, kwarg) + def property_to_python_class(self, p): + """Return a dictionary with template data necessary to render a schema + property as a Python class. + + Used for "container" sub-classes such as `QueryContainer`, where each + sub-class is represented by a Python DSL class. + + The format is as follows: + + ```python + { + "property_name": "the name of the property", + "name": "the class name to use for the property", + "docstring": "the formatted docstring as a list of strings", + "args": [ # a Python description of each class attribute + "name": "the name of the attribute", + "type": "the Python type hint for the attribute", + "doc": ["formatted lines of documentation to add to class docstring"], + "required": bool + ], + "params": [ + "name": "the attribute name", + "param": "the param dictionary to include in `_param_defs` for the class", + ], # a DSL-specific description of interesting attributes + "is_single_field": bool # True for single-key dicts with field key + "is_multi_field": bool # True for multi-key dicts with field keys + } + ``` + """ + k = { + "property_name": p["name"], + "name": "".join([w.title() for w in p["name"].split("_")]), + } + k["docstring"] = wrapped_doc(p.get("description")) + kind = p["type"]["kind"] + if kind == "instance_of": + namespace = p["type"]["type"]["namespace"] + name = p["type"]["type"]["name"] + if f"{namespace}:{name}" in TYPE_REPLACEMENTS: + namespace, name = TYPE_REPLACEMENTS[f"{namespace}:{name}"].split(":") + instance = schema.find_type(name, namespace) + if instance["kind"] == "interface": + k["args"] = [] + k["params"] = [] + for arg in instance["properties"]: + python_arg, param = self.get_attribute_data(arg) + if python_arg["required"]: + # insert in the right place so that all required arguments + # appear at the top of the argument list + i = 0 + for i in range(len(k["args"])): + if k["args"][i]["required"] is False: + break + k["args"].insert(i, python_arg) + else: + k["args"].append(python_arg) + if param: + k["params"].append(param) + else: + raise RuntimeError( + f"Cannot generate code for instances of kind '{instance['kind']}'" + ) + + elif kind == "dictionary_of": + key_type, _ = schema.get_python_type(p["type"]["key"]) + if "InstrumentedField" in key_type: + value_type, _ = schema.get_python_type(p["type"]["value"]) + if p["type"]["singleKey"]: + # special handling for single-key dicts with field key + k["args"] = [ + { + "name": "_field", + "type": add_not_set(key_type), + "doc": [":arg _field: The field to use in this query."], + "required": False, + }, + { + "name": "_value", + "type": add_not_set(add_dict_type(value_type)), + "doc": [":arg _value: The query value for the field."], + "required": False, + }, + ] + k["is_single_field"] = True else: - k["kwargs"].append(kwarg) - if param: - k["params"].append(param) - elif instance["kind"] == "type_alias": - if ( - "codegenNames" in instance - and instance["type"]["kind"] == "union_of" - and len(instance["type"]["items"]) == len(instance["codegenNames"]) - ): - k["kwargs"] = [] - for name, type_ in zip( - instance["codegenNames"], instance["type"]["items"] - ): - python_type, _ = self.get_python_type(type_) - k["kwargs"].append( + # special handling for multi-key dicts with field keys + k["args"] = [ { - "name": name, - "type": f'Union[{python_type}, "NotSet"]', + "name": "_fields", + "type": f"Optional[Mapping[{key_type}, {value_type}]]", "doc": [ - f":arg {name}: An instance of ``{python_type[3:-1]}``." + ":arg _fields: A dictionary of fields with their values." ], "required": False, - } - ) - k["has_type_alias"] = True - else: - raise RuntimeError("Cannot generate code for non-enum type aliases") - else: - raise RuntimeError( - f"Cannot generate code for instances of kind '{instance['kind']}'" - ) - return k - - def dictionary_of_to_python_class(self, p, k): - key_type, _ = schema.get_python_type(p["type"]["key"]) - if "InstrumentedField" in key_type: - value_type, _ = schema.get_python_type(p["type"]["value"]) - if p["type"]["singleKey"]: - k["kwargs"] = [ - { - "name": "_field", - "type": add_not_set(key_type), - "doc": [":arg _field: The field to use in this query."], - "required": False, - }, - { - "name": "_value", - "type": add_not_set(add_dict_type(value_type)), - "doc": [":arg _value: The query value for the field."], - "required": False, - }, - ] - k["has_field"] = True + }, + ] + k["is_multi_field"] = True else: - k["kwargs"] = [ - { - "name": "_fields", - "type": f"Optional[Mapping[{key_type}, {value_type}]]", - "doc": [ - ":arg _fields: A dictionary of fields with their values." - ], - "required": False, - }, - ] - k["has_fields"] = True - else: - raise RuntimeError(f"Cannot generate code for type {p['type']}") - return k + raise RuntimeError(f"Cannot generate code for type {p['type']}") - def property_to_python_class(self, p): - k = {"schema": p, "name": "".join([w.title() for w in p["name"].split("_")])} - k["docstring"] = wrapped_doc(p.get("description")) - kind = p["type"]["kind"] - if kind == "instance_of": - k = self.instance_of_to_python_class(p, k) - elif kind == "dictionary_of": - k = self.dictionary_of_to_python_class(p, k) else: raise RuntimeError(f"Cannot generate code for type {p['type']}") return k def interface_to_python_class(self, interface, interfaces): + """Return a dictionary with template data necessary to render an + interface a Python class. + + This is used to render interfaces that are referenced by container + classes. The current list of rendered interfaces is passed as a second + argument to allow this method to add more interfaces to it as they are + discovered. + + The returned format is as follows: + + ```python + { + "name": "the class name to use for the interface class", + "parent": "the parent class name", + "args": [ # a Python description of each class attribute + "name": "the name of the attribute", + "type": "the Python type hint for the attribute", + "doc": ["formatted lines of documentation to add to class docstring"], + "required": bool + ], + } + ``` + """ type_ = schema.find_type(interface) if type_["kind"] != "interface": raise RuntimeError(f"Type {interface} is not an interface") if "inherits" in type_ and "type" in type_["inherits"]: + # this class has parents, make sure we have all the parents in our + # list of interfaces to render parent = type_["inherits"]["type"]["name"] base = type_ while base and "inherits" in base and "type" in base["inherits"]: @@ -336,38 +413,38 @@ def interface_to_python_class(self, interface, interfaces): base["inherits"]["type"]["namespace"], ) else: + # no parent, will inherit from AttrDict parent = None - k = {"name": interface, "parent": parent, "properties": []} + k = {"name": interface, "parent": parent, "args": []} for arg in type_["properties"]: - arg_type, _ = schema.argument_to_python_type(arg) - k["properties"].append(arg_type) + arg_type, _ = schema.get_attribute_data(arg) + k["args"].append(arg_type) return k -def generate_query_classes(schema, filename): +def generate_query_py(schema, filename): + """Generate query.py with all the properties of `QueryContainer` as Python + classes. + """ classes = [] query_container = schema.find_type("QueryContainer", "_types.query_dsl") for p in query_container["properties"]: - k = schema.property_to_python_class(p) - classes.append(k) + classes.append(schema.property_to_python_class(p)) with open(filename, "wt") as f: - f.write( - query_py.render( - classes=classes, parent="Query", interfaces=sorted(schema.interfaces) - ) - ) + f.write(query_py.render(classes=classes, parent="Query")) print(f"Generated {filename}.") -def generate_interfaces(schema, interfaces, filename): +def generate_interfaces_py(schema, interfaces, filename): + """Generate interfaces.py""" classes = {} for interface in interfaces: if interface == "PipeSeparatedFlags": continue # handled as a special case schema.reset_interfaces() k = schema.interface_to_python_class(interface, interfaces) - for new_interface in schema.interfaces: + for new_interface in sorted(schema.interfaces): if new_interface not in interfaces: interfaces.append(new_interface) classes[k["name"]] = k @@ -399,6 +476,8 @@ def generate_interfaces(schema, interfaces, filename): if __name__ == "__main__": schema = ElasticsearchSchema() - generate_query_classes(schema, "elasticsearch_dsl/query.py") + generate_query_py(schema, "elasticsearch_dsl/query.py") interfaces = schema.interfaces - generate_interfaces(schema, sorted(interfaces), "elasticsearch_dsl/interfaces.py") + generate_interfaces_py( + schema, sorted(interfaces), "elasticsearch_dsl/interfaces.py" + ) diff --git a/utils/templates/interfaces.py.tpl b/utils/templates/interfaces.py.tpl index d48033d3..d178388c 100644 --- a/utils/templates/interfaces.py.tpl +++ b/utils/templates/interfaces.py.tpl @@ -1,3 +1,20 @@ +# Licensed to Elasticsearch B.V. under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch B.V. licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + from typing import Any, Dict, List, Literal, Mapping, Union from elasticsearch_dsl.document_base import InstrumentedField from elasticsearch_dsl import function as f, interfaces as i, Query @@ -8,32 +25,32 @@ PipeSeparatedFlags = str {% for k in classes %} class {{ k.name }}({% if k.parent %}{{ k.parent }}{% else %}AttrDict[Any]{% endif %}): - {% if k.properties %} + {% if k.args %} """ - {% for p in k.properties %} - {% for line in p.doc %} + {% for arg in k.args %} + {% for line in arg.doc %} {{ line }} {% endfor %} {% endfor %} """ - {% for p in k.properties %} - {{ p.name }}: {{ p.type }} + {% for arg in k.args %} + {{ arg.name }}: {{ arg.type }} {% endfor %} def __init__( self, *, - {% for p in k.properties %} - {{ p.name }}: {{ p.type }} = NOT_SET, + {% for arg in k.args %} + {{ arg.name }}: {{ arg.type }} = NOT_SET, {% endfor %} **kwargs: Any ): - {% for p in k.properties %} - if not isinstance({{ p.name }}, NotSet): - {% if "InstrumentedField" in p.type %} - kwargs["{{ p.name }}"] = str({{ p.name }}) + {% for arg in k.args %} + if not isinstance({{ arg.name }}, NotSet): + {% if "InstrumentedField" in arg.type %} + kwargs["{{ arg.name }}"] = str({{ arg.name }}) {% else %} - kwargs["{{ p.name }}"] = {{ p.name }} + kwargs["{{ arg.name }}"] = {{ arg.name }} {% endif %} {% endfor %} {% if k.parent %} diff --git a/utils/templates/query.py.tpl b/utils/templates/query.py.tpl index 1231d886..bf8899cb 100644 --- a/utils/templates/query.py.tpl +++ b/utils/templates/query.py.tpl @@ -148,16 +148,16 @@ class {{ k.name }}({{ parent }}): {% for line in k.docstring %} {{ line }} {% endfor %} - {% if k.kwargs %} + {% if k.args %} - {% for kwarg in k.kwargs %} + {% for kwarg in k.args %} {% for line in kwarg.doc %} {{ line }} {% endfor %} {% endfor %} {% endif %} """ - name = "{{ k.schema.name }}" + name = "{{ k.property_name }}" {% if k.params %} _param_defs = { {% for param in k.params %} @@ -172,11 +172,11 @@ class {{ k.name }}({{ parent }}): def __init__( self, - {% if k.kwargs and not k.has_field and not k.has_fields %} + {% if k.args and not k.is_single_field and not k.is_multi_field %} *, {% endif %} - {% for kwarg in k.kwargs %} - {{ kwarg.name }}: {{ kwarg.type }} = NOT_SET, + {% for arg in k.args %} + {{ arg.name }}: {{ arg.type }} = NOT_SET, {% endfor %} **kwargs: Any ): @@ -186,27 +186,18 @@ class {{ k.name }}({{ parent }}): for name in ScoreFunction._classes: if name in kwargs: functions.append({name: kwargs.pop(name)}) # type: ignore - {% elif k.has_field %} + {% elif k.is_single_field %} if not isinstance(_field, NotSet): kwargs[str(_field)] = _value - {% elif k.has_fields %} + {% elif k.is_multi_field %} if not isinstance(fields, NotSet): for field, value in _fields.items(): kwargs[str(field)] = value - {% elif k.has_type_alias %} - {% for kwarg in k.kwargs %} - {% if loop.index == 1 %} - if not isinstance({{ kwarg.name }}, NotSet): - {% else %} - elif not isinstance({{ kwarg.name }}, NotSet): - {% endif %} - kwargs = cast(Dict[str, Any], {{ kwarg.name }}.to_dict() if hasattr({{ kwarg.name }}, "to_dict") else {{ kwarg.name }}) - {% endfor %} {% endif %} super().__init__( - {% if not k.has_field and not k.has_fields and not k.has_type_alias %} - {% for kwarg in k.kwargs %} - {{ kwarg.name }}={{ kwarg.name }}, + {% if not k.is_single_field and not k.is_multi_field %} + {% for arg in k.args %} + {{ arg.name }}={{ arg.name }}, {% endfor %} {% endif %} **kwargs @@ -351,7 +342,7 @@ EMPTY_QUERY = MatchAll() return q __rand__ = __and__ - + {% elif k.name == "Terms" %} def _setattr(self, name: str, value: Any) -> None: super()._setattr(name, list(value))