code: def instantiate(self, substitutions):
          
          param_dict = self.substitute_params(substitutions)
          pkg, ident = self.name.rsplit(".", 1)
          pkg = "malcolm.modules.%s" % pkg
          try:
              ob = importlib.import_module(pkg)
          except ImportError as e:
              raise_with_traceback(
                  ImportError("\n%s:%d:\n%s" % (
                      self.filename, self.lineno, e)))
          try:
              ob = getattr(ob, ident)
          except AttributeError:
              raise_with_traceback(
                  ImportError("\n%s:%d:\nPackage %r has no ident %r" % (
                      self.filename, self.lineno, pkg, ident)))
          try:
              model = MethodModel.from_callable(ob, returns=False)
              args = model.validate(param_dict)
              ret = ob(**args)
          except Exception as e:
              sourcefile = inspect.getsourcefile(ob)
              lineno = inspect.getsourcelines(ob)[1]
              raise_with_traceback(
                  YamlError("\n%s:%d:\n%s:%d:\n%s" % (
                      self.filename, self.lineno, sourcefile, lineno, e)))
          else:
              return ret
docs: Keep recursing down from base using dotted name, then call it with
          self.params and args
  
          Args:
              substitutions (dict): Substitutions to make to self.param_dict
  
          Returns:
              The found object called with (*args, map_from_d)
  
          E.g. if ob is malcolm.parts, and name is "ca.CADoublePart", then the
          object will be malcolm.parts.ca.CADoublePart