123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- #!/usr/bin/env python3
- # Copyright (c) Facebook, Inc. and its affiliates.
- # All rights reserved.
- #
- # This source code is licensed under the BSD-style license found in the
- # LICENSE file in the root directory of this source tree.
- import os
- from argparse import Action
- class env(Action):
- """
- Gets argument values from ``PET_{dest}`` before defaulting
- to the given ``default`` value. For flags (e.g. ``--standalone``)
- use ``check_env`` instead.
- .. note:: when multiple option strings are specified, ``dest`` is
- the longest option string (e.g. for ``"-f", "--foo"``
- the env var to set is ``PET_FOO`` not ``PET_F``)
- Example:
- ::
- parser.add_argument("-f", "--foo", action=env, default="bar")
- ./program -> args.foo="bar"
- ./program -f baz -> args.foo="baz"
- ./program --foo baz -> args.foo="baz"
- PET_FOO="env_bar" ./program -f baz -> args.foo="baz"
- PET_FOO="env_bar" ./program --foo baz -> args.foo="baz"
- PET_FOO="env_bar" ./program -> args.foo="env_bar"
- parser.add_argument("-f", "--foo", action=env, required=True)
- ./program -> fails
- ./program -f baz -> args.foo="baz"
- PET_FOO="env_bar" ./program -> args.foo="env_bar"
- PET_FOO="env_bar" ./program -f baz -> args.foo="baz"
- """
- def __init__(self, dest, default=None, required=False, **kwargs) -> None:
- env_name = f"PET_{dest.upper()}"
- default = os.environ.get(env_name, default)
- # ``required`` means that it NEEDS to be present in the command-line args
- # rather than "this option requires a value (either set explicitly or default"
- # so if we found default then we don't "require" it to be in the command-line
- # so set it to False
- if default:
- required = False
- super().__init__(dest=dest, default=default, required=required, **kwargs)
- def __call__(self, parser, namespace, values, option_string=None):
- setattr(namespace, self.dest, values)
- class check_env(Action):
- """
- For flags, checks whether the env var ``PET_{dest}`` exists
- before defaulting to the given ``default`` value. Equivalent to
- ``store_true`` argparse built-in action except that the argument can
- be omitted from the commandline if the env var is present and has a
- non-zero value.
- .. note:: it is redundant to pass ``default=True`` for arguments
- that use this action because a flag should be ``True``
- when present and ``False`` otherwise.
- Example:
- ::
- parser.add_argument("--verbose", action=check_env)
- ./program -> args.verbose=False
- ./program --verbose -> args.verbose=True
- PET_VERBOSE=1 ./program -> args.verbose=True
- PET_VERBOSE=0 ./program -> args.verbose=False
- PET_VERBOSE=0 ./program --verbose -> args.verbose=True
- Anti-pattern (don't do this):
- ::
- parser.add_argument("--verbose", action=check_env, default=True)
- ./program -> args.verbose=True
- ./program --verbose -> args.verbose=True
- PET_VERBOSE=1 ./program -> args.verbose=True
- PET_VERBOSE=0 ./program -> args.verbose=False
- """
- def __init__(self, dest, default=False, **kwargs) -> None:
- env_name = f"PET_{dest.upper()}"
- default = bool(int(os.environ.get(env_name, "1" if default else "0")))
- super().__init__(dest=dest, const=True, default=default, nargs=0, **kwargs)
- def __call__(self, parser, namespace, values, option_string=None):
- setattr(namespace, self.dest, self.const)
|