Age | Commit message (Collapse) | Author |
|
PiperOrigin-RevId: 475611494
Change-Id: I9facdfcaece0b3c0bd2b0b38364ecd41cb06d79c
|
|
PiperOrigin-RevId: 474195462
Change-Id: I2b57d8ea6b8eb66d1f777f026fb19e5401983789
|
|
PiperOrigin-RevId: 473306343
Change-Id: I4c166f7fa34ce2f1b0bcacafbf790d4f932886d1
|
|
PiperOrigin-RevId: 453697925
Change-Id: I24a9fbbe2a690d7101b7190f4b4976d16bd0942f
|
|
Also remove the mock package in bazel WORKSPACE file.
PiperOrigin-RevId: 436585035
Change-Id: I7f8eafac5f7b10dc8f580db20c7ae60711dfdf12
|
|
PiperOrigin-RevId: 430280700
Change-Id: I62ca45c7b794989f9e8ee66094fb73c5ac7a6840
|
|
bool context (not useful) to avoid situations where someone really wanted to refer to `their_flag.value` instead. This prevents logic bugs.
There were ~10 problems found by this and cleaned up in our internal codebase.
PiperOrigin-RevId: 427295923
Change-Id: Ifc9e086133986cc14d052a06889a93c1ab0ff688
|
|
PiperOrigin-RevId: 423878454
Change-Id: Iadc82651ecd39954cfd2af6b4bae2a98388fd75b
|
|
PiperOrigin-RevId: 423095241
Change-Id: Ie78fb886746b11320e777587bf50c938d9054e37
|
|
end-of-life for more than a year now.
PiperOrigin-RevId: 405511743
Change-Id: Id0f78693a6de9474576c3cfa879caf2cc177d8f6
|
|
The `FlagHolder` object is returned from `flags.DEFINE_*()` to allow
type-safe and fully-declared access via `myflag.value`, instead of
requiring users to write `FLAGS.myflag`.
Additionally, this proxies the `.default` property from the `Flag`
object underlying the `FlagHolder`, so `FLAGS['myflag'].default` can
instead be written as simply `myflag.default`.
However, the `.present` property is not easily available today without
writing `FLAGS['myflag'].present` or `FLAGS[myflag.name].present`,
despite being relatively commonly used.
Since it intuitively makes sense for this to be available, let's proxy
it through `FlagHolder` to the underlying `Flag` object.
PiperOrigin-RevId: 386901861
Change-Id: I29e3173668080957b796c8634527382b792aa4ec
|
|
This is a required argument for custom argparse.Action classes, and is used when the `ArgumentParse` is created with a `argument_default=`.
PiperOrigin-RevId: 385601086
Change-Id: I01ef4870aa4f0e92f7e8f9be0125c9a0dba16c6f
|
|
missing required flag.
Given these required flags of float values with default value of None:
flags.mark_flags_as_required(["x", "y", "z"])
If none of the required flags are passed as arguments, the resulting error will only show the first missing required flag as an issue:
FATAL Flags parsing error: flag --x=None: Flag --x must have a value other than None.
The user will then add this required flag "x" and try again, but then get the error for "y" as a missing requirement. This loops until the user finally passes all the required flags as arguments.
Since we already know which flags are required, this changes the error message shows all missing required flags at once, so the user can make the necessary changes in a single pass with the error message showing this:
FATAL Flags parsing error:
flag --x=None: Flag --x must have a value other than None.
flag --y=None: Flag --y must have a value other than None.
flag --z=None: Flag --z must have a value other than None.
To achieve the formatting change, `app.parse_flags_with_usage` now puts the error message on a new line and adds indentation if the message is multi-line string.
PiperOrigin-RevId: 371414012
Change-Id: Id7456e9c293fb95d7b4551fd28441610af9b3030
|
|
They are considered as public flags and callers should use them instead of accessing FLAGS.test_tmpdir and FLAGS.test_srcdir.
PiperOrigin-RevId: 360948844
Change-Id: Ib3673ae55ad9b55000fb80ba60647a93fdfc0426
|
|
This is to (formally) allow using it in extension libraries.
Also add a test to cover non-comma separators.
PiperOrigin-RevId: 359820150
Change-Id: I3a384083a1634d1429b6a01b10571ebfb7ee9ac1
|
|
PiperOrigin-RevId: 357245847
Change-Id: I7637199f61f23e78646720ad406f539c89962fe3
|
|
Setting it to true, is functionally equivalent to calling `flags.mark_flag_as_required(flag_name)`, but changes the type of returned flagholder.
```
_A : FlagHolder[Optional[str]] = flags.DEFINE_string(
name='a', default=None, help='help')
flags.mark_flag_as_required('a')
```
v/s
```
_A : FlagHolder[str] = flags.DEFINE_string(
name='a', default=None, help='help', required=True)
```
PiperOrigin-RevId: 348825600
Change-Id: Ia7610af1b5c4649c20aba5cbb620eae1359ad592
|
|
With the aim of steering users away from potential pitfalls in usage of the `FlagHolder` API, this change introduces implementation overrides for the class `__eq__` and `__bool__` methods which turn any such usage into a `TypeError` at runtime.
This is to help avoid situations where a user neglects to use the `FlagHolder.value` property in cases where they intended to, e.g.,
```
>>> SOME_FLAG = flags.DEFINE_boolean(...)
>>> if SOME_FLAG: do_something()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bool() not supported for instances of type 'FlagHolder' (did you mean to use 'FlagHolder.value' instead?)
```
PiperOrigin-RevId: 338473759
Change-Id: If3b6505a3bdca03db6d96ec7cc28e7214cb1a5e7
|
|
This resolves an issue where multi-flag validators rely on specific flag combinations.
PiperOrigin-RevId: 334625442
Change-Id: I7e6b625637a70356df57a4d9cbb01c203f14df4c
|
|
This is to bridge the gap between lower case being idiomatic for command
line values, and upper case for values defined in an `Enum`. It also makes
it more consistent with `DEFINE_enum` usage, which usually uses lower case values.
Case sensitivity can be restored by passing `case_sensitive=True`.
When `case_sensitive=False` (the default), the associated flag serializers will lowercase enum member names. This seemed reasonable since help text that SCREAMS at you is inconsistent with the fact that member names will be provided most often in lowercase format.
Internally, EnumParser is re-used for simplicity.
PiperOrigin-RevId: 324594299
Change-Id: I2e15448ad00a095212756c5277b08219a9e84d55
|
|
This is to (1) make for an easier mnemonic and (2) to match the
interfaces some other test frameworks (nose, pytest) provide.
PiperOrigin-RevId: 308857342
Change-Id: Ideba06dc501a80ef41da9520f49bc18e0905f2a3
|
|
This is an analogous access as get_key_flags_for_module, but for
non-key flags.
PiperOrigin-RevId: 308653262
Change-Id: I976b7ccb793b4de7b97993bf5128b786c6bc0797
|
|
This fixes a bug where the mere act of defining an alias flag
would increment the aliased flag's `Flag.present` counter, thus
incorrectly indicating the aliased flag was always present on
the command line.
This was happening because of the combination of the alias flag's
custom flag parser and the initialization logic of `Flag`.
Essentially, the alias used a custom parser which called the
aliased flag's `Flag.parse` method, and the initialization logic
of `Flag` calls the parser to convert the default value. Thus,
when an alias was defined, the aliased flag's `parse()` method
was called, which increments the `present` counter.
Fixed by making the alias `Flag` subclass avoid calling the parser
during initialization on the default value; the aliased flag
already parsed it.
Also fixes several bugs with aliases:
* Aliasing a multi flag no longer causes the default value to
be appended to after parsing.
* The alias default value now matches the aliased default value.
* The alias present counter correctly increments after parsing.
(The aliased present counter still incorrectly increments, but
that is a pre-existing bug).
PiperOrigin-RevId: 307842972
Change-Id: If36672d4b4b2b261de6c87e7ccf3e595241522b8
|
|
While working on a bug fix for aliases, I found seemingly small
changes were having unexpected effects. To help prevent
regressions, add tests covering more pre-existing alias behavior.
Since there are a number of bugs, many asserts have comments
indicating the incorrect value they have to assert. This is
done in lieu of using @expectedFailure because most tests have
several asserts, and I want to avoid subsequent fixes
introducing unintentional changes.
PiperOrigin-RevId: 307420078
Change-Id: I8fe8457d3152423b21fd3a84fc19516698f3d81d
|
|
This adds --logger_levels, a flag that allows setting the log levels of
loggers by name.
This makes it easy to adjust log levels on a per-logger basis without having
to write application code to do so.
Changes from original:
* Use empty dict as the default value to work around some dependencies
relying on the default matching the parsed value.
* Return a copy instead of `MappingProxyType` because values are expected
to be compatible with `copy.deepcopy()`
PiperOrigin-RevId: 305493905
Change-Id: Ib826653b58d621aebc89aa1ded69647c534cde13
|
|
Multi-flags are identified by an optional second argument consisting of a set of multi-flag names.
PiperOrigin-RevId: 305287708
Change-Id: I26f1f1f40771d7e3a2d651812e6b3bf6fe3c5c17
|
|
PiperOrigin-RevId: 305120736
Change-Id: I1397f305c4471828bcdd22f07360d42522ec1b7c
|
|
This adds --logger_levels, a flag that allows setting the log levels of
loggers by name.
This makes it easy to adjust log levels on a per-logger basis without having
to write application code to do so.
PiperOrigin-RevId: 305079512
Change-Id: I9e350404aad02e9db040c106c7323e3b812d9186
|
|
always using the PY2 version.
PiperOrigin-RevId: 296947636
Change-Id: I07fd5bc14c6ff1f9b4f5150ba0a7637ca2b884cd
|
|
different approach.
Also the type annotations in _flagvalues.py should have _T instead of T.
PiperOrigin-RevId: 296243519
Change-Id: I01cc7b8ef733ac78b671252a9afe8e7038c25d1b
|
|
pattern like
```
PORT = flags.DEFINE_integer('my_project_server_default_port', ...)
def method():
PORT.value
```
Results in the name of the flag appears only once in the source code.
- No more typoes.
- Provides a local name
- Linters can catch unused flags.
- Plays well with type checkers
PiperOrigin-RevId: 294778727
Change-Id: Ib1d1a7426968c59517e1c9f2f23962ba811ef914
|
|
There is no way to explicitly trigger flag value validation programmatically
after flags are parsed. This change makes the previously private
"_assert_all_validators" method public under the name "validate_all_flags".
PiperOrigin-RevId: 292307344
Change-Id: Ifd2429d439e353b88843821aa0c95e5dc95bf2aa
|
|
None to empty string.
This doesn't change the behavior when the flag is using its default value.
PiperOrigin-RevId: 280027756
Change-Id: I69261156b67bf20d31f5133cbb2d06287b8deb58
|
|
Performing asserts on the warnings while they are being captured can
fail if the asserts (or their helper code) triggers a warning.
Fixes #108
PiperOrigin-RevId: 258438168
Change-Id: Ica91eb527445c25e258471a9e5003aaf3a713ab0
|
|
This makes the absl tests pass when
--incompatible_allow_python_version_transitions=true is set.
Many tests use subprocesses to verify behavior and were relying on
how the subprocess's Python version would match the test's Python
version. Since this stickiness is going away, to keep the test and
subprocess using the same Python version, the binaries have to be
defined twice, one for each Python version, and a select()
used with the test to select the matchiing binary.
NOTE: Under bazel and Python 3, --python_version=PY3 flag must be
specified so that bazel knows how to properly resolve selects.
PiperOrigin-RevId: 243099319
|
|
PiperOrigin-RevId: 240662701
|
|
PiperOrigin-RevId: 239564996
|
|
PiperOrigin-RevId: 232764112
|
|
Previously, the error message for mark_flags_as_mutual_exclusive said "specified", but "specified" sounds like "included in the command-line invocation. That's not necessarily equivalent, in particular because flags can have default values other than None.
mark_flags_required used a similar wording in the error message, but generated a warning when used with a flag with a default value other than None.
Instead, make both generate a warning and clarify the error message for both to "should have a value other than None", since neither validator checks that a flag value was specified in the command-line invocation. The error message should still be clear in cases where the warning is suppressed or overlooked.
Also adds a test for the existing warning behavior of mark_flag_as_required.
PiperOrigin-RevId: 228510310
|
|
This was motivated to allow tuples as input, but was expanded to allow any
iterable. Strings and non-iterables are still special cased and converted
to a single-element list. A copy of the input iterable is made so that
the flag has sole ownership over the set of values.
NOTE: Custom MultiFlag behavior change: The items of the iterable, rather than
the iterable itself, are now passed onto the underlying self.parser object.
Custom flags using DEFINE_multi or MultiFlag should update their custom flag
code as appropriate.
NOTE: Heavily modified from original PR to adjust for various lint/style
errors and from the auto-formatter.
Resolves #78
Closes #80
PiperOrigin-RevId: 226230348
|
|
This change enables the use of enum.Enum objects in multi_* style labels.
Previously the multi_enum flag in absl.flags only accepted strings. The new multi_enum_class flag accepts (lists of) Enum class members.
The text format of lists of enums when serializing into XML differs from the list format in other multi_* types of flags. This is because all other multi_* types rely on repr() to turn a list into a string (since all other multi_* types have primitive contents). With multi_enum_class, repr() prints out a list of the repr()'s of Enum objects, which are rather unsightly for public consumption (e.g., they contain the integer value of the enum flags). This change does some acrobatics to ensure XML representation of flag usage looks reasonable for lists, but those rendered lists look a little different from repr()'ed lists.
This change fixes the way multi_* flags are serialized when saved for future re-ingestion via a command line. It makes each flag value appear on a separate line, by modifying the list separator of all MultiFlag and subclasses to be '\n'.
PiperOrigin-RevId: 224405076
|
|
This is (1) to match the c++ behavior and (2) so that build based upon the flag
values are also deterministic.
PiperOrigin-RevId: 222884822
|
|
Previously the serialize method would prepend ClassName. to the value, which
the parser would not accept.
PiperOrigin-RevId: 222518525
|
|
Deep copying flags (with copy.deepcopy) is still allowed. Pickling and shallow
are now prohibited, because the notion of a shallow copy isn't entirely well
defined -- should an unpickled flag or shallow copy link back to the original
flag value?
FlagValues() already cannot be successfully serialized/deserialized with
pickle. But the error message is unrelated and raised when attempting to
*load* pickled FlagValues instances, not when saving them:
>>> from absl import flags
>>> import pickle
>>> dumped = pickle.dumps(flags.FLAGS) # no error
>>> pickle.loads(dumped)
Traceback (most recent call last)
<ipython-input-5-5a8322d34219> in <module>()
----> 1 pickle.loads(dumped)
/usr/lib/python2.7/pickle.pyc in loads(str)
1386 def loads(str):
1387 file = StringIO(str)
-> 1388 return Unpickler(file).load()
1389
1390 # Doctest
/usr/lib/python2.7/pickle.pyc in load(self)
862 while 1:
863 key = read(1)
--> 864 dispatch[key](self)
865 except _Stop, stopinst:
866 return stopinst.value
/usr/lib/python2.7/pickle.pyc in load_build(self)
1219 state = stack.pop()
1220 inst = stack[-1]
-> 1221 setstate = getattr(inst, "__setstate__", None)
1222 if setstate:
1223 setstate(state)
/usr/local/lib/python2.7/dist-packages/absl/flags/_flagvalues.pyc in __getattr__(self, name)
466 def __getattr__(self, name):
467 """Retrieves the 'value' attribute of the flag --name."""
--> 468 fl = self._flags()
469 if name not in fl:
470 raise AttributeError(name)
/usr/local/lib/python2.7/dist-packages/absl/flags/_flagvalues.pyc in _flags(self)
139
140 def _flags(self):
--> 141 return self.__dict__['__flags']
142
143 def flags_by_module_dict(self):
KeyError: '__flags'
This change causes an error to be raised earlier (as part of serialization
rather than deserialization) and with a better error message, e.g.,
>>> pickle.dumps(flags.FLAGS)
TypeError: can't pickle FlagValues
PiperOrigin-RevId: 222298474
|
|
This is so the code is more naturally Py3 compatible.
* Also converts assertRaisesRegex usages to use with statements
PiperOrigin-RevId: 218399153
|
|
PiperOrigin-RevId: 213825654
|
|
Deep copying flags (with copy.deepcopy) is still allowed. Pickling and shallow
are now prohibited, because the notion of a shallow copy isn't entirely well
defined -- should an unpickled flag or shallow copy link back to the original
flag value?
FlagValues() already cannot be successfully serialized/deserialized with
pickle. But the error message is unrelated and raised when attempting to
*load* pickled FlagValues instances, not when saving them:
>>> from absl import flags
>>> import pickle
>>> dumped = pickle.dumps(flags.FLAGS) # no error
>>> pickle.loads(dumped)
Traceback (most recent call last)
<ipython-input-5-5a8322d34219> in <module>()
----> 1 pickle.loads(dumped)
/usr/lib/python2.7/pickle.pyc in loads(str)
1386 def loads(str):
1387 file = StringIO(str)
-> 1388 return Unpickler(file).load()
1389
1390 # Doctest
/usr/lib/python2.7/pickle.pyc in load(self)
862 while 1:
863 key = read(1)
--> 864 dispatch[key](self)
865 except _Stop, stopinst:
866 return stopinst.value
/usr/lib/python2.7/pickle.pyc in load_build(self)
1219 state = stack.pop()
1220 inst = stack[-1]
-> 1221 setstate = getattr(inst, "__setstate__", None)
1222 if setstate:
1223 setstate(state)
/usr/local/lib/python2.7/dist-packages/absl/flags/_flagvalues.pyc in __getattr__(self, name)
466 def __getattr__(self, name):
467 """Retrieves the 'value' attribute of the flag --name."""
--> 468 fl = self._flags()
469 if name not in fl:
470 raise AttributeError(name)
/usr/local/lib/python2.7/dist-packages/absl/flags/_flagvalues.pyc in _flags(self)
139
140 def _flags(self):
--> 141 return self.__dict__['__flags']
142
143 def flags_by_module_dict(self):
KeyError: '__flags'
This change causes an error to be raised earlier (as part of serialization
rather than deserialization) and with a better error message, e.g.,
>>> pickle.dumps(flags.FLAGS)
TypeError: can't pickle FlagValues
PiperOrigin-RevId: 213728792
|
|
This adds a new flags define, `enum_class`, which is like `enum`, but uses
an `enum.Enum` class as the source of valid values. The resulting parsed
value is the corresponding Enum value.
Using enum_class is recommended over plain enum.
Python 2.7 note: The `enum` module is not required for absl in general, but
is required to use `enum_class`, or for absl tests to fully pass. If the
`enum` module isn't available, then absl flags can still be used, just not
the `enum_class` function. The enum34 package on PyPI is the suggested
package to use for enum support, and is the one absl assumes is used under
Python 2.7.
Python 2.7 and Bazel note: Because of how Bazel modifies PYTHONPATH, absl has
to do do some special sys.path import manipulation to make the enum module
work. In short, third party deps go before the stdlib on sys.path, so enum34's
enum module shadows Python 3's enum module, which causes problems because
enum34 is a subset of later Python 3's enum. So some sys.path futzing is done
to account for this under Bazel. This only happens if 'import enum' initially
fails, and only under Python 2.7.
PiperOrigin-RevId: 212301566
|
|
tests for current flag name validations like empty or non-string types.
PiperOrigin-RevId: 208800538
|
|
Argparse support is provided by two pieces: an argparse-compatible parser that
understands absl flags, and app.run accepting a custom flag parser.
argparse_flags.ArgumentParser is a custom argparse.ArgumentParser that
makes absl defined flags available via the argparse APIs. The argparse_flags
module contains more documentation.
app.run accepts a flags_parser argument, which is responsible for parsing
command line args and returning the value to pass onto main. The app.run
function contains more documentation.
Resolves issue #27
PiperOrigin-RevId: 208509632
|