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