1

I have just started using cement as a python framework. It seems that the default config of the app is not JSON.

It seems that Cement has JsonConfigHandler() class that could load JSON configuration into app. I have used the code below in my app:

ins = JsonConfigHandler()
ins.parse_file('/etc/luna/luna.conf')

But it gives the error below:

    return self._parse_file(file_path)
  File "/Library/Python/2.7/site-packages/cement/ext/ext_json.py", line 243, in _parse_file
    self.merge(self._json.load(open(file_path)))
AttributeError: 'NoneType' object has no attribute 'load'

Hows should I load JSON config file in cement app?

By default I load config using app.config.parse_file('/etc/my_app/app.conf') with no problem and config file contains:

[connection]
host=172.16.131.12
Alireza
  • 6,497
  • 13
  • 59
  • 132

2 Answers2

2

Apologies for not being on top of this, but here is the official response (primary developer):

You simply need to include the json extension, and then set the CementApp.Meta.config_handler to json:

from cement.core.foundation import CementApp

class MyApp(CementApp):
    class Meta:
        label = 'myapp'
        extensions = ['json']
        config_handler = 'json'
        config_extension = '.json'

This will keep the default config_files list intact, but use .json instead of .conf for the files it looks for.

derks
  • 221
  • 2
  • 4
1

JSON file /etc/luna/luna.conf:

{
    "connection": {
        "host": "172.16.131.12"
    }
}

Python:

from cement.core.foundation import CementApp
from cement.ext.ext_json import JsonConfigHandler

app = CementApp('test', config_handler=JsonConfigHandler,
                config_files=['/etc/luna/luna.conf'])
app.setup()

print(app.config.get('connection', 'host'))

Outputs 172.16.131.12


Old answer, please disregard

Don't know the library, but looking at the code it looks like you have to first call the _setup() method:

ins = JsonConfigHandler()
ins._setup(app)
ins.parse_file('/etc/luna/luna.conf')
Paco H.
  • 2,034
  • 7
  • 18
  • Inside of Cement framework calling a protected method does not seem good practice at all. I'm sure there is a better way that could feed JSON config into cement configuration handler. – Alireza Jun 01 '17 at 09:30
  • You are absolutely right @ALH, can you check if the edit I added works? – Paco H. Jun 01 '17 at 09:42
  • @ALH made another edit, it now works correctly for me. Let me know if this works for you and I'll edit the answer to reflect the correct solution clearly. – Paco H. Jun 01 '17 at 09:58
  • Thank you for your response, If in JSON I have a key like `"modern": "yes"` how should I retrieve it? It seems that a config should have a section! I cannot get `modern` by get() method. – Alireza Jun 01 '17 at 11:38
  • 1
    I don't think it's possible, if you have a look at the code the `cement.ext.ext_json.JsonConfigHandler#_parse_file` method loads the JSON config file (`self._json.load(open(file_path))`) and passes the JSON object (a dict) to `cement.ext.ext_configparser.ConfigParserConfigHandler#merge`, this method iterates over the key value pairs of the JSON dict and skips the ones where the value isn't a dict. I guess you will have to put `"modern": "yes"` inside a section. I didn't find documentation for this, it's all from what I understand from reading the code, and therefore I could be wrong. – Paco H. Jun 01 '17 at 12:19