1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
.. _guide-typed-env:
TypedEnv
========
Plumbum provides this utility class to facilitate working with environment variables.
Similar to how :class:`plumbum.cli.Application` parses command line arguments into pythonic data types,
:class:`plumbum.typed_env.TypedEnv` parses environment variables:
class MyEnv(TypedEnv):
username = TypedEnv.Str("USER", default='anonymous')
path = TypedEnv.CSV("PATH", separator=":", type=local.path)
tmp = TypedEnv.Str(["TMP", "TEMP"]) # support 'fallback' var-names
is_travis = TypedEnv.Bool("TRAVIS", default=False) # True is 'yes/true/1' (case-insensitive)
We can now instantiate this class to access its attributes::
>>> env = MyEnv()
>>> env.username
'ofer'
>>> env.path
[<LocalPath /home/ofer/bin>,
<LocalPath /usr/local/bin>,
<LocalPath /usr/local/sbin>,
<LocalPath /usr/sbin>,
<LocalPath /usr/bin>,
<LocalPath /sbin>,
<LocalPath /bin>]
>>> env.tmp
Traceback (most recent call last):
[...]
KeyError: 'TMP'
>>> env.is_travis
False
Finally, our ``TypedEnv`` object allows us ad-hoc access to the rest of the environment variables, using dot-notation::
>>> env.HOME
'/home/ofer'
We can also update the environment via our ``TypedEnv`` object:
>>> env.tmp = "/tmp"
>>> env.tmp
'/tmp'
>>> from os import environ
>>> env.TMP
'/tmp'
>>> env.is_travis = True
>>> env.TRAVIS
'yes'
>>> env.path = [local.path("/a"), local.path("/b")]
>>> env.PATH
'/a:/b'
TypedEnv as an Abstraction Layer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``TypedEnv`` class is very useful for separating your application from the actual environment variables.
It provides a layer where parsing and normalizing can take place in a centralized fashion.
For example, you might start with this simple implementation::
class CiBuildEnv(TypedEnv):
job_id = TypedEnv.Str("BUILD_ID")
Later, as the application gets more complicated, you may expand your implementation like so::
class CiBuildEnv(TypedEnv):
is_travis = TypedEnv.Bool("TRAVIS", default=False)
_travis_job_id = TypedEnv.Str("TRAVIS_JOB_ID")
_jenkins_job_id = TypedEnv.Str("BUILD_ID")
@property
def job_id(self):
return self._travis_job_id if self.is_travis else self._jenkins_job_id
TypedEnv vs. local.env
^^^^^^^^^^^^^^^^^^^^^^
It is important to note that ``TypedEnv`` is separate and unrelated to the ``LocalEnv`` object that is provided via ``local.env``.
While ``TypedEnv`` reads and writes directly to ``os.environ``,
``local.env`` is a frozen copy taken at the start of the python session.
While ``TypedEnv`` is focused on parsing environment variables to be used by the current process,
``local.env``'s primary purpose is to manipulate the environment for child processes that are spawned
via plumbum's :ref:`local commands <guide-local-commands>`.
|