NebulaGraph Python Client 5.3.0
Loading...
Searching...
No Matches
value_wrapper.py
1# Copyright 2025 vesoft-inc
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import logging
16from datetime import date, datetime, time
17from decimal import Decimal
18from typing import Any, List, Optional, Type, TypeVar, Union, overload
19
20from nebulagraph_python.decoder.data_types import ColumnType
22 ColumnToPy,
23 CompositeDataObject,
24 Edge,
25 NDuration,
26 Node,
27 NRecord,
28 NVector,
29 Path,
30 TargetType,
31)
32
33logger = logging.getLogger(__name__)
34
35
36T = TypeVar("T", bound=TargetType)
37
38
40 __slots__ = ("value", "data_type")
41
42 def __init__(self, value: Any, data_type: ColumnType):
43 self.value = value
44 self.data_type = data_type
45
46 def is_null(self) -> bool:
47 """If the value is null
48
49 Returns
50 -------
51 bool: true if value is null
52
53 """
54 return self.value is None
55
56 def is_bool(self) -> bool:
57 """Check if the Value is Boolean type
58
59 Returns
60 -------
61 bool: true if Value's type is COLUMN_TYPE_BOOL
62
63 """
64 return self.data_type == ColumnType.BOOL
65
66 def is_long(self) -> bool:
67 """Check if the Value is Long type
68
69 Returns
70 -------
71 bool: true if Value's type is COLUMN_TYPE_UINT64 or COLUMN_TYPE_INT64
72
73 """
74 return self.data_type in [ColumnType.UINT64, ColumnType.INT64]
75
76 def is_int(self) -> bool:
77 """Check if the Value is Int type
78
79 Returns
80 -------
81 bool: true if Value's type is COLUMN_TYPE_UINT8 or COLUMN_TYPE_INT8 or COLUMN_TYPE_UINT16
82 or COLUMN_TYPE_INT16 or COLUMN_TYPE_UINT32 or COLUMN_TYPE_INT32
83
84 """
85 return self.data_type in [
86 ColumnType.UINT8,
87 ColumnType.INT8,
88 ColumnType.UINT16,
89 ColumnType.INT16,
90 ColumnType.UINT32,
91 ColumnType.INT32,
92 ]
93
94 def is_float(self) -> bool:
95 """Check if the Value is Float type
96
97 Returns
98 -------
99 bool: true if Value's type is COLUMN_TYPE_FLOAT32
100
101 """
102 return self.data_type == ColumnType.FLOAT32
103
104 def is_double(self) -> bool:
105 """Check if the Value is Double type
106
107 Returns
108 -------
109 bool: true if Value's type is COLUMN_TYPE_FLOAT64
110
111 """
112 return self.data_type == ColumnType.FLOAT64
113
114 def is_string(self) -> bool:
115 """Check if the Value is String type.
116
117 Returns
118 -------
119 bool: true if Value's type is COLUMN_TYPE_STRING
120
121 """
122 return self.data_type == ColumnType.STRING
123
124 def is_list(self) -> bool:
125 """Check if the Value is List type.
126
127 Returns
128 -------
129 bool: true if Value's type is COLUMN_TYPE_LIST
130
131 """
132 return self.data_type == ColumnType.LIST
133
134 def is_node(self) -> bool:
135 """Check if the Value is Node type
136
137 Returns
138 -------
139 bool: true if Value's type is COLUMN_TYPE_NODE
140
141 """
142 return self.data_type == ColumnType.NODE
143
144 def is_edge(self) -> bool:
145 """Check if the Value is Edge type
146
147 Returns
148 -------
149 bool: true if Value's type is COLUMN_TYPE_EDGE
150
151 """
152 return self.data_type == ColumnType.EDGE
153
154 def is_local_time(self) -> bool:
155 """Check if the Value is Local Time type.
156
157 Returns
158 -------
159 bool: true if Value's type is COLUMN_TYPE_LOCALTIME
160
161 """
162 return self.data_type == ColumnType.LOCALTIME
163
164 def is_zoned_time(self) -> bool:
165 """Check if the Value is Zoned Time type
166
167 Returns
168 -------
169 bool: true if Value's type is COLUMN_TYPE_ZONEDTIME
170
171 """
172 return self.data_type == ColumnType.ZONEDTIME
173
174 def is_local_datetime(self) -> bool:
175 """Check if the Value is Local Datetime type
176
177 Returns
178 -------
179 bool: true if Value's type is COLUMN_TYPE_LOCALDATETIME
180
181 """
182 return self.data_type == ColumnType.LOCALDATETIME
183
184 def is_zoned_datetime(self) -> bool:
185 """Check if the Value is Zoned Datetime type
186
187 Returns
188 -------
189 bool: true if Value's type is COLUMN_TYPE_ZONEDDATETIME
190
191 """
192 return self.data_type == ColumnType.ZONEDDATETIME
193
194 def is_date(self) -> bool:
195 """Check if the Value is Date type
196
197 Returns
198 -------
199 bool: true if Value's type is COLUMN_TYPE_DATE
200
201 """
202 return self.data_type == ColumnType.DATE
203
204 def is_record(self) -> bool:
205 """Check if the Value is Record type
206
207 Returns
208 -------
209 bool: true if Value's type is COLUMN_TYPE_RECORD
210
211 """
212 return self.data_type == ColumnType.RECORD
213
214 def is_duration(self) -> bool:
215 """Check if the Value is Duration type
216
217 Returns
218 -------
219 bool: true if Value's type is COLUMN_TYPE_DURATION
220
221 """
222 return self.data_type == ColumnType.DURATION
223
224 def is_path(self) -> bool:
225 """Check if the Value is Path type
226
227 Returns
228 -------
229 bool: true if Value's type is COLUMN_TYPE_PATH
230
231 """
232 return self.data_type == ColumnType.PATH
233
234 def is_decimal(self) -> bool:
235 """Check if the Value is Decimal type
236
237 Returns
238 -------
239 bool: true if Value's type is COLUMN_TYPE_DECIMAL
240
241 """
242 return self.data_type == ColumnType.DECIMAL
243
244 def as_bool(self):
245 return self.castcastcast(bool)
246
247 def as_int(self):
248 return self.castcastcast(int)
249
250 def as_long(self):
251 return self.castcastcast(int)
252
253 def as_string(self):
254 return self.castcastcast(str)
255
256 def as_float(self):
257 return self.castcastcast(float)
258
259 def as_double(self):
260 return self.castcastcast(float)
261
262 def as_list(self):
263 return self.castcastcast(list)
264
265 def as_node(self):
266 return self.castcastcast(Node)
267
268 def as_edge(self):
269 return self.castcastcast(Edge)
270
271 def as_local_time(self):
272 return self.castcastcast(time)
273
274 def as_zoned_time(self):
275 return self.castcastcast(time)
276
277 def as_date(self):
278 return self.castcastcast(date)
279
280 def as_local_datetime(self):
281 return self.castcastcast(datetime)
282
283 def as_zoned_datetime(self):
284 return self.castcastcast(datetime)
285
286 def as_duration(self):
287 return self.castcastcast(NDuration)
288
289 def as_record(self):
290 return self.castcastcast(NRecord)
291
292 def as_path(self):
293 return self.castcastcast(Path)
294
295 def as_decimal(self):
296 return self.castcastcast(Decimal)
297
298 def as_embedding_vector(self):
299 return self.castcastcast(NVector)
300
301 @overload
302 def cast(self) -> TargetType:
303 """Get self.value"""
304 ...
305
306 @overload
307 def cast(self, target_type: Type[T]) -> T:
308 """Get self.value, with target_type check"""
309 ...
310
311 def cast(
312 self,
313 target_type: Optional[Type[T]] = None,
314 ) -> Union[T, TargetType]:
315 if self.value is None and target_type is None:
316 return None
317 target_type = ColumnToPy[self.data_type] if target_type is None else target_type # type: ignore
318
319 if target_type is not None:
320 if isinstance(self.value, target_type):
321 return self.value
322 else:
323 raise TypeError(
324 f"Cannot cast {type(self.value)} to {target_type}. ColumnType and value:",
325 self.data_type,
326 self.value,
327 )
328
329 def cast_primitive(self) -> Any:
330 """Convert the wrapped value to primitive Python types recursively.
331
332 For basic types, uses cast()
333 For composite types (Path, Node, Edge), calls cast_primitive()
334 For containers (Map, List, Record), recursively calls cast_primitive() on elements
335 """
336 outer = self.castcastcast()
337
338 # Handle composite types
339 if isinstance(outer, CompositeDataObject):
340 return outer.cast_primitive()
341
342 # Handle list recursively
343 if isinstance(outer, list):
344 ans = []
345 for i, v in enumerate(outer):
346 if isinstance(v, ValueWrapper):
347 ans.append(v.cast_primitive())
348 else:
349 raise TypeError(
350 f"Cannot cast list, where list[{i}] have type {type(v)}, not ValueWrapper. list[{i}]: ",
351 v,
352 )
353 return ans
354
355 return outer
356
357 def __eq__(self, other):
358 if not isinstance(other, ValueWrapper):
359 return False
360 return self.value == other.value and self.data_type == other.data_type
361
362 def __hash__(self) -> int:
363 return hash((self.value, self.data_type))
364
365
366class Row:
367 __slots__ = ("values",)
368
369 def __init__(self, values: Optional[List[ValueWrapper]] = None):
370 self.values = values if values is not None else []
371
372 def add_value(self, value: ValueWrapper):
373 """Append one value into row.
374
375 Args:
376 ----
377 value (ValueWrapper): one value of the row
378
379 """
380 self.values.append(value)
381
382 def get_values(self) -> list[ValueWrapper]:
383 """Get the values of this row.
384
385 Returns
386 -------
387 List[ValueWrapper]: list of values in this row
388
389 """
390 return self.values
list[ValueWrapper] get_values(self)
add_value(self, ValueWrapper value)
Union[T, TargetType] cast(self, Optional[Type[T]] target_type=None)