NTV.json_ntv.ntv
Created on Feb 27 2023
@author: Philippe@loco-labs.io
The ntv
module is part of the NTV.json_ntv
package (specification document).
It contains the classes NtvSingle
, NtvList
, Ntv
(abstract) for NTV entities.
For more information, see the user guide or the github repository.
1# -*- coding: utf-8 -*- 2""" 3Created on Feb 27 2023 4 5@author: Philippe@loco-labs.io 6 7The `ntv` module is part of the `NTV.json_ntv` package ([specification document]( 8https://loco-philippe.github.io/ES/JSON%20semantic%20format%20(JSON-NTV).htm)). 9 10It contains the classes `NtvSingle`, `NtvList`, `Ntv`(abstract) for NTV entities. 11 12For more information, see the 13[user guide](https://loco-philippe.github.io/NTV/documentation/user_guide.html) 14or the [github repository](https://github.com/loco-philippe/NTV). 15 16""" 17import copy 18from abc import ABC, abstractmethod 19from numbers import Number 20import json 21 22from json_ntv.namespace import NtvType, Namespace, str_type, relative_type, agreg_type 23from json_ntv.ntv_util import NtvError, NtvJsonEncoder, NtvConnector, NtvTree, NtvUtil 24from json_ntv.ntv_patch import NtvPointer 25 26 27class Ntv(ABC): 28 ''' The Ntv class is an abstract class used by `NtvSingle`and `NtvList` classes. 29 30 *Attributes :* 31 - **ntv_name** : String - name of the NTV entity 32 - **ntv_type**: NtvType - type of the entity 33 - **ntv_value**: value of the entity 34 35 *Internal attributes :* 36 - **parent**: parent NtvList entity 37 - **is_json**: True if ntv_value is a json_value 38 39 *dynamic values (@property)* 40 - `json_array` (abstract method) 41 - `type_str` 42 - `code_ntv` 43 - `max_len` 44 - `name` 45 - `tree` 46 - `val` 47 48 The methods defined in this class are : 49 50 *Ntv constructor (staticmethod)* 51 - `fast` 52 - `obj` 53 - `from_obj` 54 - `from_att` 55 56 *NTV conversion (instance methods)* 57 - `alike` 58 - `to_json_ntv` 59 - `to_obj_ntv` 60 61 *export - conversion (instance methods)* 62 - `expand` 63 - `to_fast` 64 - `to_name` 65 - `to_obj` 66 - `to_repr` 67 - `to_mermaid` 68 - `to_tuple` 69 - `to_ntvsingle` 70 - `to_ntvlist` 71 - `notype` 72 73 *tree methods (instance methods)* 74 - `childs` 75 - `pointer` 76 - `replace` 77 - `remove` 78 - `append` (NtvList only) 79 - `insert` (NtvList only) 80 81 *other instance methods* 82 - `from_value` 83 - `json_name` 84 - `set_name` 85 - `set_type` 86 - `set_value` 87 - `obj_value` (abstract method) 88 89 *utility methods* 90 - `decode_json` *(staticmethod)* 91 - `obj_ntv` *(staticmethod)* 92 ''' 93 94 def __init__(self, ntv_value, ntv_name, ntv_type): 95 '''Ntv constructor. 96 97 *Parameters* 98 99 - **ntv_value**: Json entity - value of the entity 100 - **ntv_name** : String (default None) - name of the NTV entity 101 - **ntv_type**: String or NtvType or Namespace (default None) - type of the entity 102 ''' 103 if isinstance(ntv_type, (NtvType, Namespace)): 104 self.ntv_type = ntv_type 105 elif ntv_type and ntv_type[-1] != '.': 106 self.ntv_type = NtvType.add(ntv_type) 107 elif ntv_type and ntv_type[-1] == '.': 108 self.ntv_type = Namespace.add(ntv_type) 109 else: 110 self.ntv_type = None 111 if not isinstance(ntv_name, str): 112 ntv_name = '' 113 self.ntv_name = ntv_name 114 self.ntv_value = ntv_value 115 self.is_json = NtvConnector.is_json(ntv_value) 116 self.parent = None 117 118 @staticmethod 119 def fast(data, no_typ=False, typ_auto=False): 120 ''' return an Ntv entity from data without conversion. 121 122 *Parameters* : see `obj` method''' 123 return Ntv.obj(data, no_typ=no_typ, typ_auto=typ_auto, fast=True) 124 125 @staticmethod 126 def obj(data, no_typ=False, decode_str=False, typ_auto=False, fast=False): 127 ''' return an Ntv entity from data. 128 129 *Parameters* 130 131 - **Data** can be : 132 - a tuple with value, name, typ and cat (see `from_att` method) 133 - a value to decode (see `from_obj`method) 134 - **no_typ** : boolean (default False) - if True, NtvList is with 'json' type 135 - **type_auto**: boolean (default False) - if True, default type for NtvList 136 is the ntv_type of the first Ntv in the ntv_value 137 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 138 - **decode_str**: boolean (default False) - if True, string are loaded in json data''' 139 if isinstance(data, tuple): 140 return Ntv.from_att(*data, decode_str=decode_str, fast=fast) 141 # if isinstance(data, str) and data.lstrip() and data.lstrip()[0] in '{[': 142 if isinstance(data, str): 143 try: 144 data = json.loads(data) 145 except json.JSONDecodeError: 146 pass 147 return Ntv.from_obj(data, no_typ=no_typ, decode_str=decode_str, 148 typ_auto=typ_auto, fast=fast) 149 150 @staticmethod 151 def from_att(value, name, typ, cat, decode_str=False, fast=False): 152 ''' return an Ntv entity. 153 154 *Parameters* 155 156 - **value**: Ntv entity or value to convert in an Ntv entity 157 - **name** : string - name of the Ntv entity 158 - **typ** : string or NtvType - type of the NTV entity 159 - **cat**: string - NTV category ('single', 'list') 160 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 161 - **decode_str**: boolean (default False) - if True, string are loaded as json data''' 162 163 value = Ntv._from_value(value, decode_str) 164 if value.__class__.__name__ in ['NtvSingle', 'NtvList']: 165 return value 166 if isinstance(value, list) and cat == 'list': 167 return NtvList(value, name, typ, fast=fast) 168 if cat == 'single': 169 return NtvSingle(value, name, typ, fast=fast) 170 return Ntv.from_obj(value, def_type=typ, fast=fast) 171 172 @staticmethod 173 def from_obj(value, def_type=None, def_sep=None, no_typ=False, decode_str=False, 174 typ_auto=False, fast=False): 175 ''' return an Ntv entity from an object value. 176 177 *Parameters* 178 179 - **value**: Ntv value to convert in an Ntv entity 180 - **no_typ** : boolean (default None) - if True, NtvList is with 'json' type 181 - **def_type** : NtvType or Namespace (default None) - default type of the value 182 - **def_sep**: ':', '::' or None (default None) - default separator of the value 183 - **decode_str**: boolean (default False) - if True, string are loaded as json data 184 - **type_auto**: boolean (default False) - if True, default type for NtvList 185 is the ntv_type of the first Ntv in the ntv_value 186 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion''' 187 value = Ntv._from_value(value, decode_str) 188 if value.__class__.__name__ in ['NtvSingle', 'NtvList']: 189 return value 190 ntv_value, ntv_name, str_typ, sep, is_json = Ntv.decode_json(value) 191 sep = def_sep if not sep else sep 192 if isinstance(ntv_value, list) and sep in (None, '::'): 193 return Ntv._create_ntvlist(str_typ, def_type, sep, ntv_value, 194 typ_auto, no_typ, ntv_name, fast) 195 if sep == ':' or (sep is None and isinstance(ntv_value, dict) and 196 len(ntv_value) == 1): 197 ntv_type = agreg_type(str_typ, def_type, False) 198 return NtvSingle(ntv_value, ntv_name, ntv_type, fast=fast) 199 if sep is None and not isinstance(ntv_value, dict): 200 is_single_json = isinstance(value, (int, str, float, bool)) 201 ntv_type = agreg_type(str_typ, def_type, is_single_json) 202 return NtvSingle(ntv_value, ntv_name, ntv_type, fast=fast) 203 if isinstance(ntv_value, dict) and (sep == '::' or len(ntv_value) != 1 and 204 sep is None): 205 return Ntv._create_ntvlist(str_typ, def_type, sep, ntv_value, 206 typ_auto, no_typ, ntv_name, fast) 207 raise NtvError('separator ":" is not compatible with value') 208 209 def __len__(self): 210 ''' len of ntv_value''' 211 if isinstance(self.ntv_value, list): 212 return len(self.ntv_value) 213 return 1 214 215 def __str__(self): 216 '''return string format''' 217 return self.to_obj(encoded=True) 218 219 def __repr__(self): 220 '''return classname and code''' 221 #return json.dumps(self.to_repr(False, False, False, 10), cls=NtvJsonEncoder) 222 return self.reduce(obj=False, level=3, maxi=6).to_obj(encoded=True) 223 224 def __contains__(self, item): 225 ''' item of Ntv entities''' 226 if isinstance(self.val, list): 227 return item in self.ntv_value 228 return item == self.ntv_value 229 230 def __iter__(self): 231 ''' iterator for Ntv entities''' 232 if isinstance(self, NtvSingle): 233 return iter([self.val]) 234 return iter(self.val) 235 236 def __getitem__(self, selec): 237 ''' return ntv_value item with selec: 238 - String beginning with "/" : json-pointer, 239 - string : name of the ntv, 240 - list : recursive selector 241 - tuple : list of name or index ''' 242 if selec is None or selec == [] or selec == () or selec == '': 243 return self 244 if isinstance(selec, (list, tuple)) and len(selec) == 1: 245 selec = selec[0] 246 if isinstance(selec, str) and len(selec) > 1 and selec[0] == '/': 247 selec = list(NtvPointer(selec)) 248 elif isinstance(selec, NtvPointer): 249 selec = list(selec) 250 if (selec == 0 or selec == self.ntv_name) and isinstance(self, NtvSingle): 251 return self.ntv_value 252 if isinstance(self, NtvSingle): 253 raise NtvError('item not present') 254 if isinstance(selec, tuple): 255 return [self[i] for i in selec] 256 if isinstance(selec, str) and isinstance(self, NtvList): 257 ind = [ntv.ntv_name for ntv in self.ntv_value].index(selec) 258 return self.ntv_value[ind] 259 if isinstance(selec, list) and isinstance(self, NtvList): 260 return self[selec[0]][selec[1:]] 261 return self.ntv_value[selec] 262 263 def __lt__(self, other): 264 ''' return a comparison between two ntv_value''' 265 # order: number > string > None 266 res = Ntv.lower(self, other) 267 if res is None: 268 res = None if len(self) == len(other) else len(self) < len(other) 269 res = self.to_obj(encoded=True) < other.to_obj(encoded=True) if res is None else res 270 return res 271 272 @staticmethod 273 def lower(val1, val2): 274 ''' compare two ntv_value and return True if val1 < val2, False if val1 > val2 and 275 None in the other cases''' 276 res = None 277 for v1, v2 in zip(Ntv.obj(val1).tree.leaf_nodes, Ntv.obj(val2).tree.leaf_nodes): 278 if v1.val is None: 279 res = True 280 elif isinstance(v1.val, (dict, list)): 281 res = Ntv.lower(v1.val, v2) 282 elif isinstance(v2.val, (dict, list)): 283 res = Ntv.lower(v1, v2.val) 284 elif isinstance(v1.val, Number): 285 if isinstance(v2.val, Number): 286 res = None if v1.val == v2.val else v1.val < v2.val 287 else: 288 res = False 289 elif isinstance(v1.val, str): 290 if isinstance(v2.val, Number): 291 res = True 292 elif isinstance(v2.val, str): 293 res = None if v1.val == v2.val else v1.val < v2.val 294 else: 295 res = False 296 if not res is None: 297 break 298 return res 299 300 def childs(self, obj=False, nam=False, typ=False): 301 ''' return a list of child Ntv entities or child data 302 303 *parameters* 304 305 - **obj**: boolean (default False) - return json-value 306 - **nam**: boolean (default False) - return name (with or without type) 307 - **typ**: boolean (default False) - return type (with or without name) 308 ''' 309 if isinstance(self, NtvSingle): 310 return [] 311 if not (obj or nam or typ): 312 return self.val 313 if obj: 314 return [ntv.to_obj() for ntv in self.val] 315 return [(ntv.name if nam else '') + (' - ' if nam and typ else '') + 316 (ntv.type_str if typ else '') for ntv in self.val] 317 318 def pointer(self, index=False, item_idx=None): 319 '''return a nested list of pointer from root 320 321 *Parameters* 322 323 - **index**: Boolean (default False) - use index instead of name 324 - **item_idx**: Integer (default None) - index value for the pointer 325 (useful with duplicate data)''' 326 if not self.parent: 327 return NtvPointer([]) 328 idx = item_idx if item_idx else self.parent.ntv_value.index(self) 329 num = index or (self.ntv_name == "" and self.parent.json_array) 330 pointer = self.parent.pointer(index) 331 pointer.append(idx if num else self.ntv_name) 332 return pointer 333 334 @property 335 def code_ntv(self): 336 '''return a string with the NTV code composed with 1 to 3 letters: 337 - 'l' (NtvList), 's' (NtvSingle / json_value) or 'o' (NtvSingle / obj_value) 338 - 'N' if ntv_name is present else none 339 - 'T' if ntv_type is present else none''' 340 dic = {'NtvList': 'l', 'NtvSingle': 's'} 341 code = dic[self.__class__.__name__] 342 if isinstance(self, NtvSingle) and not self.is_json: 343 code = 'o' 344 if self.ntv_name: 345 code += 'N' 346 if self.ntv_type and self.ntv_type.long_name != 'json': 347 code += 'T' 348 return code 349 350 @property 351 def max_len(self): 352 '''return the highest len of Ntv entity included''' 353 maxi = len(self) 354 if isinstance(self.ntv_value, (list, set)): 355 maxi = max(maxi, max(ntv.max_len for ntv in self.ntv_value)) 356 return maxi 357 358 @property 359 def name(self): 360 '''return the ntv_name of the entity''' 361 return self.ntv_name 362 363 @property 364 def type_str(self): 365 '''return a string with the value of the NtvType of the entity''' 366 if not self.ntv_type: 367 return '' 368 return self.ntv_type.long_name 369 370 @property 371 def val(self): 372 '''return the ntv_value of the entity''' 373 return self.ntv_value 374 375 def alike(self, ntv_value): 376 ''' return a Ntv entity with same name and type. 377 378 *Parameters* 379 380 - **ntv_value**: list of ntv values''' 381 return self.__class__(ntv_value, self.ntv_name, self.ntv_type) 382 383 def from_value(self): 384 '''return a Ntv entity from ntv_value''' 385 if isinstance(self.ntv_value, list): 386 return NtvList(self.ntv_value) 387 return Ntv.from_obj(self.ntv_value) 388 389 def json_name(self, def_type=None, string=False, explicit=False): 390 '''return the JSON name of the NTV entity (json-ntv format) 391 392 *Parameters* 393 394 - **def_typ** : NtvType or Namespace (default None) - type of the parent entity 395 - **string** : boolean (default False) - If True, return a string else a tuple 396 - **explicit** : boolean (default False) - If True, type is always included''' 397 if def_type is None: 398 def_type = '' 399 elif isinstance(def_type, (NtvType, Namespace)): 400 def_type = def_type.long_name 401 json_name = self.ntv_name if self.ntv_name else '' 402 json_type = relative_type( 403 def_type, self.type_str) if self.ntv_type else '' 404 implicit = (json_type == 'json' and (not def_type or def_type == 'json') or 405 not NtvConnector.is_json_class(self.val)) 406 if implicit and not explicit: 407 json_type = '' 408 json_sep = self._obj_sep(json_type, def_type) 409 if string: 410 return json_name + json_sep + json_type 411 return [json_name, json_sep, json_type] 412 413 def to_ntvsingle(self, name=None, typ=None, def_type=None, **kwargs): 414 '''convert NtvList entity to NtvSingle entity 415 416 *Parameters* 417 418 - **ntv_name** : String (default None) - name of the NTV entity 419 - **ntv_type**: String (default None) - type of the entity 420 - **value**: value of the entity 421 - **fast**: boolean (default False) - Ntv is created with a list of json values 422 without control 423 ''' 424 return NtvSingle(self.obj_value(def_type=def_type, **kwargs), 425 self.name if self.name else name, 426 self.type_str if self.type_str else typ) 427 428 def to_ntvlist(self, def_type=None, def_sep=None, no_typ=False, decode_str=False, 429 typ_auto=False, fast=False): 430 '''convert NtvSingle entity to NtvList entity 431 432 *Parameters* 433 434 - **value**: Ntv value to convert in an Ntv entity 435 - **no_typ** : boolean (default None) - if True, NtvList is with 'json' type 436 - **def_type** : NtvType or Namespace (default None) - default type of the value 437 - **def_sep**: ':', '::' or None (default None) - default separator of the value 438 - **decode_str**: boolean (default False) - if True, string are loaded as json data 439 - **type_auto**: boolean (default False) - if True, default type for NtvList 440 is the ntv_type of the first Ntv in the ntv_value 441 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 442 ''' 443 ntv = Ntv.from_obj(self.ntv_value, def_type, def_sep, no_typ, decode_str, 444 typ_auto, fast) 445 if ntv.__class__.__name__ == 'NtvSingle': 446 return NtvList([self]) 447 if self.ntv_name: 448 ntv.set_name(self.ntv_name) 449 return ntv 450 451 def notype(self): 452 '''convert NTV entity in a NV entity (with ntv_type is 'json' or None')''' 453 no_type = copy.copy(self) 454 for ntv in NtvTree(no_type).leaf_nodes: 455 ntv.set_type('json') 456 for ntv in NtvTree(no_type).inner_nodes: 457 ntv.set_type() 458 return no_type 459 460 def reduce(self, obj=True, maxi=6, level=3): 461 '''reduce the length and the level of the entity 462 463 *Parameters* 464 465 - **obj**: boolean (default True) - If True return jsonNTV else NTV entity 466 - **maxi**: integer (default 6) - Number of returned entities in an NtvList 467 - **level**: integer (default 6) - returned entities in an NtvList at this level is None 468 469 *return* 470 471 - **NTV entity** or **jsonNTV** 472 ''' 473 ntv = copy.copy(self) 474 cont = Ntv.obj('...') if self.json_array else Ntv.obj({'...':''}) 475 if isinstance(self, NtvSingle): 476 return ntv 477 if level == 0: 478 ntv.ntv_value = [NtvSingle('...',ntv_type=ntv.type_str)] 479 if len(self) <= maxi: 480 ntv.ntv_value = [child.reduce(False, maxi, level-1) for child in ntv] 481 return ntv 482 mid = maxi // 2 483 cont.set_type(ntv.type_str) 484 start = [child.reduce(False, maxi, level-1) for child in ntv[:mid]] 485 #middle = [NtvSingle('...',ntv_type=ntv.type_str)] 486 middle = [cont] 487 end = [child.reduce(False, maxi, level-1) for child in ntv[-mid:]] 488 ntv.ntv_value = start + middle + end 489 if obj: 490 return ntv.to_obj() 491 return ntv 492 493 def set_name(self, name='', nodes='simple'): 494 '''set new names to the entity 495 496 *Parameters* 497 498 - **name**: list or string (default '') - New name values 499 - **nodes**: string (default 'simple') - nodes to be changed 500 'simple': current entity 501 'leaves': NtvSingle entities 502 'inner': NtvList entities 503 'all': all entities ''' 504 match nodes: 505 case 'simple': 506 self.ntv_name = str(name) 507 case 'leaves': 508 if not isinstance(name, list): 509 name = [str(name)] * NtvTree(self).breadth 510 for nam, ntv in zip(name, NtvTree(self).leaf_nodes): 511 ntv.ntv_name = nam 512 case 'inner': 513 if not isinstance(name, list): 514 name = [str(name)] * len(NtvTree(self).inner_nodes) 515 for nam, ntv in zip(name, NtvTree(self).inner_nodes): 516 ntv.ntv_name = nam 517 case 'all': 518 if not isinstance(name, list): 519 name = [str(name)] * NtvTree(self).size 520 for nam, ntv in zip(name, NtvTree(self).nodes): 521 ntv.ntv_name = nam 522 case _: 523 raise NtvError('the nodes option is not valid') 524 525 def set_type(self, typ=None): 526 '''set a new type to the entity 527 528 *Parameters* 529 530 - **typ**: string, NtvType, Namespace (default None)''' 531 if typ and not isinstance(typ, (str, NtvType, Namespace)): 532 raise NtvError('the type is not a valid type') 533 self.ntv_type = str_type(typ, self.__class__.__name__ == 'NtvSingle') 534 535 def set_value(self, value=None, fast=False): 536 '''set new ntv_value of a single entity or of a list of entities included 537 538 *Parameters* 539 540 - **value**: list or single value 541 - **fast** : boolean (default False) - if True, value is not converted''' 542 if isinstance(self, NtvSingle): 543 self.ntv_value = NtvSingle(value, ntv_type=self.ntv_type, 544 fast=fast).val 545 return 546 if not isinstance(value, list): 547 value = [value] * NtvTree(self).breadth 548 ntv_val = NtvList(value, fast=fast) 549 for val, ntv in zip(ntv_val, NtvTree(self).leaf_nodes): 550 ntv.ntv_value = val.val 551 return 552 553 def to_mermaid(self, title='', disp=False, row=False, leaves=False): 554 '''return a mermaid flowchart. 555 556 *Parameters* 557 558 - **title**: String (default '') - title of the flowchart 559 - **disp**: Boolean (default False) - if true, return a display else return 560 a mermaid text diagram 561 - **row**: Boolean (default False) - if True, add the node row 562 - **leaves**: Boolean (default False) - if True, add the leaf row 563 ''' 564 option = {'title': title, 'disp': disp, 'row': row, 'leaves': leaves} 565 if disp: 566 Ntv.obj({':$mermaid': self.to_obj()}).to_obj( 567 format='obj', **option) 568 return None 569 return Ntv.obj({':$mermaid': self.to_obj()}).to_obj(format='obj', **option) 570 571 def expand(self, full=True): 572 '''return a json representation of the triplet (name, type, value)''' 573 if isinstance(self, NtvList) and full: 574 return {'name': self.name, 'type': self.type_str, 575 'value': [ntv.expand(full) for ntv in self.val]} 576 if isinstance(self, NtvSingle) and full: 577 return {'name': self.name, 'type': self.type_str, 'value': self.val} 578 exp = {} if not self.name else {'name': self.name} 579 if not self.type_str in ['json', ''] : 580 exp['type'] = self.type_str 581 if isinstance(self, NtvList): 582 exp['value'] = [ntv.expand(full) for ntv in self.val] 583 else: 584 exp['value'] = self.val 585 return exp 586 587 def to_repr(self, nam=True, typ=True, val=True, jsn=False, maxi=10): 588 '''return a simple json representation of the Ntv entity. 589 590 *Parameters* 591 592 - **nam**: Boolean(default True) - if true, the names are included 593 - **typ**: Boolean(default True) - if true, the types are included 594 - **val**: Boolean(default True) - if true, the values are included 595 - **jsn**: Boolean(default False) - if false, the 'json' type is not included 596 - **maxi**: Integer (default 10) - number of values to include for NtvList 597 entities. If maxi < 1 all the values are included. 598 ''' 599 ntv = self.code_ntv 600 if nam and typ: 601 ntv = ntv[0] 602 if self.ntv_name and nam: 603 ntv += '-' + self.ntv_name 604 if self.ntv_type and typ and (jsn or self.ntv_type.long_name != 'json'): 605 ntv += '-' + self.ntv_type.long_name 606 clas = self.__class__.__name__ 607 clas_val = self.ntv_value.__class__.__name__ 608 if clas == 'NtvSingle' and clas_val != 'NtvSingle': 609 if val: 610 if ntv: 611 ntv += '-' 612 ntv += json.dumps(self.ntv_value, cls=NtvJsonEncoder) 613 return ntv 614 if clas == 'NtvSingle' and clas_val == 'NtvSingle': 615 return {ntv: self.ntv_value.to_repr(nam, typ, val, jsn, maxi)} 616 if clas == 'NtvList': 617 maxv = len(self.ntv_value) if maxi < 1 else maxi 618 return {ntv: [ntvi.to_repr(nam, typ, val, jsn, maxi) 619 for ntvi in self.ntv_value[:maxv]]} 620 raise NtvError('the ntv entity is not consistent') 621 622 def to_name(self, default=''): 623 '''return the name of the NTV entity 624 625 *Parameters* 626 627 - **default**: string (default ''): returned value if name is not present ''' 628 if self.ntv_name == '': 629 return default 630 return self.ntv_name 631 632 def to_fast(self, def_type=None, **kwargs): 633 '''return the JSON representation of the NTV entity (json-ntv format) 634 without value conversion. 635 636 *Parameters* 637 638 - **def_type** : NtvType or Namespace (default None) - default type to apply 639 to the NTV entity 640 - **encoded** : boolean (default False) - choice for return format 641 (string/bytes if True, dict/list/tuple else) 642 - **format** : string (default 'json')- choice for return format 643 (json, cbor, obj) 644 - **simpleval** : boolean (default False) - if True, only value (without 645 name and type) is included 646 - **name** : boolean (default true) - if False, name is not included 647 - **json_array** : boolean (default false) - if True, Json-object is not used for NtvList 648 - **maxi**: Integer (default -1) - number of values to include for NtvList 649 entities. If maxi < 1 all the values are included. 650 ''' 651 option = kwargs | {'fast': True} 652 return self.to_obj(def_type=def_type, **option) 653 654 def to_obj(self, def_type=None, **kwargs): 655 '''return the JSON representation of the NTV entity (json-ntv format). 656 657 *Parameters* 658 659 - **def_type** : NtvType or Namespace (default None) - default type to apply 660 to the NTV entity 661 - **encoded** : boolean (default False) - choice for return format 662 (string/bytes if True, dict/list/tuple else) 663 - **format** : string (default 'json')- choice for return format 664 (json, cbor, obj) 665 - **simpleval** : boolean (default False) - if True, only value (without 666 name and type) is included 667 - **name** : boolean (default true) - if False, name is not included 668 - **json_array** : boolean (default false) - if True, Json-object is not used for NtvList 669 - **fast** : boolean (default False) - if True, json is created without conversion 670 - **maxi**: Integer (default -1) - number of values to include for NtvList 671 entities. If maxi < 1 all the values are included. 672 ''' 673 option = {'encoded': False, 'format': 'json', 'fast': False, 'maxi': -1, 674 'simpleval': False, 'name': True, 'json_array': False} | kwargs 675 value = self.obj_value(def_type=def_type, **option) 676 obj_name = self.json_name(def_type) 677 if not option['name']: 678 obj_name[0] = '' 679 if option['simpleval']: 680 name = '' 681 elif option['format'] in ('cbor', 'obj') and not NtvConnector.is_json_class(value): 682 name = obj_name[0] 683 else: 684 name = obj_name[0] + obj_name[1] + obj_name[2] 685 json_obj = {name: value} if name else value 686 if option['encoded'] and option['format'] == 'json': 687 return json.dumps(json_obj, cls=NtvJsonEncoder) 688 if option['encoded'] and option['format'] == 'cbor': 689 return NtvConnector.connector()['CborConnec'].to_obj_ntv(json_obj) 690 return json_obj 691 692 @staticmethod 693 def obj_ntv(value, name='', typ='', single=False): 694 '''return a json-ntv representation without using Ntv structure. 695 696 *Parameters* 697 698 - **value** : ntv-value of the json-ntv 699 - **name** : string (default '') - ntv-name of the json-ntv 700 - **typ** : string (default '') - ntv_type of the json-ntv 701 - **single** : boolean (default False) - if True, value is a single object 702 else value is a set of objetcs. 703 ''' 704 value = {} if not value else value 705 name = '' if not name else name 706 typ = '' if not typ else typ 707 ntv_list = len(value) != 1 if isinstance( 708 value, dict) else isinstance(value, list) 709 if not single and not ntv_list: 710 raise NtvError('value is not compatible with not single NTV data') 711 sep = ':' if single else '::' 712 sep = '' if not typ and (not single or single and not ntv_list) else sep 713 name += sep + typ 714 return {name: value} if name else value 715 716 def to_json_ntv(self): 717 ''' create a copy where ntv-value of the self-tree nodes is converted 718 in json-value''' 719 ntv = copy.copy(self) 720 for leaf in ntv.tree.leaf_nodes: 721 if isinstance(leaf.ntv_value, (NtvSingle, NtvList)): 722 leaf.ntv_value = leaf.ntv_value.to_obj() 723 leaf.ntv_type = NtvType('ntv') 724 elif not leaf.is_json: 725 leaf.ntv_value, leaf.ntv_name, type_str = NtvConnector.cast( 726 leaf.ntv_value, leaf.ntv_name, leaf.type_str) 727 leaf.ntv_type = NtvType.add(type_str) 728 leaf.is_json = True 729 return ntv 730 731 def to_obj_ntv(self, **kwargs): 732 ''' create a copy where ntv-value of the self-tree nodes is converted 733 in object-value 734 735 *Parameters* 736 737 - **kwargs** : parameters used in NtvConnector class (specific for each Connector)''' 738 ntv = copy.copy(self) 739 for leaf in ntv.tree.leaf_nodes: 740 if (leaf.is_json and leaf.type_str in set(NtvConnector.dic_type.values()) 741 or leaf.ntv_type is None): 742 leaf.ntv_value, leaf.ntv_name, type_str = NtvConnector.uncast( 743 leaf, **kwargs) 744 leaf.ntv_type = NtvType.add(type_str) if type_str else None 745 leaf.is_json = NtvConnector.is_json(leaf.ntv_value) 746 return ntv 747 748 def to_tuple(self, maxi=10): 749 '''return a nested tuple representation of the NTV entity 750 (NtvList/NtvSingle, ntv_name, ntv_type, ntv_value). 751 752 *Parameters* 753 754 - **maxi**: Integer (default 10) - number of values to include for NtvList 755 entities. If maxi < 1 all the values are included. 756 ''' 757 clas = self.__class__.__name__ 758 val = self.ntv_value 759 name = self.ntv_name 760 typ = None 761 if self.ntv_type: 762 typ = self.ntv_type.long_name 763 if isinstance(self, NtvSingle) and not isinstance(val, NtvSingle): 764 return (clas, name, typ, val) 765 if isinstance(self, NtvSingle) and isinstance(val, NtvSingle): 766 return (clas, name, typ, val.to_tuple(maxi=maxi)) 767 if isinstance(self, NtvList): 768 maxv = len(self.ntv_value) if maxi < 1 else maxi 769 return (clas, name, typ, [ntv.to_tuple(maxi=maxi) for ntv in val[:maxv]]) 770 raise NtvError('the ntv entity is not consistent') 771 772 def remove(self, first=True, index=None): 773 '''remove self from its parent entity. 774 775 *parameters* 776 777 - **first** : boolean (default True) - if True only the first instance 778 else all 779 - **index** : integer (default None) - index of self in its parent 780 ''' 781 parent = self.parent 782 if not parent: 783 return 784 idx = parent.ntv_value.index(self) if index is None else index 785 if not parent[idx] == self: 786 raise NtvError('the entity is not present at the index') 787 del parent.ntv_value[idx] 788 if not first and index is None: 789 while self in parent: 790 idx = parent.ntv_value.index(self) 791 del parent.ntv_value[idx] 792 if not self in parent: 793 self.parent = None 794 return 795 796 def replace(self, ntv): 797 '''replace self by ntv in the tree''' 798 parent = self.parent 799 if parent: 800 idx = parent.ntv_value.index(self) 801 parent.insert(idx, ntv) 802 del parent[idx+1] 803 if not self in parent: 804 self.parent=None 805 else: 806 self = ntv 807 808 @property 809 def tree(self): 810 '''return a tree with included entities (NtvTree object)''' 811 return NtvTree(self) 812 813 @abstractmethod 814 def obj_value(self): 815 '''return the ntv_value with different formats defined by kwargs (abstract method)''' 816 817 @property 818 @abstractmethod 819 def json_array(self): 820 ''' return the json_array dynamic attribute (abstract method)''' 821 822 @abstractmethod 823 def _obj_sep(self, json_type, def_type): 824 ''' return separator to include in json_name (abstract method)''' 825 826 @staticmethod 827 def _from_value(value, decode_str=False): 828 '''return a decoded value 829 830 *Parameters* 831 832 - **decode_str**: boolean (default False) - if True, string are loaded as json data 833 ''' 834 if isinstance(value, bytes): 835 value = Ntv.from_obj({'$cbor': value}).ntv_value 836 elif decode_str and isinstance(value, str) and value.lstrip() and\ 837 value.lstrip()[0] in '"-{[0123456789tfn': 838 try: 839 value = json.loads(value) 840 except json.JSONDecodeError: 841 pass 842 return value 843 844 @staticmethod 845 def decode_json(json_value): 846 '''return (value, name, type, separator, isjson) of a json object''' 847 if isinstance(json_value, dict) and len(json_value) == 1: 848 json_name = list(json_value.keys())[0] 849 val = json_value[json_name] 850 return (val, *NtvUtil.from_obj_name(json_name), NtvConnector.is_json(val)) 851 return (json_value, None, None, None, NtvConnector.is_json(json_value)) 852 853 @staticmethod 854 def _create_ntvlist(str_typ, def_type, sep, ntv_value, typ_auto, no_typ, ntv_name, fast): 855 '''return a NtvList with parameters from Ntv.from_obj method''' 856 def_type = agreg_type(str_typ, def_type, False) 857 sep_val = ':' if sep and def_type else None 858 if isinstance(ntv_value, dict): 859 keys = list(ntv_value.keys()) 860 values = list(ntv_value.values()) 861 ntv_list = [Ntv.from_obj({key: val}, def_type, sep_val, fast=fast) 862 for key, val in zip(keys, values)] 863 else: 864 ntv_list = [Ntv.from_obj(val, def_type, sep_val, fast=fast) 865 for val in ntv_value] 866 if typ_auto and not def_type and ntv_list: 867 def_type = ntv_list[0].ntv_type 868 def_type = 'json' if no_typ else def_type 869 return NtvList(ntv_list, ntv_name, def_type, typ_auto, fast=fast) 870 871 @staticmethod 872 def _listed(idx): 873 '''transform a tuple of tuple object in a list of list object''' 874 return [val if not isinstance(val, tuple) else Ntv._listed(val) for val in idx] 875 876 877class NtvSingle(Ntv): 878 ''' A NTV-single entity is a Ntv entity not composed with other entities. 879 880 *Attributes :* 881 - no additional attributes to those of parent class `Ntv` 882 883 *dynamic values (@property)* 884 - `json_array` 885 886 The additional methods defined in this class are : 887 888 *instance methods* 889 - `obj_value` 890 ''' 891 892 def __init__(self, value, ntv_name=None, ntv_type=None, fast=False): 893 '''NtvSingle constructor. 894 895 *Parameters* 896 897 - **ntv_name** : String (default None) - name of the NTV entity 898 - **ntv_type**: String (default None) - type of the entity 899 - **value**: value of the entity 900 - **fast**: boolean (default False) - Ntv is created with a list of json values 901 without control 902 ''' 903 if not fast: 904 value, ntv_name, ntv_type = NtvSingle._decode_s( 905 value, ntv_name, ntv_type) 906 if ntv_type and isinstance(ntv_type, str) and ntv_type[-1] == '.': 907 raise NtvError('the ntv_type is not valid') 908 super().__init__(value, ntv_name, ntv_type) 909 910 def __eq__(self, other): 911 ''' equal if name type and value are equal''' 912 return self.__class__.__name__ == other.__class__.__name__ and\ 913 self.ntv_name == other.ntv_name and self.ntv_type == other.ntv_type and\ 914 self.ntv_value == other.ntv_value 915 916 def __hash__(self): 917 '''return hash(name) + hash(type) + hash(value)''' 918 return hash(self.ntv_name) + hash(self.ntv_type) + \ 919 hash(json.dumps(self.ntv_value, cls=NtvJsonEncoder)) 920 921 def __copy__(self): 922 ''' Copy all the Ntv tree ''' 923 return self.__class__(copy.copy(self.ntv_value), self.ntv_name, 924 self.ntv_type, fast=True) 925 926 @property 927 def json_array(self): 928 ''' return the json_array dynamic attribute (always False)''' 929 return False 930 931 def obj_value(self, def_type=None, **kwargs): 932 '''return the ntv_value with different formats defined by kwargs''' 933 option = {'encoded': False, 'format': 'json', 934 'simpleval': False, 'fast': False} | kwargs 935 if option['fast'] or option['format'] in ('json', 'tuple'): 936 return self.ntv_value 937 if option['format'] == 'obj' and self.ntv_value == 'null': 938 return None 939 return NtvConnector.uncast(self, **option)[0] 940 941 def _obj_sep(self, json_type, def_type=None): 942 ''' return separator to include in json_name''' 943 if json_type or not def_type and \ 944 (isinstance(self.ntv_value, list) or 945 isinstance(self.ntv_value, dict) and len(self.ntv_value) != 1): 946 return ':' 947 return '' 948 949 @staticmethod 950 def _decode_s(ntv_value, ntv_name, ntv_type): 951 '''return adjusted ntv_value, ntv_name, ntv_type''' 952 is_json = NtvConnector.is_json(ntv_value) 953 if is_json: 954 if isinstance(ntv_value, (list)): 955 ntv_value = [NtvSingle._decode_s(val, '', ntv_type)[ 956 0] for val in ntv_value] 957 elif isinstance(ntv_value, (dict)): 958 ntv_value = {key: NtvSingle._decode_s(val, '', ntv_type)[ 959 0] for key, val in ntv_value.items()} 960 elif isinstance(ntv_value, NtvSingle): 961 ntv_value = ntv_value.to_obj() 962 return (ntv_value, ntv_name, 'ntv') 963 else: 964 ntv_value, name, typ = NtvConnector.cast(ntv_value, ntv_name) 965 ntv_type = NtvType(typ) if typ else ntv_type 966 if not ntv_type: 967 if is_json: 968 ntv_type = 'json' 969 else: 970 ntv_type = typ 971 if not ntv_name: 972 ntv_name = name 973 elif not is_json and NtvType(ntv_type) != NtvType(typ): 974 raise NtvError('ntv_value is not compatible with ntv_type') 975 return (ntv_value, ntv_name, ntv_type) 976 977 978class NtvList(Ntv): 979 '''A NTV-list entity is a Ntv entity where: 980 981 - ntv_value is a list of NTV entities, 982 - ntv_type is a default type available for included NTV entities 983 984 *Attributes :* 985 - no additional attributes to those of parent class `Ntv` 986 987 *dynamic values (@property)* 988 - `json_array` 989 990 The additional methods defined in this class are : 991 992 *instance methods* 993 - `obj_value` 994 ''' 995 996 def __init__(self, list_ntv, ntv_name=None, ntv_type=None, typ_auto=False, fast=False): 997 '''NtvList constructor. 998 999 *Parameters* 1000 1001 - **ntv_name** : String (default None) - name of the NTV entity 1002 - **ntv_type**: String (default None) - default type or namespace of 1003 the included entities 1004 - **list_ntv**: list - list of Ntv objects or obj_value of Ntv objects 1005 - **fast**: boolean (default False) - if True, Ntv is created with a list 1006 of json values without control 1007 - **type_auto**: boolean (default False) - if True, default type for NtvList 1008 is the ntv_type of the first Ntv in the ntv_value''' 1009 if isinstance(list_ntv, NtvList): 1010 ntv_value = [copy.copy(ntv) for ntv in list_ntv.ntv_value] 1011 ntv_type = list_ntv.ntv_type 1012 ntv_name = list_ntv.ntv_name 1013 elif isinstance(list_ntv, list): 1014 ntv_value = [Ntv.from_obj(ntv, ntv_type, ':', fast=fast) 1015 for ntv in list_ntv] 1016 elif isinstance(list_ntv, dict): 1017 ntv_value = [Ntv.from_obj({key: val}, ntv_type, ':', fast=fast) 1018 for key, val in list_ntv.items()] 1019 else: 1020 raise NtvError('ntv_value is not a list') 1021 if typ_auto and not ntv_type and len(ntv_value) > 0 and ntv_value[0].ntv_type: 1022 ntv_type = ntv_value[0].ntv_type 1023 super().__init__(ntv_value, ntv_name, ntv_type) 1024 for ntv in self: 1025 ntv.parent = self 1026 1027 @property 1028 def json_array(self): 1029 ''' return the json_array dynamic attribute''' 1030 set_name = {ntv.ntv_name for ntv in self} 1031 return '' in set_name or len(set_name) != len(self) or len(set_name)==1 1032 1033 def __eq__(self, other): 1034 ''' equal if name and value are equal''' 1035 return self.__class__.__name__ == other.__class__.__name__ and\ 1036 self.ntv_name == other.ntv_name and self.ntv_value == other.ntv_value 1037 1038 def __hash__(self): 1039 '''return hash(name) + hash(value)''' 1040 return hash(self.ntv_name) + hash(tuple(self.ntv_value)) 1041 1042 def __copy__(self): 1043 ''' Copy all the data ''' 1044 cop = self.__class__(self) 1045 cop.parent = None 1046 return cop 1047 1048 def __setitem__(self, ind, value): 1049 ''' replace ntv_value item at the `ind` row with `value`''' 1050 if ind < 0 or ind >= len(self): 1051 raise NtvError("out of bounds") 1052 self.ntv_value[ind] = value 1053 if isinstance(value, (NtvSingle, NtvList)): 1054 value.parent = self 1055 1056 def __delitem__(self, ind): 1057 '''remove ntv_value item at the `ind` row''' 1058 if isinstance(ind, int): 1059 self.ntv_value.pop(ind) 1060 else: 1061 self.ntv_value.pop(self.ntv_value.index(self[ind])) 1062 1063 def append(self, ntv): 1064 ''' add ntv at the end of the list of Ntv entities included''' 1065 old_parent = ntv.parent 1066 if old_parent: 1067 del(old_parent[old_parent.ntv_value.index(ntv)]) 1068 self.ntv_value.append(ntv) 1069 ntv.parent = self 1070 1071 def insert(self, idx, ntv): 1072 ''' add ntv at the index idx of the list of Ntv entities included''' 1073 old_parent = ntv.parent 1074 if old_parent: 1075 del(old_parent[old_parent.ntv_value.index(ntv)]) 1076 self.ntv_value.insert(idx, ntv) 1077 ntv.parent = self 1078 1079 def _obj_sep(self, json_type, def_type=None): 1080 ''' return separator to include in json_name''' 1081 if json_type or (len(self.ntv_value) == 1 and not self.json_array): 1082 return '::' 1083 return '' 1084 1085 def obj_value(self, def_type=None, **kwargs): 1086 '''return the ntv_value with different formats defined by kwargs 1087 ''' 1088 option = {'encoded': False, 'format': 'json', 'simpleval': False, 1089 'json_array': False, 'fast': False, 'maxi': -1} | kwargs 1090 opt2 = option | {'encoded': False} 1091 maxv = len(self.ntv_value) if option['maxi'] < 1 else option['maxi'] 1092 def_type = self.ntv_type.long_name if self.ntv_type else def_type 1093 if self.json_array or option['simpleval'] or option['json_array']: 1094 return [ntv.to_obj(def_type=def_type, **opt2) for ntv in self.ntv_value[:maxv]] 1095 values = [ntv.to_obj(def_type=def_type, **opt2) 1096 for ntv in self.ntv_value[:maxv]] 1097 return {list(val.items())[0][0]: list(val.items())[0][1] for val in values}
28class Ntv(ABC): 29 ''' The Ntv class is an abstract class used by `NtvSingle`and `NtvList` classes. 30 31 *Attributes :* 32 - **ntv_name** : String - name of the NTV entity 33 - **ntv_type**: NtvType - type of the entity 34 - **ntv_value**: value of the entity 35 36 *Internal attributes :* 37 - **parent**: parent NtvList entity 38 - **is_json**: True if ntv_value is a json_value 39 40 *dynamic values (@property)* 41 - `json_array` (abstract method) 42 - `type_str` 43 - `code_ntv` 44 - `max_len` 45 - `name` 46 - `tree` 47 - `val` 48 49 The methods defined in this class are : 50 51 *Ntv constructor (staticmethod)* 52 - `fast` 53 - `obj` 54 - `from_obj` 55 - `from_att` 56 57 *NTV conversion (instance methods)* 58 - `alike` 59 - `to_json_ntv` 60 - `to_obj_ntv` 61 62 *export - conversion (instance methods)* 63 - `expand` 64 - `to_fast` 65 - `to_name` 66 - `to_obj` 67 - `to_repr` 68 - `to_mermaid` 69 - `to_tuple` 70 - `to_ntvsingle` 71 - `to_ntvlist` 72 - `notype` 73 74 *tree methods (instance methods)* 75 - `childs` 76 - `pointer` 77 - `replace` 78 - `remove` 79 - `append` (NtvList only) 80 - `insert` (NtvList only) 81 82 *other instance methods* 83 - `from_value` 84 - `json_name` 85 - `set_name` 86 - `set_type` 87 - `set_value` 88 - `obj_value` (abstract method) 89 90 *utility methods* 91 - `decode_json` *(staticmethod)* 92 - `obj_ntv` *(staticmethod)* 93 ''' 94 95 def __init__(self, ntv_value, ntv_name, ntv_type): 96 '''Ntv constructor. 97 98 *Parameters* 99 100 - **ntv_value**: Json entity - value of the entity 101 - **ntv_name** : String (default None) - name of the NTV entity 102 - **ntv_type**: String or NtvType or Namespace (default None) - type of the entity 103 ''' 104 if isinstance(ntv_type, (NtvType, Namespace)): 105 self.ntv_type = ntv_type 106 elif ntv_type and ntv_type[-1] != '.': 107 self.ntv_type = NtvType.add(ntv_type) 108 elif ntv_type and ntv_type[-1] == '.': 109 self.ntv_type = Namespace.add(ntv_type) 110 else: 111 self.ntv_type = None 112 if not isinstance(ntv_name, str): 113 ntv_name = '' 114 self.ntv_name = ntv_name 115 self.ntv_value = ntv_value 116 self.is_json = NtvConnector.is_json(ntv_value) 117 self.parent = None 118 119 @staticmethod 120 def fast(data, no_typ=False, typ_auto=False): 121 ''' return an Ntv entity from data without conversion. 122 123 *Parameters* : see `obj` method''' 124 return Ntv.obj(data, no_typ=no_typ, typ_auto=typ_auto, fast=True) 125 126 @staticmethod 127 def obj(data, no_typ=False, decode_str=False, typ_auto=False, fast=False): 128 ''' return an Ntv entity from data. 129 130 *Parameters* 131 132 - **Data** can be : 133 - a tuple with value, name, typ and cat (see `from_att` method) 134 - a value to decode (see `from_obj`method) 135 - **no_typ** : boolean (default False) - if True, NtvList is with 'json' type 136 - **type_auto**: boolean (default False) - if True, default type for NtvList 137 is the ntv_type of the first Ntv in the ntv_value 138 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 139 - **decode_str**: boolean (default False) - if True, string are loaded in json data''' 140 if isinstance(data, tuple): 141 return Ntv.from_att(*data, decode_str=decode_str, fast=fast) 142 # if isinstance(data, str) and data.lstrip() and data.lstrip()[0] in '{[': 143 if isinstance(data, str): 144 try: 145 data = json.loads(data) 146 except json.JSONDecodeError: 147 pass 148 return Ntv.from_obj(data, no_typ=no_typ, decode_str=decode_str, 149 typ_auto=typ_auto, fast=fast) 150 151 @staticmethod 152 def from_att(value, name, typ, cat, decode_str=False, fast=False): 153 ''' return an Ntv entity. 154 155 *Parameters* 156 157 - **value**: Ntv entity or value to convert in an Ntv entity 158 - **name** : string - name of the Ntv entity 159 - **typ** : string or NtvType - type of the NTV entity 160 - **cat**: string - NTV category ('single', 'list') 161 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 162 - **decode_str**: boolean (default False) - if True, string are loaded as json data''' 163 164 value = Ntv._from_value(value, decode_str) 165 if value.__class__.__name__ in ['NtvSingle', 'NtvList']: 166 return value 167 if isinstance(value, list) and cat == 'list': 168 return NtvList(value, name, typ, fast=fast) 169 if cat == 'single': 170 return NtvSingle(value, name, typ, fast=fast) 171 return Ntv.from_obj(value, def_type=typ, fast=fast) 172 173 @staticmethod 174 def from_obj(value, def_type=None, def_sep=None, no_typ=False, decode_str=False, 175 typ_auto=False, fast=False): 176 ''' return an Ntv entity from an object value. 177 178 *Parameters* 179 180 - **value**: Ntv value to convert in an Ntv entity 181 - **no_typ** : boolean (default None) - if True, NtvList is with 'json' type 182 - **def_type** : NtvType or Namespace (default None) - default type of the value 183 - **def_sep**: ':', '::' or None (default None) - default separator of the value 184 - **decode_str**: boolean (default False) - if True, string are loaded as json data 185 - **type_auto**: boolean (default False) - if True, default type for NtvList 186 is the ntv_type of the first Ntv in the ntv_value 187 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion''' 188 value = Ntv._from_value(value, decode_str) 189 if value.__class__.__name__ in ['NtvSingle', 'NtvList']: 190 return value 191 ntv_value, ntv_name, str_typ, sep, is_json = Ntv.decode_json(value) 192 sep = def_sep if not sep else sep 193 if isinstance(ntv_value, list) and sep in (None, '::'): 194 return Ntv._create_ntvlist(str_typ, def_type, sep, ntv_value, 195 typ_auto, no_typ, ntv_name, fast) 196 if sep == ':' or (sep is None and isinstance(ntv_value, dict) and 197 len(ntv_value) == 1): 198 ntv_type = agreg_type(str_typ, def_type, False) 199 return NtvSingle(ntv_value, ntv_name, ntv_type, fast=fast) 200 if sep is None and not isinstance(ntv_value, dict): 201 is_single_json = isinstance(value, (int, str, float, bool)) 202 ntv_type = agreg_type(str_typ, def_type, is_single_json) 203 return NtvSingle(ntv_value, ntv_name, ntv_type, fast=fast) 204 if isinstance(ntv_value, dict) and (sep == '::' or len(ntv_value) != 1 and 205 sep is None): 206 return Ntv._create_ntvlist(str_typ, def_type, sep, ntv_value, 207 typ_auto, no_typ, ntv_name, fast) 208 raise NtvError('separator ":" is not compatible with value') 209 210 def __len__(self): 211 ''' len of ntv_value''' 212 if isinstance(self.ntv_value, list): 213 return len(self.ntv_value) 214 return 1 215 216 def __str__(self): 217 '''return string format''' 218 return self.to_obj(encoded=True) 219 220 def __repr__(self): 221 '''return classname and code''' 222 #return json.dumps(self.to_repr(False, False, False, 10), cls=NtvJsonEncoder) 223 return self.reduce(obj=False, level=3, maxi=6).to_obj(encoded=True) 224 225 def __contains__(self, item): 226 ''' item of Ntv entities''' 227 if isinstance(self.val, list): 228 return item in self.ntv_value 229 return item == self.ntv_value 230 231 def __iter__(self): 232 ''' iterator for Ntv entities''' 233 if isinstance(self, NtvSingle): 234 return iter([self.val]) 235 return iter(self.val) 236 237 def __getitem__(self, selec): 238 ''' return ntv_value item with selec: 239 - String beginning with "/" : json-pointer, 240 - string : name of the ntv, 241 - list : recursive selector 242 - tuple : list of name or index ''' 243 if selec is None or selec == [] or selec == () or selec == '': 244 return self 245 if isinstance(selec, (list, tuple)) and len(selec) == 1: 246 selec = selec[0] 247 if isinstance(selec, str) and len(selec) > 1 and selec[0] == '/': 248 selec = list(NtvPointer(selec)) 249 elif isinstance(selec, NtvPointer): 250 selec = list(selec) 251 if (selec == 0 or selec == self.ntv_name) and isinstance(self, NtvSingle): 252 return self.ntv_value 253 if isinstance(self, NtvSingle): 254 raise NtvError('item not present') 255 if isinstance(selec, tuple): 256 return [self[i] for i in selec] 257 if isinstance(selec, str) and isinstance(self, NtvList): 258 ind = [ntv.ntv_name for ntv in self.ntv_value].index(selec) 259 return self.ntv_value[ind] 260 if isinstance(selec, list) and isinstance(self, NtvList): 261 return self[selec[0]][selec[1:]] 262 return self.ntv_value[selec] 263 264 def __lt__(self, other): 265 ''' return a comparison between two ntv_value''' 266 # order: number > string > None 267 res = Ntv.lower(self, other) 268 if res is None: 269 res = None if len(self) == len(other) else len(self) < len(other) 270 res = self.to_obj(encoded=True) < other.to_obj(encoded=True) if res is None else res 271 return res 272 273 @staticmethod 274 def lower(val1, val2): 275 ''' compare two ntv_value and return True if val1 < val2, False if val1 > val2 and 276 None in the other cases''' 277 res = None 278 for v1, v2 in zip(Ntv.obj(val1).tree.leaf_nodes, Ntv.obj(val2).tree.leaf_nodes): 279 if v1.val is None: 280 res = True 281 elif isinstance(v1.val, (dict, list)): 282 res = Ntv.lower(v1.val, v2) 283 elif isinstance(v2.val, (dict, list)): 284 res = Ntv.lower(v1, v2.val) 285 elif isinstance(v1.val, Number): 286 if isinstance(v2.val, Number): 287 res = None if v1.val == v2.val else v1.val < v2.val 288 else: 289 res = False 290 elif isinstance(v1.val, str): 291 if isinstance(v2.val, Number): 292 res = True 293 elif isinstance(v2.val, str): 294 res = None if v1.val == v2.val else v1.val < v2.val 295 else: 296 res = False 297 if not res is None: 298 break 299 return res 300 301 def childs(self, obj=False, nam=False, typ=False): 302 ''' return a list of child Ntv entities or child data 303 304 *parameters* 305 306 - **obj**: boolean (default False) - return json-value 307 - **nam**: boolean (default False) - return name (with or without type) 308 - **typ**: boolean (default False) - return type (with or without name) 309 ''' 310 if isinstance(self, NtvSingle): 311 return [] 312 if not (obj or nam or typ): 313 return self.val 314 if obj: 315 return [ntv.to_obj() for ntv in self.val] 316 return [(ntv.name if nam else '') + (' - ' if nam and typ else '') + 317 (ntv.type_str if typ else '') for ntv in self.val] 318 319 def pointer(self, index=False, item_idx=None): 320 '''return a nested list of pointer from root 321 322 *Parameters* 323 324 - **index**: Boolean (default False) - use index instead of name 325 - **item_idx**: Integer (default None) - index value for the pointer 326 (useful with duplicate data)''' 327 if not self.parent: 328 return NtvPointer([]) 329 idx = item_idx if item_idx else self.parent.ntv_value.index(self) 330 num = index or (self.ntv_name == "" and self.parent.json_array) 331 pointer = self.parent.pointer(index) 332 pointer.append(idx if num else self.ntv_name) 333 return pointer 334 335 @property 336 def code_ntv(self): 337 '''return a string with the NTV code composed with 1 to 3 letters: 338 - 'l' (NtvList), 's' (NtvSingle / json_value) or 'o' (NtvSingle / obj_value) 339 - 'N' if ntv_name is present else none 340 - 'T' if ntv_type is present else none''' 341 dic = {'NtvList': 'l', 'NtvSingle': 's'} 342 code = dic[self.__class__.__name__] 343 if isinstance(self, NtvSingle) and not self.is_json: 344 code = 'o' 345 if self.ntv_name: 346 code += 'N' 347 if self.ntv_type and self.ntv_type.long_name != 'json': 348 code += 'T' 349 return code 350 351 @property 352 def max_len(self): 353 '''return the highest len of Ntv entity included''' 354 maxi = len(self) 355 if isinstance(self.ntv_value, (list, set)): 356 maxi = max(maxi, max(ntv.max_len for ntv in self.ntv_value)) 357 return maxi 358 359 @property 360 def name(self): 361 '''return the ntv_name of the entity''' 362 return self.ntv_name 363 364 @property 365 def type_str(self): 366 '''return a string with the value of the NtvType of the entity''' 367 if not self.ntv_type: 368 return '' 369 return self.ntv_type.long_name 370 371 @property 372 def val(self): 373 '''return the ntv_value of the entity''' 374 return self.ntv_value 375 376 def alike(self, ntv_value): 377 ''' return a Ntv entity with same name and type. 378 379 *Parameters* 380 381 - **ntv_value**: list of ntv values''' 382 return self.__class__(ntv_value, self.ntv_name, self.ntv_type) 383 384 def from_value(self): 385 '''return a Ntv entity from ntv_value''' 386 if isinstance(self.ntv_value, list): 387 return NtvList(self.ntv_value) 388 return Ntv.from_obj(self.ntv_value) 389 390 def json_name(self, def_type=None, string=False, explicit=False): 391 '''return the JSON name of the NTV entity (json-ntv format) 392 393 *Parameters* 394 395 - **def_typ** : NtvType or Namespace (default None) - type of the parent entity 396 - **string** : boolean (default False) - If True, return a string else a tuple 397 - **explicit** : boolean (default False) - If True, type is always included''' 398 if def_type is None: 399 def_type = '' 400 elif isinstance(def_type, (NtvType, Namespace)): 401 def_type = def_type.long_name 402 json_name = self.ntv_name if self.ntv_name else '' 403 json_type = relative_type( 404 def_type, self.type_str) if self.ntv_type else '' 405 implicit = (json_type == 'json' and (not def_type or def_type == 'json') or 406 not NtvConnector.is_json_class(self.val)) 407 if implicit and not explicit: 408 json_type = '' 409 json_sep = self._obj_sep(json_type, def_type) 410 if string: 411 return json_name + json_sep + json_type 412 return [json_name, json_sep, json_type] 413 414 def to_ntvsingle(self, name=None, typ=None, def_type=None, **kwargs): 415 '''convert NtvList entity to NtvSingle entity 416 417 *Parameters* 418 419 - **ntv_name** : String (default None) - name of the NTV entity 420 - **ntv_type**: String (default None) - type of the entity 421 - **value**: value of the entity 422 - **fast**: boolean (default False) - Ntv is created with a list of json values 423 without control 424 ''' 425 return NtvSingle(self.obj_value(def_type=def_type, **kwargs), 426 self.name if self.name else name, 427 self.type_str if self.type_str else typ) 428 429 def to_ntvlist(self, def_type=None, def_sep=None, no_typ=False, decode_str=False, 430 typ_auto=False, fast=False): 431 '''convert NtvSingle entity to NtvList entity 432 433 *Parameters* 434 435 - **value**: Ntv value to convert in an Ntv entity 436 - **no_typ** : boolean (default None) - if True, NtvList is with 'json' type 437 - **def_type** : NtvType or Namespace (default None) - default type of the value 438 - **def_sep**: ':', '::' or None (default None) - default separator of the value 439 - **decode_str**: boolean (default False) - if True, string are loaded as json data 440 - **type_auto**: boolean (default False) - if True, default type for NtvList 441 is the ntv_type of the first Ntv in the ntv_value 442 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 443 ''' 444 ntv = Ntv.from_obj(self.ntv_value, def_type, def_sep, no_typ, decode_str, 445 typ_auto, fast) 446 if ntv.__class__.__name__ == 'NtvSingle': 447 return NtvList([self]) 448 if self.ntv_name: 449 ntv.set_name(self.ntv_name) 450 return ntv 451 452 def notype(self): 453 '''convert NTV entity in a NV entity (with ntv_type is 'json' or None')''' 454 no_type = copy.copy(self) 455 for ntv in NtvTree(no_type).leaf_nodes: 456 ntv.set_type('json') 457 for ntv in NtvTree(no_type).inner_nodes: 458 ntv.set_type() 459 return no_type 460 461 def reduce(self, obj=True, maxi=6, level=3): 462 '''reduce the length and the level of the entity 463 464 *Parameters* 465 466 - **obj**: boolean (default True) - If True return jsonNTV else NTV entity 467 - **maxi**: integer (default 6) - Number of returned entities in an NtvList 468 - **level**: integer (default 6) - returned entities in an NtvList at this level is None 469 470 *return* 471 472 - **NTV entity** or **jsonNTV** 473 ''' 474 ntv = copy.copy(self) 475 cont = Ntv.obj('...') if self.json_array else Ntv.obj({'...':''}) 476 if isinstance(self, NtvSingle): 477 return ntv 478 if level == 0: 479 ntv.ntv_value = [NtvSingle('...',ntv_type=ntv.type_str)] 480 if len(self) <= maxi: 481 ntv.ntv_value = [child.reduce(False, maxi, level-1) for child in ntv] 482 return ntv 483 mid = maxi // 2 484 cont.set_type(ntv.type_str) 485 start = [child.reduce(False, maxi, level-1) for child in ntv[:mid]] 486 #middle = [NtvSingle('...',ntv_type=ntv.type_str)] 487 middle = [cont] 488 end = [child.reduce(False, maxi, level-1) for child in ntv[-mid:]] 489 ntv.ntv_value = start + middle + end 490 if obj: 491 return ntv.to_obj() 492 return ntv 493 494 def set_name(self, name='', nodes='simple'): 495 '''set new names to the entity 496 497 *Parameters* 498 499 - **name**: list or string (default '') - New name values 500 - **nodes**: string (default 'simple') - nodes to be changed 501 'simple': current entity 502 'leaves': NtvSingle entities 503 'inner': NtvList entities 504 'all': all entities ''' 505 match nodes: 506 case 'simple': 507 self.ntv_name = str(name) 508 case 'leaves': 509 if not isinstance(name, list): 510 name = [str(name)] * NtvTree(self).breadth 511 for nam, ntv in zip(name, NtvTree(self).leaf_nodes): 512 ntv.ntv_name = nam 513 case 'inner': 514 if not isinstance(name, list): 515 name = [str(name)] * len(NtvTree(self).inner_nodes) 516 for nam, ntv in zip(name, NtvTree(self).inner_nodes): 517 ntv.ntv_name = nam 518 case 'all': 519 if not isinstance(name, list): 520 name = [str(name)] * NtvTree(self).size 521 for nam, ntv in zip(name, NtvTree(self).nodes): 522 ntv.ntv_name = nam 523 case _: 524 raise NtvError('the nodes option is not valid') 525 526 def set_type(self, typ=None): 527 '''set a new type to the entity 528 529 *Parameters* 530 531 - **typ**: string, NtvType, Namespace (default None)''' 532 if typ and not isinstance(typ, (str, NtvType, Namespace)): 533 raise NtvError('the type is not a valid type') 534 self.ntv_type = str_type(typ, self.__class__.__name__ == 'NtvSingle') 535 536 def set_value(self, value=None, fast=False): 537 '''set new ntv_value of a single entity or of a list of entities included 538 539 *Parameters* 540 541 - **value**: list or single value 542 - **fast** : boolean (default False) - if True, value is not converted''' 543 if isinstance(self, NtvSingle): 544 self.ntv_value = NtvSingle(value, ntv_type=self.ntv_type, 545 fast=fast).val 546 return 547 if not isinstance(value, list): 548 value = [value] * NtvTree(self).breadth 549 ntv_val = NtvList(value, fast=fast) 550 for val, ntv in zip(ntv_val, NtvTree(self).leaf_nodes): 551 ntv.ntv_value = val.val 552 return 553 554 def to_mermaid(self, title='', disp=False, row=False, leaves=False): 555 '''return a mermaid flowchart. 556 557 *Parameters* 558 559 - **title**: String (default '') - title of the flowchart 560 - **disp**: Boolean (default False) - if true, return a display else return 561 a mermaid text diagram 562 - **row**: Boolean (default False) - if True, add the node row 563 - **leaves**: Boolean (default False) - if True, add the leaf row 564 ''' 565 option = {'title': title, 'disp': disp, 'row': row, 'leaves': leaves} 566 if disp: 567 Ntv.obj({':$mermaid': self.to_obj()}).to_obj( 568 format='obj', **option) 569 return None 570 return Ntv.obj({':$mermaid': self.to_obj()}).to_obj(format='obj', **option) 571 572 def expand(self, full=True): 573 '''return a json representation of the triplet (name, type, value)''' 574 if isinstance(self, NtvList) and full: 575 return {'name': self.name, 'type': self.type_str, 576 'value': [ntv.expand(full) for ntv in self.val]} 577 if isinstance(self, NtvSingle) and full: 578 return {'name': self.name, 'type': self.type_str, 'value': self.val} 579 exp = {} if not self.name else {'name': self.name} 580 if not self.type_str in ['json', ''] : 581 exp['type'] = self.type_str 582 if isinstance(self, NtvList): 583 exp['value'] = [ntv.expand(full) for ntv in self.val] 584 else: 585 exp['value'] = self.val 586 return exp 587 588 def to_repr(self, nam=True, typ=True, val=True, jsn=False, maxi=10): 589 '''return a simple json representation of the Ntv entity. 590 591 *Parameters* 592 593 - **nam**: Boolean(default True) - if true, the names are included 594 - **typ**: Boolean(default True) - if true, the types are included 595 - **val**: Boolean(default True) - if true, the values are included 596 - **jsn**: Boolean(default False) - if false, the 'json' type is not included 597 - **maxi**: Integer (default 10) - number of values to include for NtvList 598 entities. If maxi < 1 all the values are included. 599 ''' 600 ntv = self.code_ntv 601 if nam and typ: 602 ntv = ntv[0] 603 if self.ntv_name and nam: 604 ntv += '-' + self.ntv_name 605 if self.ntv_type and typ and (jsn or self.ntv_type.long_name != 'json'): 606 ntv += '-' + self.ntv_type.long_name 607 clas = self.__class__.__name__ 608 clas_val = self.ntv_value.__class__.__name__ 609 if clas == 'NtvSingle' and clas_val != 'NtvSingle': 610 if val: 611 if ntv: 612 ntv += '-' 613 ntv += json.dumps(self.ntv_value, cls=NtvJsonEncoder) 614 return ntv 615 if clas == 'NtvSingle' and clas_val == 'NtvSingle': 616 return {ntv: self.ntv_value.to_repr(nam, typ, val, jsn, maxi)} 617 if clas == 'NtvList': 618 maxv = len(self.ntv_value) if maxi < 1 else maxi 619 return {ntv: [ntvi.to_repr(nam, typ, val, jsn, maxi) 620 for ntvi in self.ntv_value[:maxv]]} 621 raise NtvError('the ntv entity is not consistent') 622 623 def to_name(self, default=''): 624 '''return the name of the NTV entity 625 626 *Parameters* 627 628 - **default**: string (default ''): returned value if name is not present ''' 629 if self.ntv_name == '': 630 return default 631 return self.ntv_name 632 633 def to_fast(self, def_type=None, **kwargs): 634 '''return the JSON representation of the NTV entity (json-ntv format) 635 without value conversion. 636 637 *Parameters* 638 639 - **def_type** : NtvType or Namespace (default None) - default type to apply 640 to the NTV entity 641 - **encoded** : boolean (default False) - choice for return format 642 (string/bytes if True, dict/list/tuple else) 643 - **format** : string (default 'json')- choice for return format 644 (json, cbor, obj) 645 - **simpleval** : boolean (default False) - if True, only value (without 646 name and type) is included 647 - **name** : boolean (default true) - if False, name is not included 648 - **json_array** : boolean (default false) - if True, Json-object is not used for NtvList 649 - **maxi**: Integer (default -1) - number of values to include for NtvList 650 entities. If maxi < 1 all the values are included. 651 ''' 652 option = kwargs | {'fast': True} 653 return self.to_obj(def_type=def_type, **option) 654 655 def to_obj(self, def_type=None, **kwargs): 656 '''return the JSON representation of the NTV entity (json-ntv format). 657 658 *Parameters* 659 660 - **def_type** : NtvType or Namespace (default None) - default type to apply 661 to the NTV entity 662 - **encoded** : boolean (default False) - choice for return format 663 (string/bytes if True, dict/list/tuple else) 664 - **format** : string (default 'json')- choice for return format 665 (json, cbor, obj) 666 - **simpleval** : boolean (default False) - if True, only value (without 667 name and type) is included 668 - **name** : boolean (default true) - if False, name is not included 669 - **json_array** : boolean (default false) - if True, Json-object is not used for NtvList 670 - **fast** : boolean (default False) - if True, json is created without conversion 671 - **maxi**: Integer (default -1) - number of values to include for NtvList 672 entities. If maxi < 1 all the values are included. 673 ''' 674 option = {'encoded': False, 'format': 'json', 'fast': False, 'maxi': -1, 675 'simpleval': False, 'name': True, 'json_array': False} | kwargs 676 value = self.obj_value(def_type=def_type, **option) 677 obj_name = self.json_name(def_type) 678 if not option['name']: 679 obj_name[0] = '' 680 if option['simpleval']: 681 name = '' 682 elif option['format'] in ('cbor', 'obj') and not NtvConnector.is_json_class(value): 683 name = obj_name[0] 684 else: 685 name = obj_name[0] + obj_name[1] + obj_name[2] 686 json_obj = {name: value} if name else value 687 if option['encoded'] and option['format'] == 'json': 688 return json.dumps(json_obj, cls=NtvJsonEncoder) 689 if option['encoded'] and option['format'] == 'cbor': 690 return NtvConnector.connector()['CborConnec'].to_obj_ntv(json_obj) 691 return json_obj 692 693 @staticmethod 694 def obj_ntv(value, name='', typ='', single=False): 695 '''return a json-ntv representation without using Ntv structure. 696 697 *Parameters* 698 699 - **value** : ntv-value of the json-ntv 700 - **name** : string (default '') - ntv-name of the json-ntv 701 - **typ** : string (default '') - ntv_type of the json-ntv 702 - **single** : boolean (default False) - if True, value is a single object 703 else value is a set of objetcs. 704 ''' 705 value = {} if not value else value 706 name = '' if not name else name 707 typ = '' if not typ else typ 708 ntv_list = len(value) != 1 if isinstance( 709 value, dict) else isinstance(value, list) 710 if not single and not ntv_list: 711 raise NtvError('value is not compatible with not single NTV data') 712 sep = ':' if single else '::' 713 sep = '' if not typ and (not single or single and not ntv_list) else sep 714 name += sep + typ 715 return {name: value} if name else value 716 717 def to_json_ntv(self): 718 ''' create a copy where ntv-value of the self-tree nodes is converted 719 in json-value''' 720 ntv = copy.copy(self) 721 for leaf in ntv.tree.leaf_nodes: 722 if isinstance(leaf.ntv_value, (NtvSingle, NtvList)): 723 leaf.ntv_value = leaf.ntv_value.to_obj() 724 leaf.ntv_type = NtvType('ntv') 725 elif not leaf.is_json: 726 leaf.ntv_value, leaf.ntv_name, type_str = NtvConnector.cast( 727 leaf.ntv_value, leaf.ntv_name, leaf.type_str) 728 leaf.ntv_type = NtvType.add(type_str) 729 leaf.is_json = True 730 return ntv 731 732 def to_obj_ntv(self, **kwargs): 733 ''' create a copy where ntv-value of the self-tree nodes is converted 734 in object-value 735 736 *Parameters* 737 738 - **kwargs** : parameters used in NtvConnector class (specific for each Connector)''' 739 ntv = copy.copy(self) 740 for leaf in ntv.tree.leaf_nodes: 741 if (leaf.is_json and leaf.type_str in set(NtvConnector.dic_type.values()) 742 or leaf.ntv_type is None): 743 leaf.ntv_value, leaf.ntv_name, type_str = NtvConnector.uncast( 744 leaf, **kwargs) 745 leaf.ntv_type = NtvType.add(type_str) if type_str else None 746 leaf.is_json = NtvConnector.is_json(leaf.ntv_value) 747 return ntv 748 749 def to_tuple(self, maxi=10): 750 '''return a nested tuple representation of the NTV entity 751 (NtvList/NtvSingle, ntv_name, ntv_type, ntv_value). 752 753 *Parameters* 754 755 - **maxi**: Integer (default 10) - number of values to include for NtvList 756 entities. If maxi < 1 all the values are included. 757 ''' 758 clas = self.__class__.__name__ 759 val = self.ntv_value 760 name = self.ntv_name 761 typ = None 762 if self.ntv_type: 763 typ = self.ntv_type.long_name 764 if isinstance(self, NtvSingle) and not isinstance(val, NtvSingle): 765 return (clas, name, typ, val) 766 if isinstance(self, NtvSingle) and isinstance(val, NtvSingle): 767 return (clas, name, typ, val.to_tuple(maxi=maxi)) 768 if isinstance(self, NtvList): 769 maxv = len(self.ntv_value) if maxi < 1 else maxi 770 return (clas, name, typ, [ntv.to_tuple(maxi=maxi) for ntv in val[:maxv]]) 771 raise NtvError('the ntv entity is not consistent') 772 773 def remove(self, first=True, index=None): 774 '''remove self from its parent entity. 775 776 *parameters* 777 778 - **first** : boolean (default True) - if True only the first instance 779 else all 780 - **index** : integer (default None) - index of self in its parent 781 ''' 782 parent = self.parent 783 if not parent: 784 return 785 idx = parent.ntv_value.index(self) if index is None else index 786 if not parent[idx] == self: 787 raise NtvError('the entity is not present at the index') 788 del parent.ntv_value[idx] 789 if not first and index is None: 790 while self in parent: 791 idx = parent.ntv_value.index(self) 792 del parent.ntv_value[idx] 793 if not self in parent: 794 self.parent = None 795 return 796 797 def replace(self, ntv): 798 '''replace self by ntv in the tree''' 799 parent = self.parent 800 if parent: 801 idx = parent.ntv_value.index(self) 802 parent.insert(idx, ntv) 803 del parent[idx+1] 804 if not self in parent: 805 self.parent=None 806 else: 807 self = ntv 808 809 @property 810 def tree(self): 811 '''return a tree with included entities (NtvTree object)''' 812 return NtvTree(self) 813 814 @abstractmethod 815 def obj_value(self): 816 '''return the ntv_value with different formats defined by kwargs (abstract method)''' 817 818 @property 819 @abstractmethod 820 def json_array(self): 821 ''' return the json_array dynamic attribute (abstract method)''' 822 823 @abstractmethod 824 def _obj_sep(self, json_type, def_type): 825 ''' return separator to include in json_name (abstract method)''' 826 827 @staticmethod 828 def _from_value(value, decode_str=False): 829 '''return a decoded value 830 831 *Parameters* 832 833 - **decode_str**: boolean (default False) - if True, string are loaded as json data 834 ''' 835 if isinstance(value, bytes): 836 value = Ntv.from_obj({'$cbor': value}).ntv_value 837 elif decode_str and isinstance(value, str) and value.lstrip() and\ 838 value.lstrip()[0] in '"-{[0123456789tfn': 839 try: 840 value = json.loads(value) 841 except json.JSONDecodeError: 842 pass 843 return value 844 845 @staticmethod 846 def decode_json(json_value): 847 '''return (value, name, type, separator, isjson) of a json object''' 848 if isinstance(json_value, dict) and len(json_value) == 1: 849 json_name = list(json_value.keys())[0] 850 val = json_value[json_name] 851 return (val, *NtvUtil.from_obj_name(json_name), NtvConnector.is_json(val)) 852 return (json_value, None, None, None, NtvConnector.is_json(json_value)) 853 854 @staticmethod 855 def _create_ntvlist(str_typ, def_type, sep, ntv_value, typ_auto, no_typ, ntv_name, fast): 856 '''return a NtvList with parameters from Ntv.from_obj method''' 857 def_type = agreg_type(str_typ, def_type, False) 858 sep_val = ':' if sep and def_type else None 859 if isinstance(ntv_value, dict): 860 keys = list(ntv_value.keys()) 861 values = list(ntv_value.values()) 862 ntv_list = [Ntv.from_obj({key: val}, def_type, sep_val, fast=fast) 863 for key, val in zip(keys, values)] 864 else: 865 ntv_list = [Ntv.from_obj(val, def_type, sep_val, fast=fast) 866 for val in ntv_value] 867 if typ_auto and not def_type and ntv_list: 868 def_type = ntv_list[0].ntv_type 869 def_type = 'json' if no_typ else def_type 870 return NtvList(ntv_list, ntv_name, def_type, typ_auto, fast=fast) 871 872 @staticmethod 873 def _listed(idx): 874 '''transform a tuple of tuple object in a list of list object''' 875 return [val if not isinstance(val, tuple) else Ntv._listed(val) for val in idx]
The Ntv class is an abstract class used by NtvSingle
and NtvList
classes.
Attributes :
- ntv_name : String - name of the NTV entity
- ntv_type: NtvType - type of the entity
- ntv_value: value of the entity
Internal attributes :
- parent: parent NtvList entity
- is_json: True if ntv_value is a json_value
dynamic values (@property)
The methods defined in this class are :
Ntv constructor (staticmethod)
NTV conversion (instance methods)
export - conversion (instance methods)
tree methods (instance methods)
other instance methods
utility methods
decode_json
(staticmethod)obj_ntv
(staticmethod)
95 def __init__(self, ntv_value, ntv_name, ntv_type): 96 '''Ntv constructor. 97 98 *Parameters* 99 100 - **ntv_value**: Json entity - value of the entity 101 - **ntv_name** : String (default None) - name of the NTV entity 102 - **ntv_type**: String or NtvType or Namespace (default None) - type of the entity 103 ''' 104 if isinstance(ntv_type, (NtvType, Namespace)): 105 self.ntv_type = ntv_type 106 elif ntv_type and ntv_type[-1] != '.': 107 self.ntv_type = NtvType.add(ntv_type) 108 elif ntv_type and ntv_type[-1] == '.': 109 self.ntv_type = Namespace.add(ntv_type) 110 else: 111 self.ntv_type = None 112 if not isinstance(ntv_name, str): 113 ntv_name = '' 114 self.ntv_name = ntv_name 115 self.ntv_value = ntv_value 116 self.is_json = NtvConnector.is_json(ntv_value) 117 self.parent = None
Ntv constructor.
Parameters
- ntv_value: Json entity - value of the entity
- ntv_name : String (default None) - name of the NTV entity
- ntv_type: String or NtvType or Namespace (default None) - type of the entity
119 @staticmethod 120 def fast(data, no_typ=False, typ_auto=False): 121 ''' return an Ntv entity from data without conversion. 122 123 *Parameters* : see `obj` method''' 124 return Ntv.obj(data, no_typ=no_typ, typ_auto=typ_auto, fast=True)
return an Ntv entity from data without conversion.
Parameters : see obj
method
126 @staticmethod 127 def obj(data, no_typ=False, decode_str=False, typ_auto=False, fast=False): 128 ''' return an Ntv entity from data. 129 130 *Parameters* 131 132 - **Data** can be : 133 - a tuple with value, name, typ and cat (see `from_att` method) 134 - a value to decode (see `from_obj`method) 135 - **no_typ** : boolean (default False) - if True, NtvList is with 'json' type 136 - **type_auto**: boolean (default False) - if True, default type for NtvList 137 is the ntv_type of the first Ntv in the ntv_value 138 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 139 - **decode_str**: boolean (default False) - if True, string are loaded in json data''' 140 if isinstance(data, tuple): 141 return Ntv.from_att(*data, decode_str=decode_str, fast=fast) 142 # if isinstance(data, str) and data.lstrip() and data.lstrip()[0] in '{[': 143 if isinstance(data, str): 144 try: 145 data = json.loads(data) 146 except json.JSONDecodeError: 147 pass 148 return Ntv.from_obj(data, no_typ=no_typ, decode_str=decode_str, 149 typ_auto=typ_auto, fast=fast)
return an Ntv entity from data.
Parameters
- Data can be :
- no_typ : boolean (default False) - if True, NtvList is with 'json' type
- type_auto: boolean (default False) - if True, default type for NtvList is the ntv_type of the first Ntv in the ntv_value
- fast : boolean (default False) - if True, Ntv entity is created without conversion
- decode_str: boolean (default False) - if True, string are loaded in json data
151 @staticmethod 152 def from_att(value, name, typ, cat, decode_str=False, fast=False): 153 ''' return an Ntv entity. 154 155 *Parameters* 156 157 - **value**: Ntv entity or value to convert in an Ntv entity 158 - **name** : string - name of the Ntv entity 159 - **typ** : string or NtvType - type of the NTV entity 160 - **cat**: string - NTV category ('single', 'list') 161 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 162 - **decode_str**: boolean (default False) - if True, string are loaded as json data''' 163 164 value = Ntv._from_value(value, decode_str) 165 if value.__class__.__name__ in ['NtvSingle', 'NtvList']: 166 return value 167 if isinstance(value, list) and cat == 'list': 168 return NtvList(value, name, typ, fast=fast) 169 if cat == 'single': 170 return NtvSingle(value, name, typ, fast=fast) 171 return Ntv.from_obj(value, def_type=typ, fast=fast)
return an Ntv entity.
Parameters
- value: Ntv entity or value to convert in an Ntv entity
- name : string - name of the Ntv entity
- typ : string or NtvType - type of the NTV entity
- cat: string - NTV category ('single', 'list')
- fast : boolean (default False) - if True, Ntv entity is created without conversion
- decode_str: boolean (default False) - if True, string are loaded as json data
173 @staticmethod 174 def from_obj(value, def_type=None, def_sep=None, no_typ=False, decode_str=False, 175 typ_auto=False, fast=False): 176 ''' return an Ntv entity from an object value. 177 178 *Parameters* 179 180 - **value**: Ntv value to convert in an Ntv entity 181 - **no_typ** : boolean (default None) - if True, NtvList is with 'json' type 182 - **def_type** : NtvType or Namespace (default None) - default type of the value 183 - **def_sep**: ':', '::' or None (default None) - default separator of the value 184 - **decode_str**: boolean (default False) - if True, string are loaded as json data 185 - **type_auto**: boolean (default False) - if True, default type for NtvList 186 is the ntv_type of the first Ntv in the ntv_value 187 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion''' 188 value = Ntv._from_value(value, decode_str) 189 if value.__class__.__name__ in ['NtvSingle', 'NtvList']: 190 return value 191 ntv_value, ntv_name, str_typ, sep, is_json = Ntv.decode_json(value) 192 sep = def_sep if not sep else sep 193 if isinstance(ntv_value, list) and sep in (None, '::'): 194 return Ntv._create_ntvlist(str_typ, def_type, sep, ntv_value, 195 typ_auto, no_typ, ntv_name, fast) 196 if sep == ':' or (sep is None and isinstance(ntv_value, dict) and 197 len(ntv_value) == 1): 198 ntv_type = agreg_type(str_typ, def_type, False) 199 return NtvSingle(ntv_value, ntv_name, ntv_type, fast=fast) 200 if sep is None and not isinstance(ntv_value, dict): 201 is_single_json = isinstance(value, (int, str, float, bool)) 202 ntv_type = agreg_type(str_typ, def_type, is_single_json) 203 return NtvSingle(ntv_value, ntv_name, ntv_type, fast=fast) 204 if isinstance(ntv_value, dict) and (sep == '::' or len(ntv_value) != 1 and 205 sep is None): 206 return Ntv._create_ntvlist(str_typ, def_type, sep, ntv_value, 207 typ_auto, no_typ, ntv_name, fast) 208 raise NtvError('separator ":" is not compatible with value')
return an Ntv entity from an object value.
Parameters
- value: Ntv value to convert in an Ntv entity
- no_typ : boolean (default None) - if True, NtvList is with 'json' type
- def_type : NtvType or Namespace (default None) - default type of the value
- def_sep: ':', '::' or None (default None) - default separator of the value
- decode_str: boolean (default False) - if True, string are loaded as json data
- type_auto: boolean (default False) - if True, default type for NtvList is the ntv_type of the first Ntv in the ntv_value
- fast : boolean (default False) - if True, Ntv entity is created without conversion
273 @staticmethod 274 def lower(val1, val2): 275 ''' compare two ntv_value and return True if val1 < val2, False if val1 > val2 and 276 None in the other cases''' 277 res = None 278 for v1, v2 in zip(Ntv.obj(val1).tree.leaf_nodes, Ntv.obj(val2).tree.leaf_nodes): 279 if v1.val is None: 280 res = True 281 elif isinstance(v1.val, (dict, list)): 282 res = Ntv.lower(v1.val, v2) 283 elif isinstance(v2.val, (dict, list)): 284 res = Ntv.lower(v1, v2.val) 285 elif isinstance(v1.val, Number): 286 if isinstance(v2.val, Number): 287 res = None if v1.val == v2.val else v1.val < v2.val 288 else: 289 res = False 290 elif isinstance(v1.val, str): 291 if isinstance(v2.val, Number): 292 res = True 293 elif isinstance(v2.val, str): 294 res = None if v1.val == v2.val else v1.val < v2.val 295 else: 296 res = False 297 if not res is None: 298 break 299 return res
compare two ntv_value and return True if val1 < val2, False if val1 > val2 and None in the other cases
301 def childs(self, obj=False, nam=False, typ=False): 302 ''' return a list of child Ntv entities or child data 303 304 *parameters* 305 306 - **obj**: boolean (default False) - return json-value 307 - **nam**: boolean (default False) - return name (with or without type) 308 - **typ**: boolean (default False) - return type (with or without name) 309 ''' 310 if isinstance(self, NtvSingle): 311 return [] 312 if not (obj or nam or typ): 313 return self.val 314 if obj: 315 return [ntv.to_obj() for ntv in self.val] 316 return [(ntv.name if nam else '') + (' - ' if nam and typ else '') + 317 (ntv.type_str if typ else '') for ntv in self.val]
return a list of child Ntv entities or child data
parameters
- obj: boolean (default False) - return json-value
- nam: boolean (default False) - return name (with or without type)
- typ: boolean (default False) - return type (with or without name)
319 def pointer(self, index=False, item_idx=None): 320 '''return a nested list of pointer from root 321 322 *Parameters* 323 324 - **index**: Boolean (default False) - use index instead of name 325 - **item_idx**: Integer (default None) - index value for the pointer 326 (useful with duplicate data)''' 327 if not self.parent: 328 return NtvPointer([]) 329 idx = item_idx if item_idx else self.parent.ntv_value.index(self) 330 num = index or (self.ntv_name == "" and self.parent.json_array) 331 pointer = self.parent.pointer(index) 332 pointer.append(idx if num else self.ntv_name) 333 return pointer
return a nested list of pointer from root
Parameters
- index: Boolean (default False) - use index instead of name
- item_idx: Integer (default None) - index value for the pointer (useful with duplicate data)
return a string with the NTV code composed with 1 to 3 letters:
- 'l' (NtvList), 's' (NtvSingle / json_value) or 'o' (NtvSingle / obj_value)
- 'N' if ntv_name is present else none
- 'T' if ntv_type is present else none
376 def alike(self, ntv_value): 377 ''' return a Ntv entity with same name and type. 378 379 *Parameters* 380 381 - **ntv_value**: list of ntv values''' 382 return self.__class__(ntv_value, self.ntv_name, self.ntv_type)
return a Ntv entity with same name and type.
Parameters
- ntv_value: list of ntv values
384 def from_value(self): 385 '''return a Ntv entity from ntv_value''' 386 if isinstance(self.ntv_value, list): 387 return NtvList(self.ntv_value) 388 return Ntv.from_obj(self.ntv_value)
return a Ntv entity from ntv_value
390 def json_name(self, def_type=None, string=False, explicit=False): 391 '''return the JSON name of the NTV entity (json-ntv format) 392 393 *Parameters* 394 395 - **def_typ** : NtvType or Namespace (default None) - type of the parent entity 396 - **string** : boolean (default False) - If True, return a string else a tuple 397 - **explicit** : boolean (default False) - If True, type is always included''' 398 if def_type is None: 399 def_type = '' 400 elif isinstance(def_type, (NtvType, Namespace)): 401 def_type = def_type.long_name 402 json_name = self.ntv_name if self.ntv_name else '' 403 json_type = relative_type( 404 def_type, self.type_str) if self.ntv_type else '' 405 implicit = (json_type == 'json' and (not def_type or def_type == 'json') or 406 not NtvConnector.is_json_class(self.val)) 407 if implicit and not explicit: 408 json_type = '' 409 json_sep = self._obj_sep(json_type, def_type) 410 if string: 411 return json_name + json_sep + json_type 412 return [json_name, json_sep, json_type]
return the JSON name of the NTV entity (json-ntv format)
Parameters
- def_typ : NtvType or Namespace (default None) - type of the parent entity
- string : boolean (default False) - If True, return a string else a tuple
- explicit : boolean (default False) - If True, type is always included
414 def to_ntvsingle(self, name=None, typ=None, def_type=None, **kwargs): 415 '''convert NtvList entity to NtvSingle entity 416 417 *Parameters* 418 419 - **ntv_name** : String (default None) - name of the NTV entity 420 - **ntv_type**: String (default None) - type of the entity 421 - **value**: value of the entity 422 - **fast**: boolean (default False) - Ntv is created with a list of json values 423 without control 424 ''' 425 return NtvSingle(self.obj_value(def_type=def_type, **kwargs), 426 self.name if self.name else name, 427 self.type_str if self.type_str else typ)
convert NtvList entity to NtvSingle entity
Parameters
- ntv_name : String (default None) - name of the NTV entity
- ntv_type: String (default None) - type of the entity
- value: value of the entity
- fast: boolean (default False) - Ntv is created with a list of json values without control
429 def to_ntvlist(self, def_type=None, def_sep=None, no_typ=False, decode_str=False, 430 typ_auto=False, fast=False): 431 '''convert NtvSingle entity to NtvList entity 432 433 *Parameters* 434 435 - **value**: Ntv value to convert in an Ntv entity 436 - **no_typ** : boolean (default None) - if True, NtvList is with 'json' type 437 - **def_type** : NtvType or Namespace (default None) - default type of the value 438 - **def_sep**: ':', '::' or None (default None) - default separator of the value 439 - **decode_str**: boolean (default False) - if True, string are loaded as json data 440 - **type_auto**: boolean (default False) - if True, default type for NtvList 441 is the ntv_type of the first Ntv in the ntv_value 442 - **fast** : boolean (default False) - if True, Ntv entity is created without conversion 443 ''' 444 ntv = Ntv.from_obj(self.ntv_value, def_type, def_sep, no_typ, decode_str, 445 typ_auto, fast) 446 if ntv.__class__.__name__ == 'NtvSingle': 447 return NtvList([self]) 448 if self.ntv_name: 449 ntv.set_name(self.ntv_name) 450 return ntv
convert NtvSingle entity to NtvList entity
Parameters
- value: Ntv value to convert in an Ntv entity
- no_typ : boolean (default None) - if True, NtvList is with 'json' type
- def_type : NtvType or Namespace (default None) - default type of the value
- def_sep: ':', '::' or None (default None) - default separator of the value
- decode_str: boolean (default False) - if True, string are loaded as json data
- type_auto: boolean (default False) - if True, default type for NtvList is the ntv_type of the first Ntv in the ntv_value
- fast : boolean (default False) - if True, Ntv entity is created without conversion
452 def notype(self): 453 '''convert NTV entity in a NV entity (with ntv_type is 'json' or None')''' 454 no_type = copy.copy(self) 455 for ntv in NtvTree(no_type).leaf_nodes: 456 ntv.set_type('json') 457 for ntv in NtvTree(no_type).inner_nodes: 458 ntv.set_type() 459 return no_type
convert NTV entity in a NV entity (with ntv_type is 'json' or None')
461 def reduce(self, obj=True, maxi=6, level=3): 462 '''reduce the length and the level of the entity 463 464 *Parameters* 465 466 - **obj**: boolean (default True) - If True return jsonNTV else NTV entity 467 - **maxi**: integer (default 6) - Number of returned entities in an NtvList 468 - **level**: integer (default 6) - returned entities in an NtvList at this level is None 469 470 *return* 471 472 - **NTV entity** or **jsonNTV** 473 ''' 474 ntv = copy.copy(self) 475 cont = Ntv.obj('...') if self.json_array else Ntv.obj({'...':''}) 476 if isinstance(self, NtvSingle): 477 return ntv 478 if level == 0: 479 ntv.ntv_value = [NtvSingle('...',ntv_type=ntv.type_str)] 480 if len(self) <= maxi: 481 ntv.ntv_value = [child.reduce(False, maxi, level-1) for child in ntv] 482 return ntv 483 mid = maxi // 2 484 cont.set_type(ntv.type_str) 485 start = [child.reduce(False, maxi, level-1) for child in ntv[:mid]] 486 #middle = [NtvSingle('...',ntv_type=ntv.type_str)] 487 middle = [cont] 488 end = [child.reduce(False, maxi, level-1) for child in ntv[-mid:]] 489 ntv.ntv_value = start + middle + end 490 if obj: 491 return ntv.to_obj() 492 return ntv
reduce the length and the level of the entity
Parameters
- obj: boolean (default True) - If True return jsonNTV else NTV entity
- maxi: integer (default 6) - Number of returned entities in an NtvList
- level: integer (default 6) - returned entities in an NtvList at this level is None
return
- NTV entity or jsonNTV
494 def set_name(self, name='', nodes='simple'): 495 '''set new names to the entity 496 497 *Parameters* 498 499 - **name**: list or string (default '') - New name values 500 - **nodes**: string (default 'simple') - nodes to be changed 501 'simple': current entity 502 'leaves': NtvSingle entities 503 'inner': NtvList entities 504 'all': all entities ''' 505 match nodes: 506 case 'simple': 507 self.ntv_name = str(name) 508 case 'leaves': 509 if not isinstance(name, list): 510 name = [str(name)] * NtvTree(self).breadth 511 for nam, ntv in zip(name, NtvTree(self).leaf_nodes): 512 ntv.ntv_name = nam 513 case 'inner': 514 if not isinstance(name, list): 515 name = [str(name)] * len(NtvTree(self).inner_nodes) 516 for nam, ntv in zip(name, NtvTree(self).inner_nodes): 517 ntv.ntv_name = nam 518 case 'all': 519 if not isinstance(name, list): 520 name = [str(name)] * NtvTree(self).size 521 for nam, ntv in zip(name, NtvTree(self).nodes): 522 ntv.ntv_name = nam 523 case _: 524 raise NtvError('the nodes option is not valid')
set new names to the entity
Parameters
- name: list or string (default '') - New name values
- nodes: string (default 'simple') - nodes to be changed 'simple': current entity 'leaves': NtvSingle entities 'inner': NtvList entities 'all': all entities
526 def set_type(self, typ=None): 527 '''set a new type to the entity 528 529 *Parameters* 530 531 - **typ**: string, NtvType, Namespace (default None)''' 532 if typ and not isinstance(typ, (str, NtvType, Namespace)): 533 raise NtvError('the type is not a valid type') 534 self.ntv_type = str_type(typ, self.__class__.__name__ == 'NtvSingle')
set a new type to the entity
Parameters
- typ: string, NtvType, Namespace (default None)
536 def set_value(self, value=None, fast=False): 537 '''set new ntv_value of a single entity or of a list of entities included 538 539 *Parameters* 540 541 - **value**: list or single value 542 - **fast** : boolean (default False) - if True, value is not converted''' 543 if isinstance(self, NtvSingle): 544 self.ntv_value = NtvSingle(value, ntv_type=self.ntv_type, 545 fast=fast).val 546 return 547 if not isinstance(value, list): 548 value = [value] * NtvTree(self).breadth 549 ntv_val = NtvList(value, fast=fast) 550 for val, ntv in zip(ntv_val, NtvTree(self).leaf_nodes): 551 ntv.ntv_value = val.val 552 return
set new ntv_value of a single entity or of a list of entities included
Parameters
- value: list or single value
- fast : boolean (default False) - if True, value is not converted
554 def to_mermaid(self, title='', disp=False, row=False, leaves=False): 555 '''return a mermaid flowchart. 556 557 *Parameters* 558 559 - **title**: String (default '') - title of the flowchart 560 - **disp**: Boolean (default False) - if true, return a display else return 561 a mermaid text diagram 562 - **row**: Boolean (default False) - if True, add the node row 563 - **leaves**: Boolean (default False) - if True, add the leaf row 564 ''' 565 option = {'title': title, 'disp': disp, 'row': row, 'leaves': leaves} 566 if disp: 567 Ntv.obj({':$mermaid': self.to_obj()}).to_obj( 568 format='obj', **option) 569 return None 570 return Ntv.obj({':$mermaid': self.to_obj()}).to_obj(format='obj', **option)
return a mermaid flowchart.
Parameters
- title: String (default '') - title of the flowchart
- disp: Boolean (default False) - if true, return a display else return a mermaid text diagram
- row: Boolean (default False) - if True, add the node row
- leaves: Boolean (default False) - if True, add the leaf row
572 def expand(self, full=True): 573 '''return a json representation of the triplet (name, type, value)''' 574 if isinstance(self, NtvList) and full: 575 return {'name': self.name, 'type': self.type_str, 576 'value': [ntv.expand(full) for ntv in self.val]} 577 if isinstance(self, NtvSingle) and full: 578 return {'name': self.name, 'type': self.type_str, 'value': self.val} 579 exp = {} if not self.name else {'name': self.name} 580 if not self.type_str in ['json', ''] : 581 exp['type'] = self.type_str 582 if isinstance(self, NtvList): 583 exp['value'] = [ntv.expand(full) for ntv in self.val] 584 else: 585 exp['value'] = self.val 586 return exp
return a json representation of the triplet (name, type, value)
588 def to_repr(self, nam=True, typ=True, val=True, jsn=False, maxi=10): 589 '''return a simple json representation of the Ntv entity. 590 591 *Parameters* 592 593 - **nam**: Boolean(default True) - if true, the names are included 594 - **typ**: Boolean(default True) - if true, the types are included 595 - **val**: Boolean(default True) - if true, the values are included 596 - **jsn**: Boolean(default False) - if false, the 'json' type is not included 597 - **maxi**: Integer (default 10) - number of values to include for NtvList 598 entities. If maxi < 1 all the values are included. 599 ''' 600 ntv = self.code_ntv 601 if nam and typ: 602 ntv = ntv[0] 603 if self.ntv_name and nam: 604 ntv += '-' + self.ntv_name 605 if self.ntv_type and typ and (jsn or self.ntv_type.long_name != 'json'): 606 ntv += '-' + self.ntv_type.long_name 607 clas = self.__class__.__name__ 608 clas_val = self.ntv_value.__class__.__name__ 609 if clas == 'NtvSingle' and clas_val != 'NtvSingle': 610 if val: 611 if ntv: 612 ntv += '-' 613 ntv += json.dumps(self.ntv_value, cls=NtvJsonEncoder) 614 return ntv 615 if clas == 'NtvSingle' and clas_val == 'NtvSingle': 616 return {ntv: self.ntv_value.to_repr(nam, typ, val, jsn, maxi)} 617 if clas == 'NtvList': 618 maxv = len(self.ntv_value) if maxi < 1 else maxi 619 return {ntv: [ntvi.to_repr(nam, typ, val, jsn, maxi) 620 for ntvi in self.ntv_value[:maxv]]} 621 raise NtvError('the ntv entity is not consistent')
return a simple json representation of the Ntv entity.
Parameters
- nam: Boolean(default True) - if true, the names are included
- typ: Boolean(default True) - if true, the types are included
- val: Boolean(default True) - if true, the values are included
- jsn: Boolean(default False) - if false, the 'json' type is not included
- maxi: Integer (default 10) - number of values to include for NtvList entities. If maxi < 1 all the values are included.
623 def to_name(self, default=''): 624 '''return the name of the NTV entity 625 626 *Parameters* 627 628 - **default**: string (default ''): returned value if name is not present ''' 629 if self.ntv_name == '': 630 return default 631 return self.ntv_name
return the name of the NTV entity
Parameters
- default: string (default ''): returned value if name is not present
633 def to_fast(self, def_type=None, **kwargs): 634 '''return the JSON representation of the NTV entity (json-ntv format) 635 without value conversion. 636 637 *Parameters* 638 639 - **def_type** : NtvType or Namespace (default None) - default type to apply 640 to the NTV entity 641 - **encoded** : boolean (default False) - choice for return format 642 (string/bytes if True, dict/list/tuple else) 643 - **format** : string (default 'json')- choice for return format 644 (json, cbor, obj) 645 - **simpleval** : boolean (default False) - if True, only value (without 646 name and type) is included 647 - **name** : boolean (default true) - if False, name is not included 648 - **json_array** : boolean (default false) - if True, Json-object is not used for NtvList 649 - **maxi**: Integer (default -1) - number of values to include for NtvList 650 entities. If maxi < 1 all the values are included. 651 ''' 652 option = kwargs | {'fast': True} 653 return self.to_obj(def_type=def_type, **option)
return the JSON representation of the NTV entity (json-ntv format) without value conversion.
Parameters
- def_type : NtvType or Namespace (default None) - default type to apply to the NTV entity
- encoded : boolean (default False) - choice for return format (string/bytes if True, dict/list/tuple else)
- format : string (default 'json')- choice for return format (json, cbor, obj)
- simpleval : boolean (default False) - if True, only value (without name and type) is included
- name : boolean (default true) - if False, name is not included
- json_array : boolean (default false) - if True, Json-object is not used for NtvList
- maxi: Integer (default -1) - number of values to include for NtvList entities. If maxi < 1 all the values are included.
655 def to_obj(self, def_type=None, **kwargs): 656 '''return the JSON representation of the NTV entity (json-ntv format). 657 658 *Parameters* 659 660 - **def_type** : NtvType or Namespace (default None) - default type to apply 661 to the NTV entity 662 - **encoded** : boolean (default False) - choice for return format 663 (string/bytes if True, dict/list/tuple else) 664 - **format** : string (default 'json')- choice for return format 665 (json, cbor, obj) 666 - **simpleval** : boolean (default False) - if True, only value (without 667 name and type) is included 668 - **name** : boolean (default true) - if False, name is not included 669 - **json_array** : boolean (default false) - if True, Json-object is not used for NtvList 670 - **fast** : boolean (default False) - if True, json is created without conversion 671 - **maxi**: Integer (default -1) - number of values to include for NtvList 672 entities. If maxi < 1 all the values are included. 673 ''' 674 option = {'encoded': False, 'format': 'json', 'fast': False, 'maxi': -1, 675 'simpleval': False, 'name': True, 'json_array': False} | kwargs 676 value = self.obj_value(def_type=def_type, **option) 677 obj_name = self.json_name(def_type) 678 if not option['name']: 679 obj_name[0] = '' 680 if option['simpleval']: 681 name = '' 682 elif option['format'] in ('cbor', 'obj') and not NtvConnector.is_json_class(value): 683 name = obj_name[0] 684 else: 685 name = obj_name[0] + obj_name[1] + obj_name[2] 686 json_obj = {name: value} if name else value 687 if option['encoded'] and option['format'] == 'json': 688 return json.dumps(json_obj, cls=NtvJsonEncoder) 689 if option['encoded'] and option['format'] == 'cbor': 690 return NtvConnector.connector()['CborConnec'].to_obj_ntv(json_obj) 691 return json_obj
return the JSON representation of the NTV entity (json-ntv format).
Parameters
- def_type : NtvType or Namespace (default None) - default type to apply to the NTV entity
- encoded : boolean (default False) - choice for return format (string/bytes if True, dict/list/tuple else)
- format : string (default 'json')- choice for return format (json, cbor, obj)
- simpleval : boolean (default False) - if True, only value (without name and type) is included
- name : boolean (default true) - if False, name is not included
- json_array : boolean (default false) - if True, Json-object is not used for NtvList
- fast : boolean (default False) - if True, json is created without conversion
- maxi: Integer (default -1) - number of values to include for NtvList entities. If maxi < 1 all the values are included.
693 @staticmethod 694 def obj_ntv(value, name='', typ='', single=False): 695 '''return a json-ntv representation without using Ntv structure. 696 697 *Parameters* 698 699 - **value** : ntv-value of the json-ntv 700 - **name** : string (default '') - ntv-name of the json-ntv 701 - **typ** : string (default '') - ntv_type of the json-ntv 702 - **single** : boolean (default False) - if True, value is a single object 703 else value is a set of objetcs. 704 ''' 705 value = {} if not value else value 706 name = '' if not name else name 707 typ = '' if not typ else typ 708 ntv_list = len(value) != 1 if isinstance( 709 value, dict) else isinstance(value, list) 710 if not single and not ntv_list: 711 raise NtvError('value is not compatible with not single NTV data') 712 sep = ':' if single else '::' 713 sep = '' if not typ and (not single or single and not ntv_list) else sep 714 name += sep + typ 715 return {name: value} if name else value
return a json-ntv representation without using Ntv structure.
Parameters
- value : ntv-value of the json-ntv
- name : string (default '') - ntv-name of the json-ntv
- typ : string (default '') - ntv_type of the json-ntv
- single : boolean (default False) - if True, value is a single object else value is a set of objetcs.
717 def to_json_ntv(self): 718 ''' create a copy where ntv-value of the self-tree nodes is converted 719 in json-value''' 720 ntv = copy.copy(self) 721 for leaf in ntv.tree.leaf_nodes: 722 if isinstance(leaf.ntv_value, (NtvSingle, NtvList)): 723 leaf.ntv_value = leaf.ntv_value.to_obj() 724 leaf.ntv_type = NtvType('ntv') 725 elif not leaf.is_json: 726 leaf.ntv_value, leaf.ntv_name, type_str = NtvConnector.cast( 727 leaf.ntv_value, leaf.ntv_name, leaf.type_str) 728 leaf.ntv_type = NtvType.add(type_str) 729 leaf.is_json = True 730 return ntv
create a copy where ntv-value of the self-tree nodes is converted in json-value
732 def to_obj_ntv(self, **kwargs): 733 ''' create a copy where ntv-value of the self-tree nodes is converted 734 in object-value 735 736 *Parameters* 737 738 - **kwargs** : parameters used in NtvConnector class (specific for each Connector)''' 739 ntv = copy.copy(self) 740 for leaf in ntv.tree.leaf_nodes: 741 if (leaf.is_json and leaf.type_str in set(NtvConnector.dic_type.values()) 742 or leaf.ntv_type is None): 743 leaf.ntv_value, leaf.ntv_name, type_str = NtvConnector.uncast( 744 leaf, **kwargs) 745 leaf.ntv_type = NtvType.add(type_str) if type_str else None 746 leaf.is_json = NtvConnector.is_json(leaf.ntv_value) 747 return ntv
create a copy where ntv-value of the self-tree nodes is converted in object-value
Parameters
- kwargs : parameters used in NtvConnector class (specific for each Connector)
749 def to_tuple(self, maxi=10): 750 '''return a nested tuple representation of the NTV entity 751 (NtvList/NtvSingle, ntv_name, ntv_type, ntv_value). 752 753 *Parameters* 754 755 - **maxi**: Integer (default 10) - number of values to include for NtvList 756 entities. If maxi < 1 all the values are included. 757 ''' 758 clas = self.__class__.__name__ 759 val = self.ntv_value 760 name = self.ntv_name 761 typ = None 762 if self.ntv_type: 763 typ = self.ntv_type.long_name 764 if isinstance(self, NtvSingle) and not isinstance(val, NtvSingle): 765 return (clas, name, typ, val) 766 if isinstance(self, NtvSingle) and isinstance(val, NtvSingle): 767 return (clas, name, typ, val.to_tuple(maxi=maxi)) 768 if isinstance(self, NtvList): 769 maxv = len(self.ntv_value) if maxi < 1 else maxi 770 return (clas, name, typ, [ntv.to_tuple(maxi=maxi) for ntv in val[:maxv]]) 771 raise NtvError('the ntv entity is not consistent')
return a nested tuple representation of the NTV entity (NtvList/NtvSingle, ntv_name, ntv_type, ntv_value).
Parameters
- maxi: Integer (default 10) - number of values to include for NtvList entities. If maxi < 1 all the values are included.
773 def remove(self, first=True, index=None): 774 '''remove self from its parent entity. 775 776 *parameters* 777 778 - **first** : boolean (default True) - if True only the first instance 779 else all 780 - **index** : integer (default None) - index of self in its parent 781 ''' 782 parent = self.parent 783 if not parent: 784 return 785 idx = parent.ntv_value.index(self) if index is None else index 786 if not parent[idx] == self: 787 raise NtvError('the entity is not present at the index') 788 del parent.ntv_value[idx] 789 if not first and index is None: 790 while self in parent: 791 idx = parent.ntv_value.index(self) 792 del parent.ntv_value[idx] 793 if not self in parent: 794 self.parent = None 795 return
remove self from its parent entity.
parameters
- first : boolean (default True) - if True only the first instance else all
- index : integer (default None) - index of self in its parent
797 def replace(self, ntv): 798 '''replace self by ntv in the tree''' 799 parent = self.parent 800 if parent: 801 idx = parent.ntv_value.index(self) 802 parent.insert(idx, ntv) 803 del parent[idx+1] 804 if not self in parent: 805 self.parent=None 806 else: 807 self = ntv
replace self by ntv in the tree
814 @abstractmethod 815 def obj_value(self): 816 '''return the ntv_value with different formats defined by kwargs (abstract method)'''
return the ntv_value with different formats defined by kwargs (abstract method)
845 @staticmethod 846 def decode_json(json_value): 847 '''return (value, name, type, separator, isjson) of a json object''' 848 if isinstance(json_value, dict) and len(json_value) == 1: 849 json_name = list(json_value.keys())[0] 850 val = json_value[json_name] 851 return (val, *NtvUtil.from_obj_name(json_name), NtvConnector.is_json(val)) 852 return (json_value, None, None, None, NtvConnector.is_json(json_value))
return (value, name, type, separator, isjson) of a json object
878class NtvSingle(Ntv): 879 ''' A NTV-single entity is a Ntv entity not composed with other entities. 880 881 *Attributes :* 882 - no additional attributes to those of parent class `Ntv` 883 884 *dynamic values (@property)* 885 - `json_array` 886 887 The additional methods defined in this class are : 888 889 *instance methods* 890 - `obj_value` 891 ''' 892 893 def __init__(self, value, ntv_name=None, ntv_type=None, fast=False): 894 '''NtvSingle constructor. 895 896 *Parameters* 897 898 - **ntv_name** : String (default None) - name of the NTV entity 899 - **ntv_type**: String (default None) - type of the entity 900 - **value**: value of the entity 901 - **fast**: boolean (default False) - Ntv is created with a list of json values 902 without control 903 ''' 904 if not fast: 905 value, ntv_name, ntv_type = NtvSingle._decode_s( 906 value, ntv_name, ntv_type) 907 if ntv_type and isinstance(ntv_type, str) and ntv_type[-1] == '.': 908 raise NtvError('the ntv_type is not valid') 909 super().__init__(value, ntv_name, ntv_type) 910 911 def __eq__(self, other): 912 ''' equal if name type and value are equal''' 913 return self.__class__.__name__ == other.__class__.__name__ and\ 914 self.ntv_name == other.ntv_name and self.ntv_type == other.ntv_type and\ 915 self.ntv_value == other.ntv_value 916 917 def __hash__(self): 918 '''return hash(name) + hash(type) + hash(value)''' 919 return hash(self.ntv_name) + hash(self.ntv_type) + \ 920 hash(json.dumps(self.ntv_value, cls=NtvJsonEncoder)) 921 922 def __copy__(self): 923 ''' Copy all the Ntv tree ''' 924 return self.__class__(copy.copy(self.ntv_value), self.ntv_name, 925 self.ntv_type, fast=True) 926 927 @property 928 def json_array(self): 929 ''' return the json_array dynamic attribute (always False)''' 930 return False 931 932 def obj_value(self, def_type=None, **kwargs): 933 '''return the ntv_value with different formats defined by kwargs''' 934 option = {'encoded': False, 'format': 'json', 935 'simpleval': False, 'fast': False} | kwargs 936 if option['fast'] or option['format'] in ('json', 'tuple'): 937 return self.ntv_value 938 if option['format'] == 'obj' and self.ntv_value == 'null': 939 return None 940 return NtvConnector.uncast(self, **option)[0] 941 942 def _obj_sep(self, json_type, def_type=None): 943 ''' return separator to include in json_name''' 944 if json_type or not def_type and \ 945 (isinstance(self.ntv_value, list) or 946 isinstance(self.ntv_value, dict) and len(self.ntv_value) != 1): 947 return ':' 948 return '' 949 950 @staticmethod 951 def _decode_s(ntv_value, ntv_name, ntv_type): 952 '''return adjusted ntv_value, ntv_name, ntv_type''' 953 is_json = NtvConnector.is_json(ntv_value) 954 if is_json: 955 if isinstance(ntv_value, (list)): 956 ntv_value = [NtvSingle._decode_s(val, '', ntv_type)[ 957 0] for val in ntv_value] 958 elif isinstance(ntv_value, (dict)): 959 ntv_value = {key: NtvSingle._decode_s(val, '', ntv_type)[ 960 0] for key, val in ntv_value.items()} 961 elif isinstance(ntv_value, NtvSingle): 962 ntv_value = ntv_value.to_obj() 963 return (ntv_value, ntv_name, 'ntv') 964 else: 965 ntv_value, name, typ = NtvConnector.cast(ntv_value, ntv_name) 966 ntv_type = NtvType(typ) if typ else ntv_type 967 if not ntv_type: 968 if is_json: 969 ntv_type = 'json' 970 else: 971 ntv_type = typ 972 if not ntv_name: 973 ntv_name = name 974 elif not is_json and NtvType(ntv_type) != NtvType(typ): 975 raise NtvError('ntv_value is not compatible with ntv_type') 976 return (ntv_value, ntv_name, ntv_type)
A NTV-single entity is a Ntv entity not composed with other entities.
Attributes :
- no additional attributes to those of parent class
Ntv
dynamic values (@property)
The additional methods defined in this class are :
instance methods
893 def __init__(self, value, ntv_name=None, ntv_type=None, fast=False): 894 '''NtvSingle constructor. 895 896 *Parameters* 897 898 - **ntv_name** : String (default None) - name of the NTV entity 899 - **ntv_type**: String (default None) - type of the entity 900 - **value**: value of the entity 901 - **fast**: boolean (default False) - Ntv is created with a list of json values 902 without control 903 ''' 904 if not fast: 905 value, ntv_name, ntv_type = NtvSingle._decode_s( 906 value, ntv_name, ntv_type) 907 if ntv_type and isinstance(ntv_type, str) and ntv_type[-1] == '.': 908 raise NtvError('the ntv_type is not valid') 909 super().__init__(value, ntv_name, ntv_type)
NtvSingle constructor.
Parameters
- ntv_name : String (default None) - name of the NTV entity
- ntv_type: String (default None) - type of the entity
- value: value of the entity
- fast: boolean (default False) - Ntv is created with a list of json values without control
932 def obj_value(self, def_type=None, **kwargs): 933 '''return the ntv_value with different formats defined by kwargs''' 934 option = {'encoded': False, 'format': 'json', 935 'simpleval': False, 'fast': False} | kwargs 936 if option['fast'] or option['format'] in ('json', 'tuple'): 937 return self.ntv_value 938 if option['format'] == 'obj' and self.ntv_value == 'null': 939 return None 940 return NtvConnector.uncast(self, **option)[0]
return the ntv_value with different formats defined by kwargs
Inherited Members
- Ntv
- fast
- obj
- from_att
- from_obj
- lower
- childs
- pointer
- code_ntv
- max_len
- name
- type_str
- val
- alike
- from_value
- json_name
- to_ntvsingle
- to_ntvlist
- notype
- reduce
- set_name
- set_type
- set_value
- to_mermaid
- expand
- to_repr
- to_name
- to_fast
- to_obj
- obj_ntv
- to_json_ntv
- to_obj_ntv
- to_tuple
- remove
- replace
- tree
- decode_json
979class NtvList(Ntv): 980 '''A NTV-list entity is a Ntv entity where: 981 982 - ntv_value is a list of NTV entities, 983 - ntv_type is a default type available for included NTV entities 984 985 *Attributes :* 986 - no additional attributes to those of parent class `Ntv` 987 988 *dynamic values (@property)* 989 - `json_array` 990 991 The additional methods defined in this class are : 992 993 *instance methods* 994 - `obj_value` 995 ''' 996 997 def __init__(self, list_ntv, ntv_name=None, ntv_type=None, typ_auto=False, fast=False): 998 '''NtvList constructor. 999 1000 *Parameters* 1001 1002 - **ntv_name** : String (default None) - name of the NTV entity 1003 - **ntv_type**: String (default None) - default type or namespace of 1004 the included entities 1005 - **list_ntv**: list - list of Ntv objects or obj_value of Ntv objects 1006 - **fast**: boolean (default False) - if True, Ntv is created with a list 1007 of json values without control 1008 - **type_auto**: boolean (default False) - if True, default type for NtvList 1009 is the ntv_type of the first Ntv in the ntv_value''' 1010 if isinstance(list_ntv, NtvList): 1011 ntv_value = [copy.copy(ntv) for ntv in list_ntv.ntv_value] 1012 ntv_type = list_ntv.ntv_type 1013 ntv_name = list_ntv.ntv_name 1014 elif isinstance(list_ntv, list): 1015 ntv_value = [Ntv.from_obj(ntv, ntv_type, ':', fast=fast) 1016 for ntv in list_ntv] 1017 elif isinstance(list_ntv, dict): 1018 ntv_value = [Ntv.from_obj({key: val}, ntv_type, ':', fast=fast) 1019 for key, val in list_ntv.items()] 1020 else: 1021 raise NtvError('ntv_value is not a list') 1022 if typ_auto and not ntv_type and len(ntv_value) > 0 and ntv_value[0].ntv_type: 1023 ntv_type = ntv_value[0].ntv_type 1024 super().__init__(ntv_value, ntv_name, ntv_type) 1025 for ntv in self: 1026 ntv.parent = self 1027 1028 @property 1029 def json_array(self): 1030 ''' return the json_array dynamic attribute''' 1031 set_name = {ntv.ntv_name for ntv in self} 1032 return '' in set_name or len(set_name) != len(self) or len(set_name)==1 1033 1034 def __eq__(self, other): 1035 ''' equal if name and value are equal''' 1036 return self.__class__.__name__ == other.__class__.__name__ and\ 1037 self.ntv_name == other.ntv_name and self.ntv_value == other.ntv_value 1038 1039 def __hash__(self): 1040 '''return hash(name) + hash(value)''' 1041 return hash(self.ntv_name) + hash(tuple(self.ntv_value)) 1042 1043 def __copy__(self): 1044 ''' Copy all the data ''' 1045 cop = self.__class__(self) 1046 cop.parent = None 1047 return cop 1048 1049 def __setitem__(self, ind, value): 1050 ''' replace ntv_value item at the `ind` row with `value`''' 1051 if ind < 0 or ind >= len(self): 1052 raise NtvError("out of bounds") 1053 self.ntv_value[ind] = value 1054 if isinstance(value, (NtvSingle, NtvList)): 1055 value.parent = self 1056 1057 def __delitem__(self, ind): 1058 '''remove ntv_value item at the `ind` row''' 1059 if isinstance(ind, int): 1060 self.ntv_value.pop(ind) 1061 else: 1062 self.ntv_value.pop(self.ntv_value.index(self[ind])) 1063 1064 def append(self, ntv): 1065 ''' add ntv at the end of the list of Ntv entities included''' 1066 old_parent = ntv.parent 1067 if old_parent: 1068 del(old_parent[old_parent.ntv_value.index(ntv)]) 1069 self.ntv_value.append(ntv) 1070 ntv.parent = self 1071 1072 def insert(self, idx, ntv): 1073 ''' add ntv at the index idx of the list of Ntv entities included''' 1074 old_parent = ntv.parent 1075 if old_parent: 1076 del(old_parent[old_parent.ntv_value.index(ntv)]) 1077 self.ntv_value.insert(idx, ntv) 1078 ntv.parent = self 1079 1080 def _obj_sep(self, json_type, def_type=None): 1081 ''' return separator to include in json_name''' 1082 if json_type or (len(self.ntv_value) == 1 and not self.json_array): 1083 return '::' 1084 return '' 1085 1086 def obj_value(self, def_type=None, **kwargs): 1087 '''return the ntv_value with different formats defined by kwargs 1088 ''' 1089 option = {'encoded': False, 'format': 'json', 'simpleval': False, 1090 'json_array': False, 'fast': False, 'maxi': -1} | kwargs 1091 opt2 = option | {'encoded': False} 1092 maxv = len(self.ntv_value) if option['maxi'] < 1 else option['maxi'] 1093 def_type = self.ntv_type.long_name if self.ntv_type else def_type 1094 if self.json_array or option['simpleval'] or option['json_array']: 1095 return [ntv.to_obj(def_type=def_type, **opt2) for ntv in self.ntv_value[:maxv]] 1096 values = [ntv.to_obj(def_type=def_type, **opt2) 1097 for ntv in self.ntv_value[:maxv]] 1098 return {list(val.items())[0][0]: list(val.items())[0][1] for val in values}
A NTV-list entity is a Ntv entity where:
- ntv_value is a list of NTV entities,
- ntv_type is a default type available for included NTV entities
Attributes :
- no additional attributes to those of parent class
Ntv
dynamic values (@property)
The additional methods defined in this class are :
instance methods
997 def __init__(self, list_ntv, ntv_name=None, ntv_type=None, typ_auto=False, fast=False): 998 '''NtvList constructor. 999 1000 *Parameters* 1001 1002 - **ntv_name** : String (default None) - name of the NTV entity 1003 - **ntv_type**: String (default None) - default type or namespace of 1004 the included entities 1005 - **list_ntv**: list - list of Ntv objects or obj_value of Ntv objects 1006 - **fast**: boolean (default False) - if True, Ntv is created with a list 1007 of json values without control 1008 - **type_auto**: boolean (default False) - if True, default type for NtvList 1009 is the ntv_type of the first Ntv in the ntv_value''' 1010 if isinstance(list_ntv, NtvList): 1011 ntv_value = [copy.copy(ntv) for ntv in list_ntv.ntv_value] 1012 ntv_type = list_ntv.ntv_type 1013 ntv_name = list_ntv.ntv_name 1014 elif isinstance(list_ntv, list): 1015 ntv_value = [Ntv.from_obj(ntv, ntv_type, ':', fast=fast) 1016 for ntv in list_ntv] 1017 elif isinstance(list_ntv, dict): 1018 ntv_value = [Ntv.from_obj({key: val}, ntv_type, ':', fast=fast) 1019 for key, val in list_ntv.items()] 1020 else: 1021 raise NtvError('ntv_value is not a list') 1022 if typ_auto and not ntv_type and len(ntv_value) > 0 and ntv_value[0].ntv_type: 1023 ntv_type = ntv_value[0].ntv_type 1024 super().__init__(ntv_value, ntv_name, ntv_type) 1025 for ntv in self: 1026 ntv.parent = self
NtvList constructor.
Parameters
- ntv_name : String (default None) - name of the NTV entity
- ntv_type: String (default None) - default type or namespace of the included entities
- list_ntv: list - list of Ntv objects or obj_value of Ntv objects
- fast: boolean (default False) - if True, Ntv is created with a list of json values without control
- type_auto: boolean (default False) - if True, default type for NtvList is the ntv_type of the first Ntv in the ntv_value
1064 def append(self, ntv): 1065 ''' add ntv at the end of the list of Ntv entities included''' 1066 old_parent = ntv.parent 1067 if old_parent: 1068 del(old_parent[old_parent.ntv_value.index(ntv)]) 1069 self.ntv_value.append(ntv) 1070 ntv.parent = self
add ntv at the end of the list of Ntv entities included
1072 def insert(self, idx, ntv): 1073 ''' add ntv at the index idx of the list of Ntv entities included''' 1074 old_parent = ntv.parent 1075 if old_parent: 1076 del(old_parent[old_parent.ntv_value.index(ntv)]) 1077 self.ntv_value.insert(idx, ntv) 1078 ntv.parent = self
add ntv at the index idx of the list of Ntv entities included
1086 def obj_value(self, def_type=None, **kwargs): 1087 '''return the ntv_value with different formats defined by kwargs 1088 ''' 1089 option = {'encoded': False, 'format': 'json', 'simpleval': False, 1090 'json_array': False, 'fast': False, 'maxi': -1} | kwargs 1091 opt2 = option | {'encoded': False} 1092 maxv = len(self.ntv_value) if option['maxi'] < 1 else option['maxi'] 1093 def_type = self.ntv_type.long_name if self.ntv_type else def_type 1094 if self.json_array or option['simpleval'] or option['json_array']: 1095 return [ntv.to_obj(def_type=def_type, **opt2) for ntv in self.ntv_value[:maxv]] 1096 values = [ntv.to_obj(def_type=def_type, **opt2) 1097 for ntv in self.ntv_value[:maxv]] 1098 return {list(val.items())[0][0]: list(val.items())[0][1] for val in values}
return the ntv_value with different formats defined by kwargs
Inherited Members
- Ntv
- fast
- obj
- from_att
- from_obj
- lower
- childs
- pointer
- code_ntv
- max_len
- name
- type_str
- val
- alike
- from_value
- json_name
- to_ntvsingle
- to_ntvlist
- notype
- reduce
- set_name
- set_type
- set_value
- to_mermaid
- expand
- to_repr
- to_name
- to_fast
- to_obj
- obj_ntv
- to_json_ntv
- to_obj_ntv
- to_tuple
- remove
- replace
- tree
- decode_json