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, mapping, 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`, `mapping`, `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
 25from json_ntv.ntv_validate import Validator
 26
 27SCH_ORG = 'https://schema.org/'
 28
 29
 30def agreg_type(str_typ, def_type, single):
 31    '''aggregate str_typ and def_type to return an Datatype or a Namespace if not single
 32
 33    *Parameters*
 34
 35        - **str_typ** : Datatype or String (long_name) - Datatype to aggregate
 36        - **def_typ** : Datatype or String (long_name) - default Datatype or Namespace
 37        - **single** : Boolean - Ntv entity concerned (True if NtvSingle)'''
 38    if isinstance(str_typ, Datatype):
 39        str_typ = str_typ.long_name
 40    def_type = str_type(def_type, single)
 41    if not str_typ and (not single or isinstance(def_type, Datatype)):
 42        return def_type
 43    if not str_typ:
 44        return Datatype('json')
 45    clas = Namespace if str_typ[-1] == '.' else Datatype
 46    if not def_type:
 47        return clas.add(str_typ)
 48    if clas == Datatype or clas == Namespace and not single:
 49        try:
 50            return clas.add(str_typ)
 51        except DatatypeError:
 52            for typ in _join_type(def_type.long_name, str_typ):
 53                try:
 54                    return clas.add(typ)
 55                except DatatypeError:
 56                    pass
 57    raise DatatypeError(str_typ + ' and ' +
 58                        def_type.long_name + ' are incompatible')
 59
 60
 61def from_file(file, name, long_parent=None):
 62    '''create a set of Datatype and Namespace associated to a custom Namespace
 63
 64    *Parameters*
 65
 66        - **file** : .ini file - description of the Datatype and Namespace
 67        - **name** : string - name of the root custom Namespace
 68        - **long_parent** : longname of the parent Namespace of the root Namespace
 69    '''
 70    long_parent = '' if not long_parent else long_parent
 71    if name[0] != '$':
 72        raise DatatypeError(name + ' is not a custom Datatype')
 73    if long_parent not in Namespace.namespaces():
 74        raise DatatypeError(long_parent + ' is not a valid Datatype')
 75    schema_nsp = Namespace(name, long_parent)
 76    config = configparser.ConfigParser()
 77    config.read(file)
 78    if name not in config.sections():
 79        raise DatatypeError(name + ' is not present in ' + str(file))
 80    _add_namespace(config, schema_nsp)
 81
 82
 83def mapping(typ=None, func=None):
 84    '''Affect a validate function (func) to a Datatype (typ) '''
 85    if typ and func:
 86        Datatype(typ).validate = func
 87    else:
 88        if isinstance(typ, str):
 89            func_lis = [typ + '_valid']
 90        elif isinstance(typ, (list, tuple)):
 91            func_lis = [typ_str + '_valid' for typ_str in typ]
 92        else:
 93            func_lis = [typ_str + '_valid' for typ_str in Datatype._types_]
 94        for func_str in func_lis:
 95            if func_str in Validator.__dict__:
 96                Datatype(func_str[:-6]).validate = Validator.__dict__[func_str]
 97
 98
 99def relative_type(str_def, str_typ):
100    '''return relative str_typ string from Datatype or Namespace str_def
101
102    *Parameters*
103
104        - **str_def** : String - long_name of the Namespace or Datatype
105        - **str_type** : String - long_name of Ntvtype to be relative '''
106    if not str_def and not str_typ:
107        return ''
108    if str_def == str_typ:
109        return ''
110    if not str_def or str_def not in str_typ:
111        return str_typ
112    if not str_typ and str_def[-1] != ".":
113        return str_def
114    str_def_split = str_def.split('.')[:-1]
115    str_typ_split = str_typ.split('.')
116    ind = 0
117    for ind, name in enumerate(str_typ_split):
118        if name not in str_def_split:
119            break
120    return '.'.join(str_typ_split[ind:])
121
122
123def str_type(long_name, single):
124    ''' create a Datatype or a Namespace from a string
125
126    *Parameters*
127
128        - **long_name** : String - name of the Namespace or Datatype
129        - **single** : Boolean - If True, default type is 'json', else None'''
130    if not long_name and single:
131        return Datatype('json')
132    if not long_name and not single:
133        return None
134    if long_name.__class__.__name__ in ['Datatype', 'Namespace']:
135        return long_name
136    if not isinstance(long_name, str):
137        raise DatatypeError('the long_name is not a string')
138    if long_name[-1] == '.':
139        return Namespace.add(long_name)
140    return Datatype(long_name)
141
142
143def _add_namespace(config, namesp):
144    '''create the child Namespace and the child Datatype of the parent namespace'''
145    if namesp.name in config.sections():
146        confname = config[namesp.name]
147        if 'namespace' in confname:
148            for nspname in json.loads(confname['namespace']):
149                nsp = Namespace(nspname, namesp, force=True)
150                _add_namespace(config, nsp)
151        if 'type' in confname:
152            for typ in json.loads(confname['type']):
153                Datatype(typ, namesp, force=True)
154
155
156def _join_type(namesp, str_typ):
157    '''join Namespace string and Datatype or Namespace string'''
158    namesp_sp = namesp.split('.')
159    str_typ_sp = str_typ.split('.')
160    idx = -1
161    if str_typ_sp[0] in namesp_sp:
162        idx = namesp_sp.index(str_typ_sp[0])
163        if namesp_sp[idx:] != str_typ_sp[:len(namesp_sp[idx:])]:
164            idx = -1
165    if idx > -1:
166        namesp_sp = namesp_sp[:idx]
167    return ['.'.join(namesp_sp[:i+1]+str_typ_sp) for i in range(len(namesp_sp)-1, -1, -1)]
168
169
170def _isin_schemaorg(name, prop=True, typ=None):
171    ''' return True if a schema.org Property is present and associated to a Type
172    or if a schema.org Type is present'''
173    n_org = name if prop else name[:-1]
174    t_org = typ[:-1] if typ else None
175    req_name = requests.get(
176        SCH_ORG + n_org, allow_redirects=True, timeout=10).content.decode()
177    if not prop:
178        return 'Type</ti' in req_name
179    is_prop = 'Property</ti' in req_name
180    if not t_org:
181        return is_prop
182    if is_prop:
183        return '/' + n_org in requests.get(SCH_ORG + t_org, allow_redirects=True,
184                                           timeout=10).content.decode()
185    return False
186
187
188class TypeBase(NtvUtil):
189    ''' type of NTV entities.
190
191    *Attributes :*
192
193    - **name** : String - name of the type
194    - **nspace** : Namespace - namespace associated
195    - **custom** : boolean - True if not referenced
196    - **validate** : function (default None) - validate function
197
198    The methods defined in this class are :
199
200    *staticmethods*
201    - `types`
202    - `add`
203
204    *dynamic values (@property)*
205    - `category`
206    - `json_type`
207    - `gen_type`
208    - `long_name`
209
210    *instance methods*
211    - `isin_namespace`
212    '''
213
214    @staticmethod
215    def types():
216        '''return the list of TypeBase created'''
217        return [nam.long_name for nam in NtvUtil._types_.values()]
218
219    @classmethod
220    def add(cls, long_name, module=False, force=False, validate=None):
221        '''activate and return a valid TypeBase defined by the long name
222
223        *parameters :*
224
225        - **long_name** : String - absolut name of the TypeBase
226        - **module** : boolean (default False) - if True search data in the
227        local .ini file, else in the distant repository
228        - **validate** : function (default None) - validate function to include
229        '''
230        if long_name == '':
231            return None
232        if long_name in cls.types():
233            return NtvUtil._types_[long_name]
234        split_name = long_name.rsplit('.', 1)
235        if split_name[-1] == '':
236            raise DatatypeError(long_name + ' is not a valid TypeBase')
237        if len(split_name) == 1:
238            return cls(split_name[0], force=force, validate=validate)
239        if len(split_name) == 2:
240            nspace = Namespace.add(
241                split_name[0]+'.', module=module, force=force)
242            return cls(split_name[1], nspace, force=force)
243        raise DatatypeError(long_name + ' is not a valid TypeBase')
244
245    def __init__(self, name, nspace=None, force=False, validate=None):
246        '''TypeBase constructor.
247
248        *Parameters*
249
250        - **name** : string - name of the Type
251        - **nspace** : Namespace (default None) - namespace associated
252        - **force** : boolean (default False) - if True, no Namespace control
253        - **validate** : function (default None) - validate function to include'''
254        if isinstance(name, TypeBase):
255            self.name = name.name
256            self.nspace = name.nspace
257            self.custom = name.custom
258            self.validate = name.validate
259            # self.gen_type = name.gen_type
260            # self.long_name = name.long_name
261            return
262        if not name or not isinstance(name, str):
263            raise DatatypeError('null name is not allowed')
264        if not name and not nspace:
265            name = 'json'
266        if not nspace:
267            nspace = NtvUtil._namespaces_['']
268        if nspace.file and SCH_ORG in nspace.file:
269            if not _isin_schemaorg(name, typ=nspace.name):
270                raise DatatypeError(name +
271                                    ' is not a schema.org Property associated to the ' +
272                                    nspace.name + 'Type ')
273        else:
274            if not (name[0] == '$' or force or name in nspace.content['type']):
275                raise DatatypeError(
276                    name + ' is not defined in ' + nspace.long_name)
277        self.name = name
278        self.nspace = nspace
279        self.custom = nspace.custom or name[0] == '$'
280        # self.gen_type = '' if self.custom else self.nspace.content['type'][self.name]
281        # self.long_name = self.nspace.long_name + self.name
282        if validate:
283            self.validate = validate
284        NtvUtil._types_[self.long_name] = self
285        return
286
287    def __eq__(self, other):
288        ''' equal if name and nspace are equal'''
289        if self is None and other is None:
290            return True
291        if self is None or other is None:
292            return False
293        if self.__class__.__name__ != other.__class__.__name__:
294            return False
295        return self.name == other.name and self.nspace == other.nspace
296
297    def __hash__(self):
298        '''return hash(name) + hash(nspace)'''
299        return hash(self.name) + hash(self.nspace)
300
301    def __str__(self):
302        '''return string format'''
303        return self.long_name
304
305    def __repr__(self):
306        '''return classname and long name'''
307        return self.__class__.__name__ + '(' + self.long_name + ')'
308
309    @property
310    def json_type(self):
311        '''return the json type of the TypeBase'''
312        if self.custom:
313            return ''
314        prop = self.nspace.content['type'][self.name]
315        if isinstance(prop, list):
316            return prop[1]
317        return 'json'
318
319    @property
320    def category(self):
321        '''return the category of the TypeBase'''
322        if self.custom:
323            return ''
324        prop = self.nspace.content['type'][self.name]
325        if isinstance(prop, list):
326            return prop[2]
327        return 'local'
328
329    @property
330    def gen_type(self):
331        '''return the generic type of the TypeBase'''
332        if self.custom:
333            return ''
334        prop = self.nspace.content['type'][self.name]
335        if isinstance(prop, list):
336            return prop[0]
337        return prop
338
339    @property
340    def long_name(self):
341        '''return a string with the absolute name'''
342        return self.nspace.long_name + self.name
343
344    def isin_namespace(self, long_name):
345        '''return the number of level between self and nspace, -1 if None'''
346        return self.nspace.is_child(Namespace.add(long_name))
347
348
349class Datatype(TypeBase):
350    ''' The Datatype of NTV entities is composed with a TypeBase and an optional
351    extension.
352
353    *Attributes :*
354
355    - **name** : String - name of the Datatype
356    - **base_name** : String - name of the TypeBase
357    - **nspace** : Namespace - namespace associated
358    - **custom** : boolean - True if not referenced
359    - **validate** : function (default None) - validate function
360    - **typebase** : TypeBase - TypeBase of the Datatype
361    - **extension** : String (default None) - extension of the TypeBase
362
363    The methods defined in this class are :
364
365    *classmethod*
366    - `add`
367
368    *dynamic values (@property)*
369    - `category`
370    - `json_type`
371    - `gen_type`
372    - `long_name` (TypeBase)
373
374    *staticmethods*
375    - `types` (TypeBase)
376
377    *instance methods*
378    - `isin_namespace` (TypeBase)
379    - `validate` (TypeBase)
380    '''
381
382    def __init__(self, full_name, module=False, force=False, validate=None):
383        '''DataType constructor.
384
385        *Parameters*
386
387        - **full_name** : String - absolut name of the Datatype
388        - **module** : boolean (default False) - if True search data in the
389        local .ini file, else in the distant repository
390        - **force** : boolean (default False) - if True, no Namespace control
391        - **validate** : function (default None) - validate function to include'''
392        if isinstance(full_name, Datatype):
393            self.name = full_name.name
394            self.base_name = full_name.base_name
395            self.typebase = full_name.typebase
396            self.extension = full_name.extension
397            return
398        spl_name = full_name.split('[', maxsplit=1)
399        long_base = spl_name[0]
400        self.extension = spl_name[1][:-1] if len(spl_name) == 2 else None
401        self.typebase = TypeBase.add(long_base, module, force, validate)
402        ext_str = '[' + self.extension + ']' if self.extension else ''
403        self.base_name = self.typebase.name
404        self.name = self.typebase.name + ext_str
405        return
406
407    @property
408    def gen_type(self):
409        '''return the generic type of the Datatype'''
410        return self.typebase.gen_type
411
412    @property
413    def json_type(self):
414        '''return the json type of the Datatype'''
415        return self.typebase.json_type
416
417    @property
418    def category(self):
419        '''return the category of the Datatype'''
420        return self.typebase.category
421
422    @property
423    def nspace(self):
424        '''return the nspace of the Datatype'''
425        return self.typebase.nspace
426
427    @property
428    def custom(self):
429        '''return the custom of the Datatype'''
430        return self.typebase.custom
431
432    @property
433    def validate(self):
434        '''return the validate of the Datatype'''
435        return self.typebase.validate
436
437    @classmethod
438    def add(cls, long_name, module=False, force=False, validate=None):
439        '''method eqivalent to the constructor'''
440        return cls(long_name, module, force, validate)
441
442
443class Namespace(NtvUtil):
444    ''' Namespace of NTV entities.
445
446    *Attributes :*
447
448    - **name** : String - name of the namespace
449    - **file** : string - location of the file init
450    - **content** : dict - {'type': <list of ntv_type names>,
451                            'namespace': <list of namespace names>}
452    - **parent** : Namespace - parent namespace
453    - **custom** : boolean - True if not referenced
454
455    The methods defined in this class are :
456
457    *staticmethods*
458    - `namespaces`
459
460    *classmethods*
461    - `add`
462
463    *dynamic values (@property)*
464    - `long_name`
465
466    *instance methods*
467    - `is_child`
468    - `is_parent`
469    '''
470    _pathconfig_ = 'https://raw.githubusercontent.com/loco-philippe/NTV/master/json_ntv/config/'
471    _global_ = "NTV_global_namespace.ini"
472
473    @staticmethod
474    def namespaces():
475        '''return the list of Namespace created'''
476        return [nam.long_name for nam in NtvUtil._namespaces_.values()]
477
478    @classmethod
479    def add(cls, long_name, module=False, force=False):
480        '''activate and return a valid Namespace defined by the long_name.
481
482        *parameters :*
483
484        - **long_name** : String - absolut name of the Namespace
485        - **module** : boolean (default False) - if True search data in the
486        local .ini file, else in the distant repository
487        '''
488        if long_name in Namespace.namespaces():
489            return NtvUtil._namespaces_[long_name]
490        split_name = long_name.rsplit('.', 2)
491        if len(split_name) == 1 or split_name[-1] != '':
492            raise DatatypeError(long_name + ' is not a valid Namespace')
493        if len(split_name) == 2:
494            return cls(split_name[0]+'.', module=module, force=force)
495        if len(split_name) == 3:
496            parent = Namespace.add(split_name[0]+'.', force=force)
497            return cls(split_name[1]+'.', parent, module=module, force=force)
498        raise DatatypeError(long_name + ' is not a valid Namespace')
499
500    def __init__(self, name='', parent=None, module=False, force=False):
501        '''
502        Namespace constructor.
503
504        *Parameters*
505
506        - **name** : String - name of the namespace
507        - **parent** : Namespace - parent namespace
508        - **module** : boolean (default False) - if True search data in the
509                        local .ini file, else in the distant repository
510        - **content** : dict : {'type': <list of ntv_type names>,
511                                'namespace': <list of namespace names>}
512        '''
513        if name and not parent:
514            parent = NtvUtil._namespaces_['']
515        if parent and parent.file and SCH_ORG in parent.file:
516            if not _isin_schemaorg(name, False):
517                raise DatatypeError(name + ' is not a schema.org Type ')
518        else:
519            if name and not (name[0] == '$' or force or name in parent.content['namespace']):
520                raise DatatypeError(
521                    name + ' is not defined in ' + parent.long_name)
522        self.name = name
523        self.parent = parent
524        self.custom = parent.custom or name[0] == '$' if parent else False
525        self.file = Namespace._file(
526            self.parent, self.name, self.custom, module)
527        self.content = Namespace._content(
528            self.file, self.name, self.custom, module)
529        NtvUtil._namespaces_[self.long_name] = self
530
531    def __eq__(self, other):
532        ''' equal if name and parent are equal'''
533        if self is None and other is None:
534            return True
535        if self is None or other is None:
536            return False
537        if self.__class__.__name__ != other.__class__.__name__:
538            return False
539        return self.name == other.name and self.parent == other.parent
540
541    def __hash__(self):
542        '''return hash(name) + hash(parent)'''
543        return hash(self.name) + hash(self.parent)
544
545    def __str__(self):
546        '''return string format'''
547        return self.long_name
548
549    def __repr__(self):
550        '''return classname and long name'''
551        return self.__class__.__name__ + '(' + self.long_name + ')'
552
553    @staticmethod
554    def _file(parent, name, custom, module):
555        '''return the file name of the Namespace configuration
556
557        *parameters :*
558
559        - **parent** : Namespace - Parent of the Namespace
560        - **name** : String - name of the Namespace
561        - **custom** : boolean - if True, return None (custom Namespace)
562        - **module** : boolean (default False) - if True search data in the
563        local .ini file, else in the distant repository
564        '''
565        if custom:
566            return None
567        if parent:
568            if 'schema.org' in parent.file or name == 'org.':
569                return SCH_ORG
570            config = configparser.ConfigParser()
571            if module:
572                p_file = Path(parent.file).stem + Path(parent.file).suffix
573                config.read(Path(json_ntv.__file__).parent / 'config' / p_file)
574            else:
575                config.read_string(requests.get(
576                    parent.file, allow_redirects=True, timeout=10).content.decode())
577            return Namespace._pathconfig_ + json.loads(config['data']['namespace'])[name]
578        return Namespace._pathconfig_ + Namespace._global_
579
580    @staticmethod
581    def _content(file, name, custom, module):
582        '''return the content of the Namespace configuration
583
584        *parameters :*
585
586        - **file** : string - file name of the parent Namespace
587        - **name** : string - name of the Namespace
588        - **custom** : boolean - if True, return empty dict (custom Namespace)
589        - **module** : boolean (default False) - if True search data in the
590        local .ini file, else in the distant repository
591
592        *return :*
593
594        - dict : {'type': <list of ntv_type names>,
595                  'namespace': <list of namespace names>}
596        '''
597        if custom or 'schema.org' in file:
598            return {'type': {}, 'namespace': {}}
599        config = configparser.ConfigParser()
600        if module:
601            p_file = Path(file).stem + Path(file).suffix
602            config.read(Path(json_ntv.__file__).parent / 'config' / p_file)
603        else:
604            config.read_string(requests.get(
605                file, allow_redirects=True, timeout=10).content.decode())
606        config_name = config['data']['name']
607        if config_name != name:
608            raise DatatypeError(file + ' is not correct')
609        return {'type': json.loads(config['data']['type']),
610                'namespace': json.loads(config['data']['namespace'])}
611
612    @property
613    def long_name(self):
614        '''return a string with the absolute name'''
615        if self.parent is None or self.parent.name == '':
616            return self.name
617        return self.parent.long_name + self.name
618
619    def is_child(self, nspace):
620        '''return the number of level between self and nspace, -1 if None'''
621        parent = self.parent
622        if self == nspace:
623            return 0
624        if not self.name:
625            return -1
626        rang = 1
627        while parent.name != '' and parent != nspace:
628            rang += 1
629            parent = parent.parent
630        if parent == nspace:
631            return rang
632        return -1
633
634    def is_parent(self, nspace):
635        '''return the number of level between self and nspace, -1 if None'''
636        return nspace.is_child(self)
637
638
639class DatatypeError(Exception):
640    ''' Datatype or Namespace Exception'''
641
642
643nroot = Namespace(module=True)
644for root_typ in nroot.content['type']:
645    # typ = Datatype(root_typ, module=True,
646    Datatype(root_typ, module=True,
647             validate=Validator.__dict__[root_typ + '_valid'])
648# mapping(Datatype.types())
649typ_json = Datatype('json')
SCH_ORG = 'https://schema.org/'
def agreg_type(str_typ, def_type, single):
31def agreg_type(str_typ, def_type, single):
32    '''aggregate str_typ and def_type to return an Datatype or a Namespace if not single
33
34    *Parameters*
35
36        - **str_typ** : Datatype or String (long_name) - Datatype to aggregate
37        - **def_typ** : Datatype or String (long_name) - default Datatype or Namespace
38        - **single** : Boolean - Ntv entity concerned (True if NtvSingle)'''
39    if isinstance(str_typ, Datatype):
40        str_typ = str_typ.long_name
41    def_type = str_type(def_type, single)
42    if not str_typ and (not single or isinstance(def_type, Datatype)):
43        return def_type
44    if not str_typ:
45        return Datatype('json')
46    clas = Namespace if str_typ[-1] == '.' else Datatype
47    if not def_type:
48        return clas.add(str_typ)
49    if clas == Datatype or clas == Namespace and not single:
50        try:
51            return clas.add(str_typ)
52        except DatatypeError:
53            for typ in _join_type(def_type.long_name, str_typ):
54                try:
55                    return clas.add(typ)
56                except DatatypeError:
57                    pass
58    raise DatatypeError(str_typ + ' and ' +
59                        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):
62def from_file(file, name, long_parent=None):
63    '''create a set of Datatype and Namespace associated to a custom Namespace
64
65    *Parameters*
66
67        - **file** : .ini file - description of the Datatype and Namespace
68        - **name** : string - name of the root custom Namespace
69        - **long_parent** : longname of the parent Namespace of the root Namespace
70    '''
71    long_parent = '' if not long_parent else long_parent
72    if name[0] != '$':
73        raise DatatypeError(name + ' is not a custom Datatype')
74    if long_parent not in Namespace.namespaces():
75        raise DatatypeError(long_parent + ' is not a valid Datatype')
76    schema_nsp = Namespace(name, long_parent)
77    config = configparser.ConfigParser()
78    config.read(file)
79    if name not in config.sections():
80        raise DatatypeError(name + ' is not present in ' + str(file))
81    _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 mapping(typ=None, func=None):
84def mapping(typ=None, func=None):
85    '''Affect a validate function (func) to a Datatype (typ) '''
86    if typ and func:
87        Datatype(typ).validate = func
88    else:
89        if isinstance(typ, str):
90            func_lis = [typ + '_valid']
91        elif isinstance(typ, (list, tuple)):
92            func_lis = [typ_str + '_valid' for typ_str in typ]
93        else:
94            func_lis = [typ_str + '_valid' for typ_str in Datatype._types_]
95        for func_str in func_lis:
96            if func_str in Validator.__dict__:
97                Datatype(func_str[:-6]).validate = Validator.__dict__[func_str]

Affect a validate function (func) to a Datatype (typ)

def relative_type(str_def, str_typ):
100def relative_type(str_def, str_typ):
101    '''return relative str_typ string from Datatype or Namespace str_def
102
103    *Parameters*
104
105        - **str_def** : String - long_name of the Namespace or Datatype
106        - **str_type** : String - long_name of Ntvtype to be relative '''
107    if not str_def and not str_typ:
108        return ''
109    if str_def == str_typ:
110        return ''
111    if not str_def or str_def not in str_typ:
112        return str_typ
113    if not str_typ and str_def[-1] != ".":
114        return str_def
115    str_def_split = str_def.split('.')[:-1]
116    str_typ_split = str_typ.split('.')
117    ind = 0
118    for ind, name in enumerate(str_typ_split):
119        if name not in str_def_split:
120            break
121    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):
124def str_type(long_name, single):
125    ''' create a Datatype or a Namespace from a string
126
127    *Parameters*
128
129        - **long_name** : String - name of the Namespace or Datatype
130        - **single** : Boolean - If True, default type is 'json', else None'''
131    if not long_name and single:
132        return Datatype('json')
133    if not long_name and not single:
134        return None
135    if long_name.__class__.__name__ in ['Datatype', 'Namespace']:
136        return long_name
137    if not isinstance(long_name, str):
138        raise DatatypeError('the long_name is not a string')
139    if long_name[-1] == '.':
140        return Namespace.add(long_name)
141    return Datatype(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 TypeBase(json_ntv.ntv_util.NtvUtil):
189class TypeBase(NtvUtil):
190    ''' type of NTV entities.
191
192    *Attributes :*
193
194    - **name** : String - name of the type
195    - **nspace** : Namespace - namespace associated
196    - **custom** : boolean - True if not referenced
197    - **validate** : function (default None) - validate function
198
199    The methods defined in this class are :
200
201    *staticmethods*
202    - `types`
203    - `add`
204
205    *dynamic values (@property)*
206    - `category`
207    - `json_type`
208    - `gen_type`
209    - `long_name`
210
211    *instance methods*
212    - `isin_namespace`
213    '''
214
215    @staticmethod
216    def types():
217        '''return the list of TypeBase created'''
218        return [nam.long_name for nam in NtvUtil._types_.values()]
219
220    @classmethod
221    def add(cls, long_name, module=False, force=False, validate=None):
222        '''activate and return a valid TypeBase defined by the long name
223
224        *parameters :*
225
226        - **long_name** : String - absolut name of the TypeBase
227        - **module** : boolean (default False) - if True search data in the
228        local .ini file, else in the distant repository
229        - **validate** : function (default None) - validate function to include
230        '''
231        if long_name == '':
232            return None
233        if long_name in cls.types():
234            return NtvUtil._types_[long_name]
235        split_name = long_name.rsplit('.', 1)
236        if split_name[-1] == '':
237            raise DatatypeError(long_name + ' is not a valid TypeBase')
238        if len(split_name) == 1:
239            return cls(split_name[0], force=force, validate=validate)
240        if len(split_name) == 2:
241            nspace = Namespace.add(
242                split_name[0]+'.', module=module, force=force)
243            return cls(split_name[1], nspace, force=force)
244        raise DatatypeError(long_name + ' is not a valid TypeBase')
245
246    def __init__(self, name, nspace=None, force=False, validate=None):
247        '''TypeBase constructor.
248
249        *Parameters*
250
251        - **name** : string - name of the Type
252        - **nspace** : Namespace (default None) - namespace associated
253        - **force** : boolean (default False) - if True, no Namespace control
254        - **validate** : function (default None) - validate function to include'''
255        if isinstance(name, TypeBase):
256            self.name = name.name
257            self.nspace = name.nspace
258            self.custom = name.custom
259            self.validate = name.validate
260            # self.gen_type = name.gen_type
261            # self.long_name = name.long_name
262            return
263        if not name or not isinstance(name, str):
264            raise DatatypeError('null name is not allowed')
265        if not name and not nspace:
266            name = 'json'
267        if not nspace:
268            nspace = NtvUtil._namespaces_['']
269        if nspace.file and SCH_ORG in nspace.file:
270            if not _isin_schemaorg(name, typ=nspace.name):
271                raise DatatypeError(name +
272                                    ' is not a schema.org Property associated to the ' +
273                                    nspace.name + 'Type ')
274        else:
275            if not (name[0] == '$' or force or name in nspace.content['type']):
276                raise DatatypeError(
277                    name + ' is not defined in ' + nspace.long_name)
278        self.name = name
279        self.nspace = nspace
280        self.custom = nspace.custom or name[0] == '$'
281        # self.gen_type = '' if self.custom else self.nspace.content['type'][self.name]
282        # self.long_name = self.nspace.long_name + self.name
283        if validate:
284            self.validate = validate
285        NtvUtil._types_[self.long_name] = self
286        return
287
288    def __eq__(self, other):
289        ''' equal if name and nspace are equal'''
290        if self is None and other is None:
291            return True
292        if self is None or other is None:
293            return False
294        if self.__class__.__name__ != other.__class__.__name__:
295            return False
296        return self.name == other.name and self.nspace == other.nspace
297
298    def __hash__(self):
299        '''return hash(name) + hash(nspace)'''
300        return hash(self.name) + hash(self.nspace)
301
302    def __str__(self):
303        '''return string format'''
304        return self.long_name
305
306    def __repr__(self):
307        '''return classname and long name'''
308        return self.__class__.__name__ + '(' + self.long_name + ')'
309
310    @property
311    def json_type(self):
312        '''return the json type of the TypeBase'''
313        if self.custom:
314            return ''
315        prop = self.nspace.content['type'][self.name]
316        if isinstance(prop, list):
317            return prop[1]
318        return 'json'
319
320    @property
321    def category(self):
322        '''return the category of the TypeBase'''
323        if self.custom:
324            return ''
325        prop = self.nspace.content['type'][self.name]
326        if isinstance(prop, list):
327            return prop[2]
328        return 'local'
329
330    @property
331    def gen_type(self):
332        '''return the generic type of the TypeBase'''
333        if self.custom:
334            return ''
335        prop = self.nspace.content['type'][self.name]
336        if isinstance(prop, list):
337            return prop[0]
338        return prop
339
340    @property
341    def long_name(self):
342        '''return a string with the absolute name'''
343        return self.nspace.long_name + self.name
344
345    def isin_namespace(self, long_name):
346        '''return the number of level between self and nspace, -1 if None'''
347        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
  • validate : function (default None) - validate function

The methods defined in this class are :

staticmethods

dynamic values (@property)

instance methods

TypeBase(name, nspace=None, force=False, validate=None)
246    def __init__(self, name, nspace=None, force=False, validate=None):
247        '''TypeBase constructor.
248
249        *Parameters*
250
251        - **name** : string - name of the Type
252        - **nspace** : Namespace (default None) - namespace associated
253        - **force** : boolean (default False) - if True, no Namespace control
254        - **validate** : function (default None) - validate function to include'''
255        if isinstance(name, TypeBase):
256            self.name = name.name
257            self.nspace = name.nspace
258            self.custom = name.custom
259            self.validate = name.validate
260            # self.gen_type = name.gen_type
261            # self.long_name = name.long_name
262            return
263        if not name or not isinstance(name, str):
264            raise DatatypeError('null name is not allowed')
265        if not name and not nspace:
266            name = 'json'
267        if not nspace:
268            nspace = NtvUtil._namespaces_['']
269        if nspace.file and SCH_ORG in nspace.file:
270            if not _isin_schemaorg(name, typ=nspace.name):
271                raise DatatypeError(name +
272                                    ' is not a schema.org Property associated to the ' +
273                                    nspace.name + 'Type ')
274        else:
275            if not (name[0] == '$' or force or name in nspace.content['type']):
276                raise DatatypeError(
277                    name + ' is not defined in ' + nspace.long_name)
278        self.name = name
279        self.nspace = nspace
280        self.custom = nspace.custom or name[0] == '$'
281        # self.gen_type = '' if self.custom else self.nspace.content['type'][self.name]
282        # self.long_name = self.nspace.long_name + self.name
283        if validate:
284            self.validate = validate
285        NtvUtil._types_[self.long_name] = self
286        return

TypeBase constructor.

Parameters

  • name : string - name of the Type
  • nspace : Namespace (default None) - namespace associated
  • force : boolean (default False) - if True, no Namespace control
  • validate : function (default None) - validate function to include
@staticmethod
def types():
215    @staticmethod
216    def types():
217        '''return the list of TypeBase created'''
218        return [nam.long_name for nam in NtvUtil._types_.values()]

return the list of TypeBase created

@classmethod
def add(cls, long_name, module=False, force=False, validate=None):
220    @classmethod
221    def add(cls, long_name, module=False, force=False, validate=None):
222        '''activate and return a valid TypeBase defined by the long name
223
224        *parameters :*
225
226        - **long_name** : String - absolut name of the TypeBase
227        - **module** : boolean (default False) - if True search data in the
228        local .ini file, else in the distant repository
229        - **validate** : function (default None) - validate function to include
230        '''
231        if long_name == '':
232            return None
233        if long_name in cls.types():
234            return NtvUtil._types_[long_name]
235        split_name = long_name.rsplit('.', 1)
236        if split_name[-1] == '':
237            raise DatatypeError(long_name + ' is not a valid TypeBase')
238        if len(split_name) == 1:
239            return cls(split_name[0], force=force, validate=validate)
240        if len(split_name) == 2:
241            nspace = Namespace.add(
242                split_name[0]+'.', module=module, force=force)
243            return cls(split_name[1], nspace, force=force)
244        raise DatatypeError(long_name + ' is not a valid TypeBase')

activate and return a valid TypeBase defined by the long name

parameters :

  • long_name : String - absolut name of the TypeBase
  • module : boolean (default False) - if True search data in the local .ini file, else in the distant repository
  • validate : function (default None) - validate function to include
name
nspace
custom
json_type
310    @property
311    def json_type(self):
312        '''return the json type of the TypeBase'''
313        if self.custom:
314            return ''
315        prop = self.nspace.content['type'][self.name]
316        if isinstance(prop, list):
317            return prop[1]
318        return 'json'

return the json type of the TypeBase

category
320    @property
321    def category(self):
322        '''return the category of the TypeBase'''
323        if self.custom:
324            return ''
325        prop = self.nspace.content['type'][self.name]
326        if isinstance(prop, list):
327            return prop[2]
328        return 'local'

return the category of the TypeBase

gen_type
330    @property
331    def gen_type(self):
332        '''return the generic type of the TypeBase'''
333        if self.custom:
334            return ''
335        prop = self.nspace.content['type'][self.name]
336        if isinstance(prop, list):
337            return prop[0]
338        return prop

return the generic type of the TypeBase

long_name
340    @property
341    def long_name(self):
342        '''return a string with the absolute name'''
343        return self.nspace.long_name + self.name

return a string with the absolute name

def isin_namespace(self, long_name):
345    def isin_namespace(self, long_name):
346        '''return the number of level between self and nspace, -1 if None'''
347        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
is_dictable
from_obj_name
decode_ntv_tab
to_ntvpointer
class Datatype(TypeBase):
350class Datatype(TypeBase):
351    ''' The Datatype of NTV entities is composed with a TypeBase and an optional
352    extension.
353
354    *Attributes :*
355
356    - **name** : String - name of the Datatype
357    - **base_name** : String - name of the TypeBase
358    - **nspace** : Namespace - namespace associated
359    - **custom** : boolean - True if not referenced
360    - **validate** : function (default None) - validate function
361    - **typebase** : TypeBase - TypeBase of the Datatype
362    - **extension** : String (default None) - extension of the TypeBase
363
364    The methods defined in this class are :
365
366    *classmethod*
367    - `add`
368
369    *dynamic values (@property)*
370    - `category`
371    - `json_type`
372    - `gen_type`
373    - `long_name` (TypeBase)
374
375    *staticmethods*
376    - `types` (TypeBase)
377
378    *instance methods*
379    - `isin_namespace` (TypeBase)
380    - `validate` (TypeBase)
381    '''
382
383    def __init__(self, full_name, module=False, force=False, validate=None):
384        '''DataType constructor.
385
386        *Parameters*
387
388        - **full_name** : String - absolut name of the Datatype
389        - **module** : boolean (default False) - if True search data in the
390        local .ini file, else in the distant repository
391        - **force** : boolean (default False) - if True, no Namespace control
392        - **validate** : function (default None) - validate function to include'''
393        if isinstance(full_name, Datatype):
394            self.name = full_name.name
395            self.base_name = full_name.base_name
396            self.typebase = full_name.typebase
397            self.extension = full_name.extension
398            return
399        spl_name = full_name.split('[', maxsplit=1)
400        long_base = spl_name[0]
401        self.extension = spl_name[1][:-1] if len(spl_name) == 2 else None
402        self.typebase = TypeBase.add(long_base, module, force, validate)
403        ext_str = '[' + self.extension + ']' if self.extension else ''
404        self.base_name = self.typebase.name
405        self.name = self.typebase.name + ext_str
406        return
407
408    @property
409    def gen_type(self):
410        '''return the generic type of the Datatype'''
411        return self.typebase.gen_type
412
413    @property
414    def json_type(self):
415        '''return the json type of the Datatype'''
416        return self.typebase.json_type
417
418    @property
419    def category(self):
420        '''return the category of the Datatype'''
421        return self.typebase.category
422
423    @property
424    def nspace(self):
425        '''return the nspace of the Datatype'''
426        return self.typebase.nspace
427
428    @property
429    def custom(self):
430        '''return the custom of the Datatype'''
431        return self.typebase.custom
432
433    @property
434    def validate(self):
435        '''return the validate of the Datatype'''
436        return self.typebase.validate
437
438    @classmethod
439    def add(cls, long_name, module=False, force=False, validate=None):
440        '''method eqivalent to the constructor'''
441        return cls(long_name, module, force, validate)

The Datatype of NTV entities is composed with a TypeBase and an optional extension.

Attributes :

  • name : String - name of the Datatype
  • base_name : String - name of the TypeBase
  • nspace : Namespace - namespace associated
  • custom : boolean - True if not referenced
  • validate : function (default None) - validate function
  • typebase : TypeBase - TypeBase of the Datatype
  • extension : String (default None) - extension of the TypeBase

The methods defined in this class are :

classmethod

dynamic values (@property)

staticmethods

instance methods

Datatype(full_name, module=False, force=False, validate=None)
383    def __init__(self, full_name, module=False, force=False, validate=None):
384        '''DataType constructor.
385
386        *Parameters*
387
388        - **full_name** : String - absolut name of the Datatype
389        - **module** : boolean (default False) - if True search data in the
390        local .ini file, else in the distant repository
391        - **force** : boolean (default False) - if True, no Namespace control
392        - **validate** : function (default None) - validate function to include'''
393        if isinstance(full_name, Datatype):
394            self.name = full_name.name
395            self.base_name = full_name.base_name
396            self.typebase = full_name.typebase
397            self.extension = full_name.extension
398            return
399        spl_name = full_name.split('[', maxsplit=1)
400        long_base = spl_name[0]
401        self.extension = spl_name[1][:-1] if len(spl_name) == 2 else None
402        self.typebase = TypeBase.add(long_base, module, force, validate)
403        ext_str = '[' + self.extension + ']' if self.extension else ''
404        self.base_name = self.typebase.name
405        self.name = self.typebase.name + ext_str
406        return

DataType constructor.

Parameters

  • full_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
  • force : boolean (default False) - if True, no Namespace control
  • validate : function (default None) - validate function to include
extension
typebase
base_name
name
gen_type
408    @property
409    def gen_type(self):
410        '''return the generic type of the Datatype'''
411        return self.typebase.gen_type

return the generic type of the Datatype

json_type
413    @property
414    def json_type(self):
415        '''return the json type of the Datatype'''
416        return self.typebase.json_type

return the json type of the Datatype

category
418    @property
419    def category(self):
420        '''return the category of the Datatype'''
421        return self.typebase.category

return the category of the Datatype

nspace
423    @property
424    def nspace(self):
425        '''return the nspace of the Datatype'''
426        return self.typebase.nspace

return the nspace of the Datatype

custom
428    @property
429    def custom(self):
430        '''return the custom of the Datatype'''
431        return self.typebase.custom

return the custom of the Datatype

validate
433    @property
434    def validate(self):
435        '''return the validate of the Datatype'''
436        return self.typebase.validate

return the validate of the Datatype

@classmethod
def add(cls, long_name, module=False, force=False, validate=None):
438    @classmethod
439    def add(cls, long_name, module=False, force=False, validate=None):
440        '''method eqivalent to the constructor'''
441        return cls(long_name, module, force, validate)

method eqivalent to the constructor

Inherited Members
TypeBase
types
long_name
isin_namespace
json_ntv.ntv_util.NtvUtil
is_dictable
from_obj_name
decode_ntv_tab
to_ntvpointer
class Namespace(json_ntv.ntv_util.NtvUtil):
444class Namespace(NtvUtil):
445    ''' Namespace of NTV entities.
446
447    *Attributes :*
448
449    - **name** : String - name of the namespace
450    - **file** : string - location of the file init
451    - **content** : dict - {'type': <list of ntv_type names>,
452                            'namespace': <list of namespace names>}
453    - **parent** : Namespace - parent namespace
454    - **custom** : boolean - True if not referenced
455
456    The methods defined in this class are :
457
458    *staticmethods*
459    - `namespaces`
460
461    *classmethods*
462    - `add`
463
464    *dynamic values (@property)*
465    - `long_name`
466
467    *instance methods*
468    - `is_child`
469    - `is_parent`
470    '''
471    _pathconfig_ = 'https://raw.githubusercontent.com/loco-philippe/NTV/master/json_ntv/config/'
472    _global_ = "NTV_global_namespace.ini"
473
474    @staticmethod
475    def namespaces():
476        '''return the list of Namespace created'''
477        return [nam.long_name for nam in NtvUtil._namespaces_.values()]
478
479    @classmethod
480    def add(cls, long_name, module=False, force=False):
481        '''activate and return a valid Namespace defined by the long_name.
482
483        *parameters :*
484
485        - **long_name** : String - absolut name of the Namespace
486        - **module** : boolean (default False) - if True search data in the
487        local .ini file, else in the distant repository
488        '''
489        if long_name in Namespace.namespaces():
490            return NtvUtil._namespaces_[long_name]
491        split_name = long_name.rsplit('.', 2)
492        if len(split_name) == 1 or split_name[-1] != '':
493            raise DatatypeError(long_name + ' is not a valid Namespace')
494        if len(split_name) == 2:
495            return cls(split_name[0]+'.', module=module, force=force)
496        if len(split_name) == 3:
497            parent = Namespace.add(split_name[0]+'.', force=force)
498            return cls(split_name[1]+'.', parent, module=module, force=force)
499        raise DatatypeError(long_name + ' is not a valid Namespace')
500
501    def __init__(self, name='', parent=None, module=False, force=False):
502        '''
503        Namespace constructor.
504
505        *Parameters*
506
507        - **name** : String - name of the namespace
508        - **parent** : Namespace - parent namespace
509        - **module** : boolean (default False) - if True search data in the
510                        local .ini file, else in the distant repository
511        - **content** : dict : {'type': <list of ntv_type names>,
512                                'namespace': <list of namespace names>}
513        '''
514        if name and not parent:
515            parent = NtvUtil._namespaces_['']
516        if parent and parent.file and SCH_ORG in parent.file:
517            if not _isin_schemaorg(name, False):
518                raise DatatypeError(name + ' is not a schema.org Type ')
519        else:
520            if name and not (name[0] == '$' or force or name in parent.content['namespace']):
521                raise DatatypeError(
522                    name + ' is not defined in ' + parent.long_name)
523        self.name = name
524        self.parent = parent
525        self.custom = parent.custom or name[0] == '$' if parent else False
526        self.file = Namespace._file(
527            self.parent, self.name, self.custom, module)
528        self.content = Namespace._content(
529            self.file, self.name, self.custom, module)
530        NtvUtil._namespaces_[self.long_name] = self
531
532    def __eq__(self, other):
533        ''' equal if name and parent are equal'''
534        if self is None and other is None:
535            return True
536        if self is None or other is None:
537            return False
538        if self.__class__.__name__ != other.__class__.__name__:
539            return False
540        return self.name == other.name and self.parent == other.parent
541
542    def __hash__(self):
543        '''return hash(name) + hash(parent)'''
544        return hash(self.name) + hash(self.parent)
545
546    def __str__(self):
547        '''return string format'''
548        return self.long_name
549
550    def __repr__(self):
551        '''return classname and long name'''
552        return self.__class__.__name__ + '(' + self.long_name + ')'
553
554    @staticmethod
555    def _file(parent, name, custom, module):
556        '''return the file name of the Namespace configuration
557
558        *parameters :*
559
560        - **parent** : Namespace - Parent of the Namespace
561        - **name** : String - name of the Namespace
562        - **custom** : boolean - if True, return None (custom Namespace)
563        - **module** : boolean (default False) - if True search data in the
564        local .ini file, else in the distant repository
565        '''
566        if custom:
567            return None
568        if parent:
569            if 'schema.org' in parent.file or name == 'org.':
570                return SCH_ORG
571            config = configparser.ConfigParser()
572            if module:
573                p_file = Path(parent.file).stem + Path(parent.file).suffix
574                config.read(Path(json_ntv.__file__).parent / 'config' / p_file)
575            else:
576                config.read_string(requests.get(
577                    parent.file, allow_redirects=True, timeout=10).content.decode())
578            return Namespace._pathconfig_ + json.loads(config['data']['namespace'])[name]
579        return Namespace._pathconfig_ + Namespace._global_
580
581    @staticmethod
582    def _content(file, name, custom, module):
583        '''return the content of the Namespace configuration
584
585        *parameters :*
586
587        - **file** : string - file name of the parent Namespace
588        - **name** : string - name of the Namespace
589        - **custom** : boolean - if True, return empty dict (custom Namespace)
590        - **module** : boolean (default False) - if True search data in the
591        local .ini file, else in the distant repository
592
593        *return :*
594
595        - dict : {'type': <list of ntv_type names>,
596                  'namespace': <list of namespace names>}
597        '''
598        if custom or 'schema.org' in file:
599            return {'type': {}, 'namespace': {}}
600        config = configparser.ConfigParser()
601        if module:
602            p_file = Path(file).stem + Path(file).suffix
603            config.read(Path(json_ntv.__file__).parent / 'config' / p_file)
604        else:
605            config.read_string(requests.get(
606                file, allow_redirects=True, timeout=10).content.decode())
607        config_name = config['data']['name']
608        if config_name != name:
609            raise DatatypeError(file + ' is not correct')
610        return {'type': json.loads(config['data']['type']),
611                'namespace': json.loads(config['data']['namespace'])}
612
613    @property
614    def long_name(self):
615        '''return a string with the absolute name'''
616        if self.parent is None or self.parent.name == '':
617            return self.name
618        return self.parent.long_name + self.name
619
620    def is_child(self, nspace):
621        '''return the number of level between self and nspace, -1 if None'''
622        parent = self.parent
623        if self == nspace:
624            return 0
625        if not self.name:
626            return -1
627        rang = 1
628        while parent.name != '' and parent != nspace:
629            rang += 1
630            parent = parent.parent
631        if parent == nspace:
632            return rang
633        return -1
634
635    def is_parent(self, nspace):
636        '''return the number of level between self and nspace, -1 if None'''
637        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)
501    def __init__(self, name='', parent=None, module=False, force=False):
502        '''
503        Namespace constructor.
504
505        *Parameters*
506
507        - **name** : String - name of the namespace
508        - **parent** : Namespace - parent namespace
509        - **module** : boolean (default False) - if True search data in the
510                        local .ini file, else in the distant repository
511        - **content** : dict : {'type': <list of ntv_type names>,
512                                'namespace': <list of namespace names>}
513        '''
514        if name and not parent:
515            parent = NtvUtil._namespaces_['']
516        if parent and parent.file and SCH_ORG in parent.file:
517            if not _isin_schemaorg(name, False):
518                raise DatatypeError(name + ' is not a schema.org Type ')
519        else:
520            if name and not (name[0] == '$' or force or name in parent.content['namespace']):
521                raise DatatypeError(
522                    name + ' is not defined in ' + parent.long_name)
523        self.name = name
524        self.parent = parent
525        self.custom = parent.custom or name[0] == '$' if parent else False
526        self.file = Namespace._file(
527            self.parent, self.name, self.custom, module)
528        self.content = Namespace._content(
529            self.file, self.name, self.custom, module)
530        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():
474    @staticmethod
475    def namespaces():
476        '''return the list of Namespace created'''
477        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):
479    @classmethod
480    def add(cls, long_name, module=False, force=False):
481        '''activate and return a valid Namespace defined by the long_name.
482
483        *parameters :*
484
485        - **long_name** : String - absolut name of the Namespace
486        - **module** : boolean (default False) - if True search data in the
487        local .ini file, else in the distant repository
488        '''
489        if long_name in Namespace.namespaces():
490            return NtvUtil._namespaces_[long_name]
491        split_name = long_name.rsplit('.', 2)
492        if len(split_name) == 1 or split_name[-1] != '':
493            raise DatatypeError(long_name + ' is not a valid Namespace')
494        if len(split_name) == 2:
495            return cls(split_name[0]+'.', module=module, force=force)
496        if len(split_name) == 3:
497            parent = Namespace.add(split_name[0]+'.', force=force)
498            return cls(split_name[1]+'.', parent, module=module, force=force)
499        raise DatatypeError(long_name + ' is not a valid Namespace')

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
name
parent
custom
file
content
long_name
613    @property
614    def long_name(self):
615        '''return a string with the absolute name'''
616        if self.parent is None or self.parent.name == '':
617            return self.name
618        return self.parent.long_name + self.name

return a string with the absolute name

def is_child(self, nspace):
620    def is_child(self, nspace):
621        '''return the number of level between self and nspace, -1 if None'''
622        parent = self.parent
623        if self == nspace:
624            return 0
625        if not self.name:
626            return -1
627        rang = 1
628        while parent.name != '' and parent != nspace:
629            rang += 1
630            parent = parent.parent
631        if parent == nspace:
632            return rang
633        return -1

return the number of level between self and nspace, -1 if None

def is_parent(self, nspace):
635    def is_parent(self, nspace):
636        '''return the number of level between self and nspace, -1 if None'''
637        return nspace.is_child(self)

return the number of level between self and nspace, -1 if None

Inherited Members
json_ntv.ntv_util.NtvUtil
is_dictable
from_obj_name
decode_ntv_tab
to_ntvpointer
class DatatypeError(builtins.Exception):
640class DatatypeError(Exception):
641    ''' Datatype or Namespace Exception'''

Datatype or Namespace Exception

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
add_note
args
nroot = Namespace()
typ_json = Datatype(json)