Beispiel #1
0
    def _create_expanded_api_model(self, stmt, parent_element,
                                   deviation_packages):
        """
            Converts the stmt to an Element in the api_model according
            to the expanded code generation algorithm.

            The expanded code generation algorithm uses the tree view of the YANG models
            to generate the API. For each data node in the YANG model a corresponding Class
            element will be created.

            In the first pass Elements that encapsulate the references are created
            this is done for all the stmts we are interested
            after this is done, resolve cross references is called on all the elements
            to resolve all the cross references (examples include
            super classes extends field in a class)

            :param `pyang.statements.Statement` stmt The statement to convert
            :param  `Element` The parent element.
            :param list of 'Package' The deviation packages.
        """

        # process typedefs first so that they are resolved
        # when we have to use them
        element = parent_element

        # identities
        if hasattr(stmt, 'i_identities'):
            for identity_stmt in stmt.i_identities.values():
                identity_class = Class(self.iskeyword)
                identity_class.stmt = identity_stmt
                identity_class.owner = parent_element
                parent_element.owned_elements.append(identity_class)
                identity_stmt.i_class = identity_class

        if hasattr(stmt, 'i_typedefs'):
            for typedef_stmt_name in stmt.i_typedefs:
                typedef_stmt = stmt.i_typedefs[typedef_stmt_name]
                self._add_enums_and_bits(typedef_stmt, parent_element)

        if stmt.keyword == 'module':
            pass

        elif stmt.keyword in ('container', 'list', 'rpc', 'input', 'output'):
            if stmt.keyword in ('input', 'output') and len(stmt.substmts) == 0:
                pass
            else:
                clazz = Class(self.iskeyword)
                stmt.i_class = clazz
                clazz.stmt = stmt
                for e in parent_element.owned_elements:
                    if e.name == clazz.name:
                        clazz.name = clazz.name + '_'

                parent_element.owned_elements.append(clazz)
                clazz.set_owner(parent_element, self.language)

                if self.language == 'cpp' and name_matches_ancestor(
                        clazz.name, parent_element):
                    clazz.name = clazz.name + '_'

                element = clazz

                if not isinstance(parent_element, Package):
                    # create a property along with the class
                    prop = Property(self.iskeyword)
                    stmt.i_property = prop
                    prop.stmt = stmt
                    prop.property_type = clazz
                    for e in parent_element.owned_elements:
                        if isinstance(e, Property):
                            s = snake_case(e.stmt.arg)
                            if snake_case(prop.stmt.arg) == s:
                                prop.name = prop.name + '_'

                    parent_element.owned_elements.append(prop)
                    prop.owner = parent_element

        elif stmt.keyword == 'leaf' or stmt.keyword == 'leaf-list' or stmt.keyword == 'anyxml':
            self._add_leaf_leaflist_prop(stmt, parent_element)

        if hasattr(stmt, 'i_deviation'):
            self._add_to_deviation_package(stmt, parent_element,
                                           deviation_packages)

        # walk the children
        _keywords = statements.data_definition_keywords + [
            'case', 'rpc', 'input', 'output'
        ]
        if hasattr(stmt, 'i_children'):
            self._sanitize_namespace(stmt)

            child_stmts = []
            if hasattr(stmt, 'i_key') and stmt.i_key is not None:
                child_stmts.extend([s for s in stmt.i_key])

            if stmt.keyword == 'rpc' and self.language == 'cpp':
                child_stmts = self._walk_children(stmt, _keywords)

            else:
                _children = [child for child in stmt.i_children \
                    if (child not in child_stmts and child.keyword in _keywords)]
                child_stmts.extend(_children)

            for child_stmt in child_stmts:
                self._create_expanded_api_model(child_stmt, element,
                                                deviation_packages)
    def _create_expanded_api_model(self, stmt, parent_element, deviation_packages):
        """
            Converts the stmt to an Element in the api_model according
            to the expanded code generation algorithm.

            The expanded code generation algorithm uses the tree view of the YANG models
            to generate the API. For each data node in the YANG model a corresponding Class
            element will be created.

            In the first pass Elements that encapsulate the references are created
            this is done for all the stmts we are interested
            after this is done, resolve cross references is called on all the elements
            to resolve all the cross references (examples include
            super classes extends field in a class)

            :param `pyang.statements.Statement` stmt The statement to convert
            :param  `Element` The parent element.
            :param list of 'Package' The deviation packages.
        """

        # process typedefs first so that they are resolved
        # when we have to use them
        element = parent_element

        # identities
        if hasattr(stmt, 'i_identities'):
            for identity_stmt in stmt.i_identities.values():
                identity_class = Class(self.iskeyword)
                identity_class.stmt = identity_stmt
                identity_class.owner = parent_element
                parent_element.owned_elements.append(identity_class)
                identity_stmt.i_class = identity_class

        if hasattr(stmt, 'i_typedefs'):
            for typedef_stmt_name in stmt.i_typedefs:
                typedef_stmt = stmt.i_typedefs[typedef_stmt_name]
                self._add_enums_and_bits(typedef_stmt, parent_element)

        if stmt.keyword == 'module':
            pass

        elif stmt.keyword in ('container', 'list', 'rpc', 'input', 'output'):
            if stmt.keyword in ('input', 'output') and len(stmt.substmts) == 0:
                pass
            else:
                clazz = Class(self.iskeyword)
                stmt.i_class = clazz
                clazz.stmt = stmt
                for e in parent_element.owned_elements:
                    if e.name == clazz.name:
                        clazz.name = clazz.name + '_'

                parent_element.owned_elements.append(clazz)
                clazz.set_owner(parent_element, self.language)

                if name_matches_ancestor(clazz.name, parent_element):
                    clazz.name = clazz.name + '_'

                element = clazz

                if not isinstance(parent_element, Package):
                    # create a property along with the class
                    prop = Property(self.iskeyword)
                    stmt.i_property = prop
                    prop.stmt = stmt
                    prop.property_type = clazz
                    for e in parent_element.owned_elements:
                        if isinstance(e, Property):
                            s = snake_case(e.stmt.arg)
                            if snake_case(prop.stmt.arg) == s:
                                prop.name = prop.name + '_'

                    parent_element.owned_elements.append(prop)
                    prop.owner = parent_element

        elif stmt.keyword == 'leaf' or stmt.keyword == 'leaf-list' or stmt.keyword == 'anyxml':
            self._add_leaf_leaflist_prop(stmt, parent_element)

        if hasattr(stmt, 'i_deviation'):
            self._add_to_deviation_package(stmt, parent_element, deviation_packages)

        # walk the children
        _keywords = statements.data_definition_keywords + ['case', 'rpc', 'input', 'output']
        if hasattr(stmt, 'i_children'):
            self._sanitize_namespace(stmt)

            child_stmts=[]
            if hasattr(stmt, 'i_key') and stmt.i_key is not None:
                child_stmts.extend([s for s in stmt.i_key])

            if stmt.keyword == 'rpc' and self.language == 'cpp':
                child_stmts = self._walk_children(stmt, _keywords)

            else:
                _children = [child for child in stmt.i_children \
                    if (child not in child_stmts and child.keyword in _keywords)]
                child_stmts.extend(_children)

            for child_stmt in child_stmts:
                self._create_expanded_api_model(child_stmt, element, deviation_packages)
Beispiel #3
0
    def _add_leaf_leaflist_prop(self, stmt, parent_element):
        prop = Property(self.iskeyword)
        stmt.i_property = prop
        prop.stmt = stmt

        for element in parent_element.owned_elements:
            if element.name == prop.name:
                prop.name = prop.name + '_'

        parent_element.owned_elements.append(prop)
        prop.owner = parent_element
        # for inlined enum types where leaf { type enumeration {
        enum_type = self.types_extractor.get_enum_type_stmt(stmt)
        bits_type = self.types_extractor.get_bits_type_stmt(stmt)
        union_type = self.types_extractor.get_union_type_stmt(stmt)
        # if the type statement is totally self contained
        # then we need to extract this type

        if stmt.keyword == 'anyxml':
            anyxml = AnyXml()
            anyxml.stmt = stmt
            # parent_element.owned_elements.append(anyxml)
            # anyxml.owner = parent_element
            prop.property_type = anyxml
        elif enum_type is not None and enum_type == stmt.search_one('type'):
            # we have to create the enum
            enum_class = Enum(self.iskeyword)
            enum_class.stmt = enum_type
            disambiguate_class_name_from_ancestors_and_siblings(
                self.language, enum_class, parent_element)
            parent_element.owned_elements.append(enum_class)
            enum_class.owner = parent_element
            prop.property_type = enum_class
            enum_type.i_enum = enum_class
            enum_type.parent.i_enum = enum_class
        elif bits_type is not None and bits_type == stmt.search_one('type'):
            # we have to create the specific subclass of FixedBitsDict
            bits_class = Bits(self.iskeyword)
            bits_class.stmt = bits_type
            parent_element.owned_elements.append(bits_class)
            bits_class.owner = parent_element
            prop.property_type = bits_class
        elif union_type is not None and union_type == stmt.search_one('type'):

            def _add_union_type(union_type_stmt, parent_element):
                for contained_type in union_type_stmt.i_type_spec.types:
                    contained_enum_type = self.types_extractor.get_enum_type_stmt(
                        contained_type)
                    contained_bits_type = self.types_extractor.get_bits_type_stmt(
                        contained_type)
                    contained_union_type = self.types_extractor.get_union_type_stmt(
                        contained_type)

                    if contained_enum_type is not None and contained_enum_type == contained_type:
                        enum_class = Enum(self.iskeyword)
                        enum_class.stmt = contained_enum_type
                        disambiguate_class_name_from_ancestors_and_siblings(
                            self.language, enum_class, parent_element)
                        parent_element.owned_elements.append(enum_class)
                        enum_class.owner = parent_element
                        contained_enum_type.i_enum = enum_class
                        contained_enum_type.parent.i_enum = enum_class

                    if contained_bits_type is not None and contained_bits_type == contained_type:
                        bits_class = Bits(self.iskeyword)
                        bits_class.stmt = contained_bits_type
                        parent_element.owned_elements.append(bits_class)
                        bits_class.owner = parent_element
                        contained_bits_type.i_bits = bits_class

                    if contained_union_type is not None and contained_union_type == contained_type:
                        _add_union_type(contained_union_type, parent_element)

            # is this embedded ?
            if union_type == stmt.search_one('type'):
                # we need to check for the types under the union to see if
                # any of them need to be handled differently
                _add_union_type(union_type, parent_element)
    def _add_leaf_leaflist_prop(self, stmt, parent_element):
        prop = Property(self.iskeyword)
        stmt.i_property = prop
        prop.stmt = stmt

        for element in parent_element.owned_elements:
            if element.name == prop.name:
                prop.name = prop.name + '_'

        parent_element.owned_elements.append(prop)
        prop.owner = parent_element
        # for inlined enum types where leaf { type enumeration {
        enum_type = self.types_extractor.get_enum_type_stmt(stmt)
        bits_type = self.types_extractor.get_bits_type_stmt(stmt)
        union_type = self.types_extractor.get_union_type_stmt(stmt)
        # if the type statement is totally self contained
        # then we need to extract this type

        if stmt.keyword == 'anyxml':
            anyxml = AnyXml()
            anyxml.stmt = stmt
            # parent_element.owned_elements.append(anyxml)
            # anyxml.owner = parent_element
            prop.property_type = anyxml
        elif enum_type is not None and enum_type == stmt.search_one('type'):
            # we have to create the enum
            enum_class = Enum(self.iskeyword)
            enum_class.stmt = enum_type
            disambiguate_class_name_from_ancestors_and_siblings(self.language, enum_class, parent_element)
            parent_element.owned_elements.append(enum_class)
            enum_class.owner = parent_element
            prop.property_type = enum_class
            enum_type.i_enum = enum_class
            enum_type.parent.i_enum = enum_class
        elif bits_type is not None and bits_type == stmt.search_one('type'):
            # we have to create the specific subclass of FixedBitsDict
            bits_class = Bits(self.iskeyword)
            bits_class.stmt = bits_type
            parent_element.owned_elements.append(bits_class)
            bits_class.owner = parent_element
            prop.property_type = bits_class
        elif union_type is not None and union_type == stmt.search_one('type'):
            def _add_union_type(union_type_stmt, parent_element):
                for contained_type in union_type_stmt.i_type_spec.types:
                    contained_enum_type = self.types_extractor.get_enum_type_stmt(contained_type)
                    contained_bits_type = self.types_extractor.get_bits_type_stmt(contained_type)
                    contained_union_type = self.types_extractor.get_union_type_stmt(contained_type)

                    if contained_enum_type is not None and contained_enum_type == contained_type:
                        enum_class = Enum(self.iskeyword)
                        enum_class.stmt = contained_enum_type
                        disambiguate_class_name_from_ancestors_and_siblings(self.language, enum_class, parent_element)
                        parent_element.owned_elements.append(enum_class)
                        enum_class.owner = parent_element
                        contained_enum_type.i_enum = enum_class
                        contained_enum_type.parent.i_enum = enum_class

                    if contained_bits_type is not None and contained_bits_type == contained_type:
                        bits_class = Bits(self.iskeyword)
                        bits_class.stmt = contained_bits_type
                        parent_element.owned_elements.append(bits_class)
                        bits_class.owner = parent_element
                        contained_bits_type.i_bits = bits_class

                    if contained_union_type is not None and contained_union_type == contained_type:
                        _add_union_type(contained_union_type, parent_element)

            # is this embedded ?
            if union_type == stmt.search_one('type'):
                # we need to check for the types under the union to see if
                # any of them need to be handled differently
                _add_union_type(union_type, parent_element)