212 lines
6.9 KiB
Plaintext
212 lines
6.9 KiB
Plaintext
|
Metadata-Version: 1.1
|
||
|
Name: constants
|
||
|
Version: 0.6.0
|
||
|
Summary: The simple way to deal with environment constants.
|
||
|
Home-page: http://github.com/3kwa/constants
|
||
|
Author: Eugene Van den Bulke
|
||
|
Author-email: eugene.vandenbulke@gmail.com
|
||
|
License: BSD
|
||
|
Description: =========
|
||
|
constants
|
||
|
=========
|
||
|
|
||
|
|
||
|
The problem?
|
||
|
============
|
||
|
|
||
|
Most applications use constants. Many constants take different values based
|
||
|
on the environment the application is executed in.
|
||
|
|
||
|
Think database credentials over development, testing, staging, production or
|
||
|
stock market execution over development, testing, paper, production ...
|
||
|
|
||
|
|
||
|
A solution
|
||
|
==========
|
||
|
|
||
|
Shamelessly inspired by the app_constants_ gem, ``constants`` aims to solve that
|
||
|
problem (and that problem only).
|
||
|
|
||
|
.ini file
|
||
|
---------
|
||
|
|
||
|
``constants`` uses the .ini file format to specify the application constants
|
||
|
values in each environment. DEFAULT values are available in every environment
|
||
|
unless specifically overridden in a section.
|
||
|
|
||
|
::
|
||
|
|
||
|
[DEFAULT]
|
||
|
something = a_default_value
|
||
|
all = 1
|
||
|
a_string = 0350
|
||
|
|
||
|
[a_section]
|
||
|
something = a_section_value
|
||
|
just_for_me = 5.0
|
||
|
flag = False
|
||
|
minutes = 365 * 24 * 60
|
||
|
|
||
|
To find out more about ini files and sections, check the Python standard
|
||
|
library configparser_ documention.
|
||
|
|
||
|
The default file is ``constants.ini`` in the current working directory. but
|
||
|
you can use any filename you want cf. Instantiation_.
|
||
|
|
||
|
Environment
|
||
|
-----------
|
||
|
|
||
|
Define the environment the application will run in. The default environment
|
||
|
variable to store that value is __CONSTANTS__, but you can use any variable
|
||
|
name you want cf. Instantiation_.
|
||
|
|
||
|
Most platform have a way to do that, in bash:
|
||
|
|
||
|
::
|
||
|
|
||
|
export __CONSTANTS__=a_section
|
||
|
|
||
|
.. _Instantiation:
|
||
|
|
||
|
Instantiation
|
||
|
-------------
|
||
|
|
||
|
>>> import constants
|
||
|
>>> consts = constants.Constants()
|
||
|
|
||
|
On instantiation, constants looks for an environement variable named
|
||
|
__CONSTANTS__ whose value is used to find out which section of the
|
||
|
constants.ini file should be used.
|
||
|
|
||
|
Constants' constructor takes two (2) optional parameters. ``variable``
|
||
|
let's you specify the name of the environment variable and ``filename``
|
||
|
the absolute path to the .ini file containing the constants definitions.
|
||
|
|
||
|
>>> consts = Constants(variable='AN_ENVIRONMENT_VARIABLE',
|
||
|
... filename='constants.cfg') # doctest: +SKIP
|
||
|
|
||
|
Values
|
||
|
------
|
||
|
|
||
|
To access the values, the instance can be used like a dictionary (getitem).
|
||
|
|
||
|
>>> consts['something']
|
||
|
'a_section_value'
|
||
|
|
||
|
Values are cast into integer, float or boolean when pertinent.
|
||
|
|
||
|
>>> consts['all']
|
||
|
1
|
||
|
>>> consts.a_string
|
||
|
'0350'
|
||
|
>>> consts.flag
|
||
|
False
|
||
|
|
||
|
Expressions are evaluated.
|
||
|
|
||
|
>>> consts.minutes
|
||
|
525600
|
||
|
|
||
|
Values can also be accessed using the . operator (getattr)
|
||
|
|
||
|
>>> consts.all
|
||
|
1
|
||
|
|
||
|
.. _Warning:
|
||
|
|
||
|
Warning
|
||
|
-------
|
||
|
|
||
|
"We are responsible adults" yet, inspired by Matthew Wilson's suggestion_ to
|
||
|
raise an exception when an attempt is made to *change a constant*, ``constants``
|
||
|
issues warnings_ ...
|
||
|
|
||
|
>>> import warnings
|
||
|
|
||
|
>>> with warnings.catch_warnings(record=True) as warning:
|
||
|
... # reassigning the constant all
|
||
|
... consts.all = 2
|
||
|
|
||
|
>>> warning[0].message
|
||
|
UserWarning('all changed to 2',)
|
||
|
|
||
|
... and *changes the constant* anyway.
|
||
|
|
||
|
>>> consts.all
|
||
|
2
|
||
|
|
||
|
It does so with the dict like assignment as well.
|
||
|
|
||
|
>>> with warnings.catch_warnings(record=True) as warning:
|
||
|
... consts['something'] = 'a_new_value'
|
||
|
|
||
|
>>> warning[0].message
|
||
|
UserWarning('something changed to a_new_value',)
|
||
|
|
||
|
>>> consts['something']
|
||
|
'a_new_value'
|
||
|
|
||
|
Logging
|
||
|
-------
|
||
|
|
||
|
``constants`` aims to be a good logging_ citizen, grafting a logger to the
|
||
|
logging tree.
|
||
|
|
||
|
All calls to the logger methods expose an extra logRecord key called ``method``.
|
||
|
|
||
|
With the logging level set to INFO, it logs one and only one useful message.
|
||
|
|
||
|
>>> import sys
|
||
|
>>> import logging
|
||
|
>>> logging.basicConfig(level=logging.INFO,
|
||
|
... stream=sys.stdout,
|
||
|
... format='%(levelname)s %(name)s.%(method)s %(message)s')
|
||
|
>>> consts = constants.Constants() # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
|
||
|
INFO constants.load
|
||
|
variable: __CONSTANTS__,
|
||
|
filename: constants.ini,
|
||
|
environment: a_section,
|
||
|
constants: {...}
|
||
|
|
||
|
At DEBUG level it becomes a tad *noisier*.
|
||
|
|
||
|
>>> logging.root.setLevel(logging.DEBUG)
|
||
|
>>> debug_me = consts.just_for_me # doctest: +ELLIPSIS
|
||
|
DEBUG constants.__getattr__ begin (..., 'just_for_me') {}
|
||
|
DEBUG constants.__getitem__ begin (..., 'just_for_me') {}
|
||
|
DEBUG constants.cast begin ('5.0',) {}
|
||
|
DEBUG constants.cast end 5.0
|
||
|
DEBUG constants.__getitem__ end 5.0
|
||
|
DEBUG constants.__getattr__ end 5.0
|
||
|
|
||
|
Installation
|
||
|
============
|
||
|
|
||
|
``constants`` is available on PyPI_ ...
|
||
|
|
||
|
::
|
||
|
|
||
|
pip install constants
|
||
|
|
||
|
... and can be forked on GitHub_.
|
||
|
|
||
|
.. _app_constants: https://github.com/leonardoborges/app_constants
|
||
|
.. _configparser: http://docs.python.org/library/configparser.html
|
||
|
.. _PyPI: http://pypi.python.org/pypi/constants
|
||
|
.. _GitHub: https://github.com/3kwa/constants
|
||
|
.. _suggestion: https://twitter.com/mw44118/status/256022281409658881
|
||
|
.. _warnings: http://docs.python.org/library/warnings.html
|
||
|
.. _logging: http://docs.python.org/library/logging.html
|
||
|
|
||
|
Platform: UNKNOWN
|
||
|
Classifier: Development Status :: 4 - Beta
|
||
|
Classifier: Intended Audience :: Developers
|
||
|
Classifier: License :: OSI Approved :: BSD License
|
||
|
Classifier: Programming Language :: Python :: 2.6
|
||
|
Classifier: Programming Language :: Python :: 2.7
|
||
|
Classifier: Programming Language :: Python :: 3.0
|
||
|
Classifier: Programming Language :: Python :: 3.1
|
||
|
Classifier: Programming Language :: Python :: 3.2
|
||
|
Classifier: Programming Language :: Python :: 3.3
|
||
|
Classifier: Topic :: Software Development :: Libraries
|