Example #1
0
def get_ptypes(prop, property_type, type_stmt, one_class_per_module, identity_subclasses):
    if prop.stmt.keyword == 'anyxml':
        return ["'str'"]

    ptypes = []
    type_spec = type_stmt.i_type_spec
    types_extractor = TypesExtractor()
    if isinstance(type_spec, UnionTypeSpec):
        for contained_type_stmt in type_spec.types:
            contained_property_type = types_extractor.get_property_type(contained_type_stmt)
            ptypes.extend(get_ptypes(prop, contained_property_type, contained_type_stmt, one_class_per_module,
                                     identity_subclasses))
    else:
        ptypes.append(get_ptype(prop, property_type, type_stmt, one_class_per_module, identity_subclasses))
    return ptypes
Example #2
0
def get_ptypes(prop, property_type, type_stmt, one_class_per_module,
               identity_subclasses):
    if prop.stmt.keyword == 'anyxml':
        return ["'str'"]

    ptypes = []
    type_spec = type_stmt.i_type_spec
    types_extractor = TypesExtractor()
    if isinstance(type_spec, UnionTypeSpec):
        for contained_type_stmt in type_spec.types:
            contained_property_type = types_extractor.get_property_type(
                contained_type_stmt)
            ptypes.extend(
                get_ptypes(prop, contained_property_type, contained_type_stmt,
                           one_class_per_module, identity_subclasses))
    else:
        ptypes.append(
            get_ptype(prop, property_type, type_stmt, one_class_per_module,
                      identity_subclasses))
    return ptypes
Example #3
0
 def _get_union_types(self, union_leaf):
     union_type = union_leaf.property_type
     contained_types = set()
     for contained_type_stmt in union_type.types:
         contained_property_type = TypesExtractor().get_property_type(contained_type_stmt)
         if isinstance(contained_property_type, UnionTypeSpec):
             contained_types.update(self._get_union_types(contained_property_type))
         elif isinstance(contained_property_type, PathTypeSpec):
             contained_types.add('%s' % self._get_leafref_comment(union_leaf))
         else:
             contained_types.add(contained_type_stmt.i_type_spec.name)
     return contained_types
Example #4
0
def get_meta_info_data(prop, property_type, type_stmt):
    """ Gets an instance of MetaInfoData that has the useful information about the property.

        Args:
            prop: The property
            property_type : The type under consideration
            type_stmt : The type stmt currently under consideration 
    """
    clazz = prop.owner
    meta_info_data = MetaInfoData(prop)
    types_extractor = TypesExtractor()
    target_type_stmt = type_stmt

    if isinstance(property_type, Class):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(),
            property_type.qn())

        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link
        elif property_type.is_identity():
            meta_info_data.mtype = 'REFERENCE_IDENTITY_CLASS'
        else:
            meta_info_data.mtype = 'REFERENCE_CLASS'
        # if the class is local use just the local name
        if property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Enum):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(),
            property_type.qn())

        meta_info_data.mtype = 'REFERENCE_ENUM_CLASS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Bits):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(),
            property_type.qn())

        meta_info_data.mtype = 'REFERENCE_BITS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    else:
        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of '
        elif prop.stmt.keyword == 'anyxml':
            meta_info_data.mtype = 'ANYXML_CLASS'
            meta_info_data.doc_link = 'anyxml'
            meta_info_data.ptype = 'object'
            return meta_info_data
        else:
            meta_info_data.mtype = 'ATTRIBUTE'
            meta_info_data.doc_link = ''

        type_spec = type_stmt.i_type_spec

        while isinstance(type_spec, PathTypeSpec):
            if not hasattr(type_spec, 'i_target_node'):
                return None
            target_type_stmt = type_spec.i_target_node.search_one('type')
            type_spec = target_type_stmt.i_type_spec

        if isinstance(type_spec, BinaryTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, BitsTypeSpec):
            # This can happen in a Union
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, BooleanTypeSpec):
            meta_info_data.ptype = 'bool'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, Decimal64TypeSpec):
            meta_info_data.ptype = 'Decimal64'
            meta_info_data.prange.append(
                ('%s' % type_spec.min.s, '%s' % type_spec.max.s))
            # ' :ref:`Decimal64 <ydk_models_types_Decimal64>`'
            meta_info_data.doc_link += ':py:class:`Decimal64 <ydk.types.Decimal64>`'
        elif isinstance(type_spec, EmptyTypeSpec):
            meta_info_data.ptype = 'Empty'
            # ' :ref:`Empty <ydk_models_types_Empty>`'
            meta_info_data.doc_link += ':py:class:`Empty <ydk.types.Empty>`'
        elif isinstance(prop.property_type, Enum):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IdentityrefTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IntTypeSpec):
            meta_info_data.ptype = 'int'
            meta_info_data.doc_link += meta_info_data.ptype
            meta_info_data.prange.append((type_spec.min, type_spec.max))
        elif isinstance(type_spec, LengthTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
            meta_info_data.prange = get_length_limits(type_spec)

        elif isinstance(type_spec, PathTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, PatternTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
            while hasattr(
                    target_type_stmt,
                    'i_typedef') and target_type_stmt.i_typedef is not None:
                target_type_stmt = target_type_stmt.i_typedef.search_one(
                    'type')
            pattern = target_type_stmt.search_one('pattern')
            if pattern is not None:
                meta_info_data.pattern.append(pattern.arg.encode('ascii'))
        elif isinstance(type_spec, RangeTypeSpec):
            meta_info_data.ptype = get_range_base_type_name(type_spec)
            meta_info_data.prange = get_range_limits(type_spec)
            meta_info_data.doc_link += meta_info_data.ptype

        elif isinstance(type_spec, StringTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, UnionTypeSpec):
            # validate against all the data types
            meta_info_data.mtype = 'REFERENCE_UNION'
            meta_info_data.ptype = 'str'
            meta_info_data.property_type = type_spec
            if len(type_spec.types) > 0:
                # meta_info_data.doc_link += 'one of { '
                for contained_type_stmt in type_spec.types:
                    enum_type_stmt = types_extractor.get_enum_type_stmt(
                        contained_type_stmt)
                    bits_type_stmt = types_extractor.get_bits_type_stmt(
                        contained_type_stmt)
                    union_type_stmt = types_extractor.get_union_type_stmt(
                        contained_type_stmt)
                    contained_property_type = contained_type_stmt.i_type_spec
                    if isinstance(contained_property_type,
                                  IdentityrefTypeSpec):
                        contained_property_type = contained_property_type.base.i_identity.i_class
                    elif enum_type_stmt is not None:
                        # this is an enumeration
                        if not hasattr(enum_type_stmt, 'i_enum'):
                            raise EmitError('Failure to get i_enum')
                        contained_property_type = enum_type_stmt.i_enum
                    elif bits_type_stmt is not None:
                        # bits
                        contained_property_type = bits_type_stmt.i_bits
                    elif union_type_stmt is not None:
                        contained_property_type = union_type_stmt
                    child_meta_info_data = get_meta_info_data(
                        prop, contained_property_type, contained_type_stmt)
                    meta_info_data.children.append(child_meta_info_data)
                    # if meta_info_data.doc_link[-1:] != ' ':
                    #    meta_info_data.doc_link += ' | '
                    # meta_info_data.doc_link += child_meta_info_data.doc_link
                # meta_info_data.doc_link += ' }'

        elif isinstance(type_spec,
                        TypeSpec) and type_spec.name == 'instance-identifier':
            # Treat as string
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        else:
            raise EmitError('Illegal path')
    return meta_info_data
 def __init__(self, ctx):
     self.ctx = ctx
     self.types_extractor = TypesExtractor()
class TestCasePrinter(object):
    def __init__(self, ctx):
        self.ctx = ctx
        self.types_extractor = TypesExtractor()

    def print_testcases(self, package, identity_subclasses):
        assert isinstance(package, Package)
        self.identity_subclasses = identity_subclasses
        self._print_header(package)
        self._print_body([p for p in package.owned_elements if isinstance(p, Class) and not p.is_identity()])
        self._print_trailer()

    def _print_header(self, package):
        self._print_imports(package)
        self._print_class_header(package)

    def _print_body(self, clazzes):
        for clazz in clazzes:
            self._print_test_case(clazz)

    def _print_trailer(self):
        self.ctx.lvl_dec()
        self.ctx.bline()
        self.ctx.writeln("if __name__ == '__main__':")
        self.ctx.lvl_inc()
        self.ctx.writeln("unittest.main()")
        self.ctx.lvl_dec()

    def _print_imports(self, package):
        self._print_common_imports()
        imports_to_print = self._get_imports(package)
        for import_to_print in imports_to_print:
            self.ctx.writeln('%s' % import_to_print)
        self.ctx.bline()

        for top_element in [t for t in package.owned_elements if isinstance(t, Class) or isinstance(t, Enum)]:
            self.ctx.writeln('from %s import %s' %
                             (package.get_py_mod_name(), top_element.name))

    def _get_imports(self, package):
        imports_to_print = []
        for imported_type in package.imported_types():
            import_stmt = 'from %s import %s' % (
                imported_type.get_py_mod_name(), imported_type.qn().split('.')[0])
            if import_stmt in imports_to_print:
                continue
            else:
                imports_to_print.append(import_stmt)
        imports_to_print.extend(x for x in self._get_properties_imports(package) if x not in imports_to_print)
        imports_to_print = sorted(imports_to_print)
        return imports_to_print

    def _get_properties_imports(self, element):
        leafref_imports = []
        if isinstance(element, Class):
            for prop in element.properties():
                if isinstance(prop.property_type, Class) and prop.property_type.is_identity():
                    ref_class = self.identity_subclasses[prop.property_type][0]
                    child_class = ref_class
                    if ref_class in self.identity_subclasses:
                        child_class = self.identity_subclasses[ref_class][0]
                    leafref_imports.append('from %s import %s' % (child_class.get_py_mod_name(), child_class.qn().split('.')[0]))
                elif isinstance(prop.property_type, PathTypeSpec):
                    if prop.stmt.i_leafref_ptr is not None:
                        ref_class = prop.stmt.i_leafref_ptr[0].parent.i_class
                        leafref_imports.append('from %s import %s' % (ref_class.get_py_mod_name(), ref_class.qn().split('.')[0]))
        for clazz in [t for t in element.owned_elements if isinstance(t, Class) and t.is_config() and not t.is_identity()]:
            leafref_imports.extend(self._get_properties_imports(clazz))
        return leafref_imports

    def _print_common_imports(self):
        self.ctx.bline()
        self.ctx.writeln('import unittest')
        self.ctx.writeln('from tests.compare import is_equal')
        self.ctx.writeln('from ydk.providers import NativeNetconfServiceProvider')
        self.ctx.writeln('from ydk.services import CRUDService')
        self.ctx.writeln('from ydk.types import Decimal64, Empty')
        self.ctx.bline()

    def _print_class_header(self, package):
        self.ctx.bline()
        self.ctx.bline()
        self.ctx.writeln('class %sTest(unittest.TestCase):' % package.name)
        self.ctx.lvl_inc()
        self._print_setup_class()
        self._print_teardown_class()
        self._print_setup(package)
        self._print_teardown(package)

    def _print_setup_class(self):
        self.ctx.bline()
        self.ctx.writeln('@classmethod')
        self.ctx.writeln('def setUpClass(self):')
        self.ctx.lvl_inc()
        self.ctx.writeln('''self.ncc = NativeNetconfServiceProvider(address='127.0.0.1' ,
                            username='******', password='******', port=12022)''')
        self.ctx.writeln('self.crud = CRUDService()')
        self.ctx.lvl_dec()

    def _print_setup(self, package):
        self.ctx.bline()
        self.ctx.writeln('def setUp(self):')
        self.ctx.lvl_inc()
        self.ctx.writeln("print '\\nIn method '+ self._testMethodName + ':'")
        for p in package.owned_elements:
            if isinstance(p, Class) and not p.is_identity() and p.is_config():
                self._print_mandatory_leafs(p)
        self.ctx.lvl_dec()

    def _print_teardown(self, package):
        self.ctx.bline()
        self.ctx.writeln('def tearDown(self):')
        self.ctx.lvl_inc()
        top_elements = [p for p in package.owned_elements if isinstance(p, Class) and not p.is_identity() and p.is_config()]
        if len(top_elements) > 0:
            self.ctx.writeln('#TEARDOWN TOP ELEMENTS')
        else:
            self.ctx.writeln('pass')
            self.ctx.bline()
        for clazz in top_elements:
            self._print_class_instance(clazz, clazz.get_key_props(), suffix='_teardown')
            self.ctx.writeln('print "Teardown %s"' % get_obj_name(clazz))
            self.ctx.writeln('try:')
            self.ctx.lvl_inc()
            self.ctx.writeln('self.crud.delete(self.ncc, %s_teardown)' % get_obj_name(clazz))
            self.ctx.lvl_dec()
            self.ctx.writeln('except Exception as e:')
            self.ctx.lvl_inc()
            self.ctx.writeln('pass')
            self.ctx.lvl_dec()
            self.ctx.bline()
        self.ctx.lvl_dec()

    def _print_teardown_class(self):
        self.ctx.bline()
        self.ctx.writeln('@classmethod')
        self.ctx.writeln('def tearDownClass(self):')
        self.ctx.lvl_inc()
        self.ctx.writeln('''self.ncc.close()''')
        self.ctx.lvl_dec()

    def _print_test_case(self, clazz):
        for prop in clazz.properties():
            if isinstance(prop.property_type, Class) and not prop.property_type.is_identity():
                self._print_test_case(prop.property_type)
        self._print_test_case_header(clazz)
        self._print_test_case_body(clazz)
        self._print_test_case_trailer()

    def _print_test_case_header(self, clazz):
        self.ctx.writeln('def test_%s(self):' % ('_'.join([snake_case(f) for f in clazz.qn().split('.')])))
        self.ctx.lvl_inc()

    def _print_test_case_trailer(self):
        self.ctx.lvl_dec()
        self.ctx.bline()

    def _print_test_case_body(self, clazz):
        if not clazz.is_config():
            self.ctx.writeln("'''This is an oper field'''")
            self.ctx.writeln('pass')
        else:
            # start building the object tree
            self._print_leafref_references(clazz)
            self._print_parents_mandatory_leafs(clazz.owner)
            self.ctx.writeln('# CREATE')
            self._print_class_instance(clazz, clazz.properties(), suffix='')
            self._print_crud_operations(get_obj_name(clazz), clazz)

    def _print_class_instance(self, clazz, props, suffix):
        if clazz is None:
            return
        owner_obj_name = ''
        obj_name = get_obj_name_with_suffix(clazz, suffix)
        if clazz.owner is not None and isinstance(clazz.owner, Class):
            owner_obj_name = get_obj_name_with_suffix(clazz.owner, suffix)
        if isinstance(clazz, Class):
            self.ctx.writeln('%s = %s()' % (obj_name, clazz.qn()))            
            self._print_properties(obj_name, props)
            if len(clazz.get_key_props()) > 0:
                self._print_list_obj_append(clazz, clazz.owner, suffix)
        if isinstance(clazz.owner, Class):
            self._print_class_instance(clazz.owner, clazz.owner.get_key_props(), suffix)
        if clazz.owner is not None and isinstance(clazz.owner, Class):
            self.ctx.writeln('%s.parent = %s' % (obj_name, owner_obj_name))

    def _print_properties(self, obj_name, properties):
        for prop in properties:
            self._print_property(obj_name, prop)

    def _print_mandatory_leafs(self, element):
        mandatory_leafs = self._get_mandatory_leafs(element)
        if len(mandatory_leafs) > 0:
            self.ctx.writeln('#MANDATORY LEAFS CREATE')
        for mandatory_leaf in mandatory_leafs:
            leafs_to_set = mandatory_leaf.clazz.get_key_props()
            leafs_to_set.extend(x for x in mandatory_leaf.props if x not in leafs_to_set)
            self._print_class_instance(mandatory_leaf.clazz, leafs_to_set, suffix='')
            self.ctx.writeln('print "Creating mandatory %s"' % snake_case(mandatory_leaf.clazz.qn() + '.' + mandatory_leaf.props[0].name))
            self.ctx.writeln('self.crud.create(self.ncc, %s)' % get_obj_name(mandatory_leaf.clazz))
            self.ctx.bline()

    def _get_mandatory_leafs(self, element):
        mandatory_leafs = []
        if hasattr(element, 'properties'):
            mandatory_info = None
            for prop in element.properties():
                mandatory = prop.stmt.search_one('mandatory')
                if mandatory is not None and mandatory.arg == 'true':
                    if mandatory_info is None:
                        mandatory_info = LeafInfo(element)
                    mandatory_info.props.append(prop)
            if mandatory_info is not None:
                mandatory_leafs.append(mandatory_info)

        for p in element.owned_elements:
            if isinstance(p, Class) and (not p.is_identity()) and p.is_config() and (p.stmt.search_one('presence') is None) and len(p.get_key_props()) == 0:
                mandatory_leafs.extend(self._get_mandatory_leafs(p))

        return mandatory_leafs

    def _print_parents_mandatory_leafs(self,clazz):
        if isinstance(clazz, Class) and not clazz.is_identity() and clazz.is_config():
            if clazz.owner is not None:
                self._print_parents_mandatory_leafs(clazz.owner)
            self._print_mandatory_leafs(clazz)

    def _print_leafref_references(self, clazz):
        leaf_ref_infos = list(reversed(self._get_leafref_references(clazz)))
        if len(leaf_ref_infos) > 0:
            self.ctx.writeln('#LEAFREF REFERENCES CREATE')
        for leaf_info in leaf_ref_infos:
            reference_clazz = leaf_info.clazz
            leafs_to_set = leaf_info.props
            leafs_to_set.extend(x for x in reference_clazz.get_key_props() if x not in leafs_to_set)
            leafs_to_set.extend(x for x in reference_clazz.properties() if x.stmt.search_one('mandatory') is not None)
            self._print_class_instance(reference_clazz, leafs_to_set, '_reference')
            self.ctx.writeln('print "Creating reference %s"' % get_obj_name(reference_clazz))
            self.ctx.writeln('self.crud.create(self.ncc, %s_reference)' % get_obj_name(reference_clazz))
            self.ctx.bline()

    def _get_leafref_references(self, clazz):
        leaf_ref_infos = []
        info = None
        for prop in clazz.properties():
            if isinstance(prop.property_type, PathTypeSpec):
                if prop.stmt.i_leafref_ptr is not None:
                    if info is None:
                        info = LeafInfo(prop.stmt.i_leafref_ptr[0].parent.i_class)
                    info.props.append(prop.stmt.i_leafref_ptr[0].i_property)
        if info is not None and info not in leaf_ref_infos:
            leaf_ref_infos.append(info)

        if clazz.owner is not None and isinstance(clazz.owner, Class):
            leaf_ref_infos.extend([x for x in self._get_leafref_references(clazz.owner) if x not in leaf_ref_infos])

        return leaf_ref_infos

    def _print_property(self, obj_name, prop):
        format_string = '%s.%s = %s'
        if prop.stmt.keyword == 'leaf-list':
            format_string = '%s.%s.append(%s)'

        type_spec = prop.property_type
        type_stmt = prop.stmt.search_one('type')

        if isinstance(type_spec, UnionTypeSpec):
            if len(type_spec.types) > 0:
                type_spec, type_stmt = self._get_union_type_spec(type_spec.types[0])

        if type_stmt is not None:
            if 'prefix' in type_stmt.arg and 'ip' in type_stmt.arg:
                self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4/32'"))
                return
            elif 'address' in type_stmt.arg and 'ipv6'  in type_stmt.arg:
                self.ctx.writeln(format_string % (obj_name, prop.name, "'123::123'"))
                return
            elif 'address' in type_stmt.arg and 'ip' in type_stmt.arg:
                self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4'"))
                return
            elif 'host' in type_stmt.arg:
                self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4'"))
                return
            elif 'mac-address' in type_stmt.arg:
                self.ctx.writeln(format_string % (obj_name, prop.name, "'00:0a:95:9d:68:16'"))
                return

        if isinstance(type_spec, Class):
            if type_spec.is_identity():
                ref_class = self.identity_subclasses[type_spec][0]
                child_class = ref_class
                if ref_class in self.identity_subclasses:
                    child_class = self.identity_subclasses[ref_class][0]
                self.ctx.writeln(format_string % (obj_name, prop.name, child_class.qn() + '()'))
        elif isinstance(type_spec, Enum):
            self.ctx.writeln(format_string % (obj_name, prop.name, type_spec.qn() + '.' + type_spec.literals[0].name))
        elif isinstance(type_spec, Bits):
            self.ctx.writeln("%s.%s['%s'] = True" % (obj_name, prop.name, list(type_spec._dictionary.keys())[0]))
        else:
            target_type_stmt = None
            while isinstance(type_spec, PathTypeSpec):
                if not hasattr(type_spec, 'i_target_node'):
                    return
                target_type_stmt = type_spec.i_target_node.search_one('type')
                type_spec = target_type_stmt.i_type_spec

            if target_type_stmt is not None:
                if 'prefix' in target_type_stmt.arg and 'ip' in target_type_stmt.arg:
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4/32'"))
                    return
                elif 'address' in target_type_stmt.arg and 'ip' in target_type_stmt.arg:
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4'"))
                    return
                elif 'host' in target_type_stmt.arg:
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4'"))
                    return

            if isinstance(type_spec, StringTypeSpec):
                self.ctx.writeln(format_string % (obj_name, prop.name, "'Hello'"))
            elif isinstance(type_spec, LengthTypeSpec):
                ranges = meta_data_util.get_length_limits(type_spec)
                for min_limit, max_limit in ranges:
                    if isinstance(min_limit, int) and isinstance(max_limit, int):
                        size = (min_limit + max_limit) / 2
                    else:
                        size = min_limit + 1
                    test_string = generate_string_of_size(size)
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'" + test_string + "'"))
                    break
            elif isinstance(type_spec, IntTypeSpec):
                self.ctx.writeln(format_string % (obj_name, prop.name, '100'))
            elif isinstance(type_spec, RangeTypeSpec):
                ranges = meta_data_util.get_range_limits(type_spec)
                for min_limit, max_limit in ranges:
                    if isinstance(min_limit, int) and isinstance(max_limit, int):
                        size = (min_limit + max_limit) / 2
                    elif isinstance(min_limit, int):
                        size = min_limit + 1
                    else:
                        size = int(min_limit) + 1
                    self.ctx.writeln(format_string % (obj_name, prop.name, str(size)))
                    break
            elif isinstance(type_spec, Decimal64TypeSpec):
                self.ctx.writeln(format_string % (obj_name, prop.name, 'Decimal64("1.0")'))
            elif isinstance(type_spec, BooleanTypeSpec):
                self.ctx.writeln(format_string % (obj_name, prop.name, 'False'))
            elif isinstance(type_spec, BinaryTypeSpec):
                self.ctx.writeln(format_string % (obj_name, prop.name, "'0x00'"))
            elif  isinstance(type_spec, EmptyTypeSpec):
                self.ctx.writeln(format_string % (obj_name, prop.name, 'Empty()'))
            elif isinstance(type_spec, PatternTypeSpec):
                target_type_stmt = prop.stmt.search_one('type')
                while hasattr(target_type_stmt, 'i_typedef') and target_type_stmt.i_typedef is not None:
                    target_type_stmt = target_type_stmt.i_typedef.search_one('type')
                pattern = target_type_stmt.search_one('pattern')
                if pattern is not None:
                    if pattern.arg == '[\w\-\.:,_@#%$\+=\|;]+':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'abc'"))
                        return
                    elif pattern.arg == '(([a-zA-Z0-9_]*\d+/){3}\d+)|(([a-zA-Z0-9_]*\d+/){4}\d+)|(([a-zA-Z0-9_]*\d+/){3}\d+\.\d+)|(([a-zA-Z0-9_]*\d+/){2}([a-zA-Z0-9_]*\d+))|(([a-zA-Z0-9_]*\d+/){2}([a-zA-Z0-9_]+))|([a-zA-Z0-9_-]*\d+)|([a-zA-Z0-9_-]*\d+\.\d+)|(mpls)|(dwdm)':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'test1'"))
                        return
                    elif pattern.arg == '(!.+)|([^!].+)':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'!Hello'"))
                        return
                    elif pattern.arg == '[a-fA-F0-9]{2}(\.[a-fA-F0-9]{4}){3,9}\.[a-fA-F0-9]{2}':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'aa.aaaa.aaaa.aaaa.aa'"))
                        return
                    elif pattern.arg == '(act)|(pre)':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'act'"))
                        return
                    elif pattern.arg == '((([a-zA-Z0-9_]*\d+)|(\*))/){2}(([a-zA-Z0-9_]*\d+)|(\*))':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'test1/test1/test1'"))
                        return
                    elif pattern.arg == '[0-9a-fA-F]{1,8}':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'aaa'"))
                        return
                    elif pattern.arg == '[a-zA-Z0-9][a-zA-Z0-9\._@$%+#:=<>\-]{0,62}':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'Hello'"))
                        return
                    elif pattern.arg == '([0-9]|[1-5][0-9]|6[0-3])|(([0-9]|[1-5][0-9]|6[0-3])-([0-9]|[1-5][0-9]|6[0-3]))|(af11)|(af12)|(af13)|(af21)|(af22)|(af23)|(af31)|(af32)|(af33)|(af41)|(af42)|(af43)|(ef)|(default)|(cs1)|(cs2)|(cs3)|(cs4)|(cs5)|(cs6)|(cs7)':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'cs123'"))
                        return
                    elif pattern.arg == '(\d+)|(\d+\-\d+)':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'123'"))
                        return
                    elif pattern.arg == '([a-zA-Z0-9_]*\d+/){1,2}([a-zA-Z0-9_]*\d+)':
                        self.ctx.writeln(format_string % (obj_name, prop.name, "'a1/a2'"))
                        return
                if prop.name == 'masklength_range':
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'1..2'"))
                elif 'address' in prop.stmt.search_one('type').arg and 'ip' in prop.stmt.search_one('type').arg:
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'1.2.3.4'"))
                elif 'domain' in prop.stmt.search_one('type').arg and 'domain' in prop.stmt.search_one('type').arg:
                    self.ctx.writeln(format_string % (obj_name, prop.name, "'example.com'"))
                else:
#print prop.stmt.search_one('type').arg
#                    if pattern is not None:
#                        print pattern.arg, prop.name
                    self.ctx.writeln("#%s.%s = %s" % (obj_name, prop.name, "'Hello'"))
            else:
#                print prop.name, type_spec.arg
                self.ctx.writeln('#%s.%s = None' % (obj_name, prop.name))

    def _get_union_type_spec(self, type_stmt):
        contained_property_type = self.types_extractor.get_property_type(type_stmt)

        if isinstance(contained_property_type, UnionTypeSpec):
            return self._get_union_type_spec(contained_property_type.types[0])
        else:
            return contained_property_type, type_stmt

    def _print_list_obj_append(self, clazz, owner, suffix):
        parent_obj_name = get_obj_name_with_suffix(owner, suffix)
        prop_name = ''
        if isinstance(owner, Class):
            for prop in owner.properties():
                if isinstance(prop.property_type, Class) and prop.property_type.name == clazz.name:
                    prop_name = prop.name
                    break
        else:
            return
        self.ctx.writeln('%s = %s()' % (parent_obj_name, owner.qn()))
        self.ctx.writeln('%s.%s.append(%s)' % (parent_obj_name, prop_name, get_obj_name_with_suffix(clazz, suffix)))

    def _print_crud_operations(self, obj_name, clazz):
        self.ctx.writeln('print "Creating test %s"' % obj_name)
        self.ctx.writeln('self.crud.create(self.ncc, %s)' % obj_name)
        self._print_crud_read_test_operation(obj_name, clazz)
        self._print_crud_delete_operation(obj_name, clazz)

    def _print_crud_read_test_operation(self, obj_name, clazz):
        self.ctx.bline()
        self.ctx.writeln('# READ')
        self._print_class_instance(clazz, clazz.get_key_props(), suffix='_read')
        self.ctx.writeln('print "Reading test %s_read"' % obj_name)
        self.ctx.writeln('%s_read_output = self.crud.read(self.ncc, %s_read)' % (obj_name, obj_name))
        self.ctx.writeln('#self.assertEqual(is_equal(%s, %s_read_output), True)' % (obj_name, obj_name))

    def _print_crud_delete_operation(self, obj_name, clazz):
        self.ctx.bline()
        self.ctx.writeln('# DELETE')
        self._print_class_instance(clazz, clazz.get_key_props(), suffix='_delete')
        self.ctx.writeln('print "Deleting test %s_delete"' % obj_name)
        self.ctx.writeln('self.crud.delete(self.ncc, %s_delete)' % (obj_name))
Example #7
0
 def __init__(self, lang, identity_subclasses):
     self.lang = lang
     self.identity_subclasses = identity_subclasses
     self.types_extractor = TypesExtractor()
     self.type_spec = None
     self.type_stmt = None
Example #8
0
class ValueBuilder(object):
    """ Return value for terminal nodes (leaf or leaf-list)."""
    def __init__(self, lang, identity_subclasses):
        self.lang = lang
        self.identity_subclasses = identity_subclasses
        self.types_extractor = TypesExtractor()
        self.type_spec = None
        self.type_stmt = None

    def get_prop_value(self, prop, default=None):
        """Return value based on prop.

        Args:
            prop (ydkgen.api_model.Property): Terminal nodes' property.
            default (str): default value.

        Returns:
            prop_value: Value get based on YANG constraints. It could be
                string, integer, BitsValue, or IdentityValue.
        """
        self._set_prop_type(prop)
        prop_value = None

        if isinstance(self.type_spec, atypes.Bits):
            prop_value = self._handle_bits()
        elif is_identity_element(self.type_spec):
            prop_value = self._handle_identity()
        elif isinstance(self.type_spec, atypes.Enum):
            prop_value = self._handle_enum()
        elif isinstance(self.type_spec, ptypes.BinaryTypeSpec):
            prop_value = self._handle_binary()
        elif isinstance(self.type_spec, ptypes.BooleanTypeSpec):
            prop_value = self._handle_boolean(prop)
        elif isinstance(self.type_spec, ptypes.Decimal64TypeSpec):
            prop_value = self._handle_decimal64()
        elif isinstance(self.type_spec, ptypes.EmptyTypeSpec):
            prop_value = self._handle_empty()
        elif isinstance(self.type_spec, ptypes.LengthTypeSpec):
            prop_value = self._handle_length()
        elif isinstance(self.type_spec, ptypes.IntTypeSpec):
            prop_value = self._handle_int()
        elif isinstance(self.type_spec, ptypes.PatternTypeSpec):
            prop_value = self._handle_pattern(prop)
        elif isinstance(self.type_spec, ptypes.RangeTypeSpec):
            prop_value = self._handle_range()
        elif isinstance(self.type_spec, ptypes.StringTypeSpec):
            prop_value = self._handle_string(default=default)

        return prop_value

    def _handle_bits(self):
        """Chose an set a bit."""
        val = choice(list(self.type_spec._dictionary.keys()))
        return BitsValue(val=val, type_spec=self.type_spec)

    def _handle_identity(self):
        """Chose and return identity from available derived identities.
        Identity could come from different bundle.
        """
        identities = set()
        self._collect_identities(self.type_spec, identities)
        if (len(identities) == 0):
            return ''
        identity = choice(list(identities))
        identity_value = '{}()'.format(get_qn(self.lang, identity))
        return IdentityValue(val=identity_value, identity=identity)

    def _handle_enum(self):
        """Chose an return enum literal."""
        literal = choice(self.type_spec.literals)
        qn = get_qn(self.lang, self.type_spec)
        return self.nmsp_sep.join([qn, literal.name])

    def _handle_binary(self):
        """Return binary value."""
        random_string = self._get_string(0)
        if sys.version_info >= (3, 0):
            bin_string = base64.b64encode(str.encode(random_string)).decode()
        else:
            bin_string = base64.b64encode(random_string)
        return self._render_string(bin_string)

    def _handle_boolean(self, prop):
        """Chose and return boolean value."""
        boolean = str(bool(getrandbits(1)))
        # hard code to enable
        if prop.name == 'enabled':
            boolean = 'True'

        if self.lang == 'cpp':
            boolean = boolean.lower()

        return boolean

    def _handle_decimal64(self, low=None, high=None):
        """Generate and return decimal64 value based on YANG constraints."""
        low = self.type_spec.min if low is None else low
        high = self.type_spec.max if high is None else high

        decimal64 = randint(low.value, high.value)
        minus = '-' if decimal64 < 0 else ''
        decimal64 = '{:=19d}'.format(decimal64)
        fractions = self.type_spec.fraction_digits
        decimal64 = '.'.join([decimal64[:-fractions], decimal64[-fractions:]])
        decimal64 = decimal64.strip('- 0')
        if decimal64.endswith('.'):
            decimal64 += '0'
        decimal64 = '"{}{}"'.format(minus, decimal64)

        if self.lang == 'cpp':
            decimal64 = 'std::string{{{}}}'.format(decimal64)
        return 'Decimal64({})'.format(decimal64)

    def _handle_empty(self):
        """Return empty value."""
        return 'Empty()'

    def _handle_length(self):
        """YANG length statement restrict string or derived string type,
        return trimmed string."""
        low, high = choice(self._get_length_limits(self.type_spec))
        self.type_spec = self.type_spec.base
        self.type_stmt = get_typedef_stmt(self.type_stmt)
        return self._handle_string(low=low, high=high)

    def _handle_int(self, low=None, high=None):
        """Return integer value based on low and high limit."""
        low = 0 if low is None else low
        high = low if high is None else high
        return self._handle_int_range(low, high)

    def _handle_int_range(self, low, high):
        """Return integer value if the YANG type statement has a `range`
        substatement.
        """
        int_value = randint(low, high)
        range_stmt = self.type_stmt.search_one('range')
        if range_stmt is not None:
            if hasattr(range_stmt, 'i_type_spec'):
                self.type_stmt = range_stmt
                self.type_spec = range_stmt.i_type_spec
                int_value = self._handle_range()
            else:
                low, high = choice(range_stmt.arg.split('|')).split('..')
                low, high = self._render_range(low, high)
                int_value = randint(low, high)

        return int_value

    def _handle_pattern(self, prop):
        """Return string value based on YANG pattern statement.

        YANG regular expression syntax (XSD) is different from Python,
        need to use come hard code value.

        """
        patterns = self._collect_patterns()

        pattern = None
        for p in patterns:
            # ignore ipv4/ipv6 zone id pattern
            if '(%[\\p{N}\\p{L}]+)?' in p.arg:
                pattern = p.arg.replace('(%[\\p{N}\\p{L}]+)?', '')
                break

        if pattern is None:
            pattern = choice(patterns).arg

        pattern_value = self._get_string(pattern=pattern)

        if 'ipv4' in self.type_stmt.arg:
            pattern_value = '10.0.0.1'
        if 'ipv6' in self.type_stmt.arg:
            pattern_value = '2001:db8::ff:2'
        if 'domain-name' in self.type_stmt.arg:
            pattern_value = 'domain.name'
        if 'phys-address' in self.type_stmt.arg:
            pattern_value = '08:56:27:6f:2b:9c'
        if 'password' in prop.name:
            pattern_value = '$0$password'
        if 'masklength_range' in prop.name:
            pattern_value = '21..24'
        if 'access_operations' in prop.name:
            pattern_value = '*'
        if prop.name in ('ip_prefix', 'address_prefix', 'fec_address'):
            pattern_value = '10.0.0.1/32'

        pattern_value = pattern_value.strip(':').lower()

        return self._render_string(pattern_value)

    def _handle_range(self):
        """Return integer value or decimal64 value based on range statement.
        """
        low, high = choice(self._get_range_limits(self.type_spec))
        self.type_spec = self.type_spec.base
        self.type_stmt = get_typedef_stmt(self.type_stmt)
        if isinstance(self.type_spec, ptypes.IntTypeSpec):
            return self._handle_int(low=low, high=high)
        elif isinstance(self.type_spec, ptypes.Decimal64TypeSpec):
            return self._handle_decimal64(low=low, high=high)

    def _handle_string(self, default=None, low=None, high=None, pattern=None):
        """Return string value."""
        string_value = self._get_string(low, high)
        string_value = default if default is not None else string_value
        return self._render_string(string_value)

    def _render_string(self, value):
        """Remove null and control characters from value and trim value by
        language.
        """
        value = ''.join(c for c in value if ord(c) >= 32)
        if self.lang == 'py':
            return '"""%s"""' % value
        elif self.lang == 'cpp':
            return 'R"(%s)"' % value

    def _set_prop_type(self, prop):
        """Set self.type_spec and self.type_stmt:

            - Trace path statement and set destination statement's
              pyang statement as self.type_stmt, pyang TypeSpec as
              self.type_spec.
            - If prop represents union property, chose one.
        """
        type_spec = prop.property_type
        type_stmt = prop.stmt.search_one('type')

        if isinstance(type_spec, ptypes.PathTypeSpec):
            type_stmt = self._get_path_target_type_stmt(type_stmt)
            type_spec = type_stmt.i_type_spec

        if isinstance(type_spec, ptypes.UnionTypeSpec):
            type_spec, type_stmt = self._get_union_type_spec(type_spec)

        self.type_spec = type_spec
        self.type_stmt = type_stmt

    def _get_path_target_type_stmt(self, type_stmt):
        """Return target pyang statement."""
        type_spec = type_stmt.i_type_spec
        while all([
                isinstance(type_spec, ptypes.PathTypeSpec),
                hasattr(type_spec, 'i_target_node')
        ]):
            type_stmt = type_spec.i_target_node.search_one('type')
            type_spec = type_stmt.i_type_spec
        return type_stmt

    def _get_union_type_spec(self, orig_type_spec):
        """Return union type_spec and type_stmt."""
        type_spec = orig_type_spec
        while isinstance(type_spec, ptypes.UnionTypeSpec):
            type_stmt = choice(type_spec.types)
            type_spec = self.types_extractor.get_property_type(type_stmt)
            if hasattr(type_spec, 'i_type_spec'):
                type_spec = type_spec.i_type_spec

        return type_spec, type_stmt

    def _collect_patterns(self):
        """Collect all patterns for derived string type."""
        patterns = []
        type_stmt = self.type_stmt
        while all([
                hasattr(type_stmt, 'i_typedef')
                and type_stmt.i_typedef is not None
        ]):
            patterns.extend(type_stmt.search('pattern'))
            type_stmt = type_stmt.i_typedef.search_one('type')
        patterns.extend(type_stmt.search('pattern'))

        return patterns

    def _collect_identities(self, identity, identities):
        """Collect identities and derived identities."""
        identity_id = id(identity)
        if identity_id in self.identity_subclasses:
            derived_identities = set(self.identity_subclasses[identity_id])
            identities |= derived_identities
            for identity in derived_identities:
                self._collect_identities(identity, identities)

    def _get_string(self, low=None, high=None, pattern=None):
        """Return string from `pattern` or a universal pattern
        [0-9a-zA-Z].
        """
        low, high = self._render_range(low, high)
        if pattern is None or is_match_all(pattern):
            pattern = r'[0-9a-zA-Z]'
        return rstr.xeger(pattern).rstrip("\\\"")

    def _get_length_limits(self, length_type):
        """Get length limits."""
        lengths = []
        for low, high in length_type.lengths:
            low, high = self._render_range(low, high)
            lengths.append((low, high))
        return lengths

    def _get_range_limits(self, range_type):
        """Get range limits."""
        ranges = []
        for low, high in range_type.ranges:
            low = self._get_range_min(range_type) if low == 'min' else low
            high = self._get_range_max(range_type) if high == 'max' else high
            ranges.append((low, high))
        return ranges

    def _get_range_min(self, range_type):
        """Get range min value."""
        range_min = range_type.base.min
        if isinstance(range_type, ptypes.Decimal64TypeSpec):
            range_min = range_min.s
        return range_min

    def _get_range_max(self, range_type):
        """Get range max value."""
        range_max = range_type.base.max
        if isinstance(range_type, ptypes.Decimal64TypeSpec):
            range_max = range_max.s
        return range_max

    def _render_range(self, low, high):
        """Change range value to integer value."""
        if low in (None, 'min'):
            low = _LOW
        low = int(low)
        if high in (None, 'max'):
            high = low
        high = int(high)
        return low, high

    @property
    def nmsp_sep(self):
        sep = '.'
        if self.lang == 'cpp':
            sep = '::'
        return sep
Example #9
0
def get_meta_info_data(prop,
                       property_type,
                       type_stmt,
                       language,
                       identity_subclasses=None):
    """ Gets an instance of MetaInfoData that has the useful information about the property.

        Args:
            prop: The property
            property_type : The type under consideration
            type_stmt : The type stmt currently under consideration
    """
    clazz = prop.owner
    meta_info_data = MetaInfoData(prop)
    types_extractor = TypesExtractor()
    target_type_stmt = type_stmt

    mandatory = prop.stmt.search_one('mandatory')
    if mandatory is not None and mandatory.arg == 'true':
        meta_info_data.mandatory = True

    presence = prop.stmt.search_one('presence')
    if presence is not None:
        meta_info_data.is_presence = True

    units = prop.stmt.search_one('units')
    if units is not None:
        meta_info_data.units = units.arg

    status = prop.stmt.search_one('status')
    if status is not None:
        meta_info_data.status = status.arg

    default_value = prop.stmt.search_one('default')
    if default_value is not None:
        meta_info_data.default_value = default_value.arg

    if isinstance(property_type, Class):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        if identity_subclasses is None:
            meta_info_data.doc_link = get_class_crossref_tag(
                property_type.name, property_type, language)
        else:
            meta_info_data.doc_link = _get_identity_docstring(
                identity_subclasses, property_type, language)
            meta_info_data.doc_link_description = 'one of the below types:'

        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            target = ''
            if isinstance(meta_info_data.doc_link, list):
                doc_link = map(lambda l: '\n\n\t\t%s' % l,
                               meta_info_data.doc_link)
                target = ''.join(doc_link)
            meta_info_data.doc_link = target
            meta_info_data.doc_link = '\n\t\t' + _get_list_doc_link_tag(
                meta_info_data, 'doc_link', language, meta_info_data.mtype)
        elif prop.stmt.keyword == 'list':
            meta_info_data.mtype = 'REFERENCE_LIST'
            meta_info_data.doc_link_description = _get_list_doc_link_tag(
                meta_info_data, 'doc_link_description', language,
                meta_info_data.mtype)
        elif property_type.is_identity():
            meta_info_data.mtype = 'REFERENCE_IDENTITY_CLASS'
        else:
            meta_info_data.mtype = 'REFERENCE_CLASS'
        # if the class is local use just the local name
        if property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Enum):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        meta_info_data.doc_link = get_class_crossref_tag(
            property_type.name, property_type, language)
        meta_info_data.mtype = 'REFERENCE_ENUM_CLASS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = _get_list_doc_link_tag(
                meta_info_data, 'doc_link', language, meta_info_data.mtype)

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Bits):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = get_bits_doc_link(property_type, language)
        meta_info_data.mtype = 'REFERENCE_BITS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = _get_list_doc_link_tag(
                meta_info_data, 'doc_link', language, meta_info_data.mtype)

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    else:
        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = _get_list_tag(language,
                                                    meta_info_data.mtype)
        elif prop.stmt.keyword == 'anyxml':
            meta_info_data.mtype = 'ANYXML_CLASS'
            meta_info_data.doc_link = 'anyxml'
            meta_info_data.ptype = 'object'
            return meta_info_data
        else:
            meta_info_data.mtype = 'ATTRIBUTE'
            meta_info_data.doc_link = ''

        type_spec = type_stmt.i_type_spec

        if isinstance(type_spec, PathTypeSpec):
            if prop.stmt.i_leafref_ptr is not None:
                reference_class = prop.stmt.i_leafref_ptr[0].parent.i_class
                reference_prop = prop.stmt.i_leafref_ptr[0].i_property
                tag = get_class_crossref_tag(reference_prop.name,
                                             reference_class, language)
                meta_info_data.target_of_leafref = tag
        while isinstance(type_spec, PathTypeSpec):
            if not hasattr(type_spec, 'i_target_node'):
                return None
            target_type_stmt = type_spec.i_target_node.search_one('type')
            type_spec = target_type_stmt.i_type_spec

        if isinstance(type_spec, BinaryTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
        elif isinstance(type_spec, BitsTypeSpec):
            # This can happen in a Union
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, BooleanTypeSpec):
            meta_info_data.ptype = 'bool'
            meta_info_data.doc_link += get_primitive_type_tag('bool', language)
        elif isinstance(type_spec, Decimal64TypeSpec):
            meta_info_data.ptype = 'Decimal64'
            meta_info_data.prange.append(
                ('%s' % str(type_spec.min.s), '%s' % str(type_spec.max.s)))
            meta_info_data.doc_link += get_primitive_type_tag(
                'Decimal64', language)
        elif isinstance(type_spec, EmptyTypeSpec):
            meta_info_data.ptype = 'Empty'
            meta_info_data.doc_link += get_primitive_type_tag(
                'Empty', language)
        elif isinstance(prop.property_type, Enum):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IdentityrefTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IntTypeSpec):
            meta_info_data.ptype = 'int'
            meta_info_data.doc_link += meta_info_data.ptype
            lower = str(type_spec.min)
            upper = str(type_spec.max)
            meta_info_data.prange.append((lower, upper))
        elif isinstance(type_spec, LengthTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
            meta_info_data.prange = get_length_limits(type_spec)

        elif isinstance(type_spec, PathTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, PatternTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
            while hasattr(
                    target_type_stmt,
                    'i_typedef') and target_type_stmt.i_typedef is not None:
                target_type_stmt = target_type_stmt.i_typedef.search_one(
                    'type')
            pattern = target_type_stmt.search_one('pattern')
            if pattern is not None:
                meta_info_data.pattern.append(pattern.arg.encode('ascii'))
        elif isinstance(type_spec, RangeTypeSpec):
            meta_info_data.ptype = get_range_base_type_name(type_spec)
            meta_info_data.prange = get_range_limits(type_spec)
            meta_info_data.doc_link += meta_info_data.ptype

        elif isinstance(type_spec, StringTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
        elif isinstance(type_spec, UnionTypeSpec):
            # validate against all the data types
            meta_info_data.mtype = 'REFERENCE_UNION'
            meta_info_data.ptype = 'str'
            meta_info_data.property_type = type_spec
            for contained_type_stmt in type_spec.types:
                contained_property_type = types_extractor.get_property_type(
                    contained_type_stmt)
                child_meta_info_data = get_meta_info_data(
                    prop,
                    contained_property_type,
                    contained_type_stmt,
                    language,
                    identity_subclasses=identity_subclasses)
                meta_info_data.children.append(child_meta_info_data)

        elif isinstance(type_spec,
                        TypeSpec) and type_spec.name == 'instance-identifier':
            # Treat as string
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
        else:
            raise EmitError('Illegal path')
    return meta_info_data
Example #10
0
def get_meta_info_data(prop, property_type, type_stmt, language, identity_subclasses=None):
    """ Gets an instance of MetaInfoData that has the useful information about the property.

        Args:
            prop: The property
            property_type : The type under consideration
            type_stmt : The type stmt currently under consideration
    """
    clazz = prop.owner
    meta_info_data = MetaInfoData(prop)
    if type_stmt is not None:
        meta_info_data.ytype = type_stmt.arg
    types_extractor = TypesExtractor()
    target_type_stmt = type_stmt

    mandatory = prop.stmt.search_one('mandatory')
    if mandatory is not None and mandatory.arg == 'true':
        meta_info_data.mandatory = True

    presence = prop.stmt.search_one('presence')
    if presence is not None:
        meta_info_data.is_presence = True

    units = prop.stmt.search_one('units')
    if units is not None:
        meta_info_data.units = units.arg

    status = prop.stmt.search_one('status')
    if status is not None:
        meta_info_data.status = status.arg

    default_value = prop.stmt.search_one('default')
    if default_value is not None:
        meta_info_data.default_value = default_value.arg

    # if the class is local use just the local name
    if prop.property_type in clazz.owned_elements:
        meta_info_data.ptype = property_type.name
    elif hasattr(property_type, 'qn'):
        meta_info_data.ptype = property_type.qn()

    if isinstance(property_type, Class):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        if identity_subclasses is None:
            meta_info_data.doc_link = get_class_crossref_tag(
                property_type.name, property_type, language)
        else:
            meta_info_data.doc_link = _get_identity_docstring(
                identity_subclasses, property_type, language)
            meta_info_data.doc_link_description = 'one of the below values:'

        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            if isinstance(meta_info_data.doc_link, list):
                doc_link = map(lambda l: '\n\n\t\t%s' % l, meta_info_data.doc_link)
                target = ''.join(doc_link)
                meta_info_data.doc_link = target
            meta_info_data.doc_link = _get_list_doc_link_tag(
                meta_info_data, 'doc_link', language, meta_info_data.mtype)
        elif prop.stmt.keyword == 'list':
            meta_info_data.mtype = 'REFERENCE_LIST'
            meta_info_data.doc_link_description = _get_list_doc_link_tag(
                meta_info_data, 'doc_link_description', language, meta_info_data.mtype)
        elif property_type.is_identity():
            meta_info_data.mtype = 'REFERENCE_IDENTITY_CLASS'
        else:
            meta_info_data.mtype = 'REFERENCE_CLASS'

    elif isinstance(property_type, Enum):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        meta_info_data.doc_link = get_class_crossref_tag(property_type.name,
                                                         property_type,
                                                         language)
        _set_mtype_docstring(meta_info_data, prop, 'REFERENCE_ENUM_CLASS', language)

    elif isinstance(property_type, Bits):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = get_bits_doc_link(property_type, language)
        _set_mtype_docstring(meta_info_data, prop, 'REFERENCE_BITS', language)

    else:
        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = _get_list_tag(language, meta_info_data.mtype)
        elif prop.stmt.keyword == 'anyxml':
            meta_info_data.mtype = 'ANYXML_CLASS'
            meta_info_data.doc_link = 'anyxml'
            meta_info_data.ptype = 'object'
            return meta_info_data
        else:
            meta_info_data.mtype = 'ATTRIBUTE'
            meta_info_data.doc_link = ''

        type_spec = type_stmt.i_type_spec

        if isinstance(type_spec, PathTypeSpec):
            if prop.stmt.i_leafref_ptr is not None:
                reference_class = prop.stmt.i_leafref_ptr[0].parent.i_class
                reference_prop = prop.stmt.i_leafref_ptr[0].i_property
                tag = get_class_crossref_tag(reference_prop.name,
                                             reference_class, language)
                meta_info_data.target_of_leafref = tag
        while isinstance(type_spec, PathTypeSpec):
            if not hasattr(type_spec, 'i_target_node'):
                return None
            target_type_stmt = type_spec.i_target_node.search_one('type')
            type_spec = target_type_stmt.i_type_spec

        if isinstance(type_spec, BinaryTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
        elif isinstance(type_spec, BitsTypeSpec):
            # This can happen in a Union
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, BooleanTypeSpec):
            meta_info_data.ptype = 'bool'
            meta_info_data.doc_link += get_primitive_type_tag('bool', language)
        elif isinstance(type_spec, Decimal64TypeSpec):
            meta_info_data.ptype = 'Decimal64'
            meta_info_data.prange.append(
                ('%s' % str(type_spec.min.s), '%s' % str(type_spec.max.s)))
            meta_info_data.doc_link += get_primitive_type_tag('Decimal64', language)
        elif isinstance(type_spec, EmptyTypeSpec):
            meta_info_data.ptype = 'Empty'
            meta_info_data.doc_link += get_primitive_type_tag('Empty', language)
        elif isinstance(prop.property_type, Enum):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IdentityrefTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IntTypeSpec):
            meta_info_data.ptype = 'int'
            meta_info_data.doc_link += meta_info_data.ptype
            lower = str(type_spec.min)
            upper = str(type_spec.max)
            meta_info_data.prange.append((lower, upper))
        elif isinstance(type_spec, LengthTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
            meta_info_data.prange = get_length_limits(type_spec)

        elif isinstance(type_spec, PathTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, PatternTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
            add_pattern_docstring(meta_info_data, target_type_stmt)

        elif isinstance(type_spec, RangeTypeSpec):
            meta_info_data.ptype = get_range_base_type_name(type_spec)
            meta_info_data.prange = get_range_limits(type_spec)
            meta_info_data.doc_link += meta_info_data.ptype

        elif isinstance(type_spec, StringTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
            add_pattern_docstring(meta_info_data, target_type_stmt)

        elif isinstance(type_spec, UnionTypeSpec):
            # validate against all the data types
            meta_info_data.mtype = 'REFERENCE_UNION'
            meta_info_data.ptype = 'str'
            meta_info_data.property_type = type_spec
            for contained_type_stmt in type_spec.types:
                contained_property_type = types_extractor.get_property_type(contained_type_stmt)
                child_meta_info_data = get_meta_info_data(
                    prop, contained_property_type, contained_type_stmt, language,
                    identity_subclasses=identity_subclasses)
                meta_info_data.children.append(child_meta_info_data)

        elif isinstance(type_spec, TypeSpec) and type_spec.name == 'instance-identifier':
            # Treat as string
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += get_primitive_type_tag('str', language)
        else:
            raise EmitError('Illegal path')

    if default_value is not None:
        meta_info_data.default_value_object = get_default_value_object(meta_info_data.ptype, property_type,                                                                   meta_info_data.clazz_name, default_value.arg,
                                                                       identity_subclasses)
    return meta_info_data
Example #11
0
def get_meta_info_data(prop, property_type, type_stmt):
    """ Gets an instance of MetaInfoData that has the useful information about the property.

        Args:
            prop: The property
            property_type : The type under consideration
            type_stmt : The type stmt currently under consideration 
    """
    clazz = prop.owner
    meta_info_data = MetaInfoData(prop)
    types_extractor = TypesExtractor()
    target_type_stmt = type_stmt

    if isinstance(property_type, Class):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(), property_type.qn())

        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link
        elif property_type.is_identity():
            meta_info_data.mtype = 'REFERENCE_IDENTITY_CLASS'
        else:
            meta_info_data.mtype = 'REFERENCE_CLASS'
        # if the class is local use just the local name
        if property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Enum):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(), property_type.qn())

        meta_info_data.mtype = 'REFERENCE_ENUM_CLASS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Bits):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(), property_type.qn())

        meta_info_data.mtype = 'REFERENCE_BITS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    else:
        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of '
        elif prop.stmt.keyword == 'anyxml':
            meta_info_data.mtype = 'ANYXML_CLASS'
            meta_info_data.doc_link = 'anyxml'
            meta_info_data.ptype = 'object'
            return meta_info_data
        else:
            meta_info_data.mtype = 'ATTRIBUTE'
            meta_info_data.doc_link = ''

        type_spec = type_stmt.i_type_spec

        while isinstance(type_spec, PathTypeSpec):
            if not hasattr(type_spec, 'i_target_node'):
                return None
            target_type_stmt = type_spec.i_target_node.search_one('type')
            type_spec = target_type_stmt.i_type_spec

        if isinstance(type_spec, BinaryTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, BitsTypeSpec):
            # This can happen in a Union
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, BooleanTypeSpec):
            meta_info_data.ptype = 'bool'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, Decimal64TypeSpec):
            meta_info_data.ptype = 'Decimal64'
            meta_info_data.prange.append(
                ('%s' % type_spec.min.s, '%s' % type_spec.max.s))
            # ' :ref:`Decimal64 <ydk_models_types_Decimal64>`'
            meta_info_data.doc_link += ':py:class:`Decimal64 <ydk.types.Decimal64>`'
        elif isinstance(type_spec, EmptyTypeSpec):
            meta_info_data.ptype = 'Empty'
            # ' :ref:`Empty <ydk_models_types_Empty>`'
            meta_info_data.doc_link += ':py:class:`Empty <ydk.types.Empty>`'
        elif isinstance(prop.property_type, Enum):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IdentityrefTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IntTypeSpec):
            meta_info_data.ptype = 'int'
            meta_info_data.doc_link += meta_info_data.ptype
            meta_info_data.prange.append((type_spec.min, type_spec.max))
        elif isinstance(type_spec, LengthTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
            meta_info_data.prange = get_length_limits(type_spec)

        elif isinstance(type_spec, PathTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, PatternTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
            while hasattr(target_type_stmt, 'i_typedef') and target_type_stmt.i_typedef is not None:
                target_type_stmt = target_type_stmt.i_typedef.search_one(
                    'type')
            pattern = target_type_stmt.search_one('pattern')
            if pattern is not None:
                meta_info_data.pattern.append(pattern.arg.encode('ascii'))
        elif isinstance(type_spec, RangeTypeSpec):
            meta_info_data.ptype = get_range_base_type_name(type_spec)
            meta_info_data.prange = get_range_limits(type_spec)
            meta_info_data.doc_link += meta_info_data.ptype

        elif isinstance(type_spec, StringTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, UnionTypeSpec):
            # validate against all the data types
            meta_info_data.mtype = 'REFERENCE_UNION'
            meta_info_data.ptype = 'str'
            meta_info_data.property_type = type_spec
            if len(type_spec.types) > 0:
                meta_info_data.doc_link += 'one of { '
                for contained_type_stmt in type_spec.types:
                    enum_type_stmt = types_extractor.get_enum_type_stmt(contained_type_stmt)
                    bits_type_stmt = types_extractor.get_bits_type_stmt(contained_type_stmt)
                    union_type_stmt = types_extractor.get_union_type_stmt(contained_type_stmt)
                    contained_property_type = contained_type_stmt.i_type_spec
                    if isinstance(contained_property_type, IdentityrefTypeSpec):
                        contained_property_type = contained_property_type.base.i_identity.i_class
                    elif enum_type_stmt is not None:
                        # this is an enumeration
                        if not hasattr(enum_type_stmt, 'i_enum'):
                            raise EmitError('Failure to get i_enum')
                        contained_property_type = enum_type_stmt.i_enum
                    elif bits_type_stmt is not None:
                        # bits
                        contained_property_type = bits_type_stmt.i_bits
                    elif union_type_stmt is not None:
                        contained_property_type = union_type_stmt
                    child_meta_info_data = get_meta_info_data(
                        prop, contained_property_type, contained_type_stmt)
                    meta_info_data.children.append(child_meta_info_data)
                    if meta_info_data.doc_link[-1:] != ' ':
                        meta_info_data.doc_link += ' | '
                    meta_info_data.doc_link += child_meta_info_data.doc_link
                meta_info_data.doc_link += ' }'

        elif isinstance(type_spec, TypeSpec) and type_spec.name == 'instance-identifier':
            # Treat as string
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        else:
            raise EmitError('Illegal path')
    return meta_info_data
Example #12
0
def get_meta_info_data(prop, property_type, type_stmt, identity_subclasses=None):
    """ Gets an instance of MetaInfoData that has the useful information about the property.

        Args:
            prop: The property
            property_type : The type under consideration
            type_stmt : The type stmt currently under consideration 
    """
    clazz = prop.owner
    meta_info_data = MetaInfoData(prop)
    types_extractor = TypesExtractor()
    target_type_stmt = type_stmt
    
    mandatory = prop.stmt.search_one('mandatory')
    if mandatory is not None and mandatory.arg == 'true':
        meta_info_data.mandatory = True

    mandatory = prop.stmt.search_one('mandatory')
    if mandatory is not None and mandatory.arg == 'true':
        meta_info_data.mandatory = True

    if isinstance(property_type, Class):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()

        doc_link_template = ':py:class:`%s <%s.%s>`'

        if identity_subclasses is None:
            meta_info_data.doc_link = doc_link_template % (
                property_type.name, 
                property_type.get_py_mod_name(), 
                property_type.qn()
            )
        else:
            meta_info_data.doc_link = _get_identity_docstring(identity_subclasses, doc_link_template, property_type)
            meta_info_data.doc_link_description = 'one of the below types:'

        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link
        elif prop.stmt.keyword == 'list':
            meta_info_data.mtype = 'REFERENCE_LIST'
            meta_info_data.doc_link_description = 'list of %s' % meta_info_data.doc_link_description
        elif property_type.is_identity():
            meta_info_data.mtype = 'REFERENCE_IDENTITY_CLASS'
        else:
            meta_info_data.mtype = 'REFERENCE_CLASS'
        # if the class is local use just the local name
        if property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Enum):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(), property_type.qn())

        meta_info_data.mtype = 'REFERENCE_ENUM_CLASS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    elif isinstance(property_type, Bits):
        meta_info_data.pmodule_name = "'%s'" % property_type.get_py_mod_name()
        meta_info_data.clazz_name = "'%s'" % property_type.qn()
        meta_info_data.doc_link = ':py:class:`%s <%s.%s>`' % (
            property_type.name, property_type.get_py_mod_name(), property_type.qn())

        meta_info_data.mtype = 'REFERENCE_BITS'
        if prop.is_many:
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of %s' % meta_info_data.doc_link

        if prop.property_type in clazz.owned_elements:
            meta_info_data.ptype = property_type.name
        else:
            meta_info_data.ptype = property_type.qn()

    else:
        if prop.stmt.keyword == 'leaf-list':
            meta_info_data.mtype = 'REFERENCE_LEAFLIST'
            meta_info_data.doc_link = 'list of '
        elif prop.stmt.keyword == 'anyxml':
            meta_info_data.mtype = 'ANYXML_CLASS'
            meta_info_data.doc_link = 'anyxml'
            meta_info_data.ptype = 'object'
            return meta_info_data
        else:
            meta_info_data.mtype = 'ATTRIBUTE'
            meta_info_data.doc_link = ''

        type_spec = type_stmt.i_type_spec

        if isinstance(type_spec, PathTypeSpec):
            if prop.stmt.i_leafref_ptr is not None:
                reference_class = prop.stmt.i_leafref_ptr[0].parent.i_class
                reference_prop = prop.stmt.i_leafref_ptr[0].i_property
                meta_info_data.target_of_leafref = ':py:class:`%s <%s.%s>`' % (reference_prop.name, reference_class.get_py_mod_name(), reference_class.qn())

        while isinstance(type_spec, PathTypeSpec):
            if not hasattr(type_spec, 'i_target_node'):
                return None
            target_type_stmt = type_spec.i_target_node.search_one('type')
            type_spec = target_type_stmt.i_type_spec

        if isinstance(type_spec, BinaryTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, BitsTypeSpec):
            # This can happen in a Union
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, BooleanTypeSpec):
            meta_info_data.ptype = 'bool'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, Decimal64TypeSpec):
            meta_info_data.ptype = 'Decimal64'
            meta_info_data.prange.append(
                ('%s' % type_spec.min.s, '%s' % type_spec.max.s))
            # ' :ref:`Decimal64 <ydk_models_types_Decimal64>`'
            meta_info_data.doc_link += ':py:class:`Decimal64 <ydk.types.Decimal64>`'
        elif isinstance(type_spec, EmptyTypeSpec):
            meta_info_data.ptype = 'Empty'
            # ' :ref:`Empty <ydk_models_types_Empty>`'
            meta_info_data.doc_link += ':py:class:`Empty <ydk.types.Empty>`'
        elif isinstance(prop.property_type, Enum):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IdentityrefTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, IntTypeSpec):
            meta_info_data.ptype = 'int'
            if not isinstance(type_spec.min, int) or not isinstance(type_spec.max, int):
                meta_info_data.ptype = 'long'
            meta_info_data.doc_link += meta_info_data.ptype
            meta_info_data.prange.append((type_spec.min, type_spec.max))
        elif isinstance(type_spec, LengthTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
            meta_info_data.prange = get_length_limits(type_spec)

        elif isinstance(type_spec, PathTypeSpec):
            raise EmitError('Illegal Code path')
        elif isinstance(type_spec, PatternTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
            while hasattr(target_type_stmt, 'i_typedef') and target_type_stmt.i_typedef is not None:
                target_type_stmt = target_type_stmt.i_typedef.search_one(
                    'type')
            pattern = target_type_stmt.search_one('pattern')
            if pattern is not None:
                meta_info_data.pattern.append(pattern.arg.encode('ascii'))
        elif isinstance(type_spec, RangeTypeSpec):
            meta_info_data.ptype = get_range_base_type_name(type_spec)
            meta_info_data.prange = get_range_limits(type_spec)
            meta_info_data.doc_link += meta_info_data.ptype

        elif isinstance(type_spec, StringTypeSpec):
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        elif isinstance(type_spec, UnionTypeSpec):
            # validate against all the data types
            meta_info_data.mtype = 'REFERENCE_UNION'
            meta_info_data.ptype = 'str'
            meta_info_data.property_type = type_spec
            if len(type_spec.types) > 0:
                # meta_info_data.doc_link += 'one of { '
                for contained_type_stmt in type_spec.types:
                    contained_property_type = types_extractor.get_property_type(contained_type_stmt)
                    child_meta_info_data = get_meta_info_data(
                        prop, contained_property_type, contained_type_stmt, identity_subclasses)
                    meta_info_data.children.append(child_meta_info_data)
                    # if meta_info_data.doc_link[-1:] != ' ':
                    #    meta_info_data.doc_link += ' | '
                    # meta_info_data.doc_link += child_meta_info_data.doc_link
                # meta_info_data.doc_link += ' }'

        elif isinstance(type_spec, TypeSpec) and type_spec.name == 'instance-identifier':
            # Treat as string
            meta_info_data.ptype = 'str'
            meta_info_data.doc_link += meta_info_data.ptype
        else:
            raise EmitError('Illegal path')
    return meta_info_data