code: def _config_parser(cls, repo, parent_commit, read_only):
          
          parent_matches_head = True
          if parent_commit is not None:
              try:
                  parent_matches_head = repo.head.commit == parent_commit
              except ValueError:
                  # We are most likely in an empty repository, so the HEAD doesn't point to a valid ref
                  pass
          # end handle parent_commit
  
          if not repo.bare and parent_matches_head:
              fp_module = osp.join(repo.working_tree_dir, cls.k_modules_file)
          else:
              assert parent_commit is not None, "need valid parent_commit in bare repositories"
              try:
                  fp_module = cls._sio_modules(parent_commit)
              except KeyError:
                  raise IOError("Could not find %s file in the tree of parent commit %s" %
                                (cls.k_modules_file, parent_commit))
              # END handle exceptions
          # END handle non-bare working tree
  
          if not read_only and (repo.bare or not parent_matches_head):
              raise ValueError("Cannot write blobs of 'historical' submodule configurations")
          # END handle writes of historical submodules
  
          return SubmoduleConfigParser(fp_module, read_only=read_only)
docs: :return: Config Parser constrained to our submodule in read or write mode
          :raise IOError: If the .gitmodules file cannot be found, either locally or in the repository
              at the given parent commit. Otherwise the exception would be delayed until the first
              access of the config parser