This repository was archived by the owner on Dec 29, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from yilei/absl
Add gflags -> absl.flags migration guidelines.
- Loading branch information
Showing
3 changed files
with
225 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
This library has been merged into [Abseil Python Common | ||
Libraries](https://github.com/abseil/abseil-py). | ||
This library has been merged into | ||
[Abseil Python Common Libraries](https://github.com/abseil/abseil-py). | ||
|
||
This repository is not maintained and will not be updated. Please use | ||
[Abseil](https://github.com/abseil/abseil-py) instead. | ||
This repository is not maintained and will not be updated. | ||
Please see [the guidelines](absl_migration/migration_guidelines.md) | ||
for migrating to [Abseil](https://github.com/abseil/abseil-py). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#!/usr/bin/env python | ||
"""Helper tool for gflags to absl.flags migration.""" | ||
|
||
from __future__ import absolute_import | ||
from __future__ import division | ||
from __future__ import print_function | ||
|
||
import argparse | ||
import os | ||
import re | ||
|
||
|
||
_MIGRATIONS = [ | ||
(r'\b(g?flags\.)DEFINE_multistring\b', r'\1DEFINE_multi_string'), | ||
(r'\b(g?flags\.)DEFINE_multi_int\b', r'\1DEFINE_multi_integer'), | ||
(r'\b(g?flags\.)RegisterValidator\b', r'\1register_validator'), | ||
(r'\b(g?flags\.)Validator\b', r'\1validator'), | ||
(r'\b(g?flags\.)RegisterMultiFlagsValidator\b', r'\1register_multi_flags_validator'), | ||
(r'\b(g?flags\.)MultiFlagsValidator\b', r'\1multi_flags_validator'), | ||
(r'\b(g?flags\.)MarkFlagAsRequired\b', r'\1mark_flag_as_required'), | ||
(r'\b(g?flags\.)MarkFlagsAsRequired\b', r'\1mark_flags_as_required'), | ||
(r'\b(g?flags\.)MarkFlagsAsMutualExclusive\b', r'\1mark_flags_as_mutual_exclusive'), | ||
(r'\b(g?flags\.)DECLARE_key_flag\b', r'\1declare_key_flag'), | ||
(r'\b(g?flags\.)ADOPT_module_key_flags\b', r'\1adopt_module_key_flags'), | ||
(r'\b(g?flags\.)DISCLAIM_key_flags\b', r'\1disclaim_key_flags'), | ||
(r'\b(g?flags\.)GetHelpWidth\b', r'\1get_help_width'), | ||
(r'\b(g?flags\.)TextWrap\b', r'\1text_wrap'), | ||
(r'\b(g?flags\.)FlagDictToArgs\b', r'\1flag_dict_to_args'), | ||
(r'\b(g?flags\.)DocToHelp\b', r'\1doc_to_help'), | ||
(r'\b(g?flags\.)FlagsError\b', r'\1Error'), | ||
(r'\b(g?flags\.)IllegalFlagValue\b', r'\1IllegalFlagValueError'), | ||
(r'\bFLAGS\.AppendFlagsIntoFile\b', r'FLAGS.append_flags_into_file'), | ||
(r'\bFLAGS\.AppendFlagValues\b', r'FLAGS.append_flag_values'), | ||
(r'\bFLAGS\.FindModuleDefiningFlag\b', r'FLAGS.find_module_defining_flag'), | ||
(r'\bFLAGS\.FindModuleIdDefiningFlag\b', r'FLAGS.find_module_id_defining_flag'), | ||
(r'\bFLAGS\.FlagsByModuleDict\b', r'FLAGS.flags_by_module_dict'), | ||
(r'\bFLAGS\.FlagsByModuleIdDict\b', r'FLAGS.flags_by_module_id_dict'), | ||
(r'\bFLAGS\.FlagsIntoString\b', r'FLAGS.flags_into_string'), | ||
(r'\bFLAGS\.FlagValuesDict\b', r'FLAGS.flag_values_dict'), | ||
(r'\bFLAGS\.IsGnuGetOpt\b', r'FLAGS.is_gnu_getopt'), | ||
(r'\bFLAGS\.IsParsed\b', r'FLAGS.is_parsed'), | ||
(r'\bFLAGS\.KeyFlagsByModuleDict\b', r'FLAGS.key_flags_by_module_dict'), | ||
(r'\bFLAGS\.MainModuleHelp\b', r'FLAGS.main_module_help'), | ||
(r'\bFLAGS\.MarkAsParsed\b', r'FLAGS.mark_as_parsed'), | ||
(r'\bFLAGS\.ModuleHelp\b', r'FLAGS.module_help'), | ||
(r'\bFLAGS\.ReadFlagsFromFiles\b', r'FLAGS.read_flags_from_files'), | ||
(r'\bFLAGS\.RemoveFlagValues\b', r'FLAGS.remove_flag_values'), | ||
(r'\bFLAGS\.Reset\b', r'FLAGS.unparse_flags'), | ||
(r'\bFLAGS\.SetDefault\b', r'FLAGS.set_default'), | ||
(r'\bFLAGS\.WriteHelpInXMLFormat\b', r'FLAGS.write_help_in_xml_format'), | ||
(r'\bFLAGS\.UseGnuGetOpt\(use_gnu_getopt=', r'FLAGS.set_gnu_getopt(gnu_getopt='), | ||
(r'\bFLAGS\.UseGnuGetOpt\(', r'FLAGS.set_gnu_getopt('), | ||
] | ||
|
||
|
||
_LEGACY_APIS_RE = re.compile( | ||
r'\b(' | ||
r'(g?flags\.DEFINE_multistring)|' | ||
r'(g?flags\.DEFINE_multi_int)|' | ||
r'(g?flags\.RegisterValidator)|' | ||
r'(g?flags\.Validator)|' | ||
r'(g?flags\.RegisterMultiFlagsValidator)|' | ||
r'(g?flags\.MultiFlagsValidator)|' | ||
r'(g?flags\.MarkFlagAsRequired)|' | ||
r'(g?flags\.MarkFlagsAsRequired)|' | ||
r'(g?flags\.MarkFlagsAsMutualExclusive)|' | ||
r'(g?flags\.DECLARE_key_flag)|' | ||
r'(g?flags\.ADOPT_module_key_flags)|' | ||
r'(g?flags\.DISCLAIM_key_flags)|' | ||
r'(g?flags\.GetHelpWidth)|' | ||
r'(g?flags\.TextWrap)|' | ||
r'(g?flags\.FlagDictToArgs)|' | ||
r'(g?flags\.DocToHelp)|' | ||
r'(g?flags\.FlagsError)|' | ||
r'(g?flags\.IllegalFlagValue)|' | ||
r'(FLAGS\.AppendFlagsIntoFile)|' | ||
r'(FLAGS\.AppendFlagValues)|' | ||
r'(FLAGS\.FindModuleDefiningFlag)|' | ||
r'(FLAGS\.FindModuleIdDefiningFlag)|' | ||
r'(FLAGS\.FlagsByModuleDict)|' | ||
r'(FLAGS\.FlagsByModuleIdDict)|' | ||
r'(FLAGS\.FlagsIntoString)|' | ||
r'(FLAGS\.FlagValuesDict)|' | ||
r'(FLAGS\.IsGnuGetOpt)|' | ||
r'(FLAGS\.IsParsed)|' | ||
r'(FLAGS\.KeyFlagsByModuleDict)|' | ||
r'(FLAGS\.MainModuleHelp)|' | ||
r'(FLAGS\.MarkAsParsed)|' | ||
r'(FLAGS\.ModuleHelp)|' | ||
r'(FLAGS\.ReadFlagsFromFiles)|' | ||
r'(FLAGS\.RemoveFlagValues)|' | ||
r'(FLAGS\.Reset)|' | ||
r'(FLAGS\.SetDefault)|' | ||
r'(FLAGS\.WriteHelpInXMLFormat)|' | ||
r'(from\ gflags\ import\ (argument_parser|exceptions|flag|flags_formatting_test|flags_unicode_literals_test|flagvalues|validators))' | ||
r')\b') | ||
|
||
|
||
def run(root_dir, migrate): | ||
for root, _, filenames in os.walk(root_dir): | ||
for filename in filenames: | ||
if not filename.endswith('.py'): | ||
continue | ||
filepath = os.path.join(root, filename) | ||
with open(filepath) as f: | ||
content = f.read() | ||
|
||
if migrate: | ||
new_content = content | ||
for m in _MIGRATIONS: | ||
new_content = re.sub(m[0], m[1], new_content) | ||
if new_content != content: | ||
with open(filepath, 'w') as f: | ||
f.write(new_content) | ||
content = new_content | ||
|
||
for index, line in enumerate(content.split('\n')): | ||
if _LEGACY_APIS_RE.search(line): | ||
print('{}:{} {}'.format(filepath, index + 1, line)) | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser( | ||
description='A gflags -> absl.flags migration tool.') | ||
parser.add_argument('--migrate', dest='migrate', action='store_true') | ||
parser.set_defaults(migrate=False) | ||
parser.add_argument('--root_dir', dest='root_dir', required=True) | ||
args = parser.parse_args() | ||
|
||
run(args.root_dir, args.migrate) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# gflags to absl.flags Migration Guidelines | ||
|
||
The [python-gflags](https://github.com/google/python-gflags) library has been merged into [Abseil Python Common Libraries](https://github.com/abseil/abseil-py). | ||
As a result, python-gflags will no longer be maintained. | ||
This document tries to help explain how to migrate from `gflags` to `absl.flags`. | ||
|
||
Note if your upstream dependencies have been migrated to `absl.flags`, | ||
we encourage you also migrating to <code>[absl.flags](https://github.com/abseil/abseil-py/tree/master/absl/flags)</code>. | ||
Otherwise there will be two global `FLAGS` objects coexisting in the same process. | ||
Both of them define flags and need to parse command-line args. | ||
|
||
## Changes | ||
|
||
This section lists the majors changes in absl.flags. | ||
|
||
### API Renaming | ||
|
||
1. Except the `DEFINE` functions, other method and function names are updated so they conform to PEP8 snake_case style. | ||
1. `DEFINE_multistring` and `DEFINE_multti_int` are renamed to `DEFINE_multi_string` and `DEFINE_multti_integer`, for consistency. | ||
1. Exceptions are renamed so they end with `Error`. Also `FlagsError` renamed to `Error`. | ||
1. All sub-modules have been made private, the public APIs should only be accessed at the package level. | ||
|
||
### Behavior Changes | ||
|
||
1. Flags now use [GNU-style](https://docs.python.org/3/library/getopt.html#getopt.gnu_getopt) parsing by default. To opt-in to non-GNU style, call `FLAGS.set_gnu_getopt(False)` before parsing flags. | ||
1. Accessing flag values before command-line args are parsed now raises the `UnparsedFlagAccessError`. | ||
1. It is no longer legal to define a flag with a default value type that mismatches the flag type. | ||
1. `FLAGS.set_default` no longer overrides the current value if the flag is set by `FLAGS.name = value`, or specified in the command line. | ||
|
||
## Migration Guidelines | ||
|
||
We suggest the following steps for migrating from `gflags` to `absl.flags`: | ||
|
||
1. Upgrade to the latest python-gflags version, which contains the new API names (see [Appendix](#appendix-renamed-apis)). | ||
1. Update the codebase to use the new APIs. | ||
* You can leverage [migrate.py](migrate.py) to perform the renames and sanity checks. Be aware that it only uses regex matching, which may have false positives or miss some cases. | ||
1. Remove the dependency on [python-gflags](https://pypi.python.org/pypi/python-gflags) and add the dependency on [absl-py](https://pypi.python.org/pypi/absl-py). Then replace `import gflags` with `from absl import flags as gflags`. | ||
1. Once step (3) succeeds, remove the import alias and just use `flags`. | ||
|
||
Depending on your project, you can choose to do these at once, or make incremental changes. | ||
|
||
## Appendix: Renamed APIs | ||
|
||
Here is a list of renamed APIs: | ||
|
||
``` | ||
DEFINE_multistring -> DEFINE_multi_string | ||
DEFINE_multi_int -> DEFINE_multi_integer | ||
RegisterValidator -> register_validator | ||
Validator -> validator | ||
RegisterMultiFlagsValidator -> register_multi_flags_validator | ||
MultiFlagsValidator -> multi_flags_validator | ||
MarkFlagAsRequired -> mark_flag_as_required | ||
MarkFlagsAsRequired -> mark_flags_as_required | ||
MarkFlagsAsMutualExclusive -> mark_flags_as_mutual_exclusive | ||
DECLARE_key_flag -> declare_key_flag | ||
ADOPT_module_key_flags -> adopt_module_key_flags | ||
DISCLAIM_key_flags -> disclaim_key_flags | ||
GetHelpWidth -> get_help_width | ||
TextWrap -> text_wrap | ||
FlagDictToArgs -> flag_dict_to_args | ||
DocToHelp -> doc_to_help | ||
FlagsError -> Error | ||
IllegalFlagValue -> IllegalFlagValueError | ||
ArgumentParser.Parse -> ArgumentParser.parse | ||
ArgumentParser.Type -> ArgumentParser.flag_type | ||
FLAGS.AppendFlagsIntoFile -> FLAGS.append_flags_into_file | ||
FLAGS.AppendFlagValues -> FLAGS.append_flag_values | ||
FLAGS.FindModuleDefiningFlag -> FLAGS.find_module_defining_flag | ||
FLAGS.FindModuleIdDefiningFlag -> FLAGS.find_module_id_defining_flag | ||
FLAGS.FlagsByModuleDict -> FLAGS.flags_by_module_dict | ||
FLAGS.FlagsByModuleIdDict -> FLAGS.flags_by_module_id_dict | ||
FLAGS.FlagsIntoString -> FLAGS.flags_into_string | ||
FLAGS.FlagValuesDict -> FLAGS.flag_values_dict | ||
FLAGS.IsGnuGetOpt -> FLAGS.is_gnu_getopt | ||
FLAGS.IsParsed -> FLAGS.is_parsed | ||
FLAGS.KeyFlagsByModuleDict -> FLAGS.key_flags_by_module_dict | ||
FLAGS.MainModuleHelp -> FLAGS.main_module_help | ||
FLAGS.MarkAsParsed -> FLAGS.mark_as_parsed | ||
FLAGS.ModuleHelp -> FLAGS.module_help | ||
FLAGS.ReadFlagsFromFiles -> FLAGS.read_flags_from_files | ||
FLAGS.RemoveFlagValues -> FLAGS.remove_flag_values | ||
FLAGS.Reset -> FLAGS.unparse_flags | ||
FLAGS.SetDefault -> FLAGS.set_default | ||
FLAGS.WriteHelpInXMLFormat -> FLAGS.write_help_in_xml_format | ||
``` |