class_docstr: Controls the setup and execution of a pipeline of processes.
class_docstr_tok: ["Controls","the","setup","and","execution","of","a","pipeline","of","processes","."]
docstr: Checks if a parameter is available as an input or output
docstr_tok: ["Checks","if","a","parameter","is","available","as","an","input","or","output"]
code: def _has_attr(self, parameter, subtype="in"):
      """Checks if a parameter is available as an input or output"""
      hierarchy = parameter.split(".")
  
      # Connecting to a workflow needs at least two values,
      # the name of the child node and the name of the input/output
      if len(hierarchy) < 2:
          return False
  
      attrname = hierarchy.pop()
      nodename = hierarchy.pop()
  
      def _check_is_already_connected(workflow, node, attrname):
          for _, _, d in workflow._graph.in_edges(
              nbunch=node, data=True
          ):
              for cd in d["connect"]:
                  if attrname == cd[1]:
                      return False
          return True
  
      targetworkflow = self
      while hierarchy:
          workflowname = hierarchy.pop(0)
          workflow = None
          for node in targetworkflow._graph.nodes():
              if node.name == workflowname:
                  if isinstance(node, Workflow):
                      workflow = node
                      break
          if workflow is None:
              return False
          # Verify input does not already have an incoming connection
          # in the hierarchy of workflows
          if subtype == "in":
              hierattrname = ".".join(hierarchy + [nodename, attrname])
              if not _check_is_already_connected(
                  targetworkflow, workflow, hierattrname
              ):
                  return False
          targetworkflow = workflow
  
      targetnode = None
      for node in targetworkflow._graph.nodes():
          if node.name == nodename:
              if isinstance(node, Workflow):
                  return False
              else:
                  targetnode = node
                  break
      if targetnode is None:
          return False
  
      if subtype == "in":
          if not hasattr(targetnode.inputs, attrname):
              return False
      else:
          if not hasattr(targetnode.outputs, attrname):
              return False
  
      # Verify input does not already have an incoming connection
      # in the target workflow
      if subtype == "in":
          if not _check_is_already_connected(
              targetworkflow, targetnode, attrname
          ):
              return False
  
      return True
  
imports: import os
  import os.path
  import sys
  from datetime import datetime
  from copy import deepcopy
  import pickle
  import shutil
  import numpy
  from ...None import config, logging
  from ...utils.misc import str2bool
  from ...utils.functions import getsource, create_function_from_source
  from ...interfaces.base import traits, TraitedSpec, TraitDictObject, TraitListObject
  from ...utils.filemanip import save_json
  from .utils import generate_expanded_graph, export_graph, write_workflow_prov, write_workflow_resources, format_dot, topological_sort, get_print_name, merge_dict, format_node
  from .base import EngineBase
  from .nodes import MapNode
label_desc: Use image node_id 19 for calling the Workflow obj's underlying member method code with example usage: obj._has_attr(parameter, subtype) and returns: True, False, True, False, False, False, False, False, False, False, False