configparser icon indicating copy to clipboard operation
configparser copied to clipboard

"global" section surprising and indistinguishable from real section named 'global' ?

Open Dieterbe opened this issue 3 years ago • 1 comments

Hello, seems that the library always adds a "global" section, even for empty files. This is surprising because it's not mentioned in the readme, nor in the api docs The way it is implemented seems particularly worrisome. While I can see how we would want a place to keep globally/un-sectioned parameters, the current approach means you cannot distinguish global parameters from a real global section. for example the below program will print the section as foo=42, whether that parameter was declared globally or in a section literally called [global] (full output after source code)

package main

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/alyu/configparser"
)

func handleErr(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	fd, err := ioutil.TempFile("", "")
	handleErr(err)

	defer os.Remove(fd.Name())

	_, err = fd.Write([]byte(`foo=42`))
	handleErr(err)

	err = fd.Close()
	handleErr(err)

	dump("empty file", fd.Name())

	fd2, err := ioutil.TempFile("", "")
	handleErr(err)

	defer os.Remove(fd2.Name())

	_, err = fd2.Write([]byte(`[global]
foo=42`))
	handleErr(err)

	err = fd2.Close()
	handleErr(err)

	dump("file with global section", fd2.Name())
}

func dump(info, fname string) {
	config, err := configparser.Read(fname)
	handleErr(err)
	fmt.Printf("### start dump of %q ###\n", info)
	fmt.Println("config.String():", config.String())

	sections, err := config.AllSections()
	handleErr(err)
	for _, s := range sections {
		fmt.Println("section: ", s.String())
		fmt.Println("# options", s.Options())
		fmt.Println("# optionNames", s.OptionNames())
	}
	fmt.Printf("### end dump of %q ###\n", info)
	fmt.Println()
	fmt.Println()
}
### start dump of "empty file" ###
config.String(): foo=42

section:  foo=42

# options map[foo:42]
# optionNames [foo]
### end dump of "empty file" ###


### start dump of "file with global section" ###
config.String(): foo=42

section:  
# options map[]
# optionNames []
section:  foo=42

# options map[foo:42]
# optionNames [foo]
### end dump of "file with global section" ###

Dieterbe avatar Jun 16 '21 18:06 Dieterbe

what i have in mind is something like this: https://github.com/grafana/configparser/commit/122fe6ae893e02d9bb79267dfd094d4738239069

seems to work, with the caveat that some of the other functionality still needs to be updated

Dieterbe avatar Jun 16 '21 19:06 Dieterbe