NTV.json_ntv.namespace
@author: Philippe@loco-labs.io
The namespace
module is part of the NTV.json_ntv
package (specification document).
It contains the Namespace
, Datatype
, DatatypeError
classes and
the functions agreg_type
, from_file
, relative_type
and str_type
.
Namespace and Datatype entities are used to define NTVtype.
For more information, see the user guide or the github repository.
1# -*- coding: utf-8 -*- 2""" 3@author: Philippe@loco-labs.io 4 5The `namespace` module is part of the `NTV.json_ntv` package ([specification document]( 6https://loco-philippe.github.io/ES/JSON%20semantic%20format%20(JSON-NTV).htm)). 7 8It contains the `Namespace`, `Datatype`, `DatatypeError` classes and 9the functions `agreg_type`, `from_file`, `relative_type` and `str_type`. 10 11Namespace and Datatype entities are used to define NTVtype. 12 13For more information, see the 14[user guide](https://loco-philippe.github.io/NTV/documentation/user_guide.html) 15or the [github repository](https://github.com/loco-philippe/NTV). 16 17""" 18import configparser 19from pathlib import Path 20import json 21import requests 22 23import json_ntv 24from json_ntv.ntv_util import NtvUtil 25 26def agreg_type(str_typ, def_type, single): 27 '''aggregate str_typ and def_type to return an Datatype or a Namespace if not single 28 29 *Parameters* 30 31 - **str_typ** : Datatype or String (long_name) - Datatype to aggregate 32 - **def_typ** : Datatype or String (long_name) - default Datatype or Namespace 33 - **single** : Boolean - Ntv entity concerned (True if NtvSingle)''' 34 if isinstance(str_typ, Datatype): 35 str_typ = str_typ.long_name 36 def_type = str_type(def_type, single) 37 if not str_typ and (not single or isinstance(def_type, Datatype)): 38 return def_type 39 if not str_typ: 40 return Datatype('json') 41 clas = Namespace if str_typ[-1] == '.' else Datatype 42 if not def_type: 43 return clas.add(str_typ) 44 if clas == Datatype or clas == Namespace and not single: 45 try: 46 return clas.add(str_typ) 47 except DatatypeError: 48 return clas.add(_join_type(def_type.long_name, str_typ)) 49 raise DatatypeError(str_typ + ' and ' + def_type.long_name + ' are incompatible') 50 51def from_file(file, name, long_parent=None): 52 '''create a set of Datatype and Namespace associated to a custom Namespace 53 54 *Parameters* 55 56 - **file** : .ini file - description of the Datatype and Namespace 57 - **name** : string - name of the root custom Namespace 58 - **long_parent** : longname of the parent Namespace of the root Namespace 59 ''' 60 long_parent = '' if not long_parent else long_parent 61 if name[0] != '$': 62 raise DatatypeError(name + ' is not a custom Datatype') 63 if not long_parent in Namespace.namespaces(): 64 raise DatatypeError(long_parent + ' is not a valid Datatype') 65 schema_nsp = Namespace(name, long_parent) 66 config = configparser.ConfigParser() 67 config.read(file) 68 _add_namespace(config, schema_nsp) 69 70def relative_type(str_def, str_typ): 71 '''return relative str_typ string from Datatype or Namespace str_def 72 73 *Parameters* 74 75 - **str_def** : String - long_name of the Namespace or Datatype 76 - **str_type** : String - long_name of Ntvtype to be relative ''' 77 if not str_def and not str_typ: 78 return '' 79 if str_def == str_typ: 80 return '' 81 if not str_def or not str_def in str_typ: 82 return str_typ 83 if not str_typ and str_def[-1] != ".": 84 return str_def 85 str_def_split = str_def.split('.')[:-1] 86 str_typ_split = str_typ.split('.') 87 ind = 0 88 for ind, name in enumerate(str_typ_split): 89 if not name in str_def_split: 90 break 91 return '.'.join(str_typ_split[ind:]) 92 93 94def str_type(long_name, single): 95 ''' create a Datatype or a Namespace from a string 96 97 *Parameters* 98 99 - **long_name** : String - name of the Namespace or Datatype 100 - **single** : Boolean - If True, default type is 'json', else None''' 101 if not long_name and single: 102 return Datatype('json') 103 if not long_name and not single: 104 return None 105 if long_name.__class__.__name__ in ['Datatype', 'Namespace']: 106 return long_name 107 if not isinstance(long_name, str): 108 raise DatatypeError('the long_name is not a string') 109 if long_name[-1] == '.': 110 return Namespace.add(long_name) 111 return Datatype.add(long_name) 112 113def _add_namespace(config, namesp): 114 '''create the child Namespace and the child Datatype of the parent namespace''' 115 if namesp.name in config.sections(): 116 confname = config[namesp.name] 117 if 'namespace' in confname: 118 for nspname in json.loads(confname['namespace']): 119 nsp = Namespace(nspname, namesp, force=True) 120 _add_namespace(config, nsp) 121 if 'type' in confname: 122 for typ in json.loads(confname['type']): 123 Datatype(typ, namesp, force=True) 124 125def _join_type(namesp, str_typ): 126 '''join Namespace string and Datatype or Namespace string''' 127 namesp_split = namesp.split('.')[:-1] 128 for name in str_typ.split('.'): 129 if not name in namesp_split: 130 namesp_split.append(name) 131 return '.'.join(namesp_split) 132 133 134class Datatype(NtvUtil): 135 ''' type of NTV entities. 136 137 *Attributes :* 138 139 - **name** : String - name of the type 140 - **nspace** : Namespace - namespace associated 141 - **custom** : boolean - True if not referenced 142 143 The methods defined in this class are : 144 145 *classmethods* 146 - `types` 147 - `add` 148 149 *dynamic values (@property)* 150 - `gen_type` 151 - `long_name` 152 153 *instance methods* 154 - `isin_namespace` 155 ''' 156 157 @staticmethod 158 def types(): 159 '''return the list of Datatype created''' 160 return [nam.long_name for nam in NtvUtil._types_.values()] 161 162 @classmethod 163 def add(cls, long_name, module=False, force=False): 164 '''activate and return a valid Datatype defined by the long name 165 166 *parameters :* 167 168 - **long_name** : String - absolut name of the Datatype 169 - **module** : boolean (default False) - if True search data in the 170 local .ini file, else in the distant repository 171 ''' 172 if long_name == '': 173 return None 174 if long_name in Datatype.types(): 175 return NtvUtil._types_[long_name] 176 split_name = long_name.rsplit('.', 1) 177 if split_name[-1] == '': 178 raise DatatypeError(long_name + ' is not a valid Datatype') 179 if len(split_name) == 1: 180 return cls(split_name[0], force=force) 181 if len(split_name) == 2: 182 nspace = Namespace.add(split_name[0]+'.', module=module, force=force) 183 return cls(split_name[1], nspace, force=force) 184 raise DatatypeError(long_name + ' is not a valid Datatype') 185 186 def __init__(self, name, nspace=None, force=False): 187 '''Datatype constructor. 188 189 *Parameters* 190 191 - **name** : string - name of the Type 192 - **nspace** : Namespace (default None) - namespace associated''' 193 if isinstance(name, Datatype): 194 self.name = name.name 195 self.nspace = name.nspace 196 self.custom = name.custom 197 return 198 if not name or not isinstance(name, str): 199 raise DatatypeError('null name is not allowed') 200 if not name and not nspace: 201 name = 'json' 202 if not nspace: 203 nspace = NtvUtil._namespaces_[''] 204 if name[0] != '$' and not force and not name in nspace.content['type']: 205 raise DatatypeError(name + ' is not defined in ' + nspace.long_name) 206 self.name = name 207 self.nspace = nspace 208 self.custom = nspace.custom or name[0] == '$' 209 NtvUtil._types_[self.long_name] = self 210 return 211 212 def __eq__(self, other): 213 ''' equal if name and nspace are equal''' 214 if self is None and other is None: 215 return True 216 if self is None or other is None: 217 return False 218 if self.__class__.__name__ != other.__class__.__name__: 219 return False 220 return self.name == other.name and self.nspace == other.nspace 221 def __hash__(self): 222 '''return hash(name) + hash(nspace)''' 223 return hash(self.name) + hash(self.nspace) 224 225 def __str__(self): 226 '''return string format''' 227 return self.long_name 228 229 def __repr__(self): 230 '''return classname and long name''' 231 return self.__class__.__name__ + '(' + self.long_name + ')' 232 233 @property 234 def gen_type(self): 235 '''return the generic type of the Datatype''' 236 if self.custom: 237 return '' 238 return self.nspace.content['type'][self.name] 239 240 @property 241 def long_name(self): 242 '''return a string with the absolute name''' 243 return self.nspace.long_name + self.name 244 245 def isin_namespace(self, long_name): 246 '''return the number of level between self and nspace, -1 if None''' 247 return self.nspace.is_child(Namespace.add(long_name)) 248 249 250class Namespace(NtvUtil): 251 ''' Namespace of NTV entities. 252 253 *Attributes :* 254 255 - **name** : String - name of the namespace 256 - **file** : string - location of the file init 257 - **content** : dict - {'type': <list of ntv_type names>, 258 'namespace': <list of namespace names>} 259 - **parent** : Namespace - parent namespace 260 - **custom** : boolean - True if not referenced 261 262 The methods defined in this class are : 263 264 *staticmethods* 265 - `namespaces` 266 267 *classmethods* 268 - `add` 269 270 *dynamic values (@property)* 271 - `long_name` 272 273 *instance methods* 274 - `is_child` 275 - `is_parent` 276 ''' 277 _pathconfig_ = 'https://raw.githubusercontent.com/loco-philippe/NTV/master/json_ntv/config/' 278 _global_ = "NTV_global_namespace.ini" 279 280 @staticmethod 281 def namespaces(): 282 '''return the list of Namespace created''' 283 return [nam.long_name for nam in NtvUtil._namespaces_.values()] 284 285 @classmethod 286 def add(cls, long_name, module=False, force=False): 287 '''activate and return a valid Namespace defined by the long_name. 288 289 *parameters :* 290 291 - **long_name** : String - absolut name of the Namespace 292 - **module** : boolean (default False) - if True search data in the 293 local .ini file, else in the distant repository 294 ''' 295 if long_name in Namespace.namespaces(): 296 return NtvUtil._namespaces_[long_name] 297 split_name = long_name.rsplit('.', 2) 298 if len(split_name) == 1 or split_name[-1] != '': 299 raise DatatypeError(long_name + ' is not a valid classname') 300 if len(split_name) == 2: 301 return cls(split_name[0]+'.', module=module, force=force) 302 if len(split_name) == 3: 303 parent = Namespace.add(split_name[0]+'.', force=force) 304 return cls(split_name[1]+'.', parent, module=module, force=force) 305 raise DatatypeError(long_name + ' is not a valid classname') 306 307 def __init__(self, name='', parent=None, module=False, force=False): 308 ''' 309 Namespace constructor. 310 311 *Parameters* 312 313 - **name** : String - name of the namespace 314 - **parent** : Namespace - parent namespace 315 - **module** : boolean (default False) - if True search data in the 316 local .ini file, else in the distant repository 317 - **content** : dict : {'type': <list of ntv_type names>, 318 'namespace': <list of namespace names>} 319 ''' 320 if name and not parent: 321 parent = NtvUtil._namespaces_[''] 322 if name and name[0] != '$' and not force and \ 323 not name in parent.content['namespace']: 324 raise DatatypeError(name + ' is not defined in ' + parent.long_name) 325 self.name = name 326 self.parent = parent 327 self.custom = parent.custom or name[0] == '$' if parent else False 328 self.file = Namespace._file(self.parent, self.name, self.custom, module) 329 self.content = Namespace._content(self.file, self.name, self.custom, module) 330 NtvUtil._namespaces_[self.long_name] = self 331 332 def __eq__(self, other): 333 ''' equal if name and parent are equal''' 334 if self is None and other is None: 335 return True 336 if self is None or other is None: 337 return False 338 if self.__class__.__name__ != other.__class__.__name__: 339 return False 340 return self.name == other.name and self.parent == other.parent 341 342 def __hash__(self): 343 '''return hash(name) + hash(parent)''' 344 return hash(self.name) + hash(self.parent) 345 346 def __str__(self): 347 '''return string format''' 348 return self.long_name 349 350 def __repr__(self): 351 '''return classname and long name''' 352 return self.__class__.__name__ + '(' + self.long_name + ')' 353 354 @staticmethod 355 def _file(parent, name, custom, module): 356 '''return the file name of the Namespace configuration 357 358 *parameters :* 359 360 - **parent** : Namespace - Parent of the Namespace 361 - **name** : String - name of the Namespace 362 - **custom** : boolean - if True, return None (custom Namespace) 363 - **module** : boolean (default False) - if True search data in the 364 local .ini file, else in the distant repository 365 ''' 366 if custom: 367 return None 368 if parent: 369 config = configparser.ConfigParser() 370 if module: 371 p_file = Path(parent.file).stem + Path(parent.file).suffix 372 config.read(Path(json_ntv.__file__).parent / 'config' / p_file) 373 else: 374 config.read_string(requests.get( 375 parent.file, allow_redirects=True).content.decode()) 376 return Namespace._pathconfig_ + json.loads(config['data']['namespace'])[name] 377 return Namespace._pathconfig_ + Namespace._global_ 378 379 @staticmethod 380 def _content(file, name, custom, module): 381 '''return the content of the Namespace configuration 382 383 *parameters :* 384 385 - **file** : string - file name of the parent Namespace 386 - **name** : string - name of the Namespace 387 - **custom** : boolean - if True, return empty dict (custom Namespace) 388 - **module** : boolean (default False) - if True search data in the 389 local .ini file, else in the distant repository 390 391 *return :* 392 393 - dict : {'type': <list of ntv_type names>, 394 'namespace': <list of namespace names>} 395 ''' 396 if custom: 397 return {'type': {}, 'namespace': {}} 398 config = configparser.ConfigParser() 399 if module: 400 p_file = Path(file).stem + Path(file).suffix 401 config.read(Path(json_ntv.__file__).parent / 'config' / p_file) 402 else: 403 config.read_string(requests.get( 404 file, allow_redirects=True).content.decode()) 405 config_name = config['data']['name'] 406 if config_name != name: 407 raise DatatypeError(file + ' is not correct') 408 return {'type': json.loads(config['data']['type']), 409 'namespace': json.loads(config['data']['namespace'])} 410 411 @property 412 def long_name(self): 413 '''return a string with the absolute name''' 414 if self.parent is None or self.parent.name == '': 415 return self.name 416 return self.parent.long_name + self.name 417 418 def is_child(self, nspace): 419 '''return the number of level between self and nspace, -1 if None''' 420 parent = self.parent 421 if not self.name: 422 return -1 423 if self == nspace: 424 return 0 425 rang = 1 426 while parent.name != '' and parent != nspace: 427 rang += 1 428 parent = parent.parent 429 if parent == nspace: 430 return rang 431 if parent.name == '': 432 return -1 433 434 def is_parent(self, nspace): 435 '''return the number of level between self and nspace, -1 if None''' 436 return nspace.is_child(self) 437 438 439class DatatypeError(Exception): 440 ''' Datatype or Namespace Exception''' 441 # pass 442 443nroot = Namespace(module=True) 444for root_typ in nroot.content['type'].keys(): 445 typ = Datatype.add(root_typ, module=True) 446typ_json = Datatype('json')
27def agreg_type(str_typ, def_type, single): 28 '''aggregate str_typ and def_type to return an Datatype or a Namespace if not single 29 30 *Parameters* 31 32 - **str_typ** : Datatype or String (long_name) - Datatype to aggregate 33 - **def_typ** : Datatype or String (long_name) - default Datatype or Namespace 34 - **single** : Boolean - Ntv entity concerned (True if NtvSingle)''' 35 if isinstance(str_typ, Datatype): 36 str_typ = str_typ.long_name 37 def_type = str_type(def_type, single) 38 if not str_typ and (not single or isinstance(def_type, Datatype)): 39 return def_type 40 if not str_typ: 41 return Datatype('json') 42 clas = Namespace if str_typ[-1] == '.' else Datatype 43 if not def_type: 44 return clas.add(str_typ) 45 if clas == Datatype or clas == Namespace and not single: 46 try: 47 return clas.add(str_typ) 48 except DatatypeError: 49 return clas.add(_join_type(def_type.long_name, str_typ)) 50 raise DatatypeError(str_typ + ' and ' + def_type.long_name + ' are incompatible')
aggregate str_typ and def_type to return an Datatype or a Namespace if not single
Parameters
- **str_typ** : Datatype or String (long_name) - Datatype to aggregate
- **def_typ** : Datatype or String (long_name) - default Datatype or Namespace
- **single** : Boolean - Ntv entity concerned (True if NtvSingle)
52def from_file(file, name, long_parent=None): 53 '''create a set of Datatype and Namespace associated to a custom Namespace 54 55 *Parameters* 56 57 - **file** : .ini file - description of the Datatype and Namespace 58 - **name** : string - name of the root custom Namespace 59 - **long_parent** : longname of the parent Namespace of the root Namespace 60 ''' 61 long_parent = '' if not long_parent else long_parent 62 if name[0] != '$': 63 raise DatatypeError(name + ' is not a custom Datatype') 64 if not long_parent in Namespace.namespaces(): 65 raise DatatypeError(long_parent + ' is not a valid Datatype') 66 schema_nsp = Namespace(name, long_parent) 67 config = configparser.ConfigParser() 68 config.read(file) 69 _add_namespace(config, schema_nsp)
create a set of Datatype and Namespace associated to a custom Namespace
Parameters
- **file** : .ini file - description of the Datatype and Namespace
- **name** : string - name of the root custom Namespace
- **long_parent** : longname of the parent Namespace of the root Namespace
71def relative_type(str_def, str_typ): 72 '''return relative str_typ string from Datatype or Namespace str_def 73 74 *Parameters* 75 76 - **str_def** : String - long_name of the Namespace or Datatype 77 - **str_type** : String - long_name of Ntvtype to be relative ''' 78 if not str_def and not str_typ: 79 return '' 80 if str_def == str_typ: 81 return '' 82 if not str_def or not str_def in str_typ: 83 return str_typ 84 if not str_typ and str_def[-1] != ".": 85 return str_def 86 str_def_split = str_def.split('.')[:-1] 87 str_typ_split = str_typ.split('.') 88 ind = 0 89 for ind, name in enumerate(str_typ_split): 90 if not name in str_def_split: 91 break 92 return '.'.join(str_typ_split[ind:])
return relative str_typ string from Datatype or Namespace str_def
Parameters
- **str_def** : String - long_name of the Namespace or Datatype
- **str_type** : String - long_name of Ntvtype to be relative
95def str_type(long_name, single): 96 ''' create a Datatype or a Namespace from a string 97 98 *Parameters* 99 100 - **long_name** : String - name of the Namespace or Datatype 101 - **single** : Boolean - If True, default type is 'json', else None''' 102 if not long_name and single: 103 return Datatype('json') 104 if not long_name and not single: 105 return None 106 if long_name.__class__.__name__ in ['Datatype', 'Namespace']: 107 return long_name 108 if not isinstance(long_name, str): 109 raise DatatypeError('the long_name is not a string') 110 if long_name[-1] == '.': 111 return Namespace.add(long_name) 112 return Datatype.add(long_name)
create a Datatype or a Namespace from a string
Parameters
- **long_name** : String - name of the Namespace or Datatype
- **single** : Boolean - If True, default type is 'json', else None
135class Datatype(NtvUtil): 136 ''' type of NTV entities. 137 138 *Attributes :* 139 140 - **name** : String - name of the type 141 - **nspace** : Namespace - namespace associated 142 - **custom** : boolean - True if not referenced 143 144 The methods defined in this class are : 145 146 *classmethods* 147 - `types` 148 - `add` 149 150 *dynamic values (@property)* 151 - `gen_type` 152 - `long_name` 153 154 *instance methods* 155 - `isin_namespace` 156 ''' 157 158 @staticmethod 159 def types(): 160 '''return the list of Datatype created''' 161 return [nam.long_name for nam in NtvUtil._types_.values()] 162 163 @classmethod 164 def add(cls, long_name, module=False, force=False): 165 '''activate and return a valid Datatype defined by the long name 166 167 *parameters :* 168 169 - **long_name** : String - absolut name of the Datatype 170 - **module** : boolean (default False) - if True search data in the 171 local .ini file, else in the distant repository 172 ''' 173 if long_name == '': 174 return None 175 if long_name in Datatype.types(): 176 return NtvUtil._types_[long_name] 177 split_name = long_name.rsplit('.', 1) 178 if split_name[-1] == '': 179 raise DatatypeError(long_name + ' is not a valid Datatype') 180 if len(split_name) == 1: 181 return cls(split_name[0], force=force) 182 if len(split_name) == 2: 183 nspace = Namespace.add(split_name[0]+'.', module=module, force=force) 184 return cls(split_name[1], nspace, force=force) 185 raise DatatypeError(long_name + ' is not a valid Datatype') 186 187 def __init__(self, name, nspace=None, force=False): 188 '''Datatype constructor. 189 190 *Parameters* 191 192 - **name** : string - name of the Type 193 - **nspace** : Namespace (default None) - namespace associated''' 194 if isinstance(name, Datatype): 195 self.name = name.name 196 self.nspace = name.nspace 197 self.custom = name.custom 198 return 199 if not name or not isinstance(name, str): 200 raise DatatypeError('null name is not allowed') 201 if not name and not nspace: 202 name = 'json' 203 if not nspace: 204 nspace = NtvUtil._namespaces_[''] 205 if name[0] != '$' and not force and not name in nspace.content['type']: 206 raise DatatypeError(name + ' is not defined in ' + nspace.long_name) 207 self.name = name 208 self.nspace = nspace 209 self.custom = nspace.custom or name[0] == '$' 210 NtvUtil._types_[self.long_name] = self 211 return 212 213 def __eq__(self, other): 214 ''' equal if name and nspace are equal''' 215 if self is None and other is None: 216 return True 217 if self is None or other is None: 218 return False 219 if self.__class__.__name__ != other.__class__.__name__: 220 return False 221 return self.name == other.name and self.nspace == other.nspace 222 def __hash__(self): 223 '''return hash(name) + hash(nspace)''' 224 return hash(self.name) + hash(self.nspace) 225 226 def __str__(self): 227 '''return string format''' 228 return self.long_name 229 230 def __repr__(self): 231 '''return classname and long name''' 232 return self.__class__.__name__ + '(' + self.long_name + ')' 233 234 @property 235 def gen_type(self): 236 '''return the generic type of the Datatype''' 237 if self.custom: 238 return '' 239 return self.nspace.content['type'][self.name] 240 241 @property 242 def long_name(self): 243 '''return a string with the absolute name''' 244 return self.nspace.long_name + self.name 245 246 def isin_namespace(self, long_name): 247 '''return the number of level between self and nspace, -1 if None''' 248 return self.nspace.is_child(Namespace.add(long_name))
type of NTV entities.
Attributes :
- name : String - name of the type
- nspace : Namespace - namespace associated
- custom : boolean - True if not referenced
The methods defined in this class are :
classmethods
dynamic values (@property)
instance methods
187 def __init__(self, name, nspace=None, force=False): 188 '''Datatype constructor. 189 190 *Parameters* 191 192 - **name** : string - name of the Type 193 - **nspace** : Namespace (default None) - namespace associated''' 194 if isinstance(name, Datatype): 195 self.name = name.name 196 self.nspace = name.nspace 197 self.custom = name.custom 198 return 199 if not name or not isinstance(name, str): 200 raise DatatypeError('null name is not allowed') 201 if not name and not nspace: 202 name = 'json' 203 if not nspace: 204 nspace = NtvUtil._namespaces_[''] 205 if name[0] != '$' and not force and not name in nspace.content['type']: 206 raise DatatypeError(name + ' is not defined in ' + nspace.long_name) 207 self.name = name 208 self.nspace = nspace 209 self.custom = nspace.custom or name[0] == '$' 210 NtvUtil._types_[self.long_name] = self 211 return
Datatype constructor.
Parameters
- name : string - name of the Type
- nspace : Namespace (default None) - namespace associated
158 @staticmethod 159 def types(): 160 '''return the list of Datatype created''' 161 return [nam.long_name for nam in NtvUtil._types_.values()]
return the list of Datatype created
163 @classmethod 164 def add(cls, long_name, module=False, force=False): 165 '''activate and return a valid Datatype defined by the long name 166 167 *parameters :* 168 169 - **long_name** : String - absolut name of the Datatype 170 - **module** : boolean (default False) - if True search data in the 171 local .ini file, else in the distant repository 172 ''' 173 if long_name == '': 174 return None 175 if long_name in Datatype.types(): 176 return NtvUtil._types_[long_name] 177 split_name = long_name.rsplit('.', 1) 178 if split_name[-1] == '': 179 raise DatatypeError(long_name + ' is not a valid Datatype') 180 if len(split_name) == 1: 181 return cls(split_name[0], force=force) 182 if len(split_name) == 2: 183 nspace = Namespace.add(split_name[0]+'.', module=module, force=force) 184 return cls(split_name[1], nspace, force=force) 185 raise DatatypeError(long_name + ' is not a valid Datatype')
activate and return a valid Datatype defined by the long name
parameters :
- long_name : String - absolut name of the Datatype
- module : boolean (default False) - if True search data in the local .ini file, else in the distant repository
246 def isin_namespace(self, long_name): 247 '''return the number of level between self and nspace, -1 if None''' 248 return self.nspace.is_child(Namespace.add(long_name))
return the number of level between self and nspace, -1 if None
Inherited Members
- json_ntv.ntv_util.NtvUtil
- from_obj_name
- decode_ntv_tab
251class Namespace(NtvUtil): 252 ''' Namespace of NTV entities. 253 254 *Attributes :* 255 256 - **name** : String - name of the namespace 257 - **file** : string - location of the file init 258 - **content** : dict - {'type': <list of ntv_type names>, 259 'namespace': <list of namespace names>} 260 - **parent** : Namespace - parent namespace 261 - **custom** : boolean - True if not referenced 262 263 The methods defined in this class are : 264 265 *staticmethods* 266 - `namespaces` 267 268 *classmethods* 269 - `add` 270 271 *dynamic values (@property)* 272 - `long_name` 273 274 *instance methods* 275 - `is_child` 276 - `is_parent` 277 ''' 278 _pathconfig_ = 'https://raw.githubusercontent.com/loco-philippe/NTV/master/json_ntv/config/' 279 _global_ = "NTV_global_namespace.ini" 280 281 @staticmethod 282 def namespaces(): 283 '''return the list of Namespace created''' 284 return [nam.long_name for nam in NtvUtil._namespaces_.values()] 285 286 @classmethod 287 def add(cls, long_name, module=False, force=False): 288 '''activate and return a valid Namespace defined by the long_name. 289 290 *parameters :* 291 292 - **long_name** : String - absolut name of the Namespace 293 - **module** : boolean (default False) - if True search data in the 294 local .ini file, else in the distant repository 295 ''' 296 if long_name in Namespace.namespaces(): 297 return NtvUtil._namespaces_[long_name] 298 split_name = long_name.rsplit('.', 2) 299 if len(split_name) == 1 or split_name[-1] != '': 300 raise DatatypeError(long_name + ' is not a valid classname') 301 if len(split_name) == 2: 302 return cls(split_name[0]+'.', module=module, force=force) 303 if len(split_name) == 3: 304 parent = Namespace.add(split_name[0]+'.', force=force) 305 return cls(split_name[1]+'.', parent, module=module, force=force) 306 raise DatatypeError(long_name + ' is not a valid classname') 307 308 def __init__(self, name='', parent=None, module=False, force=False): 309 ''' 310 Namespace constructor. 311 312 *Parameters* 313 314 - **name** : String - name of the namespace 315 - **parent** : Namespace - parent namespace 316 - **module** : boolean (default False) - if True search data in the 317 local .ini file, else in the distant repository 318 - **content** : dict : {'type': <list of ntv_type names>, 319 'namespace': <list of namespace names>} 320 ''' 321 if name and not parent: 322 parent = NtvUtil._namespaces_[''] 323 if name and name[0] != '$' and not force and \ 324 not name in parent.content['namespace']: 325 raise DatatypeError(name + ' is not defined in ' + parent.long_name) 326 self.name = name 327 self.parent = parent 328 self.custom = parent.custom or name[0] == '$' if parent else False 329 self.file = Namespace._file(self.parent, self.name, self.custom, module) 330 self.content = Namespace._content(self.file, self.name, self.custom, module) 331 NtvUtil._namespaces_[self.long_name] = self 332 333 def __eq__(self, other): 334 ''' equal if name and parent are equal''' 335 if self is None and other is None: 336 return True 337 if self is None or other is None: 338 return False 339 if self.__class__.__name__ != other.__class__.__name__: 340 return False 341 return self.name == other.name and self.parent == other.parent 342 343 def __hash__(self): 344 '''return hash(name) + hash(parent)''' 345 return hash(self.name) + hash(self.parent) 346 347 def __str__(self): 348 '''return string format''' 349 return self.long_name 350 351 def __repr__(self): 352 '''return classname and long name''' 353 return self.__class__.__name__ + '(' + self.long_name + ')' 354 355 @staticmethod 356 def _file(parent, name, custom, module): 357 '''return the file name of the Namespace configuration 358 359 *parameters :* 360 361 - **parent** : Namespace - Parent of the Namespace 362 - **name** : String - name of the Namespace 363 - **custom** : boolean - if True, return None (custom Namespace) 364 - **module** : boolean (default False) - if True search data in the 365 local .ini file, else in the distant repository 366 ''' 367 if custom: 368 return None 369 if parent: 370 config = configparser.ConfigParser() 371 if module: 372 p_file = Path(parent.file).stem + Path(parent.file).suffix 373 config.read(Path(json_ntv.__file__).parent / 'config' / p_file) 374 else: 375 config.read_string(requests.get( 376 parent.file, allow_redirects=True).content.decode()) 377 return Namespace._pathconfig_ + json.loads(config['data']['namespace'])[name] 378 return Namespace._pathconfig_ + Namespace._global_ 379 380 @staticmethod 381 def _content(file, name, custom, module): 382 '''return the content of the Namespace configuration 383 384 *parameters :* 385 386 - **file** : string - file name of the parent Namespace 387 - **name** : string - name of the Namespace 388 - **custom** : boolean - if True, return empty dict (custom Namespace) 389 - **module** : boolean (default False) - if True search data in the 390 local .ini file, else in the distant repository 391 392 *return :* 393 394 - dict : {'type': <list of ntv_type names>, 395 'namespace': <list of namespace names>} 396 ''' 397 if custom: 398 return {'type': {}, 'namespace': {}} 399 config = configparser.ConfigParser() 400 if module: 401 p_file = Path(file).stem + Path(file).suffix 402 config.read(Path(json_ntv.__file__).parent / 'config' / p_file) 403 else: 404 config.read_string(requests.get( 405 file, allow_redirects=True).content.decode()) 406 config_name = config['data']['name'] 407 if config_name != name: 408 raise DatatypeError(file + ' is not correct') 409 return {'type': json.loads(config['data']['type']), 410 'namespace': json.loads(config['data']['namespace'])} 411 412 @property 413 def long_name(self): 414 '''return a string with the absolute name''' 415 if self.parent is None or self.parent.name == '': 416 return self.name 417 return self.parent.long_name + self.name 418 419 def is_child(self, nspace): 420 '''return the number of level between self and nspace, -1 if None''' 421 parent = self.parent 422 if not self.name: 423 return -1 424 if self == nspace: 425 return 0 426 rang = 1 427 while parent.name != '' and parent != nspace: 428 rang += 1 429 parent = parent.parent 430 if parent == nspace: 431 return rang 432 if parent.name == '': 433 return -1 434 435 def is_parent(self, nspace): 436 '''return the number of level between self and nspace, -1 if None''' 437 return nspace.is_child(self)
Namespace of NTV entities.
Attributes :
- name : String - name of the namespace
- file : string - location of the file init
- content : dict - {'type':
- ,
'namespace':- }
- parent : Namespace - parent namespace
- custom : boolean - True if not referenced
The methods defined in this class are :
staticmethods
classmethods
dynamic values (@property)
instance methods
308 def __init__(self, name='', parent=None, module=False, force=False): 309 ''' 310 Namespace constructor. 311 312 *Parameters* 313 314 - **name** : String - name of the namespace 315 - **parent** : Namespace - parent namespace 316 - **module** : boolean (default False) - if True search data in the 317 local .ini file, else in the distant repository 318 - **content** : dict : {'type': <list of ntv_type names>, 319 'namespace': <list of namespace names>} 320 ''' 321 if name and not parent: 322 parent = NtvUtil._namespaces_[''] 323 if name and name[0] != '$' and not force and \ 324 not name in parent.content['namespace']: 325 raise DatatypeError(name + ' is not defined in ' + parent.long_name) 326 self.name = name 327 self.parent = parent 328 self.custom = parent.custom or name[0] == '$' if parent else False 329 self.file = Namespace._file(self.parent, self.name, self.custom, module) 330 self.content = Namespace._content(self.file, self.name, self.custom, module) 331 NtvUtil._namespaces_[self.long_name] = self
Namespace constructor.
Parameters
- name : String - name of the namespace
- parent : Namespace - parent namespace
- module : boolean (default False) - if True search data in the local .ini file, else in the distant repository
- content : dict : {'type':
- ,
'namespace':- }
281 @staticmethod 282 def namespaces(): 283 '''return the list of Namespace created''' 284 return [nam.long_name for nam in NtvUtil._namespaces_.values()]
return the list of Namespace created
286 @classmethod 287 def add(cls, long_name, module=False, force=False): 288 '''activate and return a valid Namespace defined by the long_name. 289 290 *parameters :* 291 292 - **long_name** : String - absolut name of the Namespace 293 - **module** : boolean (default False) - if True search data in the 294 local .ini file, else in the distant repository 295 ''' 296 if long_name in Namespace.namespaces(): 297 return NtvUtil._namespaces_[long_name] 298 split_name = long_name.rsplit('.', 2) 299 if len(split_name) == 1 or split_name[-1] != '': 300 raise DatatypeError(long_name + ' is not a valid classname') 301 if len(split_name) == 2: 302 return cls(split_name[0]+'.', module=module, force=force) 303 if len(split_name) == 3: 304 parent = Namespace.add(split_name[0]+'.', force=force) 305 return cls(split_name[1]+'.', parent, module=module, force=force) 306 raise DatatypeError(long_name + ' is not a valid classname')
activate and return a valid Namespace defined by the long_name.
parameters :
- long_name : String - absolut name of the Namespace
- module : boolean (default False) - if True search data in the local .ini file, else in the distant repository
419 def is_child(self, nspace): 420 '''return the number of level between self and nspace, -1 if None''' 421 parent = self.parent 422 if not self.name: 423 return -1 424 if self == nspace: 425 return 0 426 rang = 1 427 while parent.name != '' and parent != nspace: 428 rang += 1 429 parent = parent.parent 430 if parent == nspace: 431 return rang 432 if parent.name == '': 433 return -1
return the number of level between self and nspace, -1 if None
435 def is_parent(self, nspace): 436 '''return the number of level between self and nspace, -1 if None''' 437 return nspace.is_child(self)
return the number of level between self and nspace, -1 if None
Inherited Members
- json_ntv.ntv_util.NtvUtil
- from_obj_name
- decode_ntv_tab
Datatype or Namespace Exception
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback