code: def make_block_creator(yaml_path, filename=None):
      # type: (str, str) -> Callable[..., List[Controller]]
      
      sections, yamlname, docstring = Section.from_yaml(yaml_path, filename)
      yamldir = os.path.dirname(yaml_path)
  
      # Check we have only one controller
      controller_sections = [s for s in sections if s.section == "controllers"]
      assert len(controller_sections) == 1, \
          "Expected exactly 1 controller, got %s" % (controller_sections,)
      controller_section = controller_sections[0]
  
      def block_creator(kwargs):
          # Create the param dict of the static defined arguments
          defines = _create_defines(sections, yamlname, yamldir, kwargs)
          controllers, parts = _create_blocks_and_parts(sections, defines)
          # Make the controller
          controller = controller_section.instantiate(defines)
          for part in parts:
              controller.add_part(part)
          controllers.append(controller)
          return controllers
  
      creator = creator_with_nice_signature(
          block_creator, sections, yamlname, yaml_path, docstring)
      return creator
docs: Make a collection function that will create a list of blocks
  
      Args:
          yaml_path (str): File path to YAML file, or a file in the same dir
          filename (str): If give, use this filename as the last element in
              the yaml_path (so yaml_path can be __file__)
  
      Returns:
          function: A collection function decorated with @takes. This can be
              used in other blocks or instantiated by the process. If the
              YAML text specified controllers or parts then a block instance
              with the given name will be instantiated. If there are any
              blocks listed then they will be called. All created blocks
              by this or any sub collection will be returned