DiffSK / configobj

Python 3+ compatible port of the configobj library
https://configobj.readthedocs.org
Other
321 stars 76 forks source link

Empty string keyword results in NestingError #202

Closed raratiru closed 4 years ago

raratiru commented 4 years ago

In my Django configuration I define a root logger:

{
    "LOGGING": {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {},
        "filters": {},
        "handlers": {},
        "loggers": {
            "": {},  # The root logger
            "django": {},
            "celery": {},
        },
    }
}

When I :

config = ConfigObj()
config.filename = config_path
config.indent_type = "    "
config.interpolation = False
config.write()

the result is like that:

[LOGGING]
    [[formatters]]
    [[filters]]
    [[handlers]]
    [[loggers]]
        [[[""]]]  # Line 95
        [[[django]]]
        [[[celery]]]

When I ConfigObj('conf.ini') I get the error:

...
  File "/home/.virtualenvs/pod/lib/python3.8/site-packages/configobj.py", line 1229, in __init__
    self._load(infile, configspec)

  File "/home/.virtualenvs/pod/lib/python3.8/site-packages/configobj.py", line 1318, in _load
    raise error

  File "<string>", line unknown
NestingError: Cannot compute the section depth at line 95.

Is it a bug? If not, how can I define the root logger?

joeydumont commented 4 years ago

I'm not sure how to replicate this. Could you provide the input, the script to create the output, and the expected output? I tried, but I wasn't sure how you got from your JSON root logger to your ini config file, and what you wanted ConfigObj to do.

raratiru commented 4 years ago

Sorry, I was rather sloppy.

This is the code that reproduces the issue.

With Python-3.8.2 and configobj-5.0.6:

config = ConfigObj() config.filename = "conf.ini" config.indent_type = " " config.interpolation = False

config["LOGGING"] = { "version": 1, "disable_existing_loggers": False, "formatters": {}, "filters": {}, "handlers": {}, "loggers": { "": {}, # The root logger "django": {}, "celery": {}, }, }

config.write()

* Inspect `conf.ini` (as expected):
```bash
$ cat conf.ini
[LOGGING]
    version = 1
    disable_existing_loggers = False
    [[formatters]]
    [[filters]]
    [[handlers]]
    [[loggers]]
        [[[""]]]  # Line 8
        [[[django]]]
        [[[celery]]]

load_config = ConfigObj("conf.ini")

Traceback (most recent call last):

File "/home/.virtualenvs/pod/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3331, in run_code exec(code_obj, self.user_global_ns, self.user_ns)

File "", line 1, in load_config = ConfigObj("conf.ini")

File "/home/.virtualenvs/pod/lib/python3.8/site-packages/configobj.py", line 1229, in init self._load(infile, configspec)

File "/home/.virtualenvs/pod/lib/python3.8/site-packages/configobj.py", line 1318, in _load raise error

File "", line unknown NestingError: Cannot compute the section depth at line 8.


Issue
-------

* I expected `ConfigObj` to load the `conf.ini` file that has the correct contents, created by `ConfigObj`, but instead it raises this error.
joeydumont commented 4 years ago

I don't think the two issues are related. Tracing the issue, I think it comes from the parsing section. See the _sectionmarker regex in __init__.py (line 1062):

_sectionmarker = re.compile(r'''^                                           
        (\s*)                     # 1: indentation                              
        ((?:\[\s*)+)              # 2: section marker open                      
        (                         # 3: section name open                        
            (?:"\s*\S.*?\s*")|    # at least one non-space with double quotes   
            (?:'\s*\S.*?\s*')|    # at least one non-space with single quotes   
            (?:[^'"\s].*?)        # at least one non-space unquoted             
        )                         # section name close                          
        ((?:\s*\])+)              # 4: section marker close                     
        (\s*(?:\#.*)?)?           # 5: optional comment  

To be marked a section, a section heading must contain at least a non-space character, either surrounded by double quotes, single quotes, or unquoted. You could try adding a case in the section name portion of the regex that fits your needs (two double quotes). Make sure it goes well with the rest of the parsing though.

raratiru commented 4 years ago

Thank you!

Since this is an intended behavior, I can programmatically cope with it when initializing the config object.