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')
def agreg_type(str_typ, def_type, single):
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)
def from_file(file, name, long_parent=None):
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
def relative_type(str_def, str_typ):
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
def str_type(long_name, single):
 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
class Datatype(json_ntv.ntv_util.NtvUtil):
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

Datatype(name, nspace=None, force=False)
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
@staticmethod
def types():
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

@classmethod
def add(cls, long_name, module=False, force=False):
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
gen_type

return the generic type of the Datatype

long_name

return a string with the absolute name

def isin_namespace(self, long_name):
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
class Namespace(json_ntv.ntv_util.NtvUtil):
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

Namespace(name='', parent=None, module=False, force=False)
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': }
@staticmethod
def namespaces():
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

@classmethod
def add(cls, long_name, module=False, force=False):
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
long_name

return a string with the absolute name

def is_child(self, nspace):
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

def is_parent(self, nspace):
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
class DatatypeError(builtins.Exception):
440class DatatypeError(Exception):
441    ''' Datatype or Namespace Exception'''
442    # pass

Datatype or Namespace Exception

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback