docs: def get_merged_config(**options):
      """Get the final merged configuration for supvervisord, as a string.
  
      This is the top-level function exported by this module.  It combines
      the config file from the main project with default settings and those
      specified in the command-line, processes various special section names,
      and returns the resulting configuration as a string.
      """
      #  Find and load the containing project module.
      #  This can be specified explicity using the --project-dir option.
      #  Otherwise, we attempt to guess by looking for the manage.py file.
      project_dir = options.get("project_dir")
      if project_dir is None:
          project_dir = guess_project_dir()
      # Find the config file to load.
      # Default to <project-dir>/supervisord.conf.
      config_file = options.get("config_file")
      if config_file is None:
          config_file = os.path.join(project_dir,CONFIG_FILE)
      #  Build the default template context variables.
      #  This is mostly useful information about the project and environment.
      ctx = {
          "PROJECT_DIR": project_dir,
          "PYTHON": os.path.realpath(os.path.abspath(sys.executable)),
          "SUPERVISOR_OPTIONS": rerender_options(options),
          "settings": settings,
          "environ": os.environ,
      }
      #  Initialise the ConfigParser.
      #  Fortunately for us, ConfigParser has merge-multiple-config-files
      #  functionality built into it.  You just read each file in turn, and
      #  values from later files overwrite values from former.
      cfg = RawConfigParser()
      #  Start from the default configuration options.
      data = render_config(DEFAULT_CONFIG,ctx)
      cfg.readfp(StringIO(data))
      #  Add in the project-specific config file.
      with open(config_file,"r") as f:
          data = render_config(f.read(),ctx)
      cfg.readfp(StringIO(data))
      #  Add in the options specified on the command-line.
      cfg.readfp(StringIO(get_config_from_options(**options)))
      #  Add options from [program:__defaults__] to each program section
      #  if it happens to be missing that option.
      PROG_DEFAULTS = "program:__defaults__"
      if cfg.has_section(PROG_DEFAULTS):
          for option in cfg.options(PROG_DEFAULTS):
              default = cfg.get(PROG_DEFAULTS,option)
              for section in cfg.sections():
                  if section.startswith("program:"):
                      if not cfg.has_option(section,option):
                          cfg.set(section,option,default)
          cfg.remove_section(PROG_DEFAULTS)
      #  Add options from [program:__overrides__] to each program section
      #  regardless of whether they already have that option.
      PROG_OVERRIDES = "program:__overrides__"
      if cfg.has_section(PROG_OVERRIDES):
          for option in cfg.options(PROG_OVERRIDES):
              override = cfg.get(PROG_OVERRIDES,option)
              for section in cfg.sections():
                  if section.startswith("program:"):
                      cfg.set(section,option,override)
          cfg.remove_section(PROG_OVERRIDES)
      #  Make sure we've got a port configured for supervisorctl to
      #  talk to supervisord.  It's passworded based on secret key.
      #  If they have configured a unix socket then use that, otherwise
      #  use an inet server on localhost at fixed-but-randomish port.
      username = hashlib.md5(settings.SECRET_KEY).hexdigest()[:7]
      password = hashlib.md5(username).hexdigest()
      if cfg.has_section("unix_http_server"):
          set_if_missing(cfg,"unix_http_server","username",username)
          set_if_missing(cfg,"unix_http_server","password",password)
          serverurl = "unix://" + cfg.get("unix_http_server","file")
      else:
          #  This picks a "random" port in the 9000 range to listen on.
          #  It's derived from the secret key, so it's stable for a given
          #  project but multiple projects are unlikely to collide.
          port = int(hashlib.md5(password).hexdigest()[:3],16) % 1000
          addr = "127.0.0.1:9%03d" % (port,)
          set_if_missing(cfg,"inet_http_server","port",addr)
          set_if_missing(cfg,"inet_http_server","username",username)
          set_if_missing(cfg,"inet_http_server","password",password)
          serverurl = "http://" + cfg.get("inet_http_server","port")
      set_if_missing(cfg,"supervisorctl","serverurl",serverurl)
      set_if_missing(cfg,"supervisorctl","username",username)
      set_if_missing(cfg,"supervisorctl","password",password)
      set_if_missing(cfg,"rpcinterface:supervisor",
                         "supervisor.rpcinterface_factory",
                         "supervisor.rpcinterface:make_main_rpcinterface")
      #  Remove any [program:] sections with exclude=true
      for section in cfg.sections():
          try:
              if cfg.getboolean(section,"exclude"):
                  cfg.remove_section(section)
          except NoOptionError:
              pass
      #  Sanity-check to give better error messages.
      for section in cfg.sections():
          if section.startswith("program:"):
              if not cfg.has_option(section,"command"):
                  msg = "Process name '%s' has no command configured"
                  raise ValueError(msg % (section.split(":",1)[-1]))
      #  Write it out to a StringIO and return the data
      s = StringIO()
      cfg.write(s)
      return s.getvalue()