code: def _base_flow_decorator(decofunc, *args, **kwargs):
      """
      Decorator prototype for all flow (class) decorators. This function gets
      specialized and imported for all decorators types by
      _import_plugin_decorators().
      """
      if args:
          # No keyword arguments specified for the decorator, e.g. @foobar.
          # The first argument is the class to be decorated.
          cls = args[0]
          if isinstance(cls, type) and issubclass(cls, FlowSpec):
              # flow decorators add attributes in the class dictionary,
              # _flow_decorators. _flow_decorators is of type `{key:[decos]}`
              if (
                  decofunc.name in cls._flow_decorators
                  and not decofunc.allow_multiple
              ):
                  raise DuplicateFlowDecoratorException(decofunc.name)
              else:
                  deco_instance = decofunc(
                      attributes=kwargs, statically_defined=True
                  )
                  cls._flow_decorators.setdefault(
                      decofunc.name, []
                  ).append(deco_instance)
          else:
              raise BadFlowDecoratorException(decofunc.name)
          return cls
      else:
          # Keyword arguments specified, e.g. @foobar(a=1, b=2).
          # Return a decorator function that will get the actual
          # function to be decorated as the first argument.
          def wrap(f):
              return _base_flow_decorator(decofunc, f, **kwargs)
  
          return wrap
  
imports: from functools import partial
  import json
  import re
  import os
  import sys
  from .flowspec import FlowSpec
  from .exception import MetaflowInternalError, MetaflowException, InvalidDecoratorAttribute
  from metaflow._vendor import click
label_desc: Use image node_id 3 for calling a global function with example usage: _base_flow_decorator(decofunc) and returns: cls, wrap, _base_flow_decorator