2

I'm currently learning Flask and I just set up a config file I load into the app with:

app.config.from_object('myconfigmodule')

The config module has two classes in it, Config and DebugConfig and DebugConfig inherits Config. I'd like to use @property getters to get config variables rather than accessing them with app.config['myvar'] because it makes for cleaner code. I set this up and app.config does not see the properties but I can still access the config class members with app.config['myvar']

This is the error I get when I start my app:

Traceback (most recent call last):
File "runserver.py", line 3, in <module>
app.run(host=app.config['_APP_HOST'], debug=app.config.Debug)
AttributeError: 'Config' object has no attribute 'Debug'

In the config class the Debug property is as follows:

class Config (object):
    _APP_DEBUG = False

    @property
    def Debug (self):
        return self._APP_DEBUG

Am I doing something wrong here or does Flask just not like properties in configs for some reason? Thanks for any help!

RocketDonkey
  • 36,383
  • 7
  • 80
  • 84
jay
  • 655
  • 1
  • 6
  • 6
  • The `Config` object is instantiated with the `app.config.from_object('myapp.config.Config')` call. Flask takes it from there and populates `app.config` invisibly with its values. I'd assume it would take the properties from the `Config` class and allow those, but it doesn't seem to be the case. It's likely just taking the class variables and popping them into a dictionary rather than properly instantiating the class. – jay Jan 09 '13 at 04:53
  • @miku's answer below seems to hit the nail on the head, so disregard my (now deleted) comment :) – RocketDonkey Jan 09 '13 at 04:59

1 Answers1

3

Flask has it's own Config class (a dict subclass) and it will pick out the attributes of the object given to from_object, rather that using the given object as is, as can be seen in the source code:

# class Config(dict):
# ...
    for key in dir(obj):
        if key.isupper():
            self[key] = getattr(obj, key)

As you can see, it will only use uppercase attributes.

Here's an example by hand:

>>> from flask import config
>>> class X(object):
...     REGULAR = True
...     ignored = "not uppercase"
...     def __init__(self):
...         self.not_used = "because lowercase"
...         self.OK = True
...     
...     @property
...     def UPPER_PROP(self):
...         return True
...     
...     @property
...     def MIXED_case(self):
...         return "wont work"
... 
>>> x = X()
>>> c = config.Config(None)
>>> c.from_object(x)
>>> c
<Config {'REGULAR': True, 'OK': True, 'UPPER_PROP': True}>

That said, nothing will hold you back, if you want to implement something like a dot-dict'd subclass of flasks' Config. Whether the potential confusion caused by a non-standard approach outweighs the gains in code readability is something you can decide based on the scope of your project.

miku
  • 181,842
  • 47
  • 306
  • 310
  • 1
    Now that I see how `from_object` works it makes a lot more sense! Thanks for the help and for reminding me I should be looking at the source myself when I get stuck on something that I feel "should" work. – jay Jan 09 '13 at 05:17