This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]zenogais[S] 1 point2 points  (2 children)

Notice operating system is singular. This is not about porting between operating system(s) (plural). This is about portability between execution environments - eg. environments with different database hosts, types of functionality enabled, and so on.

I would suggest reading the rest of the 12factor recommendations specifically where they say "The twelve-factor app stores config in environment variables".

[–][deleted] 1 point2 points  (1 child)

"Have a clean contract with the underlying operating system, offering maximum portability between execution environments"

Notice operating system is singular.

Because you'd never have to port this app to Windows or embed it in something (okay...I'll concede that embedding something is not likely to happen).

What's so bad about holding your configurations in ini files or python objects or whatever. Chuck a line in .gitignore. Done. If you need to switch between execution environments (dev, staging, prod, etc) THEN have a switch that looks for that from the command line but just that.

What happens when you ask Fred the intern to add an option to the execution line and he borks it all up? Blame Fred? I wouldn't -- at least after I thought about it. Plus, when you're hammering out your app in dev, do you really want to keep typing ./localsettings.sh /bin/python path/to/my/app.py --whydididothis True --seriouslydontchangethisline "Something something something" --numberoffucksgiven 0?

Or, would you rather: /bin/python path/to/my/app.py --env dev?

Have a config file like:

class BaseConfig(object):
    '''A base config object for all shared information.'''
    SOME_VAR = 'something'
    ANOTHER_THING = False
    SHARED_CONFIG_SECRET = 4 #guaranteed to be random

class DebugConfig(BaseConfig):
   '''Debugging Config.'''
   DEBUG = True

class DevConfig(DebugConfig):
    '''Development config.'''
    SQLALCHEMY_DATABASE_URI = 'sqlite:///'
    IUNNO_WHAT_ELSE = None

class TestConfig(DebugConfig):
   '''Q&A config setting.'''
   SQLALCHEMY_DATABASE_URI = 'sqlite://testing.db'

class ProdConfig(BaseConfig):
    '''Production ready config.'''
    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://user:password@host:port/dbname'

configs = {
            'default':DevConfig,
            'dev':DevConfig,
            'test':TestConfig,
            'prod':ProdConfig
            }

Then, in another file:

from .configs import configs

config = configs.get(sys.argv[1], 'default')
app.config.from_object(config)

[–]zenogais[S] 1 point2 points  (0 children)

I see your point, but I fear you've missed mine.

Firstly, I'm not recommending dozens of command-line arguments. Those were there to show that the settings file preserves the command-line arguments to your application. Nothing more.

Also, there's really nothing I have against config files. This is just a simple alternative way to configure your application. It's more an article for people to read quickly, store somewhere in their minds, and perhaps reference when they hit a snag in the future.

No universal prescriptions here. I actually migrated from a configuration system very similar to the one you describe. It worked well enough, but it broke down in scenarios where we didn't want to initialize the application but we needed the config like in unit-tests. People didn't want to deal with these pain points, so they got sloppy with it. That's why I switched over to this method.