code: def validate_module(pipeline, module_num, callback):
      """Validate a module and execute the callback on error on the main thread
  
      pipeline - a pipeline to be validated
      module_num - the module number of the module to be validated
      callback - a callback with the signature, "fn(setting, message, pipeline_data)"
      where setting is the setting that is in error and message is the message to
      display.
      """
      modules = [
          m for m in pipeline.modules() if m.module_num == module_num
      ]
      if len(modules) != 1:
          return
      module = modules[0]
      level = logging.INFO
      setting_idx = None
      message = None
      try:
          level = logging.ERROR
          module.test_valid(
              pipeline
          )  # this method validates each visible
          # setting first, then the module itself.
          level = logging.WARNING
          module.test_module_warnings(pipeline)
          level = logging.INFO
      except ValidationError as instance:
          message = instance.message
          setting_idx = [
              m.key() for m in module.visible_settings()
          ].index(instance.get_setting().key())
      except Exception as e:
          LOGGER.error("Error in validation thread", e)
      wx.CallAfter(callback, setting_idx, message, level)
  
imports: import logging
  import threading
  import time
  import wx
  from cellprofiler_core.setting import ValidationError
  import cellprofiler.gui.constants.module_view
  from cellprofiler.gui.module_view._validation_request_controller import ValidationRequestController
label_desc: Use image node_id 27 for calling a global function with example usage: validate_module(pipeline, module_num, callback) without return types