"""Support for simplified access to data on nodes of type omni.graph.tutorials.SimpleDataPy

This is a tutorial node. It creates both an input and output attribute of every simple  supported data type. The values are
modified in a simple way so that the compute modifies values.  It is the same as node omni.graph.tutorials.SimpleData, except
it is implemented in Python instead of C++.
"""

import carb
import sys
import traceback

import omni.graph.core as og
import omni.graph.core._omni_graph_core as _og
import omni.graph.tools.ogn as ogn



class OgnTutorialSimpleDataPyDatabase(og.Database):
    """Helper class providing simplified access to data on nodes of type omni.graph.tutorials.SimpleDataPy

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.a_bool
            inputs.a_constant_input
            inputs.a_double
            inputs.a_float
            inputs.a_half
            inputs.a_int
            inputs.a_int64
            inputs.a_objectId
            inputs.a_path
            inputs.a_string
            inputs.a_token
            inputs.a_uchar
            inputs.a_uint
            inputs.a_uint64
        Outputs:
            outputs.a_a_boolUiName
            outputs.a_bool
            outputs.a_double
            outputs.a_float
            outputs.a_half
            outputs.a_int
            outputs.a_int64
            outputs.a_nodeTypeUiName
            outputs.a_objectId
            outputs.a_path
            outputs.a_string
            outputs.a_token
            outputs.a_uchar
            outputs.a_uint
            outputs.a_uint64
    """

    # Imprint the generator and target ABI versions in the file for JIT generation
    GENERATOR_VERSION = (1, 41, 3)
    TARGET_VERSION = (2, 139, 12)

    # This is an internal object that provides per-class storage of a per-node data dictionary
    PER_NODE_DATA = {}

    # This is an internal object that describes unchanging attributes in a generic way
    # The values in this list are in no particular order, as a per-attribute tuple
    #     Name, Type, ExtendedTypeIndex, UiName, Description, Metadata,
    #     Is_Required, DefaultValue, Is_Deprecated, DeprecationMsg
    # You should not need to access any of this data directly, use the defined database interfaces
    INTERFACE = og.Database._get_interface([
        ('inputs:a_bool', 'bool', 0, 'Simple Boolean Input', 'This is an attribute of type boolean', {ogn.MetadataKeys.DEFAULT: 'true'}, False, True, False, ''),
        ('inputs:a_constant_input', 'int', 0, None, 'This is an input attribute whose value can be set but can only be connected as a source.', {ogn.MetadataKeys.OUTPUT_ONLY: '1'}, True, 0, False, ''),
        ('inputs:a_double', 'double', 0, None, 'This is an attribute of type 64 bit floating point', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_float', 'float', 0, None, 'This is an attribute of type 32 bit floating point', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_half', 'half', 0, None, 'This is an attribute of type 16 bit float', {ogn.MetadataKeys.DEFAULT: '0.0'}, True, 0.0, False, ''),
        ('inputs:a_int', 'int', 0, None, 'This is an attribute of type 32 bit integer', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_int64', 'int64', 0, None, 'This is an attribute of type 64 bit integer', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_objectId', 'objectId', 0, None, 'This is an attribute of type objectId', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_path', 'path', 0, None, 'This is an attribute of type path', {ogn.MetadataKeys.DEFAULT: '""'}, True, "", False, ''),
        ('inputs:a_string', 'string', 0, None, 'This is an attribute of type string', {ogn.MetadataKeys.DEFAULT: '"helloString"'}, True, "helloString", False, ''),
        ('inputs:a_token', 'token', 0, None, 'This is an attribute of type interned string with fast comparison and hashing', {ogn.MetadataKeys.DEFAULT: '"helloToken"'}, True, "helloToken", False, ''),
        ('inputs:a_uchar', 'uchar', 0, None, 'This is an attribute of type unsigned 8 bit integer', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_uint', 'uint', 0, None, 'This is an attribute of type unsigned 32 bit integer', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('inputs:a_uint64', 'uint64', 0, None, 'This is an attribute of type unsigned 64 bit integer', {ogn.MetadataKeys.DEFAULT: '0'}, True, 0, False, ''),
        ('outputs:a_a_boolUiName', 'string', 0, None, 'Computed attribute containing the UI name of input a_bool', {}, True, None, False, ''),
        ('outputs:a_bool', 'bool', 0, None, 'This is a computed attribute of type boolean', {}, True, None, False, ''),
        ('outputs:a_double', 'double', 0, None, 'This is a computed attribute of type 64 bit floating point', {}, True, None, False, ''),
        ('outputs:a_float', 'float', 0, None, 'This is a computed attribute of type 32 bit floating point', {}, True, None, False, ''),
        ('outputs:a_half', 'half', 0, None, 'This is a computed attribute of type 16 bit float', {}, True, None, False, ''),
        ('outputs:a_int', 'int', 0, None, 'This is a computed attribute of type 32 bit integer', {}, True, None, False, ''),
        ('outputs:a_int64', 'int64', 0, None, 'This is a computed attribute of type 64 bit integer', {}, True, None, False, ''),
        ('outputs:a_nodeTypeUiName', 'string', 0, None, 'Computed attribute containing the UI name of this node type', {}, True, None, False, ''),
        ('outputs:a_objectId', 'objectId', 0, None, 'This is a computed attribute of type objectId', {}, True, None, False, ''),
        ('outputs:a_path', 'path', 0, None, 'This is a computed attribute of type path', {ogn.MetadataKeys.DEFAULT: '"/Child"'}, True, "/Child", False, ''),
        ('outputs:a_string', 'string', 0, None, 'This is a computed attribute of type string', {ogn.MetadataKeys.DEFAULT: '"This string is empty"'}, True, "This string is empty", False, ''),
        ('outputs:a_token', 'token', 0, None, 'This is a computed attribute of type interned string with fast comparison and hashing', {}, True, None, False, ''),
        ('outputs:a_uchar', 'uchar', 0, None, 'This is a computed attribute of type unsigned 8 bit integer', {}, True, None, False, ''),
        ('outputs:a_uint', 'uint', 0, None, 'This is a computed attribute of type unsigned 32 bit integer', {}, True, None, False, ''),
        ('outputs:a_uint64', 'uint64', 0, None, 'This is a computed attribute of type unsigned 64 bit integer', {}, True, None, False, ''),
    ])

    @classmethod
    def _populate_role_data(cls):
        """Populate a role structure with the non-default roles on this node type"""
        role_data = super()._populate_role_data()
        role_data.inputs.a_objectId = og.AttributeRole.OBJECT_ID
        role_data.inputs.a_path = og.AttributeRole.PATH
        role_data.inputs.a_string = og.AttributeRole.TEXT
        role_data.outputs.a_a_boolUiName = og.AttributeRole.TEXT
        role_data.outputs.a_nodeTypeUiName = og.AttributeRole.TEXT
        role_data.outputs.a_objectId = og.AttributeRole.OBJECT_ID
        role_data.outputs.a_path = og.AttributeRole.PATH
        role_data.outputs.a_string = og.AttributeRole.TEXT
        return role_data

    class ValuesForInputs(og.DynamicAttributeAccess):
        LOCAL_PROPERTY_NAMES = {"a_bool", "a_constant_input", "a_double", "a_float", "a_half", "a_int", "a_int64", "a_objectId", "a_path", "a_string", "a_token", "a_uchar", "a_uint", "a_uint64", "_setting_locked", "_batchedReadAttributes", "_batchedReadValues"}
        """Helper class that creates natural hierarchical access to input attributes"""
        def __init__(self, node: og.Node, attributes, dynamic_attributes: og.DynamicAttributeInterface):
            """Initialize simplified access for the attribute data"""
            context = node.get_graph().get_default_graph_context()
            super().__init__(context, node, attributes, dynamic_attributes)
            self._batchedReadAttributes = [self._attributes.a_bool, self._attributes.a_constant_input, self._attributes.a_double, self._attributes.a_float, self._attributes.a_half, self._attributes.a_int, self._attributes.a_int64, self._attributes.a_objectId, self._attributes.a_path, self._attributes.a_string, self._attributes.a_token, self._attributes.a_uchar, self._attributes.a_uint, self._attributes.a_uint64]
            self._batchedReadValues = [True, 0, 0, 0, 0.0, 0, 0, 0, "", "helloString", "helloToken", 0, 0, 0]

        @property
        def a_bool(self):
            return self._batchedReadValues[0]

        @a_bool.setter
        def a_bool(self, value):
            self._batchedReadValues[0] = value

        @property
        def a_constant_input(self):
            return self._batchedReadValues[1]

        @a_constant_input.setter
        def a_constant_input(self, value):
            self._batchedReadValues[1] = value

        @property
        def a_double(self):
            return self._batchedReadValues[2]

        @a_double.setter
        def a_double(self, value):
            self._batchedReadValues[2] = value

        @property
        def a_float(self):
            return self._batchedReadValues[3]

        @a_float.setter
        def a_float(self, value):
            self._batchedReadValues[3] = value

        @property
        def a_half(self):
            return self._batchedReadValues[4]

        @a_half.setter
        def a_half(self, value):
            self._batchedReadValues[4] = value

        @property
        def a_int(self):
            return self._batchedReadValues[5]

        @a_int.setter
        def a_int(self, value):
            self._batchedReadValues[5] = value

        @property
        def a_int64(self):
            return self._batchedReadValues[6]

        @a_int64.setter
        def a_int64(self, value):
            self._batchedReadValues[6] = value

        @property
        def a_objectId(self):
            return self._batchedReadValues[7]

        @a_objectId.setter
        def a_objectId(self, value):
            self._batchedReadValues[7] = value

        @property
        def a_path(self):
            return self._batchedReadValues[8]

        @a_path.setter
        def a_path(self, value):
            self._batchedReadValues[8] = value

        @property
        def a_string(self):
            return self._batchedReadValues[9]

        @a_string.setter
        def a_string(self, value):
            self._batchedReadValues[9] = value

        @property
        def a_token(self):
            return self._batchedReadValues[10]

        @a_token.setter
        def a_token(self, value):
            self._batchedReadValues[10] = value

        @property
        def a_uchar(self):
            return self._batchedReadValues[11]

        @a_uchar.setter
        def a_uchar(self, value):
            self._batchedReadValues[11] = value

        @property
        def a_uint(self):
            return self._batchedReadValues[12]

        @a_uint.setter
        def a_uint(self, value):
            self._batchedReadValues[12] = value

        @property
        def a_uint64(self):
            return self._batchedReadValues[13]

        @a_uint64.setter
        def a_uint64(self, value):
            self._batchedReadValues[13] = value

        def __getattr__(self, item: str):
            if item in self.LOCAL_PROPERTY_NAMES:
                return object.__getattribute__(self, item)
            else:
                return super().__getattr__(item)

        def __setattr__(self, item: str, new_value):
            if item in self.LOCAL_PROPERTY_NAMES:
                object.__setattr__(self, item, new_value)
            else:
                super().__setattr__(item, new_value)

        def _prefetch(self):
            readAttributes = self._batchedReadAttributes
            newValues = _og._prefetch_input_attributes_data(readAttributes)
            if len(readAttributes) == len(newValues):
                self._batchedReadValues = newValues

    class ValuesForOutputs(og.DynamicAttributeAccess):
        LOCAL_PROPERTY_NAMES = {"a_a_boolUiName", "a_bool", "a_double", "a_float", "a_half", "a_int", "a_int64", "a_nodeTypeUiName", "a_objectId", "a_path", "a_string", "a_token", "a_uchar", "a_uint", "a_uint64", "_batchedWriteValues"}
        """Helper class that creates natural hierarchical access to output attributes"""
        def __init__(self, node: og.Node, attributes, dynamic_attributes: og.DynamicAttributeInterface):
            """Initialize simplified access for the attribute data"""
            context = node.get_graph().get_default_graph_context()
            super().__init__(context, node, attributes, dynamic_attributes)
            self.a_a_boolUiName_size = None
            self.a_nodeTypeUiName_size = None
            self.a_path_size = 6
            self.a_string_size = 20
            self._batchedWriteValues = { }

        @property
        def a_a_boolUiName(self):
            value = self._batchedWriteValues.get(self._attributes.a_a_boolUiName)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_a_boolUiName)
                return data_view.get()

        @a_a_boolUiName.setter
        def a_a_boolUiName(self, value):
            self._batchedWriteValues[self._attributes.a_a_boolUiName] = value

        @property
        def a_bool(self):
            value = self._batchedWriteValues.get(self._attributes.a_bool)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_bool)
                return data_view.get()

        @a_bool.setter
        def a_bool(self, value):
            self._batchedWriteValues[self._attributes.a_bool] = value

        @property
        def a_double(self):
            value = self._batchedWriteValues.get(self._attributes.a_double)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_double)
                return data_view.get()

        @a_double.setter
        def a_double(self, value):
            self._batchedWriteValues[self._attributes.a_double] = value

        @property
        def a_float(self):
            value = self._batchedWriteValues.get(self._attributes.a_float)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_float)
                return data_view.get()

        @a_float.setter
        def a_float(self, value):
            self._batchedWriteValues[self._attributes.a_float] = value

        @property
        def a_half(self):
            value = self._batchedWriteValues.get(self._attributes.a_half)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_half)
                return data_view.get()

        @a_half.setter
        def a_half(self, value):
            self._batchedWriteValues[self._attributes.a_half] = value

        @property
        def a_int(self):
            value = self._batchedWriteValues.get(self._attributes.a_int)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_int)
                return data_view.get()

        @a_int.setter
        def a_int(self, value):
            self._batchedWriteValues[self._attributes.a_int] = value

        @property
        def a_int64(self):
            value = self._batchedWriteValues.get(self._attributes.a_int64)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_int64)
                return data_view.get()

        @a_int64.setter
        def a_int64(self, value):
            self._batchedWriteValues[self._attributes.a_int64] = value

        @property
        def a_nodeTypeUiName(self):
            value = self._batchedWriteValues.get(self._attributes.a_nodeTypeUiName)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_nodeTypeUiName)
                return data_view.get()

        @a_nodeTypeUiName.setter
        def a_nodeTypeUiName(self, value):
            self._batchedWriteValues[self._attributes.a_nodeTypeUiName] = value

        @property
        def a_objectId(self):
            value = self._batchedWriteValues.get(self._attributes.a_objectId)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_objectId)
                return data_view.get()

        @a_objectId.setter
        def a_objectId(self, value):
            self._batchedWriteValues[self._attributes.a_objectId] = value

        @property
        def a_path(self):
            value = self._batchedWriteValues.get(self._attributes.a_path)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_path)
                return data_view.get()

        @a_path.setter
        def a_path(self, value):
            self._batchedWriteValues[self._attributes.a_path] = value

        @property
        def a_string(self):
            value = self._batchedWriteValues.get(self._attributes.a_string)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_string)
                return data_view.get()

        @a_string.setter
        def a_string(self, value):
            self._batchedWriteValues[self._attributes.a_string] = value

        @property
        def a_token(self):
            value = self._batchedWriteValues.get(self._attributes.a_token)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_token)
                return data_view.get()

        @a_token.setter
        def a_token(self, value):
            self._batchedWriteValues[self._attributes.a_token] = value

        @property
        def a_uchar(self):
            value = self._batchedWriteValues.get(self._attributes.a_uchar)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_uchar)
                return data_view.get()

        @a_uchar.setter
        def a_uchar(self, value):
            self._batchedWriteValues[self._attributes.a_uchar] = value

        @property
        def a_uint(self):
            value = self._batchedWriteValues.get(self._attributes.a_uint)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_uint)
                return data_view.get()

        @a_uint.setter
        def a_uint(self, value):
            self._batchedWriteValues[self._attributes.a_uint] = value

        @property
        def a_uint64(self):
            value = self._batchedWriteValues.get(self._attributes.a_uint64)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.a_uint64)
                return data_view.get()

        @a_uint64.setter
        def a_uint64(self, value):
            self._batchedWriteValues[self._attributes.a_uint64] = value

        def __getattr__(self, item: str):
            if item in self.LOCAL_PROPERTY_NAMES:
                return object.__getattribute__(self, item)
            else:
                return super().__getattr__(item)

        def __setattr__(self, item: str, new_value):
            if item in self.LOCAL_PROPERTY_NAMES:
                object.__setattr__(self, item, new_value)
            else:
                super().__setattr__(item, new_value)

        def _commit(self):
            _og._commit_output_attributes_data(self._batchedWriteValues)
            self._batchedWriteValues = { }

    class ValuesForState(og.DynamicAttributeAccess):
        """Helper class that creates natural hierarchical access to state attributes"""
        def __init__(self, node: og.Node, attributes, dynamic_attributes: og.DynamicAttributeInterface):
            """Initialize simplified access for the attribute data"""
            context = node.get_graph().get_default_graph_context()
            super().__init__(context, node, attributes, dynamic_attributes)

    def __init__(self, node):
        super().__init__(node)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_INPUT)
        self.inputs = OgnTutorialSimpleDataPyDatabase.ValuesForInputs(node, self.attributes.inputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_OUTPUT)
        self.outputs = OgnTutorialSimpleDataPyDatabase.ValuesForOutputs(node, self.attributes.outputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_STATE)
        self.state = OgnTutorialSimpleDataPyDatabase.ValuesForState(node, self.attributes.state, dynamic_attributes)

    class abi:
        """Class defining the ABI interface for the node type"""

        @staticmethod
        def get_node_type():
            get_node_type_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'get_node_type', None)
            if callable(get_node_type_function):
                return get_node_type_function()
            return 'omni.graph.tutorials.SimpleDataPy'

        @staticmethod
        def compute(context, node):
            def database_valid():
                return True
            try:
                per_node_data = OgnTutorialSimpleDataPyDatabase.PER_NODE_DATA[node.node_id()]
                db = per_node_data.get('_db')
                if db is None:
                    db = OgnTutorialSimpleDataPyDatabase(node)
                    per_node_data['_db'] = db
                if not database_valid():
                    per_node_data['_db'] = None
                    return False
            except:
                db = OgnTutorialSimpleDataPyDatabase(node)

            try:
                compute_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'compute', None)
                if callable(compute_function) and compute_function.__code__.co_argcount > 1:
                    return compute_function(context, node)

                db.inputs._prefetch()
                db.inputs._setting_locked = True
                with og.in_compute():
                    return OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS.compute(db)
            except Exception as error:
                stack_trace = "".join(traceback.format_tb(sys.exc_info()[2].tb_next))
                db.log_error(f'Assertion raised in compute - {error}\n{stack_trace}', add_context=False)
            finally:
                db.inputs._setting_locked = False
                db.outputs._commit()
            return False

        @staticmethod
        def initialize(context, node):
            OgnTutorialSimpleDataPyDatabase._initialize_per_node_data(node)
            initialize_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'initialize', None)
            if callable(initialize_function):
                initialize_function(context, node)

            per_node_data = OgnTutorialSimpleDataPyDatabase.PER_NODE_DATA[node.node_id()]
            def on_connection_or_disconnection(*args):
                per_node_data['_db'] = None

            node.register_on_connected_callback(on_connection_or_disconnection)
            node.register_on_disconnected_callback(on_connection_or_disconnection)

        @staticmethod
        def release(node):
            release_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'release', None)
            if callable(release_function):
                release_function(node)
            OgnTutorialSimpleDataPyDatabase._release_per_node_data(node)

        @staticmethod
        def release_instance(node, target):
            OgnTutorialSimpleDataPyDatabase._release_per_node_instance_data(node, target)

        @staticmethod
        def update_node_version(context, node, old_version, new_version):
            update_node_version_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'update_node_version', None)
            if callable(update_node_version_function):
                return update_node_version_function(context, node, old_version, new_version)
            return False

        @staticmethod
        def initialize_type(node_type):
            initialize_type_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'initialize_type', None)
            needs_initializing = True
            if callable(initialize_type_function):
                needs_initializing = initialize_type_function(node_type)
            if needs_initializing:
                node_type.set_metadata(ogn.MetadataKeys.EXTENSION, "omni.graph.tutorials")
                node_type.set_metadata(ogn.MetadataKeys.UI_NAME, "Tutorial Python Node: Attributes With Simple Data")
                node_type.set_metadata(ogn.MetadataKeys.ICON_COLOR, "#FF00FF00")
                node_type.set_metadata(ogn.MetadataKeys.ICON_BACKGROUND_COLOR, "#7FFF0000")
                node_type.set_metadata(ogn.MetadataKeys.ICON_BORDER_COLOR, "#FF0000FF")
                node_type.set_metadata(ogn.MetadataKeys.CATEGORIES, "tutorials")
                node_type.set_metadata(ogn.MetadataKeys.DESCRIPTION, "This is a tutorial node. It creates both an input and output attribute of every simple  supported data type. The values are modified in a simple way so that the compute modifies values.  It is the same as node omni.graph.tutorials.SimpleData, except it is implemented in Python instead of C++.")
                node_type.set_metadata(ogn.MetadataKeys.LANGUAGE, "Python")
                icon_path = carb.tokens.get_tokens_interface().resolve("${omni.graph.tutorials}")
                icon_path = icon_path + '/' + "ogn/icons/omni.graph.tutorials.SimpleDataPy.svg"
                node_type.set_metadata(ogn.MetadataKeys.ICON_PATH, icon_path)
                OgnTutorialSimpleDataPyDatabase.INTERFACE.add_to_node_type(node_type)

        @staticmethod
        def on_connection_type_resolve(node):
            on_connection_type_resolve_function = getattr(OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS, 'on_connection_type_resolve', None)
            if callable(on_connection_type_resolve_function):
                on_connection_type_resolve_function(node)

    NODE_TYPE_CLASS = None

    @staticmethod
    def register(node_type_class):
        OgnTutorialSimpleDataPyDatabase.NODE_TYPE_CLASS = node_type_class
        og.register_node_type(OgnTutorialSimpleDataPyDatabase.abi, 1)

    @staticmethod
    def deregister():
        og.deregister_node_type("omni.graph.tutorials.SimpleDataPy")
