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