15
15
# specific language governing permissions and limitations
16
16
# under the License.
17
17
18
+ import json
18
19
from datetime import date , datetime
19
20
from fnmatch import fnmatch
20
21
from typing import (
@@ -56,7 +57,59 @@ def __init__(self, *args: Any, **kwargs: Any):
56
57
self .args , self .kwargs = args , kwargs
57
58
58
59
59
- class InstrumentedField :
60
+ class InstrumentedExpression :
61
+ """Proxy object for a ES|QL expression."""
62
+
63
+ def __init__ (self , expr : str ):
64
+ self ._expr = expr
65
+
66
+ def __str__ (self ) -> str :
67
+ return self ._expr
68
+
69
+ def __repr__ (self ) -> str :
70
+ return f"InstrumentedExpression[{ self ._expr } ]"
71
+
72
+ def __pos__ (self ) -> "InstrumentedExpression" :
73
+ return self
74
+
75
+ def __neg__ (self ) -> "InstrumentedExpression" :
76
+ return InstrumentedExpression (f"-({ self ._expr } )" )
77
+
78
+ def __eq__ (self , value : Any ) -> "InstrumentedExpression" : # type: ignore[override]
79
+ return InstrumentedExpression (f"{ self ._expr } == { json .dumps (value )} " )
80
+
81
+ def __ne__ (self , value : Any ) -> "InstrumentedExpression" : # type: ignore[override]
82
+ return InstrumentedExpression (f"{ self ._expr } != { json .dumps (value )} " )
83
+
84
+ def __lt__ (self , value : Any ) -> "InstrumentedExpression" :
85
+ return InstrumentedExpression (f"{ self ._expr } < { json .dumps (value )} " )
86
+
87
+ def __gt__ (self , value : Any ) -> "InstrumentedExpression" :
88
+ return InstrumentedExpression (f"{ self ._expr } > { json .dumps (value )} " )
89
+
90
+ def __le__ (self , value : Any ) -> "InstrumentedExpression" :
91
+ return InstrumentedExpression (f"{ self ._expr } <= { json .dumps (value )} " )
92
+
93
+ def __ge__ (self , value : Any ) -> "InstrumentedExpression" :
94
+ return InstrumentedExpression (f"{ self ._expr } >= { json .dumps (value )} " )
95
+
96
+ def __add__ (self , value : Any ) -> "InstrumentedExpression" :
97
+ return InstrumentedExpression (f"{ self ._expr } + { json .dumps (value )} " )
98
+
99
+ def __sub__ (self , value : Any ) -> "InstrumentedExpression" :
100
+ return InstrumentedExpression (f"{ self ._expr } - { json .dumps (value )} " )
101
+
102
+ def __mul__ (self , value : Any ) -> "InstrumentedExpression" :
103
+ return InstrumentedExpression (f"{ self ._expr } * { json .dumps (value )} " )
104
+
105
+ def __truediv__ (self , value : Any ) -> "InstrumentedExpression" :
106
+ return InstrumentedExpression (f"{ self ._expr } / { json .dumps (value )} " )
107
+
108
+ def __mod__ (self , value : Any ) -> "InstrumentedExpression" :
109
+ return InstrumentedExpression (f"{ self ._expr } % { json .dumps (value )} " )
110
+
111
+
112
+ class InstrumentedField (InstrumentedExpression ):
60
113
"""Proxy object for a mapped document field.
61
114
62
115
An object of this instance is returned when a field is accessed as a class
@@ -71,8 +124,8 @@ class MyDocument(Document):
71
124
s = s.sort(-MyDocument.name) # sort by name in descending order
72
125
"""
73
126
74
- def __init__ (self , name : str , field : Field ):
75
- self . _name = name
127
+ def __init__ (self , name : str , field : Optional [ Field ] ):
128
+ super (). __init__ ( name )
76
129
self ._field = field
77
130
78
131
# note that the return value type here assumes classes will only be used to
@@ -83,26 +136,41 @@ def __getattr__(self, attr: str) -> "InstrumentedField":
83
136
# first let's see if this is an attribute of this object
84
137
return super ().__getattribute__ (attr ) # type: ignore[no-any-return]
85
138
except AttributeError :
86
- try :
87
- # next we see if we have a sub-field with this name
88
- return InstrumentedField (f"{ self ._name } .{ attr } " , self ._field [attr ])
89
- except KeyError :
90
- # lastly we let the wrapped field resolve this attribute
91
- return getattr (self ._field , attr ) # type: ignore[no-any-return]
92
-
93
- def __pos__ (self ) -> str :
139
+ if self ._field :
140
+ try :
141
+ # next we see if we have a sub-field with this name
142
+ return InstrumentedField (f"{ self ._expr } .{ attr } " , self ._field [attr ])
143
+ except KeyError :
144
+ # lastly we let the wrapped field resolve this attribute
145
+ return getattr (self ._field , attr ) # type: ignore[no-any-return]
146
+ else :
147
+ raise
148
+
149
+ def __pos__ (self ) -> str : # type: ignore[override]
94
150
"""Return the field name representation for ascending sort order"""
95
- return f"{ self ._name } "
151
+ return f"{ self ._expr } "
96
152
97
- def __neg__ (self ) -> str :
153
+ def __neg__ (self ) -> str : # type: ignore[override]
98
154
"""Return the field name representation for descending sort order"""
99
- return f"-{ self ._name } "
155
+ return f"-{ self ._expr } "
156
+
157
+ def asc (self ) -> "InstrumentedField" :
158
+ return InstrumentedField (f"{ self ._expr } ASC" , None )
159
+
160
+ def desc (self ) -> "InstrumentedField" :
161
+ return InstrumentedField (f"{ self ._expr } DESC" , None )
162
+
163
+ def nulls_first (self ) -> "InstrumentedField" :
164
+ return InstrumentedField (f"{ self ._expr } NULLS FIRST" , None )
165
+
166
+ def nulls_last (self ) -> "InstrumentedField" :
167
+ return InstrumentedField (f"{ self ._expr } NULLS LAST" , None )
100
168
101
169
def __str__ (self ) -> str :
102
- return self ._name
170
+ return self ._expr
103
171
104
172
def __repr__ (self ) -> str :
105
- return f"InstrumentedField[{ self ._name } ]"
173
+ return f"InstrumentedField[{ self ._expr } ]"
106
174
107
175
108
176
class DocumentMeta (type ):
0 commit comments