Larger applications tend to need different environments, e.g. one for development, one for staging (i.e. demo for the client), maybe one for testing, and finally one for production use.
Pyramid uses INI files and you have to tell your web server, which INI file it shall use. It would be possible to implement scenarios like above with these. But in the past I had also the need to deploy the same environment to different hosts, and each host needed a slightly different configuration. Also, I prefer YAML over INI, and like to have the specific configuration inherit settings from a global configuration.
Therefore I created my own component, called Rc.
Parenchym sports a UNIX-like directory layout, and thus the configuration files are located in a directory named etc. The global configuration is stored here in file rc.yml. For each host there’s a subdirectory named like the hostname, and here is also a file rc.yml. This one, though, has only settings that differ from the global settings.
On startup, Rc reads and merges these files into a dict. The Rc component is available as request.registry.settings['rc’]. Additionally it updates Pyramid’s settings with its settings, so that you may call request.registry.settings['environment’] directly, to get what you have defined in your rc file.
If you like to publish your source code say, on github, you naturally will include your configuration settings. And these may contain sensitive data, like passwords. Which precautions can you take that you not accidentally publish sensitive data? The github docs, in summa, say that there is no way to prevent such, and that it is not really possible to be undone.
So, the point is: don’t publish your credentials!
But you surely want to keep your configuration in source control. Therefore, Rc allows you to outsource sensitive data in a separate file called rcsecrets.yml. And this file alone you can exclude from source control.
If e.g. .gitignore is properly set up, you still keep the main configuration in git and can happily publish it.
See “Implementation” above.
Lets say your application has two modules which process emails for different purposes. You put the credentials for your email account into the rc file and you are set. But later on you decide, the second module must use its own email account. Well, you put credentials for the second account into the rc file, too. But now you must also change the source code of your second module into the new configuration keys. This is ugly.
With Rc’s references you handle circumstances like these gracefully. Rc’s keys are segmented like this: foo.bar.baz : myvalue. With a reference you can tell Rc to duplicate all keys that start with a certain pattern, and create new keys that start with the start of the reference.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# Resource gmail.imap.user: foo gmail.imap.pwd: bar ^^^^^^^^^^ ^^^ \ \_ ref_suffix \___________ ref_prefix as given in referring node # Module infobox.rc_ref_imap: gmail.imap ^^^^^^^ ^^^^ ^^^^^^^^^^ \ \ \_ ref_prefix \ \______ infix \____________________ prefix Reading these will also create nodes: infobox.imap.user infobox.imap.pwd
As you can see, you define the settings for a resource like an email account independently from the settings of your modules. From your module’s settings you can then reference a resource.
In our scenario from the beginning, at first both modules can reference the same resource. As the modules diverge, you may add a second resource and let the settings of module 2 reference this one. This change is completely transparent to your code.