Spaces:
Running
Running
Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +77 -0
- .idea/aws.xml +14 -0
- .idea/misc.xml +3 -0
- .idea/workspace.xml +24 -1
- main.py +49 -3
- venv/bin/convert-caffe2-to-onnx +8 -0
- venv/bin/convert-onnx-to-caffe2 +8 -0
- venv/bin/import_pb_to_tensorboard +8 -0
- venv/bin/isympy +8 -0
- venv/bin/markdown_py +8 -0
- venv/bin/saved_model_cli +8 -0
- venv/bin/tensorboard +8 -0
- venv/bin/tf_upgrade_v2 +8 -0
- venv/bin/tflite_convert +8 -0
- venv/bin/toco +8 -0
- venv/bin/toco_from_protos +8 -0
- venv/bin/torchrun +8 -0
- venv/bin/transformers-cli +8 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/INSTALLER +1 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/LICENSE.md +30 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/METADATA +146 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/RECORD +74 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/WHEEL +5 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/entry_points.txt +22 -0
- venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/top_level.txt +1 -0
- venv/lib/python3.11/site-packages/__pycache__/isympy.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/__pycache__/nest_asyncio.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/__init__.py +13 -0
- venv/lib/python3.11/site-packages/absl/__pycache__/__init__.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/__pycache__/app.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/__pycache__/command_name.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/app.py +480 -0
- venv/lib/python3.11/site-packages/absl/app.pyi +99 -0
- venv/lib/python3.11/site-packages/absl/command_name.py +63 -0
- venv/lib/python3.11/site-packages/absl/flags/__init__.py +225 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/__init__.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_argument_parser.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_defines.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_exceptions.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_flag.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_flagvalues.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_helpers.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_validators.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/_validators_classes.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/__pycache__/argparse_flags.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/absl/flags/_argument_parser.py +638 -0
- venv/lib/python3.11/site-packages/absl/flags/_defines.py +1686 -0
- venv/lib/python3.11/site-packages/absl/flags/_exceptions.py +108 -0
- venv/lib/python3.11/site-packages/absl/flags/_flag.py +556 -0
- venv/lib/python3.11/site-packages/absl/flags/_flagvalues.py +1480 -0
.gitattributes
CHANGED
@@ -52,3 +52,80 @@ venv/lib/python3.11/site-packages/pandas/_libs/join.cpython-311-darwin.so filter
|
|
52 |
venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
53 |
venv/lib/python3.11/site-packages/uvloop/loop.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
54 |
venv/lib/python3.11/site-packages/watchfiles/_rust_notify.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
53 |
venv/lib/python3.11/site-packages/uvloop/loop.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
54 |
venv/lib/python3.11/site-packages/watchfiles/_rust_notify.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
55 |
+
venv/lib/python3.11/site-packages/clang/native/libclang.dylib filter=lfs diff=lfs merge=lfs -text
|
56 |
+
venv/lib/python3.11/site-packages/grpc/_cython/cygrpc.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
57 |
+
venv/lib/python3.11/site-packages/h5py/.dylibs/libhdf5.200.dylib filter=lfs diff=lfs merge=lfs -text
|
58 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_chlo.so filter=lfs diff=lfs merge=lfs -text
|
59 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_mlir.so filter=lfs diff=lfs merge=lfs -text
|
60 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_mlirDialectsSparseTensor.so filter=lfs diff=lfs merge=lfs -text
|
61 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_mlirHlo.so filter=lfs diff=lfs merge=lfs -text
|
62 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_stablehlo.so filter=lfs diff=lfs merge=lfs -text
|
63 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_tpu_ext.so filter=lfs diff=lfs merge=lfs -text
|
64 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/_triton_ext.so filter=lfs diff=lfs merge=lfs -text
|
65 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/libjaxlib_mlir_capi.dylib filter=lfs diff=lfs merge=lfs -text
|
66 |
+
venv/lib/python3.11/site-packages/jaxlib/mlir/_mlir_libs/register_jax_dialects.so filter=lfs diff=lfs merge=lfs -text
|
67 |
+
venv/lib/python3.11/site-packages/jaxlib/xla_extension.so filter=lfs diff=lfs merge=lfs -text
|
68 |
+
venv/lib/python3.11/site-packages/ml_dtypes/_ml_dtypes_ext.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
69 |
+
venv/lib/python3.11/site-packages/scipy/.dylibs/libgfortran.5.dylib filter=lfs diff=lfs merge=lfs -text
|
70 |
+
venv/lib/python3.11/site-packages/scipy/.dylibs/libopenblas.0.dylib filter=lfs diff=lfs merge=lfs -text
|
71 |
+
venv/lib/python3.11/site-packages/scipy/io/_fast_matrix_market/_fmm_core.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
72 |
+
venv/lib/python3.11/site-packages/scipy/linalg/_flapack.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
73 |
+
venv/lib/python3.11/site-packages/scipy/misc/face.dat filter=lfs diff=lfs merge=lfs -text
|
74 |
+
venv/lib/python3.11/site-packages/scipy/optimize/_highs/_highs_wrapper.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
75 |
+
venv/lib/python3.11/site-packages/scipy/sparse/_sparsetools.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
76 |
+
venv/lib/python3.11/site-packages/scipy/special/_ufuncs.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
77 |
+
venv/lib/python3.11/site-packages/scipy/special/cython_special.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
78 |
+
venv/lib/python3.11/site-packages/scipy/stats/_unuran/unuran_wrapper.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
79 |
+
venv/lib/python3.11/site-packages/sympy/polys/benchmarks/__pycache__/bench_solvers.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
|
80 |
+
venv/lib/python3.11/site-packages/tensorflow/compiler/mlir/quantization/tensorflow/calibrator/pywrap_calibration.so filter=lfs diff=lfs merge=lfs -text
|
81 |
+
venv/lib/python3.11/site-packages/tensorflow/compiler/mlir/quantization/tensorflow/python/pywrap_quantize_model.so filter=lfs diff=lfs merge=lfs -text
|
82 |
+
venv/lib/python3.11/site-packages/tensorflow/compiler/mlir/stablehlo/stablehlo_extension.so filter=lfs diff=lfs merge=lfs -text
|
83 |
+
venv/lib/python3.11/site-packages/tensorflow/compiler/tf2tensorrt/_pywrap_py_utils.so filter=lfs diff=lfs merge=lfs -text
|
84 |
+
venv/lib/python3.11/site-packages/tensorflow/libtensorflow_cc.2.dylib filter=lfs diff=lfs merge=lfs -text
|
85 |
+
venv/lib/python3.11/site-packages/tensorflow/libtensorflow_framework.2.dylib filter=lfs diff=lfs merge=lfs -text
|
86 |
+
venv/lib/python3.11/site-packages/tensorflow/lite/python/analyzer_wrapper/_pywrap_analyzer_wrapper.so filter=lfs diff=lfs merge=lfs -text
|
87 |
+
venv/lib/python3.11/site-packages/tensorflow/lite/python/interpreter_wrapper/_pywrap_tensorflow_interpreter_wrapper.so filter=lfs diff=lfs merge=lfs -text
|
88 |
+
venv/lib/python3.11/site-packages/tensorflow/lite/python/metrics/_pywrap_tensorflow_lite_metrics_wrapper.so filter=lfs diff=lfs merge=lfs -text
|
89 |
+
venv/lib/python3.11/site-packages/tensorflow/lite/python/optimize/_pywrap_tensorflow_lite_calibration_wrapper.so filter=lfs diff=lfs merge=lfs -text
|
90 |
+
venv/lib/python3.11/site-packages/tensorflow/python/_pywrap_dtensor_device.so filter=lfs diff=lfs merge=lfs -text
|
91 |
+
venv/lib/python3.11/site-packages/tensorflow/python/_pywrap_mlir.so filter=lfs diff=lfs merge=lfs -text
|
92 |
+
venv/lib/python3.11/site-packages/tensorflow/python/_pywrap_parallel_device.so filter=lfs diff=lfs merge=lfs -text
|
93 |
+
venv/lib/python3.11/site-packages/tensorflow/python/_pywrap_quantize_training.so filter=lfs diff=lfs merge=lfs -text
|
94 |
+
venv/lib/python3.11/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so filter=lfs diff=lfs merge=lfs -text
|
95 |
+
venv/lib/python3.11/site-packages/tensorflow/python/_pywrap_tfe.so filter=lfs diff=lfs merge=lfs -text
|
96 |
+
venv/lib/python3.11/site-packages/tensorflow/python/client/_pywrap_debug_events_writer.so filter=lfs diff=lfs merge=lfs -text
|
97 |
+
venv/lib/python3.11/site-packages/tensorflow/python/client/_pywrap_device_lib.so filter=lfs diff=lfs merge=lfs -text
|
98 |
+
venv/lib/python3.11/site-packages/tensorflow/python/client/_pywrap_events_writer.so filter=lfs diff=lfs merge=lfs -text
|
99 |
+
venv/lib/python3.11/site-packages/tensorflow/python/client/_pywrap_tf_session.so filter=lfs diff=lfs merge=lfs -text
|
100 |
+
venv/lib/python3.11/site-packages/tensorflow/python/data/experimental/service/_pywrap_server_lib.so filter=lfs diff=lfs merge=lfs -text
|
101 |
+
venv/lib/python3.11/site-packages/tensorflow/python/data/experimental/service/_pywrap_utils.so filter=lfs diff=lfs merge=lfs -text
|
102 |
+
venv/lib/python3.11/site-packages/tensorflow/python/flags_pybind.so filter=lfs diff=lfs merge=lfs -text
|
103 |
+
venv/lib/python3.11/site-packages/tensorflow/python/framework/_op_def_library_pybind.so filter=lfs diff=lfs merge=lfs -text
|
104 |
+
venv/lib/python3.11/site-packages/tensorflow/python/framework/_op_def_registry.so filter=lfs diff=lfs merge=lfs -text
|
105 |
+
venv/lib/python3.11/site-packages/tensorflow/python/framework/_proto_comparators.so filter=lfs diff=lfs merge=lfs -text
|
106 |
+
venv/lib/python3.11/site-packages/tensorflow/python/framework/_test_metrics_util.so filter=lfs diff=lfs merge=lfs -text
|
107 |
+
venv/lib/python3.11/site-packages/tensorflow/python/framework/lib_native_proto_caster.dylib filter=lfs diff=lfs merge=lfs -text
|
108 |
+
venv/lib/python3.11/site-packages/tensorflow/python/grappler/_pywrap_tf_cluster.so filter=lfs diff=lfs merge=lfs -text
|
109 |
+
venv/lib/python3.11/site-packages/tensorflow/python/grappler/_pywrap_tf_item.so filter=lfs diff=lfs merge=lfs -text
|
110 |
+
venv/lib/python3.11/site-packages/tensorflow/python/grappler/_pywrap_tf_optimizer.so filter=lfs diff=lfs merge=lfs -text
|
111 |
+
venv/lib/python3.11/site-packages/tensorflow/python/lib/io/_pywrap_file_io.so filter=lfs diff=lfs merge=lfs -text
|
112 |
+
venv/lib/python3.11/site-packages/tensorflow/python/lib/io/_pywrap_record_io.so filter=lfs diff=lfs merge=lfs -text
|
113 |
+
venv/lib/python3.11/site-packages/tensorflow/python/platform/_pywrap_tf2.so filter=lfs diff=lfs merge=lfs -text
|
114 |
+
venv/lib/python3.11/site-packages/tensorflow/python/profiler/internal/_pywrap_profiler.so filter=lfs diff=lfs merge=lfs -text
|
115 |
+
venv/lib/python3.11/site-packages/tensorflow/python/saved_model/pywrap_saved_model.so filter=lfs diff=lfs merge=lfs -text
|
116 |
+
venv/lib/python3.11/site-packages/tensorflow/python/tpu/_pywrap_tpu_embedding.so filter=lfs diff=lfs merge=lfs -text
|
117 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_pywrap_checkpoint_reader.so filter=lfs diff=lfs merge=lfs -text
|
118 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_pywrap_kernel_registry.so filter=lfs diff=lfs merge=lfs -text
|
119 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_pywrap_stat_summarizer.so filter=lfs diff=lfs merge=lfs -text
|
120 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_pywrap_tfprof.so filter=lfs diff=lfs merge=lfs -text
|
121 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_pywrap_transform_graph.so filter=lfs diff=lfs merge=lfs -text
|
122 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_pywrap_utils.so filter=lfs diff=lfs merge=lfs -text
|
123 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/_tf_stack.so filter=lfs diff=lfs merge=lfs -text
|
124 |
+
venv/lib/python3.11/site-packages/tensorflow/python/util/pywrap_xla_ops.so filter=lfs diff=lfs merge=lfs -text
|
125 |
+
venv/lib/python3.11/site-packages/tensorflow_io_gcs_filesystem/core/python/ops/libtensorflow_io_gcs_filesystem.so filter=lfs diff=lfs merge=lfs -text
|
126 |
+
venv/lib/python3.11/site-packages/tensorstore/_tensorstore.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
127 |
+
venv/lib/python3.11/site-packages/tokenizers/tokenizers.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text
|
128 |
+
venv/lib/python3.11/site-packages/torch/bin/protoc filter=lfs diff=lfs merge=lfs -text
|
129 |
+
venv/lib/python3.11/site-packages/torch/bin/protoc-3.13.0.0 filter=lfs diff=lfs merge=lfs -text
|
130 |
+
venv/lib/python3.11/site-packages/torch/lib/libtorch_cpu.dylib filter=lfs diff=lfs merge=lfs -text
|
131 |
+
venv/lib/python3.11/site-packages/torch/lib/libtorch_python.dylib filter=lfs diff=lfs merge=lfs -text
|
.idea/aws.xml
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="accountSettings">
|
4 |
+
<option name="activeRegion" value="us-east-1" />
|
5 |
+
<option name="recentlyUsedRegions">
|
6 |
+
<list>
|
7 |
+
<option value="us-east-1" />
|
8 |
+
</list>
|
9 |
+
</option>
|
10 |
+
</component>
|
11 |
+
<component name="connectionManager">
|
12 |
+
<option name="activeConnectionId" value="sso;us-east-1;https://view.awsapps.com/start" />
|
13 |
+
</component>
|
14 |
+
</project>
|
.idea/misc.xml
CHANGED
@@ -1,4 +1,7 @@
|
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
<project version="4">
|
|
|
|
|
|
|
3 |
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (gradioapp)" project-jdk-type="Python SDK" />
|
4 |
</project>
|
|
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
<project version="4">
|
3 |
+
<component name="Black">
|
4 |
+
<option name="sdkName" value="Python 3.11 (gradioapp)" />
|
5 |
+
</component>
|
6 |
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (gradioapp)" project-jdk-type="Python SDK" />
|
7 |
</project>
|
.idea/workspace.xml
CHANGED
@@ -20,6 +20,13 @@
|
|
20 |
<component name="MarkdownSettingsMigration">
|
21 |
<option name="stateVersion" value="1" />
|
22 |
</component>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
<component name="ProjectId" id="2gPvQaTZU4mio8cyiCqtVWjrRzU" />
|
24 |
<component name="ProjectViewState">
|
25 |
<option name="hideEmptyMiddlePackages" value="true" />
|
@@ -27,13 +34,15 @@
|
|
27 |
</component>
|
28 |
<component name="PropertiesComponent">{
|
29 |
"keyToString": {
|
|
|
30 |
"RunOnceActivity.ShowReadmeOnStart": "true",
|
31 |
-
"settings.editor.selected.configurable": "
|
32 |
}
|
33 |
}</component>
|
34 |
<component name="RunManager">
|
35 |
<configuration name="main" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
36 |
<module name="gradioapp" />
|
|
|
37 |
<option name="INTERPRETER_OPTIONS" value="" />
|
38 |
<option name="PARENT_ENVS" value="true" />
|
39 |
<envs>
|
@@ -54,6 +63,13 @@
|
|
54 |
<method v="2" />
|
55 |
</configuration>
|
56 |
</component>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
58 |
<component name="TaskManager">
|
59 |
<task active="true" id="Default" summary="Default task">
|
@@ -65,4 +81,11 @@
|
|
65 |
</task>
|
66 |
<servers />
|
67 |
</component>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
</project>
|
|
|
20 |
<component name="MarkdownSettingsMigration">
|
21 |
<option name="stateVersion" value="1" />
|
22 |
</component>
|
23 |
+
<component name="ProblemsViewState">
|
24 |
+
<option name="selectedTabId" value="DEPENDENCY_CHECKER_PROBLEMS_TAB" />
|
25 |
+
</component>
|
26 |
+
<component name="ProjectColorInfo">{
|
27 |
+
"customColor": "",
|
28 |
+
"associatedIndex": 0
|
29 |
+
}</component>
|
30 |
<component name="ProjectId" id="2gPvQaTZU4mio8cyiCqtVWjrRzU" />
|
31 |
<component name="ProjectViewState">
|
32 |
<option name="hideEmptyMiddlePackages" value="true" />
|
|
|
34 |
</component>
|
35 |
<component name="PropertiesComponent">{
|
36 |
"keyToString": {
|
37 |
+
"Python.main.executor": "Run",
|
38 |
"RunOnceActivity.ShowReadmeOnStart": "true",
|
39 |
+
"settings.editor.selected.configurable": "preferences.pluginManager"
|
40 |
}
|
41 |
}</component>
|
42 |
<component name="RunManager">
|
43 |
<configuration name="main" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
44 |
<module name="gradioapp" />
|
45 |
+
<option name="ENV_FILES" value="" />
|
46 |
<option name="INTERPRETER_OPTIONS" value="" />
|
47 |
<option name="PARENT_ENVS" value="true" />
|
48 |
<envs>
|
|
|
63 |
<method v="2" />
|
64 |
</configuration>
|
65 |
</component>
|
66 |
+
<component name="SharedIndexes">
|
67 |
+
<attachedChunks>
|
68 |
+
<set>
|
69 |
+
<option value="bundled-python-sdk-48aec45f0201-746f403e7f0c-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-241.17011.127" />
|
70 |
+
</set>
|
71 |
+
</attachedChunks>
|
72 |
+
</component>
|
73 |
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
74 |
<component name="TaskManager">
|
75 |
<task active="true" id="Default" summary="Default task">
|
|
|
81 |
</task>
|
82 |
<servers />
|
83 |
</component>
|
84 |
+
<component name="XDebuggerManager">
|
85 |
+
<watches-manager>
|
86 |
+
<configuration name="PythonConfigurationType">
|
87 |
+
<watch expression="messages[0]["generated_text"]" language="Python" />
|
88 |
+
</configuration>
|
89 |
+
</watches-manager>
|
90 |
+
</component>
|
91 |
</project>
|
main.py
CHANGED
@@ -3,13 +3,59 @@
|
|
3 |
# Press ⌃R to execute it or replace it with your code.
|
4 |
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
|
5 |
|
|
|
6 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
-
def greet(name, intensity):
|
9 |
-
return "Hello........., " + name + "!" * int(intensity)
|
10 |
|
11 |
demo = gr.Interface(
|
12 |
-
fn=
|
13 |
inputs=["text", "slider"],
|
14 |
outputs=["text"],
|
15 |
)
|
|
|
3 |
# Press ⌃R to execute it or replace it with your code.
|
4 |
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
|
5 |
|
6 |
+
|
7 |
import gradio as gr
|
8 |
+
from transformers import pipeline
|
9 |
+
from transformers import Conversation
|
10 |
+
|
11 |
+
|
12 |
+
def chatwith_blenderbot400m():
|
13 |
+
chatbot = pipeline(task="conversational", model="facebook/blenderbot-400M-distill")
|
14 |
+
user_message = "What are some fun activities I can do in the winter?"
|
15 |
+
conversation = Conversation(user_message)
|
16 |
+
print(conversation)
|
17 |
+
print(type(conversation))
|
18 |
+
conversation = chatbot(conversation)
|
19 |
+
print(conversation)
|
20 |
+
conversation.add_message(
|
21 |
+
{"role": "user", "content": "I would like to do outdoor activities. Which activities can I do?"})
|
22 |
+
conversation = chatbot(conversation)
|
23 |
+
print(conversation)
|
24 |
+
|
25 |
+
|
26 |
+
def chatwith_qwen2_1point5b_instruct():
|
27 |
+
chatbot = pipeline(task="text-generation", model="Qwen/Qwen2-1.5B-Instruct")
|
28 |
+
messages = [{"role": "user", "content": "What are some fun activities I can do in the winter?"}]
|
29 |
+
|
30 |
+
messages = chatbot(messages, max_new_tokens=50)[0]["generated_text"]
|
31 |
+
print(messages)
|
32 |
+
|
33 |
+
messages.append({"role": "user", "content": "I would like to do outdoor activities. Which activities can I do?"})
|
34 |
+
print(messages)
|
35 |
+
messages = chatbot(messages, max_new_tokens=50)[0]["generated_text"]
|
36 |
+
print(messages)
|
37 |
+
|
38 |
+
def chatwith_qwen2_1point5b_instruct(prompt, max_newtokens):
|
39 |
+
print("Aaaaa")
|
40 |
+
chatbot = pipeline(task="text-generation", model="Qwen/Qwen2-1.5B-Instruct")
|
41 |
+
|
42 |
+
messages = [{"role": "user", "content": prompt}]
|
43 |
+
messages = chatbot(messages, max_new_tokens=max_newtokens)[0]["generated_text"]
|
44 |
+
return messages
|
45 |
+
|
46 |
+
#chatwith_blenderbot400m()
|
47 |
+
#chatwith_qwen2_1point5b_instruct()
|
48 |
+
|
49 |
+
# prompt = "What are some fun activities I can do in the winter?"
|
50 |
+
# max_newtokens = 2
|
51 |
+
# print(chatwith_qwen2_1point5b_instruct(prompt, max_newtokens))
|
52 |
+
|
53 |
+
# def greet(name, intensity):
|
54 |
+
# return "Hello........., " + name + "!" * int(intensity)
|
55 |
|
|
|
|
|
56 |
|
57 |
demo = gr.Interface(
|
58 |
+
fn=chatwith_qwen2_1point5b_instruct,
|
59 |
inputs=["text", "slider"],
|
60 |
outputs=["text"],
|
61 |
)
|
venv/bin/convert-caffe2-to-onnx
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from caffe2.python.onnx.bin.conversion import caffe2_to_onnx
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(caffe2_to_onnx())
|
venv/bin/convert-onnx-to-caffe2
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from caffe2.python.onnx.bin.conversion import onnx_to_caffe2
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(onnx_to_caffe2())
|
venv/bin/import_pb_to_tensorboard
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorflow.python.tools.import_pb_to_tensorboard import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/isympy
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from isympy import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/markdown_py
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from markdown.__main__ import run
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(run())
|
venv/bin/saved_model_cli
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorflow.python.tools.saved_model_cli import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/tensorboard
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorboard.main import run_main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(run_main())
|
venv/bin/tf_upgrade_v2
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorflow.tools.compatibility.tf_upgrade_v2_main import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/tflite_convert
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorflow.lite.python.tflite_convert import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/toco
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorflow.lite.python.tflite_convert import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/toco_from_protos
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tensorflow.lite.toco.python.toco_from_protos import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/torchrun
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from torch.distributed.run import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/bin/transformers-cli
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/Users/phi.tran/Development/learning/gradioapp/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from transformers.commands.transformers_cli import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/LICENSE.md
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
BSD 3-Clause License
|
2 |
+
|
3 |
+
Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
|
4 |
+
Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
|
5 |
+
Copyright 2004 Manfred Stienstra (the original version)
|
6 |
+
|
7 |
+
Redistribution and use in source and binary forms, with or without
|
8 |
+
modification, are permitted provided that the following conditions are met:
|
9 |
+
|
10 |
+
1. Redistributions of source code must retain the above copyright notice, this
|
11 |
+
list of conditions and the following disclaimer.
|
12 |
+
|
13 |
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
14 |
+
this list of conditions and the following disclaimer in the documentation
|
15 |
+
and/or other materials provided with the distribution.
|
16 |
+
|
17 |
+
3. Neither the name of the copyright holder nor the names of its
|
18 |
+
contributors may be used to endorse or promote products derived from
|
19 |
+
this software without specific prior written permission.
|
20 |
+
|
21 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
22 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
23 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
24 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
25 |
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
26 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
27 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
28 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
29 |
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
30 |
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/METADATA
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: Markdown
|
3 |
+
Version: 3.6
|
4 |
+
Summary: Python implementation of John Gruber's Markdown.
|
5 |
+
Author: Manfred Stienstra, Yuri Takhteyev
|
6 |
+
Author-email: Waylan limberg <python.markdown@gmail.com>
|
7 |
+
Maintainer: Isaac Muse
|
8 |
+
Maintainer-email: Waylan Limberg <python.markdown@gmail.com>
|
9 |
+
License: BSD 3-Clause License
|
10 |
+
|
11 |
+
Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
|
12 |
+
Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
|
13 |
+
Copyright 2004 Manfred Stienstra (the original version)
|
14 |
+
|
15 |
+
Redistribution and use in source and binary forms, with or without
|
16 |
+
modification, are permitted provided that the following conditions are met:
|
17 |
+
|
18 |
+
1. Redistributions of source code must retain the above copyright notice, this
|
19 |
+
list of conditions and the following disclaimer.
|
20 |
+
|
21 |
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
22 |
+
this list of conditions and the following disclaimer in the documentation
|
23 |
+
and/or other materials provided with the distribution.
|
24 |
+
|
25 |
+
3. Neither the name of the copyright holder nor the names of its
|
26 |
+
contributors may be used to endorse or promote products derived from
|
27 |
+
this software without specific prior written permission.
|
28 |
+
|
29 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
30 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
31 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
32 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
33 |
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
34 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
35 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
36 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
37 |
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38 |
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39 |
+
|
40 |
+
Project-URL: Homepage, https://Python-Markdown.github.io/
|
41 |
+
Project-URL: Documentation, https://Python-Markdown.github.io/
|
42 |
+
Project-URL: Repository, https://github.com/Python-Markdown/markdown
|
43 |
+
Project-URL: Issue Tracker, https://github.com/Python-Markdown/markdown/issues
|
44 |
+
Project-URL: Changelog, https://python-markdown.github.io/changelog/
|
45 |
+
Keywords: markdown,markdown-parser,python-markdown,markdown-to-html
|
46 |
+
Classifier: Development Status :: 5 - Production/Stable
|
47 |
+
Classifier: License :: OSI Approved :: BSD License
|
48 |
+
Classifier: Operating System :: OS Independent
|
49 |
+
Classifier: Programming Language :: Python
|
50 |
+
Classifier: Programming Language :: Python :: 3
|
51 |
+
Classifier: Programming Language :: Python :: 3.8
|
52 |
+
Classifier: Programming Language :: Python :: 3.9
|
53 |
+
Classifier: Programming Language :: Python :: 3.10
|
54 |
+
Classifier: Programming Language :: Python :: 3.11
|
55 |
+
Classifier: Programming Language :: Python :: 3.12
|
56 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
57 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
58 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
59 |
+
Classifier: Topic :: Communications :: Email :: Filters
|
60 |
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries
|
61 |
+
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
|
62 |
+
Classifier: Topic :: Software Development :: Documentation
|
63 |
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
64 |
+
Classifier: Topic :: Text Processing :: Filters
|
65 |
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
66 |
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
67 |
+
Requires-Python: >=3.8
|
68 |
+
Description-Content-Type: text/markdown
|
69 |
+
License-File: LICENSE.md
|
70 |
+
Requires-Dist: importlib-metadata >=4.4 ; python_version < "3.10"
|
71 |
+
Provides-Extra: docs
|
72 |
+
Requires-Dist: mkdocs >=1.5 ; extra == 'docs'
|
73 |
+
Requires-Dist: mkdocs-nature >=0.6 ; extra == 'docs'
|
74 |
+
Requires-Dist: mdx-gh-links >=0.2 ; extra == 'docs'
|
75 |
+
Requires-Dist: mkdocstrings[python] ; extra == 'docs'
|
76 |
+
Requires-Dist: mkdocs-gen-files ; extra == 'docs'
|
77 |
+
Requires-Dist: mkdocs-section-index ; extra == 'docs'
|
78 |
+
Requires-Dist: mkdocs-literate-nav ; extra == 'docs'
|
79 |
+
Provides-Extra: testing
|
80 |
+
Requires-Dist: coverage ; extra == 'testing'
|
81 |
+
Requires-Dist: pyyaml ; extra == 'testing'
|
82 |
+
|
83 |
+
[Python-Markdown][]
|
84 |
+
===================
|
85 |
+
|
86 |
+
[![Build Status][build-button]][build]
|
87 |
+
[![Coverage Status][codecov-button]][codecov]
|
88 |
+
[![Latest Version][mdversion-button]][md-pypi]
|
89 |
+
[![Python Versions][pyversion-button]][md-pypi]
|
90 |
+
[![BSD License][bsdlicense-button]][bsdlicense]
|
91 |
+
[![Code of Conduct][codeofconduct-button]][Code of Conduct]
|
92 |
+
|
93 |
+
[build-button]: https://github.com/Python-Markdown/markdown/workflows/CI/badge.svg?event=push
|
94 |
+
[build]: https://github.com/Python-Markdown/markdown/actions?query=workflow%3ACI+event%3Apush
|
95 |
+
[codecov-button]: https://codecov.io/gh/Python-Markdown/markdown/branch/master/graph/badge.svg
|
96 |
+
[codecov]: https://codecov.io/gh/Python-Markdown/markdown
|
97 |
+
[mdversion-button]: https://img.shields.io/pypi/v/Markdown.svg
|
98 |
+
[md-pypi]: https://pypi.org/project/Markdown/
|
99 |
+
[pyversion-button]: https://img.shields.io/pypi/pyversions/Markdown.svg
|
100 |
+
[bsdlicense-button]: https://img.shields.io/badge/license-BSD-yellow.svg
|
101 |
+
[bsdlicense]: https://opensource.org/licenses/BSD-3-Clause
|
102 |
+
[codeofconduct-button]: https://img.shields.io/badge/code%20of%20conduct-contributor%20covenant-green.svg?style=flat-square
|
103 |
+
[Code of Conduct]: https://github.com/Python-Markdown/markdown/blob/master/CODE_OF_CONDUCT.md
|
104 |
+
|
105 |
+
This is a Python implementation of John Gruber's [Markdown][].
|
106 |
+
It is almost completely compliant with the reference implementation,
|
107 |
+
though there are a few known issues. See [Features][] for information
|
108 |
+
on what exactly is supported and what is not. Additional features are
|
109 |
+
supported by the [Available Extensions][].
|
110 |
+
|
111 |
+
[Python-Markdown]: https://Python-Markdown.github.io/
|
112 |
+
[Markdown]: https://daringfireball.net/projects/markdown/
|
113 |
+
[Features]: https://Python-Markdown.github.io#Features
|
114 |
+
[Available Extensions]: https://Python-Markdown.github.io/extensions
|
115 |
+
|
116 |
+
Documentation
|
117 |
+
-------------
|
118 |
+
|
119 |
+
```bash
|
120 |
+
pip install markdown
|
121 |
+
```
|
122 |
+
```python
|
123 |
+
import markdown
|
124 |
+
html = markdown.markdown(your_text_string)
|
125 |
+
```
|
126 |
+
|
127 |
+
For more advanced [installation] and [usage] documentation, see the `docs/` directory
|
128 |
+
of the distribution or the project website at <https://Python-Markdown.github.io/>.
|
129 |
+
|
130 |
+
[installation]: https://python-markdown.github.io/install/
|
131 |
+
[usage]: https://python-markdown.github.io/reference/
|
132 |
+
|
133 |
+
See the change log at <https://python-markdown.github.io/changelog/>.
|
134 |
+
|
135 |
+
Support
|
136 |
+
-------
|
137 |
+
|
138 |
+
You may report bugs, ask for help, and discuss various other issues on the [bug tracker][].
|
139 |
+
|
140 |
+
[bug tracker]: https://github.com/Python-Markdown/markdown/issues
|
141 |
+
|
142 |
+
Code of Conduct
|
143 |
+
---------------
|
144 |
+
|
145 |
+
Everyone interacting in the Python-Markdown project's code bases, issue trackers,
|
146 |
+
and mailing lists is expected to follow the [Code of Conduct].
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/RECORD
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
../../../bin/markdown_py,sha256=RmOYegb2TT6H4cvF6C-bx0BGqZJkndQtRFVj5nu2TMM,260
|
2 |
+
Markdown-3.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
3 |
+
Markdown-3.6.dist-info/LICENSE.md,sha256=e6TrbRCzKy0R3OE4ITQDUc27swuozMZ4Qdsv_Ybnmso,1650
|
4 |
+
Markdown-3.6.dist-info/METADATA,sha256=8_ETqzTxcOemQXj7ujUabMFcDBDGtsRrccFDr1-XWvc,7040
|
5 |
+
Markdown-3.6.dist-info/RECORD,,
|
6 |
+
Markdown-3.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
7 |
+
Markdown-3.6.dist-info/entry_points.txt,sha256=lMEyiiA_ZZyfPCBlDviBl-SiU0cfoeuEKpwxw361sKQ,1102
|
8 |
+
Markdown-3.6.dist-info/top_level.txt,sha256=IAxs8x618RXoH1uCqeLLxXsDefJvE_mIibr_M4sOlyk,9
|
9 |
+
markdown/__init__.py,sha256=dfzwwdpG9L8QLEPBpLFPIHx_BN056aZXp9xZifTxYIU,1777
|
10 |
+
markdown/__main__.py,sha256=innFBxRqwPBNxG1zhKktJji4bnRKtVyYYd30ID13Tcw,5859
|
11 |
+
markdown/__meta__.py,sha256=DqtqnYYLznrkvI1G4JalBc4WpgOp48naNoG9zlMWZas,1712
|
12 |
+
markdown/__pycache__/__init__.cpython-311.pyc,,
|
13 |
+
markdown/__pycache__/__main__.cpython-311.pyc,,
|
14 |
+
markdown/__pycache__/__meta__.cpython-311.pyc,,
|
15 |
+
markdown/__pycache__/blockparser.cpython-311.pyc,,
|
16 |
+
markdown/__pycache__/blockprocessors.cpython-311.pyc,,
|
17 |
+
markdown/__pycache__/core.cpython-311.pyc,,
|
18 |
+
markdown/__pycache__/htmlparser.cpython-311.pyc,,
|
19 |
+
markdown/__pycache__/inlinepatterns.cpython-311.pyc,,
|
20 |
+
markdown/__pycache__/postprocessors.cpython-311.pyc,,
|
21 |
+
markdown/__pycache__/preprocessors.cpython-311.pyc,,
|
22 |
+
markdown/__pycache__/serializers.cpython-311.pyc,,
|
23 |
+
markdown/__pycache__/test_tools.cpython-311.pyc,,
|
24 |
+
markdown/__pycache__/treeprocessors.cpython-311.pyc,,
|
25 |
+
markdown/__pycache__/util.cpython-311.pyc,,
|
26 |
+
markdown/blockparser.py,sha256=j4CQImVpiq7g9pz8wCxvzT61X_T2iSAjXupHJk8P3eA,5728
|
27 |
+
markdown/blockprocessors.py,sha256=koY5rq8DixzBCHcquvZJp6x2JYyBGjrwxMWNZhd6D2U,27013
|
28 |
+
markdown/core.py,sha256=DyyzDsmd-KcuEp8ZWUKJAeUCt7B7G3J3NeqZqp3LphI,21335
|
29 |
+
markdown/extensions/__init__.py,sha256=9z1khsdKCVrmrJ_2GfxtPAdjD3FyMe5vhC7wmM4O9m0,4822
|
30 |
+
markdown/extensions/__pycache__/__init__.cpython-311.pyc,,
|
31 |
+
markdown/extensions/__pycache__/abbr.cpython-311.pyc,,
|
32 |
+
markdown/extensions/__pycache__/admonition.cpython-311.pyc,,
|
33 |
+
markdown/extensions/__pycache__/attr_list.cpython-311.pyc,,
|
34 |
+
markdown/extensions/__pycache__/codehilite.cpython-311.pyc,,
|
35 |
+
markdown/extensions/__pycache__/def_list.cpython-311.pyc,,
|
36 |
+
markdown/extensions/__pycache__/extra.cpython-311.pyc,,
|
37 |
+
markdown/extensions/__pycache__/fenced_code.cpython-311.pyc,,
|
38 |
+
markdown/extensions/__pycache__/footnotes.cpython-311.pyc,,
|
39 |
+
markdown/extensions/__pycache__/legacy_attrs.cpython-311.pyc,,
|
40 |
+
markdown/extensions/__pycache__/legacy_em.cpython-311.pyc,,
|
41 |
+
markdown/extensions/__pycache__/md_in_html.cpython-311.pyc,,
|
42 |
+
markdown/extensions/__pycache__/meta.cpython-311.pyc,,
|
43 |
+
markdown/extensions/__pycache__/nl2br.cpython-311.pyc,,
|
44 |
+
markdown/extensions/__pycache__/sane_lists.cpython-311.pyc,,
|
45 |
+
markdown/extensions/__pycache__/smarty.cpython-311.pyc,,
|
46 |
+
markdown/extensions/__pycache__/tables.cpython-311.pyc,,
|
47 |
+
markdown/extensions/__pycache__/toc.cpython-311.pyc,,
|
48 |
+
markdown/extensions/__pycache__/wikilinks.cpython-311.pyc,,
|
49 |
+
markdown/extensions/abbr.py,sha256=JqFOfU7JlhIFY06-nZnSU0wDqneFKKWMe95eXB-iLtc,3250
|
50 |
+
markdown/extensions/admonition.py,sha256=Hqcn3I8JG0i-OPWdoqI189TmlQRgH6bs5PmpCANyLlg,6547
|
51 |
+
markdown/extensions/attr_list.py,sha256=t3PrgAr5Ebldnq3nJNbteBt79bN0ccXS5RemmQfUZ9g,7820
|
52 |
+
markdown/extensions/codehilite.py,sha256=ChlmpM6S--j-UK7t82859UpYjm8EftdiLqmgDnknyes,13503
|
53 |
+
markdown/extensions/def_list.py,sha256=J3NVa6CllfZPsboJCEycPyRhtjBHnOn8ET6omEvVlDo,4029
|
54 |
+
markdown/extensions/extra.py,sha256=1vleT284kued4HQBtF83IjSumJVo0q3ng6MjTkVNfNQ,2163
|
55 |
+
markdown/extensions/fenced_code.py,sha256=-fYSmRZ9DTYQ8HO9b_78i47kVyVu6mcVJlqVTMdzvo4,8300
|
56 |
+
markdown/extensions/footnotes.py,sha256=bRFlmIBOKDI5efG1jZfDkMoV2osfqWip1rN1j2P-mMg,16710
|
57 |
+
markdown/extensions/legacy_attrs.py,sha256=oWcyNrfP0F6zsBoBOaD5NiwrJyy4kCpgQLl12HA7JGU,2788
|
58 |
+
markdown/extensions/legacy_em.py,sha256=-Z_w4PEGSS-Xg-2-BtGAnXwwy5g5GDgv2tngASnPgxg,1693
|
59 |
+
markdown/extensions/md_in_html.py,sha256=y4HEWEnkvfih22fojcaJeAmjx1AtF8N-a_jb6IDFfts,16546
|
60 |
+
markdown/extensions/meta.py,sha256=v_4Uq7nbcQ76V1YAvqVPiNLbRLIQHJsnfsk-tN70RmY,2600
|
61 |
+
markdown/extensions/nl2br.py,sha256=9KKcrPs62c3ENNnmOJZs0rrXXqUtTCfd43j1_OPpmgU,1090
|
62 |
+
markdown/extensions/sane_lists.py,sha256=ogAKcm7gEpcXV7fSTf8JZH5YdKAssPCEOUzdGM3C9Tw,2150
|
63 |
+
markdown/extensions/smarty.py,sha256=yqT0OiE2AqYrqqZtcUFFmp2eJsQHomiKzgyG2JFb9rI,11048
|
64 |
+
markdown/extensions/tables.py,sha256=oTDvGD1qp9xjVWPGYNgDBWe9NqsX5gS6UU5wUsQ1bC8,8741
|
65 |
+
markdown/extensions/toc.py,sha256=PGg-EqbBubm3n0b633r8Xa9kc6JIdbo20HGAOZ6GEl8,18322
|
66 |
+
markdown/extensions/wikilinks.py,sha256=j7D2sozica6sqXOUa_GuAXqIzxp-7Hi60bfXymiuma8,3285
|
67 |
+
markdown/htmlparser.py,sha256=dEr6IE7i9b6Tc1gdCLZGeWw6g6-E-jK1Z4KPj8yGk8Q,14332
|
68 |
+
markdown/inlinepatterns.py,sha256=7_HF5nTOyQag_CyBgU4wwmuI6aMjtadvGadyS9IP21w,38256
|
69 |
+
markdown/postprocessors.py,sha256=eYi6eW0mGudmWpmsW45hduLwX66Zr8Bf44WyU9vKp-I,4807
|
70 |
+
markdown/preprocessors.py,sha256=pq5NnHKkOSVQeIo-ajC-Yt44kvyMV97D04FBOQXctJM,3224
|
71 |
+
markdown/serializers.py,sha256=YtAFYQoOdp_TAmYGow6nBo0eB6I-Sl4PTLdLDfQJHwQ,7174
|
72 |
+
markdown/test_tools.py,sha256=MtN4cf3ZPDtb83wXLTol-3q3aIGRIkJ2zWr6fd-RgVE,8662
|
73 |
+
markdown/treeprocessors.py,sha256=o4dnoZZsIeVV8qR45Njr8XgwKleWYDS5pv8dKQhJvv8,17651
|
74 |
+
markdown/util.py,sha256=vJ1E0xjMzDAlTqLUSJWgdEvxdQfLXDEYUssOQMw9kPQ,13929
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: bdist_wheel (0.43.0)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/entry_points.txt
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[console_scripts]
|
2 |
+
markdown_py = markdown.__main__:run
|
3 |
+
|
4 |
+
[markdown.extensions]
|
5 |
+
abbr = markdown.extensions.abbr:AbbrExtension
|
6 |
+
admonition = markdown.extensions.admonition:AdmonitionExtension
|
7 |
+
attr_list = markdown.extensions.attr_list:AttrListExtension
|
8 |
+
codehilite = markdown.extensions.codehilite:CodeHiliteExtension
|
9 |
+
def_list = markdown.extensions.def_list:DefListExtension
|
10 |
+
extra = markdown.extensions.extra:ExtraExtension
|
11 |
+
fenced_code = markdown.extensions.fenced_code:FencedCodeExtension
|
12 |
+
footnotes = markdown.extensions.footnotes:FootnoteExtension
|
13 |
+
legacy_attrs = markdown.extensions.legacy_attrs:LegacyAttrExtension
|
14 |
+
legacy_em = markdown.extensions.legacy_em:LegacyEmExtension
|
15 |
+
md_in_html = markdown.extensions.md_in_html:MarkdownInHtmlExtension
|
16 |
+
meta = markdown.extensions.meta:MetaExtension
|
17 |
+
nl2br = markdown.extensions.nl2br:Nl2BrExtension
|
18 |
+
sane_lists = markdown.extensions.sane_lists:SaneListExtension
|
19 |
+
smarty = markdown.extensions.smarty:SmartyExtension
|
20 |
+
tables = markdown.extensions.tables:TableExtension
|
21 |
+
toc = markdown.extensions.toc:TocExtension
|
22 |
+
wikilinks = markdown.extensions.wikilinks:WikiLinkExtension
|
venv/lib/python3.11/site-packages/Markdown-3.6.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
markdown
|
venv/lib/python3.11/site-packages/__pycache__/isympy.cpython-311.pyc
ADDED
Binary file (11.3 kB). View file
|
|
venv/lib/python3.11/site-packages/__pycache__/nest_asyncio.cpython-311.pyc
ADDED
Binary file (13.3 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/__init__.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
venv/lib/python3.11/site-packages/absl/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (206 Bytes). View file
|
|
venv/lib/python3.11/site-packages/absl/__pycache__/app.cpython-311.pyc
ADDED
Binary file (21.2 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/__pycache__/command_name.cpython-311.pyc
ADDED
Binary file (2.74 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/app.py
ADDED
@@ -0,0 +1,480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
|
15 |
+
"""Generic entry point for Abseil Python applications.
|
16 |
+
|
17 |
+
To use this module, define a ``main`` function with a single ``argv`` argument
|
18 |
+
and call ``app.run(main)``. For example::
|
19 |
+
|
20 |
+
def main(argv):
|
21 |
+
if len(argv) > 1:
|
22 |
+
raise app.UsageError('Too many command-line arguments.')
|
23 |
+
|
24 |
+
if __name__ == '__main__':
|
25 |
+
app.run(main)
|
26 |
+
"""
|
27 |
+
|
28 |
+
import collections
|
29 |
+
import errno
|
30 |
+
import os
|
31 |
+
import pdb
|
32 |
+
import sys
|
33 |
+
import textwrap
|
34 |
+
import traceback
|
35 |
+
|
36 |
+
from absl import command_name
|
37 |
+
from absl import flags
|
38 |
+
from absl import logging
|
39 |
+
|
40 |
+
try:
|
41 |
+
import faulthandler
|
42 |
+
except ImportError:
|
43 |
+
faulthandler = None
|
44 |
+
|
45 |
+
FLAGS = flags.FLAGS
|
46 |
+
|
47 |
+
flags.DEFINE_boolean('run_with_pdb', False, 'Set to true for PDB debug mode')
|
48 |
+
flags.DEFINE_boolean('pdb_post_mortem', False,
|
49 |
+
'Set to true to handle uncaught exceptions with PDB '
|
50 |
+
'post mortem.')
|
51 |
+
flags.DEFINE_alias('pdb', 'pdb_post_mortem')
|
52 |
+
flags.DEFINE_boolean('run_with_profiling', False,
|
53 |
+
'Set to true for profiling the script. '
|
54 |
+
'Execution will be slower, and the output format might '
|
55 |
+
'change over time.')
|
56 |
+
flags.DEFINE_string('profile_file', None,
|
57 |
+
'Dump profile information to a file (for python -m '
|
58 |
+
'pstats). Implies --run_with_profiling.')
|
59 |
+
flags.DEFINE_boolean('use_cprofile_for_profiling', True,
|
60 |
+
'Use cProfile instead of the profile module for '
|
61 |
+
'profiling. This has no effect unless '
|
62 |
+
'--run_with_profiling is set.')
|
63 |
+
flags.DEFINE_boolean('only_check_args', False,
|
64 |
+
'Set to true to validate args and exit.',
|
65 |
+
allow_hide_cpp=True)
|
66 |
+
|
67 |
+
|
68 |
+
# If main() exits via an abnormal exception, call into these
|
69 |
+
# handlers before exiting.
|
70 |
+
EXCEPTION_HANDLERS = []
|
71 |
+
|
72 |
+
|
73 |
+
class Error(Exception):
|
74 |
+
pass
|
75 |
+
|
76 |
+
|
77 |
+
class UsageError(Error):
|
78 |
+
"""Exception raised when the arguments supplied by the user are invalid.
|
79 |
+
|
80 |
+
Raise this when the arguments supplied are invalid from the point of
|
81 |
+
view of the application. For example when two mutually exclusive
|
82 |
+
flags have been supplied or when there are not enough non-flag
|
83 |
+
arguments. It is distinct from flags.Error which covers the lower
|
84 |
+
level of parsing and validating individual flags.
|
85 |
+
"""
|
86 |
+
|
87 |
+
def __init__(self, message, exitcode=1):
|
88 |
+
super(UsageError, self).__init__(message)
|
89 |
+
self.exitcode = exitcode
|
90 |
+
|
91 |
+
|
92 |
+
class HelpFlag(flags.BooleanFlag):
|
93 |
+
"""Special boolean flag that displays usage and raises SystemExit."""
|
94 |
+
NAME = 'help'
|
95 |
+
SHORT_NAME = '?'
|
96 |
+
|
97 |
+
def __init__(self):
|
98 |
+
super(HelpFlag, self).__init__(
|
99 |
+
self.NAME, False, 'show this help',
|
100 |
+
short_name=self.SHORT_NAME, allow_hide_cpp=True)
|
101 |
+
|
102 |
+
def parse(self, arg):
|
103 |
+
if self._parse(arg):
|
104 |
+
usage(shorthelp=True, writeto_stdout=True)
|
105 |
+
# Advertise --helpfull on stdout, since usage() was on stdout.
|
106 |
+
print()
|
107 |
+
print('Try --helpfull to get a list of all flags.')
|
108 |
+
sys.exit(1)
|
109 |
+
|
110 |
+
|
111 |
+
class HelpshortFlag(HelpFlag):
|
112 |
+
"""--helpshort is an alias for --help."""
|
113 |
+
NAME = 'helpshort'
|
114 |
+
SHORT_NAME = None
|
115 |
+
|
116 |
+
|
117 |
+
class HelpfullFlag(flags.BooleanFlag):
|
118 |
+
"""Display help for flags in the main module and all dependent modules."""
|
119 |
+
|
120 |
+
def __init__(self):
|
121 |
+
super(HelpfullFlag, self).__init__(
|
122 |
+
'helpfull', False, 'show full help', allow_hide_cpp=True)
|
123 |
+
|
124 |
+
def parse(self, arg):
|
125 |
+
if self._parse(arg):
|
126 |
+
usage(writeto_stdout=True)
|
127 |
+
sys.exit(1)
|
128 |
+
|
129 |
+
|
130 |
+
class HelpXMLFlag(flags.BooleanFlag):
|
131 |
+
"""Similar to HelpfullFlag, but generates output in XML format."""
|
132 |
+
|
133 |
+
def __init__(self):
|
134 |
+
super(HelpXMLFlag, self).__init__(
|
135 |
+
'helpxml', False, 'like --helpfull, but generates XML output',
|
136 |
+
allow_hide_cpp=True)
|
137 |
+
|
138 |
+
def parse(self, arg):
|
139 |
+
if self._parse(arg):
|
140 |
+
flags.FLAGS.write_help_in_xml_format(sys.stdout)
|
141 |
+
sys.exit(1)
|
142 |
+
|
143 |
+
|
144 |
+
def parse_flags_with_usage(args):
|
145 |
+
"""Tries to parse the flags, print usage, and exit if unparsable.
|
146 |
+
|
147 |
+
Args:
|
148 |
+
args: [str], a non-empty list of the command line arguments including
|
149 |
+
program name.
|
150 |
+
|
151 |
+
Returns:
|
152 |
+
[str], a non-empty list of remaining command line arguments after parsing
|
153 |
+
flags, including program name.
|
154 |
+
"""
|
155 |
+
try:
|
156 |
+
return FLAGS(args)
|
157 |
+
except flags.Error as error:
|
158 |
+
message = str(error)
|
159 |
+
if '\n' in message:
|
160 |
+
final_message = 'FATAL Flags parsing error:\n%s\n' % textwrap.indent(
|
161 |
+
message, ' ')
|
162 |
+
else:
|
163 |
+
final_message = 'FATAL Flags parsing error: %s\n' % message
|
164 |
+
sys.stderr.write(final_message)
|
165 |
+
sys.stderr.write('Pass --helpshort or --helpfull to see help on flags.\n')
|
166 |
+
sys.exit(1)
|
167 |
+
|
168 |
+
|
169 |
+
_define_help_flags_called = False
|
170 |
+
|
171 |
+
|
172 |
+
def define_help_flags():
|
173 |
+
"""Registers help flags. Idempotent."""
|
174 |
+
# Use a global to ensure idempotence.
|
175 |
+
global _define_help_flags_called
|
176 |
+
|
177 |
+
if not _define_help_flags_called:
|
178 |
+
flags.DEFINE_flag(HelpFlag())
|
179 |
+
flags.DEFINE_flag(HelpshortFlag()) # alias for --help
|
180 |
+
flags.DEFINE_flag(HelpfullFlag())
|
181 |
+
flags.DEFINE_flag(HelpXMLFlag())
|
182 |
+
_define_help_flags_called = True
|
183 |
+
|
184 |
+
|
185 |
+
def _register_and_parse_flags_with_usage(
|
186 |
+
argv=None,
|
187 |
+
flags_parser=parse_flags_with_usage,
|
188 |
+
):
|
189 |
+
"""Registers help flags, parses arguments and shows usage if appropriate.
|
190 |
+
|
191 |
+
This also calls sys.exit(0) if flag --only_check_args is True.
|
192 |
+
|
193 |
+
Args:
|
194 |
+
argv: [str], a non-empty list of the command line arguments including
|
195 |
+
program name, sys.argv is used if None.
|
196 |
+
flags_parser: Callable[[List[Text]], Any], the function used to parse flags.
|
197 |
+
The return value of this function is passed to `main` untouched.
|
198 |
+
It must guarantee FLAGS is parsed after this function is called.
|
199 |
+
|
200 |
+
Returns:
|
201 |
+
The return value of `flags_parser`. When using the default `flags_parser`,
|
202 |
+
it returns the following:
|
203 |
+
[str], a non-empty list of remaining command line arguments after parsing
|
204 |
+
flags, including program name.
|
205 |
+
|
206 |
+
Raises:
|
207 |
+
Error: Raised when flags_parser is called, but FLAGS is not parsed.
|
208 |
+
SystemError: Raised when it's called more than once.
|
209 |
+
"""
|
210 |
+
if _register_and_parse_flags_with_usage.done:
|
211 |
+
raise SystemError('Flag registration can be done only once.')
|
212 |
+
|
213 |
+
define_help_flags()
|
214 |
+
|
215 |
+
original_argv = sys.argv if argv is None else argv
|
216 |
+
args_to_main = flags_parser(original_argv)
|
217 |
+
if not FLAGS.is_parsed():
|
218 |
+
raise Error('FLAGS must be parsed after flags_parser is called.')
|
219 |
+
|
220 |
+
# Exit when told so.
|
221 |
+
if FLAGS.only_check_args:
|
222 |
+
sys.exit(0)
|
223 |
+
# Immediately after flags are parsed, bump verbosity to INFO if the flag has
|
224 |
+
# not been set.
|
225 |
+
if FLAGS['verbosity'].using_default_value:
|
226 |
+
FLAGS.verbosity = 0
|
227 |
+
_register_and_parse_flags_with_usage.done = True
|
228 |
+
|
229 |
+
return args_to_main
|
230 |
+
|
231 |
+
_register_and_parse_flags_with_usage.done = False
|
232 |
+
|
233 |
+
|
234 |
+
def _run_main(main, argv):
|
235 |
+
"""Calls main, optionally with pdb or profiler."""
|
236 |
+
if FLAGS.run_with_pdb:
|
237 |
+
sys.exit(pdb.runcall(main, argv))
|
238 |
+
elif FLAGS.run_with_profiling or FLAGS.profile_file:
|
239 |
+
# Avoid import overhead since most apps (including performance-sensitive
|
240 |
+
# ones) won't be run with profiling.
|
241 |
+
# pylint: disable=g-import-not-at-top
|
242 |
+
import atexit
|
243 |
+
if FLAGS.use_cprofile_for_profiling:
|
244 |
+
import cProfile as profile
|
245 |
+
else:
|
246 |
+
import profile
|
247 |
+
profiler = profile.Profile()
|
248 |
+
if FLAGS.profile_file:
|
249 |
+
atexit.register(profiler.dump_stats, FLAGS.profile_file)
|
250 |
+
else:
|
251 |
+
atexit.register(profiler.print_stats)
|
252 |
+
sys.exit(profiler.runcall(main, argv))
|
253 |
+
else:
|
254 |
+
sys.exit(main(argv))
|
255 |
+
|
256 |
+
|
257 |
+
def _call_exception_handlers(exception):
|
258 |
+
"""Calls any installed exception handlers."""
|
259 |
+
for handler in EXCEPTION_HANDLERS:
|
260 |
+
try:
|
261 |
+
if handler.wants(exception):
|
262 |
+
handler.handle(exception)
|
263 |
+
except: # pylint: disable=bare-except
|
264 |
+
try:
|
265 |
+
# We don't want to stop for exceptions in the exception handlers but
|
266 |
+
# we shouldn't hide them either.
|
267 |
+
logging.error(traceback.format_exc())
|
268 |
+
except: # pylint: disable=bare-except
|
269 |
+
# In case even the logging statement fails, ignore.
|
270 |
+
pass
|
271 |
+
|
272 |
+
|
273 |
+
def run(
|
274 |
+
main,
|
275 |
+
argv=None,
|
276 |
+
flags_parser=parse_flags_with_usage,
|
277 |
+
):
|
278 |
+
"""Begins executing the program.
|
279 |
+
|
280 |
+
Args:
|
281 |
+
main: The main function to execute. It takes an single argument "argv",
|
282 |
+
which is a list of command line arguments with parsed flags removed.
|
283 |
+
The return value is passed to `sys.exit`, and so for example
|
284 |
+
a return value of 0 or None results in a successful termination, whereas
|
285 |
+
a return value of 1 results in abnormal termination.
|
286 |
+
For more details, see https://docs.python.org/3/library/sys#sys.exit
|
287 |
+
argv: A non-empty list of the command line arguments including program name,
|
288 |
+
sys.argv is used if None.
|
289 |
+
flags_parser: Callable[[List[Text]], Any], the function used to parse flags.
|
290 |
+
The return value of this function is passed to `main` untouched.
|
291 |
+
It must guarantee FLAGS is parsed after this function is called.
|
292 |
+
Should be passed as a keyword-only arg which will become mandatory in a
|
293 |
+
future release.
|
294 |
+
- Parses command line flags with the flag module.
|
295 |
+
- If there are any errors, prints usage().
|
296 |
+
- Calls main() with the remaining arguments.
|
297 |
+
- If main() raises a UsageError, prints usage and the error message.
|
298 |
+
"""
|
299 |
+
try:
|
300 |
+
args = _run_init(
|
301 |
+
sys.argv if argv is None else argv,
|
302 |
+
flags_parser,
|
303 |
+
)
|
304 |
+
while _init_callbacks:
|
305 |
+
callback = _init_callbacks.popleft()
|
306 |
+
callback()
|
307 |
+
try:
|
308 |
+
_run_main(main, args)
|
309 |
+
except UsageError as error:
|
310 |
+
usage(shorthelp=True, detailed_error=error, exitcode=error.exitcode)
|
311 |
+
except:
|
312 |
+
exc = sys.exc_info()[1]
|
313 |
+
# Don't try to post-mortem debug successful SystemExits, since those
|
314 |
+
# mean there wasn't actually an error. In particular, the test framework
|
315 |
+
# raises SystemExit(False) even if all tests passed.
|
316 |
+
if isinstance(exc, SystemExit) and not exc.code:
|
317 |
+
raise
|
318 |
+
|
319 |
+
# Check the tty so that we don't hang waiting for input in an
|
320 |
+
# non-interactive scenario.
|
321 |
+
if FLAGS.pdb_post_mortem and sys.stdout.isatty():
|
322 |
+
traceback.print_exc()
|
323 |
+
print()
|
324 |
+
print(' *** Entering post-mortem debugging ***')
|
325 |
+
print()
|
326 |
+
pdb.post_mortem()
|
327 |
+
raise
|
328 |
+
except Exception as e:
|
329 |
+
_call_exception_handlers(e)
|
330 |
+
raise
|
331 |
+
|
332 |
+
# Callbacks which have been deferred until after _run_init has been called.
|
333 |
+
_init_callbacks = collections.deque()
|
334 |
+
|
335 |
+
|
336 |
+
def call_after_init(callback):
|
337 |
+
"""Calls the given callback only once ABSL has finished initialization.
|
338 |
+
|
339 |
+
If ABSL has already finished initialization when ``call_after_init`` is
|
340 |
+
called then the callback is executed immediately, otherwise `callback` is
|
341 |
+
stored to be executed after ``app.run`` has finished initializing (aka. just
|
342 |
+
before the main function is called).
|
343 |
+
|
344 |
+
If called after ``app.run``, this is equivalent to calling ``callback()`` in
|
345 |
+
the caller thread. If called before ``app.run``, callbacks are run
|
346 |
+
sequentially (in an undefined order) in the same thread as ``app.run``.
|
347 |
+
|
348 |
+
Args:
|
349 |
+
callback: a callable to be called once ABSL has finished initialization.
|
350 |
+
This may be immediate if initialization has already finished. It
|
351 |
+
takes no arguments and returns nothing.
|
352 |
+
"""
|
353 |
+
if _run_init.done:
|
354 |
+
callback()
|
355 |
+
else:
|
356 |
+
_init_callbacks.append(callback)
|
357 |
+
|
358 |
+
|
359 |
+
def _run_init(
|
360 |
+
argv,
|
361 |
+
flags_parser,
|
362 |
+
):
|
363 |
+
"""Does one-time initialization and re-parses flags on rerun."""
|
364 |
+
if _run_init.done:
|
365 |
+
return flags_parser(argv)
|
366 |
+
command_name.make_process_name_useful()
|
367 |
+
# Set up absl logging handler.
|
368 |
+
logging.use_absl_handler()
|
369 |
+
args = _register_and_parse_flags_with_usage(
|
370 |
+
argv=argv,
|
371 |
+
flags_parser=flags_parser,
|
372 |
+
)
|
373 |
+
if faulthandler:
|
374 |
+
try:
|
375 |
+
faulthandler.enable()
|
376 |
+
except Exception: # pylint: disable=broad-except
|
377 |
+
# Some tests verify stderr output very closely, so don't print anything.
|
378 |
+
# Disabled faulthandler is a low-impact error.
|
379 |
+
pass
|
380 |
+
_run_init.done = True
|
381 |
+
return args
|
382 |
+
|
383 |
+
|
384 |
+
_run_init.done = False
|
385 |
+
|
386 |
+
|
387 |
+
def usage(shorthelp=False, writeto_stdout=False, detailed_error=None,
|
388 |
+
exitcode=None):
|
389 |
+
"""Writes __main__'s docstring to stderr with some help text.
|
390 |
+
|
391 |
+
Args:
|
392 |
+
shorthelp: bool, if True, prints only flags from the main module,
|
393 |
+
rather than all flags.
|
394 |
+
writeto_stdout: bool, if True, writes help message to stdout,
|
395 |
+
rather than to stderr.
|
396 |
+
detailed_error: str, additional detail about why usage info was presented.
|
397 |
+
exitcode: optional integer, if set, exits with this status code after
|
398 |
+
writing help.
|
399 |
+
"""
|
400 |
+
if writeto_stdout:
|
401 |
+
stdfile = sys.stdout
|
402 |
+
else:
|
403 |
+
stdfile = sys.stderr
|
404 |
+
|
405 |
+
doc = sys.modules['__main__'].__doc__
|
406 |
+
if not doc:
|
407 |
+
doc = '\nUSAGE: %s [flags]\n' % sys.argv[0]
|
408 |
+
doc = flags.text_wrap(doc, indent=' ', firstline_indent='')
|
409 |
+
else:
|
410 |
+
# Replace all '%s' with sys.argv[0], and all '%%' with '%'.
|
411 |
+
num_specifiers = doc.count('%') - 2 * doc.count('%%')
|
412 |
+
try:
|
413 |
+
doc %= (sys.argv[0],) * num_specifiers
|
414 |
+
except (OverflowError, TypeError, ValueError):
|
415 |
+
# Just display the docstring as-is.
|
416 |
+
pass
|
417 |
+
if shorthelp:
|
418 |
+
flag_str = FLAGS.main_module_help()
|
419 |
+
else:
|
420 |
+
flag_str = FLAGS.get_help()
|
421 |
+
try:
|
422 |
+
stdfile.write(doc)
|
423 |
+
if flag_str:
|
424 |
+
stdfile.write('\nflags:\n')
|
425 |
+
stdfile.write(flag_str)
|
426 |
+
stdfile.write('\n')
|
427 |
+
if detailed_error is not None:
|
428 |
+
stdfile.write('\n%s\n' % detailed_error)
|
429 |
+
except IOError as e:
|
430 |
+
# We avoid printing a huge backtrace if we get EPIPE, because
|
431 |
+
# "foo.par --help | less" is a frequent use case.
|
432 |
+
if e.errno != errno.EPIPE:
|
433 |
+
raise
|
434 |
+
if exitcode is not None:
|
435 |
+
sys.exit(exitcode)
|
436 |
+
|
437 |
+
|
438 |
+
class ExceptionHandler(object):
|
439 |
+
"""Base exception handler from which other may inherit."""
|
440 |
+
|
441 |
+
def wants(self, exc):
|
442 |
+
"""Returns whether this handler wants to handle the exception or not.
|
443 |
+
|
444 |
+
This base class returns True for all exceptions by default. Override in
|
445 |
+
subclass if it wants to be more selective.
|
446 |
+
|
447 |
+
Args:
|
448 |
+
exc: Exception, the current exception.
|
449 |
+
"""
|
450 |
+
del exc # Unused.
|
451 |
+
return True
|
452 |
+
|
453 |
+
def handle(self, exc):
|
454 |
+
"""Do something with the current exception.
|
455 |
+
|
456 |
+
Args:
|
457 |
+
exc: Exception, the current exception
|
458 |
+
|
459 |
+
This method must be overridden.
|
460 |
+
"""
|
461 |
+
raise NotImplementedError()
|
462 |
+
|
463 |
+
|
464 |
+
def install_exception_handler(handler):
|
465 |
+
"""Installs an exception handler.
|
466 |
+
|
467 |
+
Args:
|
468 |
+
handler: ExceptionHandler, the exception handler to install.
|
469 |
+
|
470 |
+
Raises:
|
471 |
+
TypeError: Raised when the handler was not of the correct type.
|
472 |
+
|
473 |
+
All installed exception handlers will be called if main() exits via
|
474 |
+
an abnormal exception, i.e. not one of SystemExit, KeyboardInterrupt,
|
475 |
+
FlagsError or UsageError.
|
476 |
+
"""
|
477 |
+
if not isinstance(handler, ExceptionHandler):
|
478 |
+
raise TypeError('handler of type %s does not inherit from ExceptionHandler'
|
479 |
+
% type(handler))
|
480 |
+
EXCEPTION_HANDLERS.append(handler)
|
venv/lib/python3.11/site-packages/absl/app.pyi
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from typing import Any, Callable, Collection, Iterable, List, NoReturn, Optional, Text, TypeVar, Union, overload
|
3 |
+
|
4 |
+
from absl.flags import _flag
|
5 |
+
|
6 |
+
|
7 |
+
_MainArgs = TypeVar('_MainArgs')
|
8 |
+
_Exc = TypeVar('_Exc', bound=Exception)
|
9 |
+
|
10 |
+
|
11 |
+
class ExceptionHandler():
|
12 |
+
|
13 |
+
def wants(self, exc: _Exc) -> bool:
|
14 |
+
...
|
15 |
+
|
16 |
+
def handle(self, exc: _Exc):
|
17 |
+
...
|
18 |
+
|
19 |
+
|
20 |
+
EXCEPTION_HANDLERS: List[ExceptionHandler] = ...
|
21 |
+
|
22 |
+
|
23 |
+
class HelpFlag(_flag.BooleanFlag):
|
24 |
+
def __init__(self):
|
25 |
+
...
|
26 |
+
|
27 |
+
|
28 |
+
class HelpshortFlag(HelpFlag):
|
29 |
+
...
|
30 |
+
|
31 |
+
|
32 |
+
class HelpfullFlag(_flag.BooleanFlag):
|
33 |
+
def __init__(self):
|
34 |
+
...
|
35 |
+
|
36 |
+
|
37 |
+
class HelpXMLFlag(_flag.BooleanFlag):
|
38 |
+
def __init__(self):
|
39 |
+
...
|
40 |
+
|
41 |
+
|
42 |
+
def define_help_flags() -> None:
|
43 |
+
...
|
44 |
+
|
45 |
+
|
46 |
+
@overload
|
47 |
+
def usage(shorthelp: Union[bool, int] = ...,
|
48 |
+
writeto_stdout: Union[bool, int] = ...,
|
49 |
+
detailed_error: Optional[Any] = ...,
|
50 |
+
exitcode: None = ...) -> None:
|
51 |
+
...
|
52 |
+
|
53 |
+
|
54 |
+
@overload
|
55 |
+
def usage(shorthelp: Union[bool, int] = ...,
|
56 |
+
writeto_stdout: Union[bool, int] = ...,
|
57 |
+
detailed_error: Optional[Any] = ...,
|
58 |
+
exitcode: int = ...) -> NoReturn:
|
59 |
+
...
|
60 |
+
|
61 |
+
|
62 |
+
def install_exception_handler(handler: ExceptionHandler) -> None:
|
63 |
+
...
|
64 |
+
|
65 |
+
|
66 |
+
class Error(Exception):
|
67 |
+
...
|
68 |
+
|
69 |
+
|
70 |
+
class UsageError(Error):
|
71 |
+
exitcode: int
|
72 |
+
|
73 |
+
|
74 |
+
def parse_flags_with_usage(args: List[Text]) -> List[Text]:
|
75 |
+
...
|
76 |
+
|
77 |
+
|
78 |
+
def call_after_init(callback: Callable[[], Any]) -> None:
|
79 |
+
...
|
80 |
+
|
81 |
+
|
82 |
+
# Without the flag_parser argument, `main` should require a List[Text].
|
83 |
+
@overload
|
84 |
+
def run(
|
85 |
+
main: Callable[[List[Text]], Any],
|
86 |
+
argv: Optional[List[Text]] = ...,
|
87 |
+
*,
|
88 |
+
) -> NoReturn:
|
89 |
+
...
|
90 |
+
|
91 |
+
|
92 |
+
@overload
|
93 |
+
def run(
|
94 |
+
main: Callable[[_MainArgs], Any],
|
95 |
+
argv: Optional[List[Text]] = ...,
|
96 |
+
*,
|
97 |
+
flags_parser: Callable[[List[Text]], _MainArgs],
|
98 |
+
) -> NoReturn:
|
99 |
+
...
|
venv/lib/python3.11/site-packages/absl/command_name.py
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
|
15 |
+
"""A tiny stand alone library to change the kernel process name on Linux."""
|
16 |
+
|
17 |
+
import os
|
18 |
+
import sys
|
19 |
+
|
20 |
+
# This library must be kept small and stand alone. It is used by small things
|
21 |
+
# that require no extension modules.
|
22 |
+
|
23 |
+
|
24 |
+
def make_process_name_useful():
|
25 |
+
"""Sets the process name to something better than 'python' if possible."""
|
26 |
+
set_kernel_process_name(os.path.basename(sys.argv[0]))
|
27 |
+
|
28 |
+
|
29 |
+
def set_kernel_process_name(name):
|
30 |
+
"""Changes the Kernel's /proc/self/status process name on Linux.
|
31 |
+
|
32 |
+
The kernel name is NOT what will be shown by the ps or top command.
|
33 |
+
It is a 15 character string stored in the kernel's process table that
|
34 |
+
is included in the kernel log when a process is OOM killed.
|
35 |
+
The first 15 bytes of name are used. Non-ASCII unicode is replaced with '?'.
|
36 |
+
|
37 |
+
Does nothing if /proc/self/comm cannot be written or prctl() fails.
|
38 |
+
|
39 |
+
Args:
|
40 |
+
name: bytes|unicode, the Linux kernel's command name to set.
|
41 |
+
"""
|
42 |
+
if not isinstance(name, bytes):
|
43 |
+
name = name.encode('ascii', 'replace')
|
44 |
+
try:
|
45 |
+
# This is preferred to using ctypes to try and call prctl() when possible.
|
46 |
+
with open('/proc/self/comm', 'wb') as proc_comm:
|
47 |
+
proc_comm.write(name[:15])
|
48 |
+
except EnvironmentError:
|
49 |
+
try:
|
50 |
+
import ctypes # pylint: disable=g-import-not-at-top
|
51 |
+
except ImportError:
|
52 |
+
return # No ctypes.
|
53 |
+
try:
|
54 |
+
libc = ctypes.CDLL('libc.so.6')
|
55 |
+
except EnvironmentError:
|
56 |
+
return # No libc.so.6.
|
57 |
+
pr_set_name = ctypes.c_ulong(15) # linux/prctl.h PR_SET_NAME value.
|
58 |
+
zero = ctypes.c_ulong(0)
|
59 |
+
try:
|
60 |
+
libc.prctl(pr_set_name, name, zero, zero, zero)
|
61 |
+
# Ignore the prctl return value. Nothing we can do if it errored.
|
62 |
+
except AttributeError:
|
63 |
+
return # No prctl.
|
venv/lib/python3.11/site-packages/absl/flags/__init__.py
ADDED
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
"""This package is used to define and parse command line flags.
|
15 |
+
|
16 |
+
This package defines a *distributed* flag-definition policy: rather than
|
17 |
+
an application having to define all flags in or near main(), each Python
|
18 |
+
module defines flags that are useful to it. When one Python module
|
19 |
+
imports another, it gains access to the other's flags. (This is
|
20 |
+
implemented by having all modules share a common, global registry object
|
21 |
+
containing all the flag information.)
|
22 |
+
|
23 |
+
Flags are defined through the use of one of the DEFINE_xxx functions.
|
24 |
+
The specific function used determines how the flag is parsed, checked,
|
25 |
+
and optionally type-converted, when it's seen on the command line.
|
26 |
+
"""
|
27 |
+
|
28 |
+
import getopt
|
29 |
+
import os
|
30 |
+
import re
|
31 |
+
import sys
|
32 |
+
import types
|
33 |
+
import warnings
|
34 |
+
|
35 |
+
from absl.flags import _argument_parser
|
36 |
+
from absl.flags import _defines
|
37 |
+
from absl.flags import _exceptions
|
38 |
+
from absl.flags import _flag
|
39 |
+
from absl.flags import _flagvalues
|
40 |
+
from absl.flags import _helpers
|
41 |
+
from absl.flags import _validators
|
42 |
+
|
43 |
+
__all__ = (
|
44 |
+
'DEFINE',
|
45 |
+
'DEFINE_flag',
|
46 |
+
'DEFINE_string',
|
47 |
+
'DEFINE_boolean',
|
48 |
+
'DEFINE_bool',
|
49 |
+
'DEFINE_float',
|
50 |
+
'DEFINE_integer',
|
51 |
+
'DEFINE_enum',
|
52 |
+
'DEFINE_enum_class',
|
53 |
+
'DEFINE_list',
|
54 |
+
'DEFINE_spaceseplist',
|
55 |
+
'DEFINE_multi',
|
56 |
+
'DEFINE_multi_string',
|
57 |
+
'DEFINE_multi_integer',
|
58 |
+
'DEFINE_multi_float',
|
59 |
+
'DEFINE_multi_enum',
|
60 |
+
'DEFINE_multi_enum_class',
|
61 |
+
'DEFINE_alias',
|
62 |
+
# Flag validators.
|
63 |
+
'register_validator',
|
64 |
+
'validator',
|
65 |
+
'register_multi_flags_validator',
|
66 |
+
'multi_flags_validator',
|
67 |
+
'mark_flag_as_required',
|
68 |
+
'mark_flags_as_required',
|
69 |
+
'mark_flags_as_mutual_exclusive',
|
70 |
+
'mark_bool_flags_as_mutual_exclusive',
|
71 |
+
# Flag modifiers.
|
72 |
+
'set_default',
|
73 |
+
'override_value',
|
74 |
+
# Key flag related functions.
|
75 |
+
'declare_key_flag',
|
76 |
+
'adopt_module_key_flags',
|
77 |
+
'disclaim_key_flags',
|
78 |
+
# Module exceptions.
|
79 |
+
'Error',
|
80 |
+
'CantOpenFlagFileError',
|
81 |
+
'DuplicateFlagError',
|
82 |
+
'IllegalFlagValueError',
|
83 |
+
'UnrecognizedFlagError',
|
84 |
+
'UnparsedFlagAccessError',
|
85 |
+
'ValidationError',
|
86 |
+
'FlagNameConflictsWithMethodError',
|
87 |
+
# Public classes.
|
88 |
+
'Flag',
|
89 |
+
'BooleanFlag',
|
90 |
+
'EnumFlag',
|
91 |
+
'EnumClassFlag',
|
92 |
+
'MultiFlag',
|
93 |
+
'MultiEnumClassFlag',
|
94 |
+
'FlagHolder',
|
95 |
+
'FlagValues',
|
96 |
+
'ArgumentParser',
|
97 |
+
'BooleanParser',
|
98 |
+
'EnumParser',
|
99 |
+
'EnumClassParser',
|
100 |
+
'ArgumentSerializer',
|
101 |
+
'FloatParser',
|
102 |
+
'IntegerParser',
|
103 |
+
'BaseListParser',
|
104 |
+
'ListParser',
|
105 |
+
'ListSerializer',
|
106 |
+
'EnumClassListSerializer',
|
107 |
+
'CsvListSerializer',
|
108 |
+
'WhitespaceSeparatedListParser',
|
109 |
+
'EnumClassSerializer',
|
110 |
+
# Helper functions.
|
111 |
+
'get_help_width',
|
112 |
+
'text_wrap',
|
113 |
+
'flag_dict_to_args',
|
114 |
+
'doc_to_help',
|
115 |
+
# The global FlagValues instance.
|
116 |
+
'FLAGS',
|
117 |
+
)
|
118 |
+
|
119 |
+
# Initialize the FLAGS_MODULE as early as possible.
|
120 |
+
# It's only used by adopt_module_key_flags to take SPECIAL_FLAGS into account.
|
121 |
+
_helpers.FLAGS_MODULE = sys.modules[__name__]
|
122 |
+
|
123 |
+
# Add current module to disclaimed module ids.
|
124 |
+
_helpers.disclaim_module_ids.add(id(sys.modules[__name__]))
|
125 |
+
|
126 |
+
# DEFINE functions. They are explained in more details in the module doc string.
|
127 |
+
# pylint: disable=invalid-name
|
128 |
+
DEFINE = _defines.DEFINE
|
129 |
+
DEFINE_flag = _defines.DEFINE_flag
|
130 |
+
DEFINE_string = _defines.DEFINE_string
|
131 |
+
DEFINE_boolean = _defines.DEFINE_boolean
|
132 |
+
DEFINE_bool = DEFINE_boolean # Match C++ API.
|
133 |
+
DEFINE_float = _defines.DEFINE_float
|
134 |
+
DEFINE_integer = _defines.DEFINE_integer
|
135 |
+
DEFINE_enum = _defines.DEFINE_enum
|
136 |
+
DEFINE_enum_class = _defines.DEFINE_enum_class
|
137 |
+
DEFINE_list = _defines.DEFINE_list
|
138 |
+
DEFINE_spaceseplist = _defines.DEFINE_spaceseplist
|
139 |
+
DEFINE_multi = _defines.DEFINE_multi
|
140 |
+
DEFINE_multi_string = _defines.DEFINE_multi_string
|
141 |
+
DEFINE_multi_integer = _defines.DEFINE_multi_integer
|
142 |
+
DEFINE_multi_float = _defines.DEFINE_multi_float
|
143 |
+
DEFINE_multi_enum = _defines.DEFINE_multi_enum
|
144 |
+
DEFINE_multi_enum_class = _defines.DEFINE_multi_enum_class
|
145 |
+
DEFINE_alias = _defines.DEFINE_alias
|
146 |
+
# pylint: enable=invalid-name
|
147 |
+
|
148 |
+
# Flag validators.
|
149 |
+
register_validator = _validators.register_validator
|
150 |
+
validator = _validators.validator
|
151 |
+
register_multi_flags_validator = _validators.register_multi_flags_validator
|
152 |
+
multi_flags_validator = _validators.multi_flags_validator
|
153 |
+
mark_flag_as_required = _validators.mark_flag_as_required
|
154 |
+
mark_flags_as_required = _validators.mark_flags_as_required
|
155 |
+
mark_flags_as_mutual_exclusive = _validators.mark_flags_as_mutual_exclusive
|
156 |
+
mark_bool_flags_as_mutual_exclusive = _validators.mark_bool_flags_as_mutual_exclusive
|
157 |
+
|
158 |
+
# Flag modifiers.
|
159 |
+
set_default = _defines.set_default
|
160 |
+
override_value = _defines.override_value
|
161 |
+
|
162 |
+
# Key flag related functions.
|
163 |
+
declare_key_flag = _defines.declare_key_flag
|
164 |
+
adopt_module_key_flags = _defines.adopt_module_key_flags
|
165 |
+
disclaim_key_flags = _defines.disclaim_key_flags
|
166 |
+
|
167 |
+
# Module exceptions.
|
168 |
+
# pylint: disable=invalid-name
|
169 |
+
Error = _exceptions.Error
|
170 |
+
CantOpenFlagFileError = _exceptions.CantOpenFlagFileError
|
171 |
+
DuplicateFlagError = _exceptions.DuplicateFlagError
|
172 |
+
IllegalFlagValueError = _exceptions.IllegalFlagValueError
|
173 |
+
UnrecognizedFlagError = _exceptions.UnrecognizedFlagError
|
174 |
+
UnparsedFlagAccessError = _exceptions.UnparsedFlagAccessError
|
175 |
+
ValidationError = _exceptions.ValidationError
|
176 |
+
FlagNameConflictsWithMethodError = _exceptions.FlagNameConflictsWithMethodError
|
177 |
+
|
178 |
+
# Public classes.
|
179 |
+
Flag = _flag.Flag
|
180 |
+
BooleanFlag = _flag.BooleanFlag
|
181 |
+
EnumFlag = _flag.EnumFlag
|
182 |
+
EnumClassFlag = _flag.EnumClassFlag
|
183 |
+
MultiFlag = _flag.MultiFlag
|
184 |
+
MultiEnumClassFlag = _flag.MultiEnumClassFlag
|
185 |
+
FlagHolder = _flagvalues.FlagHolder
|
186 |
+
FlagValues = _flagvalues.FlagValues
|
187 |
+
ArgumentParser = _argument_parser.ArgumentParser
|
188 |
+
BooleanParser = _argument_parser.BooleanParser
|
189 |
+
EnumParser = _argument_parser.EnumParser
|
190 |
+
EnumClassParser = _argument_parser.EnumClassParser
|
191 |
+
ArgumentSerializer = _argument_parser.ArgumentSerializer
|
192 |
+
FloatParser = _argument_parser.FloatParser
|
193 |
+
IntegerParser = _argument_parser.IntegerParser
|
194 |
+
BaseListParser = _argument_parser.BaseListParser
|
195 |
+
ListParser = _argument_parser.ListParser
|
196 |
+
ListSerializer = _argument_parser.ListSerializer
|
197 |
+
EnumClassListSerializer = _argument_parser.EnumClassListSerializer
|
198 |
+
CsvListSerializer = _argument_parser.CsvListSerializer
|
199 |
+
WhitespaceSeparatedListParser = _argument_parser.WhitespaceSeparatedListParser
|
200 |
+
EnumClassSerializer = _argument_parser.EnumClassSerializer
|
201 |
+
# pylint: enable=invalid-name
|
202 |
+
|
203 |
+
# Helper functions.
|
204 |
+
get_help_width = _helpers.get_help_width
|
205 |
+
text_wrap = _helpers.text_wrap
|
206 |
+
flag_dict_to_args = _helpers.flag_dict_to_args
|
207 |
+
doc_to_help = _helpers.doc_to_help
|
208 |
+
|
209 |
+
# Special flags.
|
210 |
+
_helpers.SPECIAL_FLAGS = FlagValues()
|
211 |
+
|
212 |
+
DEFINE_string(
|
213 |
+
'flagfile', '',
|
214 |
+
'Insert flag definitions from the given file into the command line.',
|
215 |
+
_helpers.SPECIAL_FLAGS) # pytype: disable=wrong-arg-types
|
216 |
+
|
217 |
+
DEFINE_string('undefok', '',
|
218 |
+
'comma-separated list of flag names that it is okay to specify '
|
219 |
+
'on the command line even if the program does not define a flag '
|
220 |
+
'with that name. IMPORTANT: flags in this list that have '
|
221 |
+
'arguments MUST use the --flag=value format.',
|
222 |
+
_helpers.SPECIAL_FLAGS) # pytype: disable=wrong-arg-types
|
223 |
+
|
224 |
+
#: The global FlagValues instance.
|
225 |
+
FLAGS = _flagvalues.FLAGS
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (5.18 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_argument_parser.cpython-311.pyc
ADDED
Binary file (35.3 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_defines.cpython-311.pyc
ADDED
Binary file (55.7 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_exceptions.cpython-311.pyc
ADDED
Binary file (5.29 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_flag.cpython-311.pyc
ADDED
Binary file (28.5 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_flagvalues.cpython-311.pyc
ADDED
Binary file (67.6 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_helpers.cpython-311.pyc
ADDED
Binary file (16.2 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_validators.cpython-311.pyc
ADDED
Binary file (16.2 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/_validators_classes.cpython-311.pyc
ADDED
Binary file (8.52 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/__pycache__/argparse_flags.cpython-311.pyc
ADDED
Binary file (16.7 kB). View file
|
|
venv/lib/python3.11/site-packages/absl/flags/_argument_parser.py
ADDED
@@ -0,0 +1,638 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
|
15 |
+
"""Contains base classes used to parse and convert arguments.
|
16 |
+
|
17 |
+
Do NOT import this module directly. Import the flags package and use the
|
18 |
+
aliases defined at the package level instead.
|
19 |
+
"""
|
20 |
+
|
21 |
+
import collections
|
22 |
+
import csv
|
23 |
+
import enum
|
24 |
+
import io
|
25 |
+
import string
|
26 |
+
from typing import Generic, List, Iterable, Optional, Sequence, Text, Type, TypeVar, Union
|
27 |
+
from xml.dom import minidom
|
28 |
+
|
29 |
+
from absl.flags import _helpers
|
30 |
+
|
31 |
+
_T = TypeVar('_T')
|
32 |
+
_ET = TypeVar('_ET', bound=enum.Enum)
|
33 |
+
_N = TypeVar('_N', int, float)
|
34 |
+
|
35 |
+
|
36 |
+
def _is_integer_type(instance):
|
37 |
+
"""Returns True if instance is an integer, and not a bool."""
|
38 |
+
return (isinstance(instance, int) and
|
39 |
+
not isinstance(instance, bool))
|
40 |
+
|
41 |
+
|
42 |
+
class _ArgumentParserCache(type):
|
43 |
+
"""Metaclass used to cache and share argument parsers among flags."""
|
44 |
+
|
45 |
+
_instances = {}
|
46 |
+
|
47 |
+
def __call__(cls, *args, **kwargs):
|
48 |
+
"""Returns an instance of the argument parser cls.
|
49 |
+
|
50 |
+
This method overrides behavior of the __new__ methods in
|
51 |
+
all subclasses of ArgumentParser (inclusive). If an instance
|
52 |
+
for cls with the same set of arguments exists, this instance is
|
53 |
+
returned, otherwise a new instance is created.
|
54 |
+
|
55 |
+
If any keyword arguments are defined, or the values in args
|
56 |
+
are not hashable, this method always returns a new instance of
|
57 |
+
cls.
|
58 |
+
|
59 |
+
Args:
|
60 |
+
*args: Positional initializer arguments.
|
61 |
+
**kwargs: Initializer keyword arguments.
|
62 |
+
|
63 |
+
Returns:
|
64 |
+
An instance of cls, shared or new.
|
65 |
+
"""
|
66 |
+
if kwargs:
|
67 |
+
return type.__call__(cls, *args, **kwargs)
|
68 |
+
else:
|
69 |
+
instances = cls._instances
|
70 |
+
key = (cls,) + tuple(args)
|
71 |
+
try:
|
72 |
+
return instances[key]
|
73 |
+
except KeyError:
|
74 |
+
# No cache entry for key exists, create a new one.
|
75 |
+
return instances.setdefault(key, type.__call__(cls, *args))
|
76 |
+
except TypeError:
|
77 |
+
# An object in args cannot be hashed, always return
|
78 |
+
# a new instance.
|
79 |
+
return type.__call__(cls, *args)
|
80 |
+
|
81 |
+
|
82 |
+
class ArgumentParser(Generic[_T], metaclass=_ArgumentParserCache):
|
83 |
+
"""Base class used to parse and convert arguments.
|
84 |
+
|
85 |
+
The :meth:`parse` method checks to make sure that the string argument is a
|
86 |
+
legal value and convert it to a native type. If the value cannot be
|
87 |
+
converted, it should throw a ``ValueError`` exception with a human
|
88 |
+
readable explanation of why the value is illegal.
|
89 |
+
|
90 |
+
Subclasses should also define a syntactic_help string which may be
|
91 |
+
presented to the user to describe the form of the legal values.
|
92 |
+
|
93 |
+
Argument parser classes must be stateless, since instances are cached
|
94 |
+
and shared between flags. Initializer arguments are allowed, but all
|
95 |
+
member variables must be derived from initializer arguments only.
|
96 |
+
"""
|
97 |
+
|
98 |
+
syntactic_help: Text = ''
|
99 |
+
|
100 |
+
def parse(self, argument: Text) -> Optional[_T]:
|
101 |
+
"""Parses the string argument and returns the native value.
|
102 |
+
|
103 |
+
By default it returns its argument unmodified.
|
104 |
+
|
105 |
+
Args:
|
106 |
+
argument: string argument passed in the commandline.
|
107 |
+
|
108 |
+
Raises:
|
109 |
+
ValueError: Raised when it fails to parse the argument.
|
110 |
+
TypeError: Raised when the argument has the wrong type.
|
111 |
+
|
112 |
+
Returns:
|
113 |
+
The parsed value in native type.
|
114 |
+
"""
|
115 |
+
if not isinstance(argument, str):
|
116 |
+
raise TypeError('flag value must be a string, found "{}"'.format(
|
117 |
+
type(argument)))
|
118 |
+
return argument
|
119 |
+
|
120 |
+
def flag_type(self) -> Text:
|
121 |
+
"""Returns a string representing the type of the flag."""
|
122 |
+
return 'string'
|
123 |
+
|
124 |
+
def _custom_xml_dom_elements(
|
125 |
+
self, doc: minidom.Document
|
126 |
+
) -> List[minidom.Element]:
|
127 |
+
"""Returns a list of minidom.Element to add additional flag information.
|
128 |
+
|
129 |
+
Args:
|
130 |
+
doc: minidom.Document, the DOM document it should create nodes from.
|
131 |
+
"""
|
132 |
+
del doc # Unused.
|
133 |
+
return []
|
134 |
+
|
135 |
+
|
136 |
+
class ArgumentSerializer(Generic[_T]):
|
137 |
+
"""Base class for generating string representations of a flag value."""
|
138 |
+
|
139 |
+
def serialize(self, value: _T) -> Text:
|
140 |
+
"""Returns a serialized string of the value."""
|
141 |
+
return str(value)
|
142 |
+
|
143 |
+
|
144 |
+
class NumericParser(ArgumentParser[_N]):
|
145 |
+
"""Parser of numeric values.
|
146 |
+
|
147 |
+
Parsed value may be bounded to a given upper and lower bound.
|
148 |
+
"""
|
149 |
+
|
150 |
+
lower_bound: Optional[_N]
|
151 |
+
upper_bound: Optional[_N]
|
152 |
+
|
153 |
+
def is_outside_bounds(self, val: _N) -> bool:
|
154 |
+
"""Returns whether the value is outside the bounds or not."""
|
155 |
+
return ((self.lower_bound is not None and val < self.lower_bound) or
|
156 |
+
(self.upper_bound is not None and val > self.upper_bound))
|
157 |
+
|
158 |
+
def parse(self, argument: Text) -> _N:
|
159 |
+
"""See base class."""
|
160 |
+
val = self.convert(argument)
|
161 |
+
if self.is_outside_bounds(val):
|
162 |
+
raise ValueError('%s is not %s' % (val, self.syntactic_help))
|
163 |
+
return val
|
164 |
+
|
165 |
+
def _custom_xml_dom_elements(
|
166 |
+
self, doc: minidom.Document
|
167 |
+
) -> List[minidom.Element]:
|
168 |
+
elements = []
|
169 |
+
if self.lower_bound is not None:
|
170 |
+
elements.append(_helpers.create_xml_dom_element(
|
171 |
+
doc, 'lower_bound', self.lower_bound))
|
172 |
+
if self.upper_bound is not None:
|
173 |
+
elements.append(_helpers.create_xml_dom_element(
|
174 |
+
doc, 'upper_bound', self.upper_bound))
|
175 |
+
return elements
|
176 |
+
|
177 |
+
def convert(self, argument: Text) -> _N:
|
178 |
+
"""Returns the correct numeric value of argument.
|
179 |
+
|
180 |
+
Subclass must implement this method, and raise TypeError if argument is not
|
181 |
+
string or has the right numeric type.
|
182 |
+
|
183 |
+
Args:
|
184 |
+
argument: string argument passed in the commandline, or the numeric type.
|
185 |
+
|
186 |
+
Raises:
|
187 |
+
TypeError: Raised when argument is not a string or the right numeric type.
|
188 |
+
ValueError: Raised when failed to convert argument to the numeric value.
|
189 |
+
"""
|
190 |
+
raise NotImplementedError
|
191 |
+
|
192 |
+
|
193 |
+
class FloatParser(NumericParser[float]):
|
194 |
+
"""Parser of floating point values.
|
195 |
+
|
196 |
+
Parsed value may be bounded to a given upper and lower bound.
|
197 |
+
"""
|
198 |
+
number_article = 'a'
|
199 |
+
number_name = 'number'
|
200 |
+
syntactic_help = ' '.join((number_article, number_name))
|
201 |
+
|
202 |
+
def __init__(
|
203 |
+
self,
|
204 |
+
lower_bound: Optional[float] = None,
|
205 |
+
upper_bound: Optional[float] = None,
|
206 |
+
) -> None:
|
207 |
+
super(FloatParser, self).__init__()
|
208 |
+
self.lower_bound = lower_bound
|
209 |
+
self.upper_bound = upper_bound
|
210 |
+
sh = self.syntactic_help
|
211 |
+
if lower_bound is not None and upper_bound is not None:
|
212 |
+
sh = ('%s in the range [%s, %s]' % (sh, lower_bound, upper_bound))
|
213 |
+
elif lower_bound == 0:
|
214 |
+
sh = 'a non-negative %s' % self.number_name
|
215 |
+
elif upper_bound == 0:
|
216 |
+
sh = 'a non-positive %s' % self.number_name
|
217 |
+
elif upper_bound is not None:
|
218 |
+
sh = '%s <= %s' % (self.number_name, upper_bound)
|
219 |
+
elif lower_bound is not None:
|
220 |
+
sh = '%s >= %s' % (self.number_name, lower_bound)
|
221 |
+
self.syntactic_help = sh
|
222 |
+
|
223 |
+
def convert(self, argument: Union[int, float, str]) -> float:
|
224 |
+
"""Returns the float value of argument."""
|
225 |
+
if (_is_integer_type(argument) or isinstance(argument, float) or
|
226 |
+
isinstance(argument, str)):
|
227 |
+
return float(argument)
|
228 |
+
else:
|
229 |
+
raise TypeError(
|
230 |
+
'Expect argument to be a string, int, or float, found {}'.format(
|
231 |
+
type(argument)))
|
232 |
+
|
233 |
+
def flag_type(self) -> Text:
|
234 |
+
"""See base class."""
|
235 |
+
return 'float'
|
236 |
+
|
237 |
+
|
238 |
+
class IntegerParser(NumericParser[int]):
|
239 |
+
"""Parser of an integer value.
|
240 |
+
|
241 |
+
Parsed value may be bounded to a given upper and lower bound.
|
242 |
+
"""
|
243 |
+
number_article = 'an'
|
244 |
+
number_name = 'integer'
|
245 |
+
syntactic_help = ' '.join((number_article, number_name))
|
246 |
+
|
247 |
+
def __init__(
|
248 |
+
self, lower_bound: Optional[int] = None, upper_bound: Optional[int] = None
|
249 |
+
) -> None:
|
250 |
+
super(IntegerParser, self).__init__()
|
251 |
+
self.lower_bound = lower_bound
|
252 |
+
self.upper_bound = upper_bound
|
253 |
+
sh = self.syntactic_help
|
254 |
+
if lower_bound is not None and upper_bound is not None:
|
255 |
+
sh = ('%s in the range [%s, %s]' % (sh, lower_bound, upper_bound))
|
256 |
+
elif lower_bound == 1:
|
257 |
+
sh = 'a positive %s' % self.number_name
|
258 |
+
elif upper_bound == -1:
|
259 |
+
sh = 'a negative %s' % self.number_name
|
260 |
+
elif lower_bound == 0:
|
261 |
+
sh = 'a non-negative %s' % self.number_name
|
262 |
+
elif upper_bound == 0:
|
263 |
+
sh = 'a non-positive %s' % self.number_name
|
264 |
+
elif upper_bound is not None:
|
265 |
+
sh = '%s <= %s' % (self.number_name, upper_bound)
|
266 |
+
elif lower_bound is not None:
|
267 |
+
sh = '%s >= %s' % (self.number_name, lower_bound)
|
268 |
+
self.syntactic_help = sh
|
269 |
+
|
270 |
+
def convert(self, argument: Union[int, Text]) -> int:
|
271 |
+
"""Returns the int value of argument."""
|
272 |
+
if _is_integer_type(argument):
|
273 |
+
return argument
|
274 |
+
elif isinstance(argument, str):
|
275 |
+
base = 10
|
276 |
+
if len(argument) > 2 and argument[0] == '0':
|
277 |
+
if argument[1] == 'o':
|
278 |
+
base = 8
|
279 |
+
elif argument[1] == 'x':
|
280 |
+
base = 16
|
281 |
+
return int(argument, base)
|
282 |
+
else:
|
283 |
+
raise TypeError('Expect argument to be a string or int, found {}'.format(
|
284 |
+
type(argument)))
|
285 |
+
|
286 |
+
def flag_type(self) -> Text:
|
287 |
+
"""See base class."""
|
288 |
+
return 'int'
|
289 |
+
|
290 |
+
|
291 |
+
class BooleanParser(ArgumentParser[bool]):
|
292 |
+
"""Parser of boolean values."""
|
293 |
+
|
294 |
+
def parse(self, argument: Union[Text, int]) -> bool:
|
295 |
+
"""See base class."""
|
296 |
+
if isinstance(argument, str):
|
297 |
+
if argument.lower() in ('true', 't', '1'):
|
298 |
+
return True
|
299 |
+
elif argument.lower() in ('false', 'f', '0'):
|
300 |
+
return False
|
301 |
+
else:
|
302 |
+
raise ValueError('Non-boolean argument to boolean flag', argument)
|
303 |
+
elif isinstance(argument, int):
|
304 |
+
# Only allow bool or integer 0, 1.
|
305 |
+
# Note that float 1.0 == True, 0.0 == False.
|
306 |
+
bool_value = bool(argument)
|
307 |
+
if argument == bool_value:
|
308 |
+
return bool_value
|
309 |
+
else:
|
310 |
+
raise ValueError('Non-boolean argument to boolean flag', argument)
|
311 |
+
|
312 |
+
raise TypeError('Non-boolean argument to boolean flag', argument)
|
313 |
+
|
314 |
+
def flag_type(self) -> Text:
|
315 |
+
"""See base class."""
|
316 |
+
return 'bool'
|
317 |
+
|
318 |
+
|
319 |
+
class EnumParser(ArgumentParser[Text]):
|
320 |
+
"""Parser of a string enum value (a string value from a given set)."""
|
321 |
+
|
322 |
+
def __init__(
|
323 |
+
self, enum_values: Iterable[Text], case_sensitive: bool = True
|
324 |
+
) -> None:
|
325 |
+
"""Initializes EnumParser.
|
326 |
+
|
327 |
+
Args:
|
328 |
+
enum_values: [str], a non-empty list of string values in the enum.
|
329 |
+
case_sensitive: bool, whether or not the enum is to be case-sensitive.
|
330 |
+
|
331 |
+
Raises:
|
332 |
+
ValueError: When enum_values is empty.
|
333 |
+
"""
|
334 |
+
if not enum_values:
|
335 |
+
raise ValueError(
|
336 |
+
'enum_values cannot be empty, found "{}"'.format(enum_values))
|
337 |
+
if isinstance(enum_values, str):
|
338 |
+
raise ValueError(
|
339 |
+
'enum_values cannot be a str, found "{}"'.format(enum_values)
|
340 |
+
)
|
341 |
+
super(EnumParser, self).__init__()
|
342 |
+
self.enum_values = list(enum_values)
|
343 |
+
self.case_sensitive = case_sensitive
|
344 |
+
|
345 |
+
def parse(self, argument: Text) -> Text:
|
346 |
+
"""Determines validity of argument and returns the correct element of enum.
|
347 |
+
|
348 |
+
Args:
|
349 |
+
argument: str, the supplied flag value.
|
350 |
+
|
351 |
+
Returns:
|
352 |
+
The first matching element from enum_values.
|
353 |
+
|
354 |
+
Raises:
|
355 |
+
ValueError: Raised when argument didn't match anything in enum.
|
356 |
+
"""
|
357 |
+
if self.case_sensitive:
|
358 |
+
if argument not in self.enum_values:
|
359 |
+
raise ValueError('value should be one of <%s>' %
|
360 |
+
'|'.join(self.enum_values))
|
361 |
+
else:
|
362 |
+
return argument
|
363 |
+
else:
|
364 |
+
if argument.upper() not in [value.upper() for value in self.enum_values]:
|
365 |
+
raise ValueError('value should be one of <%s>' %
|
366 |
+
'|'.join(self.enum_values))
|
367 |
+
else:
|
368 |
+
return [value for value in self.enum_values
|
369 |
+
if value.upper() == argument.upper()][0]
|
370 |
+
|
371 |
+
def flag_type(self) -> Text:
|
372 |
+
"""See base class."""
|
373 |
+
return 'string enum'
|
374 |
+
|
375 |
+
|
376 |
+
class EnumClassParser(ArgumentParser[_ET]):
|
377 |
+
"""Parser of an Enum class member."""
|
378 |
+
|
379 |
+
def __init__(
|
380 |
+
self, enum_class: Type[_ET], case_sensitive: bool = True
|
381 |
+
) -> None:
|
382 |
+
"""Initializes EnumParser.
|
383 |
+
|
384 |
+
Args:
|
385 |
+
enum_class: class, the Enum class with all possible flag values.
|
386 |
+
case_sensitive: bool, whether or not the enum is to be case-sensitive. If
|
387 |
+
False, all member names must be unique when case is ignored.
|
388 |
+
|
389 |
+
Raises:
|
390 |
+
TypeError: When enum_class is not a subclass of Enum.
|
391 |
+
ValueError: When enum_class is empty.
|
392 |
+
"""
|
393 |
+
if not issubclass(enum_class, enum.Enum):
|
394 |
+
raise TypeError('{} is not a subclass of Enum.'.format(enum_class))
|
395 |
+
if not enum_class.__members__:
|
396 |
+
raise ValueError('enum_class cannot be empty, but "{}" is empty.'
|
397 |
+
.format(enum_class))
|
398 |
+
if not case_sensitive:
|
399 |
+
members = collections.Counter(
|
400 |
+
name.lower() for name in enum_class.__members__)
|
401 |
+
duplicate_keys = {
|
402 |
+
member for member, count in members.items() if count > 1
|
403 |
+
}
|
404 |
+
if duplicate_keys:
|
405 |
+
raise ValueError(
|
406 |
+
'Duplicate enum values for {} using case_sensitive=False'.format(
|
407 |
+
duplicate_keys))
|
408 |
+
|
409 |
+
super(EnumClassParser, self).__init__()
|
410 |
+
self.enum_class = enum_class
|
411 |
+
self._case_sensitive = case_sensitive
|
412 |
+
if case_sensitive:
|
413 |
+
self._member_names = tuple(enum_class.__members__)
|
414 |
+
else:
|
415 |
+
self._member_names = tuple(
|
416 |
+
name.lower() for name in enum_class.__members__)
|
417 |
+
|
418 |
+
@property
|
419 |
+
def member_names(self) -> Sequence[Text]:
|
420 |
+
"""The accepted enum names, in lowercase if not case sensitive."""
|
421 |
+
return self._member_names
|
422 |
+
|
423 |
+
def parse(self, argument: Union[_ET, Text]) -> _ET:
|
424 |
+
"""Determines validity of argument and returns the correct element of enum.
|
425 |
+
|
426 |
+
Args:
|
427 |
+
argument: str or Enum class member, the supplied flag value.
|
428 |
+
|
429 |
+
Returns:
|
430 |
+
The first matching Enum class member in Enum class.
|
431 |
+
|
432 |
+
Raises:
|
433 |
+
ValueError: Raised when argument didn't match anything in enum.
|
434 |
+
"""
|
435 |
+
if isinstance(argument, self.enum_class):
|
436 |
+
return argument # pytype: disable=bad-return-type
|
437 |
+
elif not isinstance(argument, str):
|
438 |
+
raise ValueError(
|
439 |
+
'{} is not an enum member or a name of a member in {}'.format(
|
440 |
+
argument, self.enum_class))
|
441 |
+
key = EnumParser(
|
442 |
+
self._member_names, case_sensitive=self._case_sensitive).parse(argument)
|
443 |
+
if self._case_sensitive:
|
444 |
+
return self.enum_class[key]
|
445 |
+
else:
|
446 |
+
# If EnumParser.parse() return a value, we're guaranteed to find it
|
447 |
+
# as a member of the class
|
448 |
+
return next(value for name, value in self.enum_class.__members__.items()
|
449 |
+
if name.lower() == key.lower())
|
450 |
+
|
451 |
+
def flag_type(self) -> Text:
|
452 |
+
"""See base class."""
|
453 |
+
return 'enum class'
|
454 |
+
|
455 |
+
|
456 |
+
class ListSerializer(Generic[_T], ArgumentSerializer[List[_T]]):
|
457 |
+
|
458 |
+
def __init__(self, list_sep: Text) -> None:
|
459 |
+
self.list_sep = list_sep
|
460 |
+
|
461 |
+
def serialize(self, value: List[_T]) -> Text:
|
462 |
+
"""See base class."""
|
463 |
+
return self.list_sep.join([str(x) for x in value])
|
464 |
+
|
465 |
+
|
466 |
+
class EnumClassListSerializer(ListSerializer[_ET]):
|
467 |
+
"""A serializer for :class:`MultiEnumClass` flags.
|
468 |
+
|
469 |
+
This serializer simply joins the output of `EnumClassSerializer` using a
|
470 |
+
provided separator.
|
471 |
+
"""
|
472 |
+
|
473 |
+
def __init__(self, list_sep: Text, **kwargs) -> None:
|
474 |
+
"""Initializes EnumClassListSerializer.
|
475 |
+
|
476 |
+
Args:
|
477 |
+
list_sep: String to be used as a separator when serializing
|
478 |
+
**kwargs: Keyword arguments to the `EnumClassSerializer` used to serialize
|
479 |
+
individual values.
|
480 |
+
"""
|
481 |
+
super(EnumClassListSerializer, self).__init__(list_sep)
|
482 |
+
self._element_serializer = EnumClassSerializer(**kwargs)
|
483 |
+
|
484 |
+
def serialize(self, value: Union[_ET, List[_ET]]) -> Text:
|
485 |
+
"""See base class."""
|
486 |
+
if isinstance(value, list):
|
487 |
+
return self.list_sep.join(
|
488 |
+
self._element_serializer.serialize(x) for x in value)
|
489 |
+
else:
|
490 |
+
return self._element_serializer.serialize(value)
|
491 |
+
|
492 |
+
|
493 |
+
class CsvListSerializer(ListSerializer[Text]):
|
494 |
+
|
495 |
+
def serialize(self, value: List[Text]) -> Text:
|
496 |
+
"""Serializes a list as a CSV string or unicode."""
|
497 |
+
output = io.StringIO()
|
498 |
+
writer = csv.writer(output, delimiter=self.list_sep)
|
499 |
+
writer.writerow([str(x) for x in value])
|
500 |
+
serialized_value = output.getvalue().strip()
|
501 |
+
|
502 |
+
# We need the returned value to be pure ascii or Unicodes so that
|
503 |
+
# when the xml help is generated they are usefully encodable.
|
504 |
+
return str(serialized_value)
|
505 |
+
|
506 |
+
|
507 |
+
class EnumClassSerializer(ArgumentSerializer[_ET]):
|
508 |
+
"""Class for generating string representations of an enum class flag value."""
|
509 |
+
|
510 |
+
def __init__(self, lowercase: bool) -> None:
|
511 |
+
"""Initializes EnumClassSerializer.
|
512 |
+
|
513 |
+
Args:
|
514 |
+
lowercase: If True, enum member names are lowercased during serialization.
|
515 |
+
"""
|
516 |
+
self._lowercase = lowercase
|
517 |
+
|
518 |
+
def serialize(self, value: _ET) -> Text:
|
519 |
+
"""Returns a serialized string of the Enum class value."""
|
520 |
+
as_string = str(value.name)
|
521 |
+
return as_string.lower() if self._lowercase else as_string
|
522 |
+
|
523 |
+
|
524 |
+
class BaseListParser(ArgumentParser):
|
525 |
+
"""Base class for a parser of lists of strings.
|
526 |
+
|
527 |
+
To extend, inherit from this class; from the subclass ``__init__``, call::
|
528 |
+
|
529 |
+
super().__init__(token, name)
|
530 |
+
|
531 |
+
where token is a character used to tokenize, and name is a description
|
532 |
+
of the separator.
|
533 |
+
"""
|
534 |
+
|
535 |
+
def __init__(
|
536 |
+
self, token: Optional[Text] = None, name: Optional[Text] = None
|
537 |
+
) -> None:
|
538 |
+
assert name
|
539 |
+
super(BaseListParser, self).__init__()
|
540 |
+
self._token = token
|
541 |
+
self._name = name
|
542 |
+
self.syntactic_help = 'a %s separated list' % self._name
|
543 |
+
|
544 |
+
def parse(self, argument: Text) -> List[Text]:
|
545 |
+
"""See base class."""
|
546 |
+
if isinstance(argument, list):
|
547 |
+
return argument
|
548 |
+
elif not argument:
|
549 |
+
return []
|
550 |
+
else:
|
551 |
+
return [s.strip() for s in argument.split(self._token)]
|
552 |
+
|
553 |
+
def flag_type(self) -> Text:
|
554 |
+
"""See base class."""
|
555 |
+
return '%s separated list of strings' % self._name
|
556 |
+
|
557 |
+
|
558 |
+
class ListParser(BaseListParser):
|
559 |
+
"""Parser for a comma-separated list of strings."""
|
560 |
+
|
561 |
+
def __init__(self) -> None:
|
562 |
+
super(ListParser, self).__init__(',', 'comma')
|
563 |
+
|
564 |
+
def parse(self, argument: Union[Text, List[Text]]) -> List[Text]:
|
565 |
+
"""Parses argument as comma-separated list of strings."""
|
566 |
+
if isinstance(argument, list):
|
567 |
+
return argument
|
568 |
+
elif not argument:
|
569 |
+
return []
|
570 |
+
else:
|
571 |
+
try:
|
572 |
+
return [s.strip() for s in list(csv.reader([argument], strict=True))[0]]
|
573 |
+
except csv.Error as e:
|
574 |
+
# Provide a helpful report for case like
|
575 |
+
# --listflag="$(printf 'hello,\nworld')"
|
576 |
+
# IOW, list flag values containing naked newlines. This error
|
577 |
+
# was previously "reported" by allowing csv.Error to
|
578 |
+
# propagate.
|
579 |
+
raise ValueError('Unable to parse the value %r as a %s: %s'
|
580 |
+
% (argument, self.flag_type(), e))
|
581 |
+
|
582 |
+
def _custom_xml_dom_elements(
|
583 |
+
self, doc: minidom.Document
|
584 |
+
) -> List[minidom.Element]:
|
585 |
+
elements = super(ListParser, self)._custom_xml_dom_elements(doc)
|
586 |
+
elements.append(_helpers.create_xml_dom_element(
|
587 |
+
doc, 'list_separator', repr(',')))
|
588 |
+
return elements
|
589 |
+
|
590 |
+
|
591 |
+
class WhitespaceSeparatedListParser(BaseListParser):
|
592 |
+
"""Parser for a whitespace-separated list of strings."""
|
593 |
+
|
594 |
+
def __init__(self, comma_compat: bool = False) -> None:
|
595 |
+
"""Initializer.
|
596 |
+
|
597 |
+
Args:
|
598 |
+
comma_compat: bool, whether to support comma as an additional separator.
|
599 |
+
If False then only whitespace is supported. This is intended only for
|
600 |
+
backwards compatibility with flags that used to be comma-separated.
|
601 |
+
"""
|
602 |
+
self._comma_compat = comma_compat
|
603 |
+
name = 'whitespace or comma' if self._comma_compat else 'whitespace'
|
604 |
+
super(WhitespaceSeparatedListParser, self).__init__(None, name)
|
605 |
+
|
606 |
+
def parse(self, argument: Union[Text, List[Text]]) -> List[Text]:
|
607 |
+
"""Parses argument as whitespace-separated list of strings.
|
608 |
+
|
609 |
+
It also parses argument as comma-separated list of strings if requested.
|
610 |
+
|
611 |
+
Args:
|
612 |
+
argument: string argument passed in the commandline.
|
613 |
+
|
614 |
+
Returns:
|
615 |
+
[str], the parsed flag value.
|
616 |
+
"""
|
617 |
+
if isinstance(argument, list):
|
618 |
+
return argument
|
619 |
+
elif not argument:
|
620 |
+
return []
|
621 |
+
else:
|
622 |
+
if self._comma_compat:
|
623 |
+
argument = argument.replace(',', ' ')
|
624 |
+
return argument.split()
|
625 |
+
|
626 |
+
def _custom_xml_dom_elements(
|
627 |
+
self, doc: minidom.Document
|
628 |
+
) -> List[minidom.Element]:
|
629 |
+
elements = super(WhitespaceSeparatedListParser, self
|
630 |
+
)._custom_xml_dom_elements(doc)
|
631 |
+
separators = list(string.whitespace)
|
632 |
+
if self._comma_compat:
|
633 |
+
separators.append(',')
|
634 |
+
separators.sort()
|
635 |
+
for sep_char in separators:
|
636 |
+
elements.append(_helpers.create_xml_dom_element(
|
637 |
+
doc, 'list_separator', repr(sep_char)))
|
638 |
+
return elements
|
venv/lib/python3.11/site-packages/absl/flags/_defines.py
ADDED
@@ -0,0 +1,1686 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
"""This modules contains flags DEFINE functions.
|
15 |
+
|
16 |
+
Do NOT import this module directly. Import the flags package and use the
|
17 |
+
aliases defined at the package level instead.
|
18 |
+
"""
|
19 |
+
|
20 |
+
import enum
|
21 |
+
import sys
|
22 |
+
import types
|
23 |
+
import typing
|
24 |
+
from typing import Text, List, Any, TypeVar, Optional, Union, Type, Iterable, overload
|
25 |
+
|
26 |
+
from absl.flags import _argument_parser
|
27 |
+
from absl.flags import _exceptions
|
28 |
+
from absl.flags import _flag
|
29 |
+
from absl.flags import _flagvalues
|
30 |
+
from absl.flags import _helpers
|
31 |
+
from absl.flags import _validators
|
32 |
+
|
33 |
+
_helpers.disclaim_module_ids.add(id(sys.modules[__name__]))
|
34 |
+
|
35 |
+
_T = TypeVar('_T')
|
36 |
+
_ET = TypeVar('_ET', bound=enum.Enum)
|
37 |
+
|
38 |
+
|
39 |
+
def _register_bounds_validator_if_needed(parser, name, flag_values):
|
40 |
+
"""Enforces lower and upper bounds for numeric flags.
|
41 |
+
|
42 |
+
Args:
|
43 |
+
parser: NumericParser (either FloatParser or IntegerParser), provides lower
|
44 |
+
and upper bounds, and help text to display.
|
45 |
+
name: str, name of the flag
|
46 |
+
flag_values: FlagValues.
|
47 |
+
"""
|
48 |
+
if parser.lower_bound is not None or parser.upper_bound is not None:
|
49 |
+
|
50 |
+
def checker(value):
|
51 |
+
if value is not None and parser.is_outside_bounds(value):
|
52 |
+
message = '%s is not %s' % (value, parser.syntactic_help)
|
53 |
+
raise _exceptions.ValidationError(message)
|
54 |
+
return True
|
55 |
+
|
56 |
+
_validators.register_validator(name, checker, flag_values=flag_values)
|
57 |
+
|
58 |
+
|
59 |
+
@overload
|
60 |
+
def DEFINE( # pylint: disable=invalid-name
|
61 |
+
parser: _argument_parser.ArgumentParser[_T],
|
62 |
+
name: Text,
|
63 |
+
default: Any,
|
64 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
65 |
+
flag_values: _flagvalues.FlagValues = ...,
|
66 |
+
serializer: Optional[_argument_parser.ArgumentSerializer[_T]] = ...,
|
67 |
+
module_name: Optional[Text] = ...,
|
68 |
+
required: 'typing.Literal[True]' = ...,
|
69 |
+
**args: Any
|
70 |
+
) -> _flagvalues.FlagHolder[_T]:
|
71 |
+
...
|
72 |
+
|
73 |
+
|
74 |
+
@overload
|
75 |
+
def DEFINE( # pylint: disable=invalid-name
|
76 |
+
parser: _argument_parser.ArgumentParser[_T],
|
77 |
+
name: Text,
|
78 |
+
default: Optional[Any],
|
79 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
80 |
+
flag_values: _flagvalues.FlagValues = ...,
|
81 |
+
serializer: Optional[_argument_parser.ArgumentSerializer[_T]] = ...,
|
82 |
+
module_name: Optional[Text] = ...,
|
83 |
+
required: bool = ...,
|
84 |
+
**args: Any
|
85 |
+
) -> _flagvalues.FlagHolder[Optional[_T]]:
|
86 |
+
...
|
87 |
+
|
88 |
+
|
89 |
+
def DEFINE( # pylint: disable=invalid-name
|
90 |
+
parser,
|
91 |
+
name,
|
92 |
+
default,
|
93 |
+
help, # pylint: disable=redefined-builtin
|
94 |
+
flag_values=_flagvalues.FLAGS,
|
95 |
+
serializer=None,
|
96 |
+
module_name=None,
|
97 |
+
required=False,
|
98 |
+
**args):
|
99 |
+
"""Registers a generic Flag object.
|
100 |
+
|
101 |
+
NOTE: in the docstrings of all DEFINE* functions, "registers" is short
|
102 |
+
for "creates a new flag and registers it".
|
103 |
+
|
104 |
+
Auxiliary function: clients should use the specialized ``DEFINE_<type>``
|
105 |
+
function instead.
|
106 |
+
|
107 |
+
Args:
|
108 |
+
parser: :class:`ArgumentParser`, used to parse the flag arguments.
|
109 |
+
name: str, the flag name.
|
110 |
+
default: The default value of the flag.
|
111 |
+
help: str, the help message.
|
112 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
113 |
+
flag will be registered. This should almost never need to be overridden.
|
114 |
+
serializer: :class:`ArgumentSerializer`, the flag serializer instance.
|
115 |
+
module_name: str, the name of the Python module declaring this flag. If not
|
116 |
+
provided, it will be computed using the stack trace of this call.
|
117 |
+
required: bool, is this a required flag. This must be used as a keyword
|
118 |
+
argument.
|
119 |
+
**args: dict, the extra keyword args that are passed to ``Flag.__init__``.
|
120 |
+
|
121 |
+
Returns:
|
122 |
+
a handle to defined flag.
|
123 |
+
"""
|
124 |
+
return DEFINE_flag(
|
125 |
+
_flag.Flag(parser, serializer, name, default, help, **args),
|
126 |
+
flag_values,
|
127 |
+
module_name,
|
128 |
+
required=True if required else False,
|
129 |
+
)
|
130 |
+
|
131 |
+
|
132 |
+
@overload
|
133 |
+
def DEFINE_flag( # pylint: disable=invalid-name
|
134 |
+
flag: _flag.Flag[_T],
|
135 |
+
flag_values: _flagvalues.FlagValues = ...,
|
136 |
+
module_name: Optional[Text] = ...,
|
137 |
+
required: 'typing.Literal[True]' = ...,
|
138 |
+
) -> _flagvalues.FlagHolder[_T]:
|
139 |
+
...
|
140 |
+
|
141 |
+
|
142 |
+
@overload
|
143 |
+
def DEFINE_flag( # pylint: disable=invalid-name
|
144 |
+
flag: _flag.Flag[_T],
|
145 |
+
flag_values: _flagvalues.FlagValues = ...,
|
146 |
+
module_name: Optional[Text] = ...,
|
147 |
+
required: bool = ...,
|
148 |
+
) -> _flagvalues.FlagHolder[Optional[_T]]:
|
149 |
+
...
|
150 |
+
|
151 |
+
|
152 |
+
def DEFINE_flag( # pylint: disable=invalid-name
|
153 |
+
flag,
|
154 |
+
flag_values=_flagvalues.FLAGS,
|
155 |
+
module_name=None,
|
156 |
+
required=False):
|
157 |
+
"""Registers a :class:`Flag` object with a :class:`FlagValues` object.
|
158 |
+
|
159 |
+
By default, the global :const:`FLAGS` ``FlagValue`` object is used.
|
160 |
+
|
161 |
+
Typical users will use one of the more specialized DEFINE_xxx
|
162 |
+
functions, such as :func:`DEFINE_string` or :func:`DEFINE_integer`. But
|
163 |
+
developers who need to create :class:`Flag` objects themselves should use
|
164 |
+
this function to register their flags.
|
165 |
+
|
166 |
+
Args:
|
167 |
+
flag: :class:`Flag`, a flag that is key to the module.
|
168 |
+
flag_values: :class:`FlagValues`, the ``FlagValues`` instance with which the
|
169 |
+
flag will be registered. This should almost never need to be overridden.
|
170 |
+
module_name: str, the name of the Python module declaring this flag. If not
|
171 |
+
provided, it will be computed using the stack trace of this call.
|
172 |
+
required: bool, is this a required flag. This must be used as a keyword
|
173 |
+
argument.
|
174 |
+
|
175 |
+
Returns:
|
176 |
+
a handle to defined flag.
|
177 |
+
"""
|
178 |
+
if required and flag.default is not None:
|
179 |
+
raise ValueError('Required flag --%s cannot have a non-None default' %
|
180 |
+
flag.name)
|
181 |
+
# Copying the reference to flag_values prevents pychecker warnings.
|
182 |
+
fv = flag_values
|
183 |
+
fv[flag.name] = flag
|
184 |
+
# Tell flag_values who's defining the flag.
|
185 |
+
if module_name:
|
186 |
+
module = sys.modules.get(module_name)
|
187 |
+
else:
|
188 |
+
module, module_name = _helpers.get_calling_module_object_and_name()
|
189 |
+
flag_values.register_flag_by_module(module_name, flag)
|
190 |
+
flag_values.register_flag_by_module_id(id(module), flag)
|
191 |
+
if required:
|
192 |
+
_validators.mark_flag_as_required(flag.name, fv)
|
193 |
+
ensure_non_none_value = (flag.default is not None) or required
|
194 |
+
return _flagvalues.FlagHolder(
|
195 |
+
fv, flag, ensure_non_none_value=ensure_non_none_value)
|
196 |
+
|
197 |
+
|
198 |
+
def set_default(flag_holder: _flagvalues.FlagHolder[_T], value: _T) -> None:
|
199 |
+
"""Changes the default value of the provided flag object.
|
200 |
+
|
201 |
+
The flag's current value is also updated if the flag is currently using
|
202 |
+
the default value, i.e. not specified in the command line, and not set
|
203 |
+
by FLAGS.name = value.
|
204 |
+
|
205 |
+
Args:
|
206 |
+
flag_holder: FlagHolder, the flag to modify.
|
207 |
+
value: The new default value.
|
208 |
+
|
209 |
+
Raises:
|
210 |
+
IllegalFlagValueError: Raised when value is not valid.
|
211 |
+
"""
|
212 |
+
flag_holder._flagvalues.set_default(flag_holder.name, value) # pylint: disable=protected-access
|
213 |
+
|
214 |
+
|
215 |
+
def override_value(flag_holder: _flagvalues.FlagHolder[_T], value: _T) -> None:
|
216 |
+
"""Overrides the value of the provided flag.
|
217 |
+
|
218 |
+
This value takes precedent over the default value and, when called after flag
|
219 |
+
parsing, any value provided at the command line.
|
220 |
+
|
221 |
+
Args:
|
222 |
+
flag_holder: FlagHolder, the flag to modify.
|
223 |
+
value: The new value.
|
224 |
+
|
225 |
+
Raises:
|
226 |
+
IllegalFlagValueError: The value did not pass the flag parser or validators.
|
227 |
+
"""
|
228 |
+
fv = flag_holder._flagvalues # pylint: disable=protected-access
|
229 |
+
# Ensure the new value satisfies the flag's parser while avoiding side
|
230 |
+
# effects of calling parse().
|
231 |
+
parsed = fv[flag_holder.name]._parse(value) # pylint: disable=protected-access
|
232 |
+
if parsed != value:
|
233 |
+
raise _exceptions.IllegalFlagValueError(
|
234 |
+
'flag %s: parsed value %r not equal to original %r'
|
235 |
+
% (flag_holder.name, parsed, value)
|
236 |
+
)
|
237 |
+
setattr(fv, flag_holder.name, value)
|
238 |
+
|
239 |
+
|
240 |
+
def _internal_declare_key_flags(
|
241 |
+
flag_names: List[str],
|
242 |
+
flag_values: _flagvalues.FlagValues = _flagvalues.FLAGS,
|
243 |
+
key_flag_values: Optional[_flagvalues.FlagValues] = None,
|
244 |
+
) -> None:
|
245 |
+
"""Declares a flag as key for the calling module.
|
246 |
+
|
247 |
+
Internal function. User code should call declare_key_flag or
|
248 |
+
adopt_module_key_flags instead.
|
249 |
+
|
250 |
+
Args:
|
251 |
+
flag_names: [str], a list of names of already-registered Flag objects.
|
252 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
253 |
+
flags listed in flag_names have registered (the value of the flag_values
|
254 |
+
argument from the ``DEFINE_*`` calls that defined those flags). This
|
255 |
+
should almost never need to be overridden.
|
256 |
+
key_flag_values: :class:`FlagValues`, the FlagValues instance that (among
|
257 |
+
possibly many other things) keeps track of the key flags for each module.
|
258 |
+
Default ``None`` means "same as flag_values". This should almost never
|
259 |
+
need to be overridden.
|
260 |
+
|
261 |
+
Raises:
|
262 |
+
UnrecognizedFlagError: Raised when the flag is not defined.
|
263 |
+
"""
|
264 |
+
key_flag_values = key_flag_values or flag_values
|
265 |
+
|
266 |
+
module = _helpers.get_calling_module()
|
267 |
+
|
268 |
+
for flag_name in flag_names:
|
269 |
+
key_flag_values.register_key_flag_for_module(module, flag_values[flag_name])
|
270 |
+
|
271 |
+
|
272 |
+
def declare_key_flag(
|
273 |
+
flag_name: Union[Text, _flagvalues.FlagHolder],
|
274 |
+
flag_values: _flagvalues.FlagValues = _flagvalues.FLAGS,
|
275 |
+
) -> None:
|
276 |
+
"""Declares one flag as key to the current module.
|
277 |
+
|
278 |
+
Key flags are flags that are deemed really important for a module.
|
279 |
+
They are important when listing help messages; e.g., if the
|
280 |
+
--helpshort command-line flag is used, then only the key flags of the
|
281 |
+
main module are listed (instead of all flags, as in the case of
|
282 |
+
--helpfull).
|
283 |
+
|
284 |
+
Sample usage::
|
285 |
+
|
286 |
+
flags.declare_key_flag('flag_1')
|
287 |
+
|
288 |
+
Args:
|
289 |
+
flag_name: str | :class:`FlagHolder`, the name or holder of an already
|
290 |
+
declared flag. (Redeclaring flags as key, including flags implicitly key
|
291 |
+
because they were declared in this module, is a no-op.)
|
292 |
+
Positional-only parameter.
|
293 |
+
flag_values: :class:`FlagValues`, the FlagValues instance in which the
|
294 |
+
flag will be declared as a key flag. This should almost never need to be
|
295 |
+
overridden.
|
296 |
+
|
297 |
+
Raises:
|
298 |
+
ValueError: Raised if flag_name not defined as a Python flag.
|
299 |
+
"""
|
300 |
+
flag_name, flag_values = _flagvalues.resolve_flag_ref(flag_name, flag_values)
|
301 |
+
if flag_name in _helpers.SPECIAL_FLAGS:
|
302 |
+
# Take care of the special flags, e.g., --flagfile, --undefok.
|
303 |
+
# These flags are defined in SPECIAL_FLAGS, and are treated
|
304 |
+
# specially during flag parsing, taking precedence over the
|
305 |
+
# user-defined flags.
|
306 |
+
_internal_declare_key_flags([flag_name],
|
307 |
+
flag_values=_helpers.SPECIAL_FLAGS,
|
308 |
+
key_flag_values=flag_values)
|
309 |
+
return
|
310 |
+
try:
|
311 |
+
_internal_declare_key_flags([flag_name], flag_values=flag_values)
|
312 |
+
except KeyError:
|
313 |
+
raise ValueError('Flag --%s is undefined. To set a flag as a key flag '
|
314 |
+
'first define it in Python.' % flag_name)
|
315 |
+
|
316 |
+
|
317 |
+
def adopt_module_key_flags(
|
318 |
+
module: Any, flag_values: _flagvalues.FlagValues = _flagvalues.FLAGS
|
319 |
+
) -> None:
|
320 |
+
"""Declares that all flags key to a module are key to the current module.
|
321 |
+
|
322 |
+
Args:
|
323 |
+
module: module, the module object from which all key flags will be declared
|
324 |
+
as key flags to the current module.
|
325 |
+
flag_values: :class:`FlagValues`, the FlagValues instance in which the
|
326 |
+
flags will be declared as key flags. This should almost never need to be
|
327 |
+
overridden.
|
328 |
+
|
329 |
+
Raises:
|
330 |
+
Error: Raised when given an argument that is a module name (a string),
|
331 |
+
instead of a module object.
|
332 |
+
"""
|
333 |
+
if not isinstance(module, types.ModuleType):
|
334 |
+
raise _exceptions.Error('Expected a module object, not %r.' % (module,))
|
335 |
+
_internal_declare_key_flags(
|
336 |
+
[f.name for f in flag_values.get_key_flags_for_module(module.__name__)],
|
337 |
+
flag_values=flag_values)
|
338 |
+
# If module is this flag module, take _helpers.SPECIAL_FLAGS into account.
|
339 |
+
if module == _helpers.FLAGS_MODULE:
|
340 |
+
_internal_declare_key_flags(
|
341 |
+
# As we associate flags with get_calling_module_object_and_name(), the
|
342 |
+
# special flags defined in this module are incorrectly registered with
|
343 |
+
# a different module. So, we can't use get_key_flags_for_module.
|
344 |
+
# Instead, we take all flags from _helpers.SPECIAL_FLAGS (a private
|
345 |
+
# FlagValues, where no other module should register flags).
|
346 |
+
[_helpers.SPECIAL_FLAGS[name].name for name in _helpers.SPECIAL_FLAGS],
|
347 |
+
flag_values=_helpers.SPECIAL_FLAGS,
|
348 |
+
key_flag_values=flag_values)
|
349 |
+
|
350 |
+
|
351 |
+
def disclaim_key_flags() -> None:
|
352 |
+
"""Declares that the current module will not define any more key flags.
|
353 |
+
|
354 |
+
Normally, the module that calls the DEFINE_xxx functions claims the
|
355 |
+
flag to be its key flag. This is undesirable for modules that
|
356 |
+
define additional DEFINE_yyy functions with its own flag parsers and
|
357 |
+
serializers, since that module will accidentally claim flags defined
|
358 |
+
by DEFINE_yyy as its key flags. After calling this function, the
|
359 |
+
module disclaims flag definitions thereafter, so the key flags will
|
360 |
+
be correctly attributed to the caller of DEFINE_yyy.
|
361 |
+
|
362 |
+
After calling this function, the module will not be able to define
|
363 |
+
any more flags. This function will affect all FlagValues objects.
|
364 |
+
"""
|
365 |
+
globals_for_caller = sys._getframe(1).f_globals # pylint: disable=protected-access
|
366 |
+
module, _ = _helpers.get_module_object_and_name(globals_for_caller)
|
367 |
+
_helpers.disclaim_module_ids.add(id(module))
|
368 |
+
|
369 |
+
|
370 |
+
@overload
|
371 |
+
def DEFINE_string( # pylint: disable=invalid-name
|
372 |
+
name: Text,
|
373 |
+
default: Optional[Text],
|
374 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
375 |
+
flag_values: _flagvalues.FlagValues = ...,
|
376 |
+
*,
|
377 |
+
required: 'typing.Literal[True]',
|
378 |
+
**args: Any
|
379 |
+
) -> _flagvalues.FlagHolder[Text]:
|
380 |
+
...
|
381 |
+
|
382 |
+
|
383 |
+
@overload
|
384 |
+
def DEFINE_string( # pylint: disable=invalid-name
|
385 |
+
name: Text,
|
386 |
+
default: None,
|
387 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
388 |
+
flag_values: _flagvalues.FlagValues = ...,
|
389 |
+
required: bool = ...,
|
390 |
+
**args: Any
|
391 |
+
) -> _flagvalues.FlagHolder[Optional[Text]]:
|
392 |
+
...
|
393 |
+
|
394 |
+
|
395 |
+
@overload
|
396 |
+
def DEFINE_string( # pylint: disable=invalid-name
|
397 |
+
name: Text,
|
398 |
+
default: Text,
|
399 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
400 |
+
flag_values: _flagvalues.FlagValues = ...,
|
401 |
+
required: bool = ...,
|
402 |
+
**args: Any
|
403 |
+
) -> _flagvalues.FlagHolder[Text]:
|
404 |
+
...
|
405 |
+
|
406 |
+
|
407 |
+
def DEFINE_string( # pylint: disable=invalid-name,redefined-builtin
|
408 |
+
name,
|
409 |
+
default,
|
410 |
+
help,
|
411 |
+
flag_values=_flagvalues.FLAGS,
|
412 |
+
required=False,
|
413 |
+
**args):
|
414 |
+
"""Registers a flag whose value can be any string."""
|
415 |
+
parser = _argument_parser.ArgumentParser[str]()
|
416 |
+
serializer = _argument_parser.ArgumentSerializer[str]()
|
417 |
+
return DEFINE(
|
418 |
+
parser,
|
419 |
+
name,
|
420 |
+
default,
|
421 |
+
help,
|
422 |
+
flag_values,
|
423 |
+
serializer,
|
424 |
+
required=True if required else False,
|
425 |
+
**args,
|
426 |
+
)
|
427 |
+
|
428 |
+
|
429 |
+
@overload
|
430 |
+
def DEFINE_boolean( # pylint: disable=invalid-name
|
431 |
+
name: Text,
|
432 |
+
default: Union[None, Text, bool, int],
|
433 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
434 |
+
flag_values: _flagvalues.FlagValues = ...,
|
435 |
+
module_name: Optional[Text] = ...,
|
436 |
+
*,
|
437 |
+
required: 'typing.Literal[True]',
|
438 |
+
**args: Any
|
439 |
+
) -> _flagvalues.FlagHolder[bool]:
|
440 |
+
...
|
441 |
+
|
442 |
+
|
443 |
+
@overload
|
444 |
+
def DEFINE_boolean( # pylint: disable=invalid-name
|
445 |
+
name: Text,
|
446 |
+
default: None,
|
447 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
448 |
+
flag_values: _flagvalues.FlagValues = ...,
|
449 |
+
module_name: Optional[Text] = ...,
|
450 |
+
required: bool = ...,
|
451 |
+
**args: Any
|
452 |
+
) -> _flagvalues.FlagHolder[Optional[bool]]:
|
453 |
+
...
|
454 |
+
|
455 |
+
|
456 |
+
@overload
|
457 |
+
def DEFINE_boolean( # pylint: disable=invalid-name
|
458 |
+
name: Text,
|
459 |
+
default: Union[Text, bool, int],
|
460 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
461 |
+
flag_values: _flagvalues.FlagValues = ...,
|
462 |
+
module_name: Optional[Text] = ...,
|
463 |
+
required: bool = ...,
|
464 |
+
**args: Any
|
465 |
+
) -> _flagvalues.FlagHolder[bool]:
|
466 |
+
...
|
467 |
+
|
468 |
+
|
469 |
+
def DEFINE_boolean( # pylint: disable=invalid-name,redefined-builtin
|
470 |
+
name,
|
471 |
+
default,
|
472 |
+
help,
|
473 |
+
flag_values=_flagvalues.FLAGS,
|
474 |
+
module_name=None,
|
475 |
+
required=False,
|
476 |
+
**args):
|
477 |
+
"""Registers a boolean flag.
|
478 |
+
|
479 |
+
Such a boolean flag does not take an argument. If a user wants to
|
480 |
+
specify a false value explicitly, the long option beginning with 'no'
|
481 |
+
must be used: i.e. --noflag
|
482 |
+
|
483 |
+
This flag will have a value of None, True or False. None is possible
|
484 |
+
if default=None and the user does not specify the flag on the command
|
485 |
+
line.
|
486 |
+
|
487 |
+
Args:
|
488 |
+
name: str, the flag name.
|
489 |
+
default: bool|str|None, the default value of the flag.
|
490 |
+
help: str, the help message.
|
491 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
492 |
+
flag will be registered. This should almost never need to be overridden.
|
493 |
+
module_name: str, the name of the Python module declaring this flag. If not
|
494 |
+
provided, it will be computed using the stack trace of this call.
|
495 |
+
required: bool, is this a required flag. This must be used as a keyword
|
496 |
+
argument.
|
497 |
+
**args: dict, the extra keyword args that are passed to ``Flag.__init__``.
|
498 |
+
|
499 |
+
Returns:
|
500 |
+
a handle to defined flag.
|
501 |
+
"""
|
502 |
+
return DEFINE_flag(
|
503 |
+
_flag.BooleanFlag(name, default, help, **args),
|
504 |
+
flag_values,
|
505 |
+
module_name,
|
506 |
+
required=True if required else False,
|
507 |
+
)
|
508 |
+
|
509 |
+
|
510 |
+
@overload
|
511 |
+
def DEFINE_float( # pylint: disable=invalid-name
|
512 |
+
name: Text,
|
513 |
+
default: Union[None, float, Text],
|
514 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
515 |
+
lower_bound: Optional[float] = ...,
|
516 |
+
upper_bound: Optional[float] = ...,
|
517 |
+
flag_values: _flagvalues.FlagValues = ...,
|
518 |
+
*,
|
519 |
+
required: 'typing.Literal[True]',
|
520 |
+
**args: Any
|
521 |
+
) -> _flagvalues.FlagHolder[float]:
|
522 |
+
...
|
523 |
+
|
524 |
+
|
525 |
+
@overload
|
526 |
+
def DEFINE_float( # pylint: disable=invalid-name
|
527 |
+
name: Text,
|
528 |
+
default: None,
|
529 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
530 |
+
lower_bound: Optional[float] = ...,
|
531 |
+
upper_bound: Optional[float] = ...,
|
532 |
+
flag_values: _flagvalues.FlagValues = ...,
|
533 |
+
required: bool = ...,
|
534 |
+
**args: Any
|
535 |
+
) -> _flagvalues.FlagHolder[Optional[float]]:
|
536 |
+
...
|
537 |
+
|
538 |
+
|
539 |
+
@overload
|
540 |
+
def DEFINE_float( # pylint: disable=invalid-name
|
541 |
+
name: Text,
|
542 |
+
default: Union[float, Text],
|
543 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
544 |
+
lower_bound: Optional[float] = ...,
|
545 |
+
upper_bound: Optional[float] = ...,
|
546 |
+
flag_values: _flagvalues.FlagValues = ...,
|
547 |
+
required: bool = ...,
|
548 |
+
**args: Any
|
549 |
+
) -> _flagvalues.FlagHolder[float]:
|
550 |
+
...
|
551 |
+
|
552 |
+
|
553 |
+
def DEFINE_float( # pylint: disable=invalid-name,redefined-builtin
|
554 |
+
name,
|
555 |
+
default,
|
556 |
+
help,
|
557 |
+
lower_bound=None,
|
558 |
+
upper_bound=None,
|
559 |
+
flag_values=_flagvalues.FLAGS,
|
560 |
+
required=False,
|
561 |
+
**args):
|
562 |
+
"""Registers a flag whose value must be a float.
|
563 |
+
|
564 |
+
If ``lower_bound`` or ``upper_bound`` are set, then this flag must be
|
565 |
+
within the given range.
|
566 |
+
|
567 |
+
Args:
|
568 |
+
name: str, the flag name.
|
569 |
+
default: float|str|None, the default value of the flag.
|
570 |
+
help: str, the help message.
|
571 |
+
lower_bound: float, min value of the flag.
|
572 |
+
upper_bound: float, max value of the flag.
|
573 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
574 |
+
flag will be registered. This should almost never need to be overridden.
|
575 |
+
required: bool, is this a required flag. This must be used as a keyword
|
576 |
+
argument.
|
577 |
+
**args: dict, the extra keyword args that are passed to :func:`DEFINE`.
|
578 |
+
|
579 |
+
Returns:
|
580 |
+
a handle to defined flag.
|
581 |
+
"""
|
582 |
+
parser = _argument_parser.FloatParser(lower_bound, upper_bound)
|
583 |
+
serializer = _argument_parser.ArgumentSerializer()
|
584 |
+
result = DEFINE(
|
585 |
+
parser,
|
586 |
+
name,
|
587 |
+
default,
|
588 |
+
help,
|
589 |
+
flag_values,
|
590 |
+
serializer,
|
591 |
+
required=True if required else False,
|
592 |
+
**args,
|
593 |
+
)
|
594 |
+
_register_bounds_validator_if_needed(parser, name, flag_values=flag_values)
|
595 |
+
return result
|
596 |
+
|
597 |
+
|
598 |
+
@overload
|
599 |
+
def DEFINE_integer( # pylint: disable=invalid-name
|
600 |
+
name: Text,
|
601 |
+
default: Union[None, int, Text],
|
602 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
603 |
+
lower_bound: Optional[int] = ...,
|
604 |
+
upper_bound: Optional[int] = ...,
|
605 |
+
flag_values: _flagvalues.FlagValues = ...,
|
606 |
+
*,
|
607 |
+
required: 'typing.Literal[True]',
|
608 |
+
**args: Any
|
609 |
+
) -> _flagvalues.FlagHolder[int]:
|
610 |
+
...
|
611 |
+
|
612 |
+
|
613 |
+
@overload
|
614 |
+
def DEFINE_integer( # pylint: disable=invalid-name
|
615 |
+
name: Text,
|
616 |
+
default: None,
|
617 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
618 |
+
lower_bound: Optional[int] = ...,
|
619 |
+
upper_bound: Optional[int] = ...,
|
620 |
+
flag_values: _flagvalues.FlagValues = ...,
|
621 |
+
required: bool = ...,
|
622 |
+
**args: Any
|
623 |
+
) -> _flagvalues.FlagHolder[Optional[int]]:
|
624 |
+
...
|
625 |
+
|
626 |
+
|
627 |
+
@overload
|
628 |
+
def DEFINE_integer( # pylint: disable=invalid-name
|
629 |
+
name: Text,
|
630 |
+
default: Union[int, Text],
|
631 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
632 |
+
lower_bound: Optional[int] = ...,
|
633 |
+
upper_bound: Optional[int] = ...,
|
634 |
+
flag_values: _flagvalues.FlagValues = ...,
|
635 |
+
required: bool = ...,
|
636 |
+
**args: Any
|
637 |
+
) -> _flagvalues.FlagHolder[int]:
|
638 |
+
...
|
639 |
+
|
640 |
+
|
641 |
+
def DEFINE_integer( # pylint: disable=invalid-name,redefined-builtin
|
642 |
+
name,
|
643 |
+
default,
|
644 |
+
help,
|
645 |
+
lower_bound=None,
|
646 |
+
upper_bound=None,
|
647 |
+
flag_values=_flagvalues.FLAGS,
|
648 |
+
required=False,
|
649 |
+
**args):
|
650 |
+
"""Registers a flag whose value must be an integer.
|
651 |
+
|
652 |
+
If ``lower_bound``, or ``upper_bound`` are set, then this flag must be
|
653 |
+
within the given range.
|
654 |
+
|
655 |
+
Args:
|
656 |
+
name: str, the flag name.
|
657 |
+
default: int|str|None, the default value of the flag.
|
658 |
+
help: str, the help message.
|
659 |
+
lower_bound: int, min value of the flag.
|
660 |
+
upper_bound: int, max value of the flag.
|
661 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
662 |
+
flag will be registered. This should almost never need to be overridden.
|
663 |
+
required: bool, is this a required flag. This must be used as a keyword
|
664 |
+
argument.
|
665 |
+
**args: dict, the extra keyword args that are passed to :func:`DEFINE`.
|
666 |
+
|
667 |
+
Returns:
|
668 |
+
a handle to defined flag.
|
669 |
+
"""
|
670 |
+
parser = _argument_parser.IntegerParser(lower_bound, upper_bound)
|
671 |
+
serializer = _argument_parser.ArgumentSerializer()
|
672 |
+
result = DEFINE(
|
673 |
+
parser,
|
674 |
+
name,
|
675 |
+
default,
|
676 |
+
help,
|
677 |
+
flag_values,
|
678 |
+
serializer,
|
679 |
+
required=True if required else False,
|
680 |
+
**args,
|
681 |
+
)
|
682 |
+
_register_bounds_validator_if_needed(parser, name, flag_values=flag_values)
|
683 |
+
return result
|
684 |
+
|
685 |
+
|
686 |
+
@overload
|
687 |
+
def DEFINE_enum( # pylint: disable=invalid-name
|
688 |
+
name: Text,
|
689 |
+
default: Optional[Text],
|
690 |
+
enum_values: Iterable[Text],
|
691 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
692 |
+
flag_values: _flagvalues.FlagValues = ...,
|
693 |
+
module_name: Optional[Text] = ...,
|
694 |
+
*,
|
695 |
+
required: 'typing.Literal[True]',
|
696 |
+
**args: Any
|
697 |
+
) -> _flagvalues.FlagHolder[Text]:
|
698 |
+
...
|
699 |
+
|
700 |
+
|
701 |
+
@overload
|
702 |
+
def DEFINE_enum( # pylint: disable=invalid-name
|
703 |
+
name: Text,
|
704 |
+
default: None,
|
705 |
+
enum_values: Iterable[Text],
|
706 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
707 |
+
flag_values: _flagvalues.FlagValues = ...,
|
708 |
+
module_name: Optional[Text] = ...,
|
709 |
+
required: bool = ...,
|
710 |
+
**args: Any
|
711 |
+
) -> _flagvalues.FlagHolder[Optional[Text]]:
|
712 |
+
...
|
713 |
+
|
714 |
+
|
715 |
+
@overload
|
716 |
+
def DEFINE_enum( # pylint: disable=invalid-name
|
717 |
+
name: Text,
|
718 |
+
default: Text,
|
719 |
+
enum_values: Iterable[Text],
|
720 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
721 |
+
flag_values: _flagvalues.FlagValues = ...,
|
722 |
+
module_name: Optional[Text] = ...,
|
723 |
+
required: bool = ...,
|
724 |
+
**args: Any
|
725 |
+
) -> _flagvalues.FlagHolder[Text]:
|
726 |
+
...
|
727 |
+
|
728 |
+
|
729 |
+
def DEFINE_enum( # pylint: disable=invalid-name,redefined-builtin
|
730 |
+
name,
|
731 |
+
default,
|
732 |
+
enum_values,
|
733 |
+
help,
|
734 |
+
flag_values=_flagvalues.FLAGS,
|
735 |
+
module_name=None,
|
736 |
+
required=False,
|
737 |
+
**args):
|
738 |
+
"""Registers a flag whose value can be any string from enum_values.
|
739 |
+
|
740 |
+
Instead of a string enum, prefer `DEFINE_enum_class`, which allows
|
741 |
+
defining enums from an `enum.Enum` class.
|
742 |
+
|
743 |
+
Args:
|
744 |
+
name: str, the flag name.
|
745 |
+
default: str|None, the default value of the flag.
|
746 |
+
enum_values: [str], a non-empty list of strings with the possible values for
|
747 |
+
the flag.
|
748 |
+
help: str, the help message.
|
749 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
750 |
+
flag will be registered. This should almost never need to be overridden.
|
751 |
+
module_name: str, the name of the Python module declaring this flag. If not
|
752 |
+
provided, it will be computed using the stack trace of this call.
|
753 |
+
required: bool, is this a required flag. This must be used as a keyword
|
754 |
+
argument.
|
755 |
+
**args: dict, the extra keyword args that are passed to ``Flag.__init__``.
|
756 |
+
|
757 |
+
Returns:
|
758 |
+
a handle to defined flag.
|
759 |
+
"""
|
760 |
+
result = DEFINE_flag(
|
761 |
+
_flag.EnumFlag(name, default, help, enum_values, **args),
|
762 |
+
flag_values,
|
763 |
+
module_name,
|
764 |
+
required=True if required else False,
|
765 |
+
)
|
766 |
+
return result
|
767 |
+
|
768 |
+
|
769 |
+
@overload
|
770 |
+
def DEFINE_enum_class( # pylint: disable=invalid-name
|
771 |
+
name: Text,
|
772 |
+
default: Union[None, _ET, Text],
|
773 |
+
enum_class: Type[_ET],
|
774 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
775 |
+
flag_values: _flagvalues.FlagValues = ...,
|
776 |
+
module_name: Optional[Text] = ...,
|
777 |
+
case_sensitive: bool = ...,
|
778 |
+
*,
|
779 |
+
required: 'typing.Literal[True]',
|
780 |
+
**args: Any
|
781 |
+
) -> _flagvalues.FlagHolder[_ET]:
|
782 |
+
...
|
783 |
+
|
784 |
+
|
785 |
+
@overload
|
786 |
+
def DEFINE_enum_class( # pylint: disable=invalid-name
|
787 |
+
name: Text,
|
788 |
+
default: None,
|
789 |
+
enum_class: Type[_ET],
|
790 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
791 |
+
flag_values: _flagvalues.FlagValues = ...,
|
792 |
+
module_name: Optional[Text] = ...,
|
793 |
+
case_sensitive: bool = ...,
|
794 |
+
required: bool = ...,
|
795 |
+
**args: Any
|
796 |
+
) -> _flagvalues.FlagHolder[Optional[_ET]]:
|
797 |
+
...
|
798 |
+
|
799 |
+
|
800 |
+
@overload
|
801 |
+
def DEFINE_enum_class( # pylint: disable=invalid-name
|
802 |
+
name: Text,
|
803 |
+
default: Union[_ET, Text],
|
804 |
+
enum_class: Type[_ET],
|
805 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
806 |
+
flag_values: _flagvalues.FlagValues = ...,
|
807 |
+
module_name: Optional[Text] = ...,
|
808 |
+
case_sensitive: bool = ...,
|
809 |
+
required: bool = ...,
|
810 |
+
**args: Any
|
811 |
+
) -> _flagvalues.FlagHolder[_ET]:
|
812 |
+
...
|
813 |
+
|
814 |
+
|
815 |
+
def DEFINE_enum_class( # pylint: disable=invalid-name,redefined-builtin
|
816 |
+
name,
|
817 |
+
default,
|
818 |
+
enum_class,
|
819 |
+
help,
|
820 |
+
flag_values=_flagvalues.FLAGS,
|
821 |
+
module_name=None,
|
822 |
+
case_sensitive=False,
|
823 |
+
required=False,
|
824 |
+
**args):
|
825 |
+
"""Registers a flag whose value can be the name of enum members.
|
826 |
+
|
827 |
+
Args:
|
828 |
+
name: str, the flag name.
|
829 |
+
default: Enum|str|None, the default value of the flag.
|
830 |
+
enum_class: class, the Enum class with all the possible values for the flag.
|
831 |
+
help: str, the help message.
|
832 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
833 |
+
flag will be registered. This should almost never need to be overridden.
|
834 |
+
module_name: str, the name of the Python module declaring this flag. If not
|
835 |
+
provided, it will be computed using the stack trace of this call.
|
836 |
+
case_sensitive: bool, whether to map strings to members of the enum_class
|
837 |
+
without considering case.
|
838 |
+
required: bool, is this a required flag. This must be used as a keyword
|
839 |
+
argument.
|
840 |
+
**args: dict, the extra keyword args that are passed to ``Flag.__init__``.
|
841 |
+
|
842 |
+
Returns:
|
843 |
+
a handle to defined flag.
|
844 |
+
"""
|
845 |
+
# NOTE: pytype fails if this is a direct return.
|
846 |
+
result = DEFINE_flag(
|
847 |
+
_flag.EnumClassFlag(
|
848 |
+
name, default, help, enum_class, case_sensitive=case_sensitive, **args
|
849 |
+
),
|
850 |
+
flag_values,
|
851 |
+
module_name,
|
852 |
+
required=True if required else False,
|
853 |
+
)
|
854 |
+
return result
|
855 |
+
|
856 |
+
|
857 |
+
@overload
|
858 |
+
def DEFINE_list( # pylint: disable=invalid-name
|
859 |
+
name: Text,
|
860 |
+
default: Union[None, Iterable[Text], Text],
|
861 |
+
help: Text, # pylint: disable=redefined-builtin
|
862 |
+
flag_values: _flagvalues.FlagValues = ...,
|
863 |
+
*,
|
864 |
+
required: 'typing.Literal[True]',
|
865 |
+
**args: Any
|
866 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
867 |
+
...
|
868 |
+
|
869 |
+
|
870 |
+
@overload
|
871 |
+
def DEFINE_list( # pylint: disable=invalid-name
|
872 |
+
name: Text,
|
873 |
+
default: None,
|
874 |
+
help: Text, # pylint: disable=redefined-builtin
|
875 |
+
flag_values: _flagvalues.FlagValues = ...,
|
876 |
+
required: bool = ...,
|
877 |
+
**args: Any
|
878 |
+
) -> _flagvalues.FlagHolder[Optional[List[Text]]]:
|
879 |
+
...
|
880 |
+
|
881 |
+
|
882 |
+
@overload
|
883 |
+
def DEFINE_list( # pylint: disable=invalid-name
|
884 |
+
name: Text,
|
885 |
+
default: Union[Iterable[Text], Text],
|
886 |
+
help: Text, # pylint: disable=redefined-builtin
|
887 |
+
flag_values: _flagvalues.FlagValues = ...,
|
888 |
+
required: bool = ...,
|
889 |
+
**args: Any
|
890 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
891 |
+
...
|
892 |
+
|
893 |
+
|
894 |
+
def DEFINE_list( # pylint: disable=invalid-name,redefined-builtin
|
895 |
+
name,
|
896 |
+
default,
|
897 |
+
help,
|
898 |
+
flag_values=_flagvalues.FLAGS,
|
899 |
+
required=False,
|
900 |
+
**args):
|
901 |
+
"""Registers a flag whose value is a comma-separated list of strings.
|
902 |
+
|
903 |
+
The flag value is parsed with a CSV parser.
|
904 |
+
|
905 |
+
Args:
|
906 |
+
name: str, the flag name.
|
907 |
+
default: list|str|None, the default value of the flag.
|
908 |
+
help: str, the help message.
|
909 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
910 |
+
flag will be registered. This should almost never need to be overridden.
|
911 |
+
required: bool, is this a required flag. This must be used as a keyword
|
912 |
+
argument.
|
913 |
+
**args: Dictionary with extra keyword args that are passed to the
|
914 |
+
``Flag.__init__``.
|
915 |
+
|
916 |
+
Returns:
|
917 |
+
a handle to defined flag.
|
918 |
+
"""
|
919 |
+
parser = _argument_parser.ListParser()
|
920 |
+
serializer = _argument_parser.CsvListSerializer(',')
|
921 |
+
return DEFINE(
|
922 |
+
parser,
|
923 |
+
name,
|
924 |
+
default,
|
925 |
+
help,
|
926 |
+
flag_values,
|
927 |
+
serializer,
|
928 |
+
required=True if required else False,
|
929 |
+
**args,
|
930 |
+
)
|
931 |
+
|
932 |
+
|
933 |
+
@overload
|
934 |
+
def DEFINE_spaceseplist( # pylint: disable=invalid-name
|
935 |
+
name: Text,
|
936 |
+
default: Union[None, Iterable[Text], Text],
|
937 |
+
help: Text, # pylint: disable=redefined-builtin
|
938 |
+
comma_compat: bool = ...,
|
939 |
+
flag_values: _flagvalues.FlagValues = ...,
|
940 |
+
*,
|
941 |
+
required: 'typing.Literal[True]',
|
942 |
+
**args: Any
|
943 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
944 |
+
...
|
945 |
+
|
946 |
+
|
947 |
+
@overload
|
948 |
+
def DEFINE_spaceseplist( # pylint: disable=invalid-name
|
949 |
+
name: Text,
|
950 |
+
default: None,
|
951 |
+
help: Text, # pylint: disable=redefined-builtin
|
952 |
+
comma_compat: bool = ...,
|
953 |
+
flag_values: _flagvalues.FlagValues = ...,
|
954 |
+
required: bool = ...,
|
955 |
+
**args: Any
|
956 |
+
) -> _flagvalues.FlagHolder[Optional[List[Text]]]:
|
957 |
+
...
|
958 |
+
|
959 |
+
|
960 |
+
@overload
|
961 |
+
def DEFINE_spaceseplist( # pylint: disable=invalid-name
|
962 |
+
name: Text,
|
963 |
+
default: Union[Iterable[Text], Text],
|
964 |
+
help: Text, # pylint: disable=redefined-builtin
|
965 |
+
comma_compat: bool = ...,
|
966 |
+
flag_values: _flagvalues.FlagValues = ...,
|
967 |
+
required: bool = ...,
|
968 |
+
**args: Any
|
969 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
970 |
+
...
|
971 |
+
|
972 |
+
|
973 |
+
def DEFINE_spaceseplist( # pylint: disable=invalid-name,redefined-builtin
|
974 |
+
name,
|
975 |
+
default,
|
976 |
+
help,
|
977 |
+
comma_compat=False,
|
978 |
+
flag_values=_flagvalues.FLAGS,
|
979 |
+
required=False,
|
980 |
+
**args):
|
981 |
+
"""Registers a flag whose value is a whitespace-separated list of strings.
|
982 |
+
|
983 |
+
Any whitespace can be used as a separator.
|
984 |
+
|
985 |
+
Args:
|
986 |
+
name: str, the flag name.
|
987 |
+
default: list|str|None, the default value of the flag.
|
988 |
+
help: str, the help message.
|
989 |
+
comma_compat: bool - Whether to support comma as an additional separator. If
|
990 |
+
false then only whitespace is supported. This is intended only for
|
991 |
+
backwards compatibility with flags that used to be comma-separated.
|
992 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
993 |
+
flag will be registered. This should almost never need to be overridden.
|
994 |
+
required: bool, is this a required flag. This must be used as a keyword
|
995 |
+
argument.
|
996 |
+
**args: Dictionary with extra keyword args that are passed to the
|
997 |
+
``Flag.__init__``.
|
998 |
+
|
999 |
+
Returns:
|
1000 |
+
a handle to defined flag.
|
1001 |
+
"""
|
1002 |
+
parser = _argument_parser.WhitespaceSeparatedListParser(
|
1003 |
+
comma_compat=comma_compat)
|
1004 |
+
serializer = _argument_parser.ListSerializer(' ')
|
1005 |
+
return DEFINE(
|
1006 |
+
parser,
|
1007 |
+
name,
|
1008 |
+
default,
|
1009 |
+
help,
|
1010 |
+
flag_values,
|
1011 |
+
serializer,
|
1012 |
+
required=True if required else False,
|
1013 |
+
**args,
|
1014 |
+
)
|
1015 |
+
|
1016 |
+
|
1017 |
+
@overload
|
1018 |
+
def DEFINE_multi( # pylint: disable=invalid-name
|
1019 |
+
parser: _argument_parser.ArgumentParser[_T],
|
1020 |
+
serializer: _argument_parser.ArgumentSerializer[_T],
|
1021 |
+
name: Text,
|
1022 |
+
default: Iterable[_T],
|
1023 |
+
help: Text, # pylint: disable=redefined-builtin
|
1024 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1025 |
+
module_name: Optional[Text] = ...,
|
1026 |
+
*,
|
1027 |
+
required: 'typing.Literal[True]',
|
1028 |
+
**args: Any
|
1029 |
+
) -> _flagvalues.FlagHolder[List[_T]]:
|
1030 |
+
...
|
1031 |
+
|
1032 |
+
|
1033 |
+
@overload
|
1034 |
+
def DEFINE_multi( # pylint: disable=invalid-name
|
1035 |
+
parser: _argument_parser.ArgumentParser[_T],
|
1036 |
+
serializer: _argument_parser.ArgumentSerializer[_T],
|
1037 |
+
name: Text,
|
1038 |
+
default: Union[None, _T],
|
1039 |
+
help: Text, # pylint: disable=redefined-builtin
|
1040 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1041 |
+
module_name: Optional[Text] = ...,
|
1042 |
+
*,
|
1043 |
+
required: 'typing.Literal[True]',
|
1044 |
+
**args: Any
|
1045 |
+
) -> _flagvalues.FlagHolder[List[_T]]:
|
1046 |
+
...
|
1047 |
+
|
1048 |
+
|
1049 |
+
@overload
|
1050 |
+
def DEFINE_multi( # pylint: disable=invalid-name
|
1051 |
+
parser: _argument_parser.ArgumentParser[_T],
|
1052 |
+
serializer: _argument_parser.ArgumentSerializer[_T],
|
1053 |
+
name: Text,
|
1054 |
+
default: None,
|
1055 |
+
help: Text, # pylint: disable=redefined-builtin
|
1056 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1057 |
+
module_name: Optional[Text] = ...,
|
1058 |
+
required: bool = ...,
|
1059 |
+
**args: Any
|
1060 |
+
) -> _flagvalues.FlagHolder[Optional[List[_T]]]:
|
1061 |
+
...
|
1062 |
+
|
1063 |
+
|
1064 |
+
@overload
|
1065 |
+
def DEFINE_multi( # pylint: disable=invalid-name
|
1066 |
+
parser: _argument_parser.ArgumentParser[_T],
|
1067 |
+
serializer: _argument_parser.ArgumentSerializer[_T],
|
1068 |
+
name: Text,
|
1069 |
+
default: Iterable[_T],
|
1070 |
+
help: Text, # pylint: disable=redefined-builtin
|
1071 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1072 |
+
module_name: Optional[Text] = ...,
|
1073 |
+
required: bool = ...,
|
1074 |
+
**args: Any
|
1075 |
+
) -> _flagvalues.FlagHolder[List[_T]]:
|
1076 |
+
...
|
1077 |
+
|
1078 |
+
|
1079 |
+
@overload
|
1080 |
+
def DEFINE_multi( # pylint: disable=invalid-name
|
1081 |
+
parser: _argument_parser.ArgumentParser[_T],
|
1082 |
+
serializer: _argument_parser.ArgumentSerializer[_T],
|
1083 |
+
name: Text,
|
1084 |
+
default: _T,
|
1085 |
+
help: Text, # pylint: disable=redefined-builtin
|
1086 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1087 |
+
module_name: Optional[Text] = ...,
|
1088 |
+
required: bool = ...,
|
1089 |
+
**args: Any
|
1090 |
+
) -> _flagvalues.FlagHolder[List[_T]]:
|
1091 |
+
...
|
1092 |
+
|
1093 |
+
|
1094 |
+
def DEFINE_multi( # pylint: disable=invalid-name,redefined-builtin
|
1095 |
+
parser,
|
1096 |
+
serializer,
|
1097 |
+
name,
|
1098 |
+
default,
|
1099 |
+
help,
|
1100 |
+
flag_values=_flagvalues.FLAGS,
|
1101 |
+
module_name=None,
|
1102 |
+
required=False,
|
1103 |
+
**args):
|
1104 |
+
"""Registers a generic MultiFlag that parses its args with a given parser.
|
1105 |
+
|
1106 |
+
Auxiliary function. Normal users should NOT use it directly.
|
1107 |
+
|
1108 |
+
Developers who need to create their own 'Parser' classes for options
|
1109 |
+
which can appear multiple times can call this module function to
|
1110 |
+
register their flags.
|
1111 |
+
|
1112 |
+
Args:
|
1113 |
+
parser: ArgumentParser, used to parse the flag arguments.
|
1114 |
+
serializer: ArgumentSerializer, the flag serializer instance.
|
1115 |
+
name: str, the flag name.
|
1116 |
+
default: Union[Iterable[T], Text, None], the default value of the flag. If
|
1117 |
+
the value is text, it will be parsed as if it was provided from the
|
1118 |
+
command line. If the value is a non-string iterable, it will be iterated
|
1119 |
+
over to create a shallow copy of the values. If it is None, it is left
|
1120 |
+
as-is.
|
1121 |
+
help: str, the help message.
|
1122 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1123 |
+
flag will be registered. This should almost never need to be overridden.
|
1124 |
+
module_name: A string, the name of the Python module declaring this flag. If
|
1125 |
+
not provided, it will be computed using the stack trace of this call.
|
1126 |
+
required: bool, is this a required flag. This must be used as a keyword
|
1127 |
+
argument.
|
1128 |
+
**args: Dictionary with extra keyword args that are passed to the
|
1129 |
+
``Flag.__init__``.
|
1130 |
+
|
1131 |
+
Returns:
|
1132 |
+
a handle to defined flag.
|
1133 |
+
"""
|
1134 |
+
result = DEFINE_flag(
|
1135 |
+
_flag.MultiFlag(parser, serializer, name, default, help, **args),
|
1136 |
+
flag_values,
|
1137 |
+
module_name,
|
1138 |
+
required=True if required else False,
|
1139 |
+
)
|
1140 |
+
return result
|
1141 |
+
|
1142 |
+
|
1143 |
+
@overload
|
1144 |
+
def DEFINE_multi_string( # pylint: disable=invalid-name
|
1145 |
+
name: Text,
|
1146 |
+
default: Union[None, Iterable[Text], Text],
|
1147 |
+
help: Text, # pylint: disable=redefined-builtin
|
1148 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1149 |
+
*,
|
1150 |
+
required: 'typing.Literal[True]',
|
1151 |
+
**args: Any
|
1152 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
1153 |
+
...
|
1154 |
+
|
1155 |
+
|
1156 |
+
@overload
|
1157 |
+
def DEFINE_multi_string( # pylint: disable=invalid-name
|
1158 |
+
name: Text,
|
1159 |
+
default: None,
|
1160 |
+
help: Text, # pylint: disable=redefined-builtin
|
1161 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1162 |
+
required: bool = ...,
|
1163 |
+
**args: Any
|
1164 |
+
) -> _flagvalues.FlagHolder[Optional[List[Text]]]:
|
1165 |
+
...
|
1166 |
+
|
1167 |
+
|
1168 |
+
@overload
|
1169 |
+
def DEFINE_multi_string( # pylint: disable=invalid-name
|
1170 |
+
name: Text,
|
1171 |
+
default: Union[Iterable[Text], Text],
|
1172 |
+
help: Text, # pylint: disable=redefined-builtin
|
1173 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1174 |
+
required: bool = ...,
|
1175 |
+
**args: Any
|
1176 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
1177 |
+
...
|
1178 |
+
|
1179 |
+
|
1180 |
+
def DEFINE_multi_string( # pylint: disable=invalid-name,redefined-builtin
|
1181 |
+
name,
|
1182 |
+
default,
|
1183 |
+
help,
|
1184 |
+
flag_values=_flagvalues.FLAGS,
|
1185 |
+
required=False,
|
1186 |
+
**args):
|
1187 |
+
"""Registers a flag whose value can be a list of any strings.
|
1188 |
+
|
1189 |
+
Use the flag on the command line multiple times to place multiple
|
1190 |
+
string values into the list. The 'default' may be a single string
|
1191 |
+
(which will be converted into a single-element list) or a list of
|
1192 |
+
strings.
|
1193 |
+
|
1194 |
+
|
1195 |
+
Args:
|
1196 |
+
name: str, the flag name.
|
1197 |
+
default: Union[Iterable[Text], Text, None], the default value of the flag;
|
1198 |
+
see :func:`DEFINE_multi`.
|
1199 |
+
help: str, the help message.
|
1200 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1201 |
+
flag will be registered. This should almost never need to be overridden.
|
1202 |
+
required: bool, is this a required flag. This must be used as a keyword
|
1203 |
+
argument.
|
1204 |
+
**args: Dictionary with extra keyword args that are passed to the
|
1205 |
+
``Flag.__init__``.
|
1206 |
+
|
1207 |
+
Returns:
|
1208 |
+
a handle to defined flag.
|
1209 |
+
"""
|
1210 |
+
parser = _argument_parser.ArgumentParser()
|
1211 |
+
serializer = _argument_parser.ArgumentSerializer()
|
1212 |
+
return DEFINE_multi(
|
1213 |
+
parser,
|
1214 |
+
serializer,
|
1215 |
+
name,
|
1216 |
+
default,
|
1217 |
+
help,
|
1218 |
+
flag_values,
|
1219 |
+
required=True if required else False,
|
1220 |
+
**args,
|
1221 |
+
)
|
1222 |
+
|
1223 |
+
|
1224 |
+
@overload
|
1225 |
+
def DEFINE_multi_integer( # pylint: disable=invalid-name
|
1226 |
+
name: Text,
|
1227 |
+
default: Union[None, Iterable[int], int, Text],
|
1228 |
+
help: Text, # pylint: disable=redefined-builtin
|
1229 |
+
lower_bound: Optional[int] = ...,
|
1230 |
+
upper_bound: Optional[int] = ...,
|
1231 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1232 |
+
*,
|
1233 |
+
required: 'typing.Literal[True]',
|
1234 |
+
**args: Any
|
1235 |
+
) -> _flagvalues.FlagHolder[List[int]]:
|
1236 |
+
...
|
1237 |
+
|
1238 |
+
|
1239 |
+
@overload
|
1240 |
+
def DEFINE_multi_integer( # pylint: disable=invalid-name
|
1241 |
+
name: Text,
|
1242 |
+
default: None,
|
1243 |
+
help: Text, # pylint: disable=redefined-builtin
|
1244 |
+
lower_bound: Optional[int] = ...,
|
1245 |
+
upper_bound: Optional[int] = ...,
|
1246 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1247 |
+
required: bool = ...,
|
1248 |
+
**args: Any
|
1249 |
+
) -> _flagvalues.FlagHolder[Optional[List[int]]]:
|
1250 |
+
...
|
1251 |
+
|
1252 |
+
|
1253 |
+
@overload
|
1254 |
+
def DEFINE_multi_integer( # pylint: disable=invalid-name
|
1255 |
+
name: Text,
|
1256 |
+
default: Union[Iterable[int], int, Text],
|
1257 |
+
help: Text, # pylint: disable=redefined-builtin
|
1258 |
+
lower_bound: Optional[int] = ...,
|
1259 |
+
upper_bound: Optional[int] = ...,
|
1260 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1261 |
+
required: bool = ...,
|
1262 |
+
**args: Any
|
1263 |
+
) -> _flagvalues.FlagHolder[List[int]]:
|
1264 |
+
...
|
1265 |
+
|
1266 |
+
|
1267 |
+
def DEFINE_multi_integer( # pylint: disable=invalid-name,redefined-builtin
|
1268 |
+
name,
|
1269 |
+
default,
|
1270 |
+
help,
|
1271 |
+
lower_bound=None,
|
1272 |
+
upper_bound=None,
|
1273 |
+
flag_values=_flagvalues.FLAGS,
|
1274 |
+
required=False,
|
1275 |
+
**args):
|
1276 |
+
"""Registers a flag whose value can be a list of arbitrary integers.
|
1277 |
+
|
1278 |
+
Use the flag on the command line multiple times to place multiple
|
1279 |
+
integer values into the list. The 'default' may be a single integer
|
1280 |
+
(which will be converted into a single-element list) or a list of
|
1281 |
+
integers.
|
1282 |
+
|
1283 |
+
Args:
|
1284 |
+
name: str, the flag name.
|
1285 |
+
default: Union[Iterable[int], Text, None], the default value of the flag;
|
1286 |
+
see `DEFINE_multi`.
|
1287 |
+
help: str, the help message.
|
1288 |
+
lower_bound: int, min values of the flag.
|
1289 |
+
upper_bound: int, max values of the flag.
|
1290 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1291 |
+
flag will be registered. This should almost never need to be overridden.
|
1292 |
+
required: bool, is this a required flag. This must be used as a keyword
|
1293 |
+
argument.
|
1294 |
+
**args: Dictionary with extra keyword args that are passed to the
|
1295 |
+
``Flag.__init__``.
|
1296 |
+
|
1297 |
+
Returns:
|
1298 |
+
a handle to defined flag.
|
1299 |
+
"""
|
1300 |
+
parser = _argument_parser.IntegerParser(lower_bound, upper_bound)
|
1301 |
+
serializer = _argument_parser.ArgumentSerializer()
|
1302 |
+
return DEFINE_multi(
|
1303 |
+
parser,
|
1304 |
+
serializer,
|
1305 |
+
name,
|
1306 |
+
default,
|
1307 |
+
help,
|
1308 |
+
flag_values,
|
1309 |
+
required=True if required else False,
|
1310 |
+
**args,
|
1311 |
+
)
|
1312 |
+
|
1313 |
+
|
1314 |
+
@overload
|
1315 |
+
def DEFINE_multi_float( # pylint: disable=invalid-name
|
1316 |
+
name: Text,
|
1317 |
+
default: Union[None, Iterable[float], float, Text],
|
1318 |
+
help: Text, # pylint: disable=redefined-builtin
|
1319 |
+
lower_bound: Optional[float] = ...,
|
1320 |
+
upper_bound: Optional[float] = ...,
|
1321 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1322 |
+
*,
|
1323 |
+
required: 'typing.Literal[True]',
|
1324 |
+
**args: Any
|
1325 |
+
) -> _flagvalues.FlagHolder[List[float]]:
|
1326 |
+
...
|
1327 |
+
|
1328 |
+
|
1329 |
+
@overload
|
1330 |
+
def DEFINE_multi_float( # pylint: disable=invalid-name
|
1331 |
+
name: Text,
|
1332 |
+
default: None,
|
1333 |
+
help: Text, # pylint: disable=redefined-builtin
|
1334 |
+
lower_bound: Optional[float] = ...,
|
1335 |
+
upper_bound: Optional[float] = ...,
|
1336 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1337 |
+
required: bool = ...,
|
1338 |
+
**args: Any
|
1339 |
+
) -> _flagvalues.FlagHolder[Optional[List[float]]]:
|
1340 |
+
...
|
1341 |
+
|
1342 |
+
|
1343 |
+
@overload
|
1344 |
+
def DEFINE_multi_float( # pylint: disable=invalid-name
|
1345 |
+
name: Text,
|
1346 |
+
default: Union[Iterable[float], float, Text],
|
1347 |
+
help: Text, # pylint: disable=redefined-builtin
|
1348 |
+
lower_bound: Optional[float] = ...,
|
1349 |
+
upper_bound: Optional[float] = ...,
|
1350 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1351 |
+
required: bool = ...,
|
1352 |
+
**args: Any
|
1353 |
+
) -> _flagvalues.FlagHolder[List[float]]:
|
1354 |
+
...
|
1355 |
+
|
1356 |
+
|
1357 |
+
def DEFINE_multi_float( # pylint: disable=invalid-name,redefined-builtin
|
1358 |
+
name,
|
1359 |
+
default,
|
1360 |
+
help,
|
1361 |
+
lower_bound=None,
|
1362 |
+
upper_bound=None,
|
1363 |
+
flag_values=_flagvalues.FLAGS,
|
1364 |
+
required=False,
|
1365 |
+
**args):
|
1366 |
+
"""Registers a flag whose value can be a list of arbitrary floats.
|
1367 |
+
|
1368 |
+
Use the flag on the command line multiple times to place multiple
|
1369 |
+
float values into the list. The 'default' may be a single float
|
1370 |
+
(which will be converted into a single-element list) or a list of
|
1371 |
+
floats.
|
1372 |
+
|
1373 |
+
Args:
|
1374 |
+
name: str, the flag name.
|
1375 |
+
default: Union[Iterable[float], Text, None], the default value of the flag;
|
1376 |
+
see `DEFINE_multi`.
|
1377 |
+
help: str, the help message.
|
1378 |
+
lower_bound: float, min values of the flag.
|
1379 |
+
upper_bound: float, max values of the flag.
|
1380 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1381 |
+
flag will be registered. This should almost never need to be overridden.
|
1382 |
+
required: bool, is this a required flag. This must be used as a keyword
|
1383 |
+
argument.
|
1384 |
+
**args: Dictionary with extra keyword args that are passed to the
|
1385 |
+
``Flag.__init__``.
|
1386 |
+
|
1387 |
+
Returns:
|
1388 |
+
a handle to defined flag.
|
1389 |
+
"""
|
1390 |
+
parser = _argument_parser.FloatParser(lower_bound, upper_bound)
|
1391 |
+
serializer = _argument_parser.ArgumentSerializer()
|
1392 |
+
return DEFINE_multi(
|
1393 |
+
parser,
|
1394 |
+
serializer,
|
1395 |
+
name,
|
1396 |
+
default,
|
1397 |
+
help,
|
1398 |
+
flag_values,
|
1399 |
+
required=True if required else False,
|
1400 |
+
**args,
|
1401 |
+
)
|
1402 |
+
|
1403 |
+
|
1404 |
+
@overload
|
1405 |
+
def DEFINE_multi_enum( # pylint: disable=invalid-name
|
1406 |
+
name: Text,
|
1407 |
+
default: Union[None, Iterable[Text], Text],
|
1408 |
+
enum_values: Iterable[Text],
|
1409 |
+
help: Text, # pylint: disable=redefined-builtin
|
1410 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1411 |
+
*,
|
1412 |
+
required: 'typing.Literal[True]',
|
1413 |
+
**args: Any
|
1414 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
1415 |
+
...
|
1416 |
+
|
1417 |
+
|
1418 |
+
@overload
|
1419 |
+
def DEFINE_multi_enum( # pylint: disable=invalid-name
|
1420 |
+
name: Text,
|
1421 |
+
default: None,
|
1422 |
+
enum_values: Iterable[Text],
|
1423 |
+
help: Text, # pylint: disable=redefined-builtin
|
1424 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1425 |
+
required: bool = ...,
|
1426 |
+
**args: Any
|
1427 |
+
) -> _flagvalues.FlagHolder[Optional[List[Text]]]:
|
1428 |
+
...
|
1429 |
+
|
1430 |
+
|
1431 |
+
@overload
|
1432 |
+
def DEFINE_multi_enum( # pylint: disable=invalid-name
|
1433 |
+
name: Text,
|
1434 |
+
default: Union[Iterable[Text], Text],
|
1435 |
+
enum_values: Iterable[Text],
|
1436 |
+
help: Text, # pylint: disable=redefined-builtin
|
1437 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1438 |
+
required: bool = ...,
|
1439 |
+
**args: Any
|
1440 |
+
) -> _flagvalues.FlagHolder[List[Text]]:
|
1441 |
+
...
|
1442 |
+
|
1443 |
+
|
1444 |
+
def DEFINE_multi_enum( # pylint: disable=invalid-name,redefined-builtin
|
1445 |
+
name,
|
1446 |
+
default,
|
1447 |
+
enum_values,
|
1448 |
+
help,
|
1449 |
+
flag_values=_flagvalues.FLAGS,
|
1450 |
+
case_sensitive=True,
|
1451 |
+
required=False,
|
1452 |
+
**args):
|
1453 |
+
"""Registers a flag whose value can be a list strings from enum_values.
|
1454 |
+
|
1455 |
+
Use the flag on the command line multiple times to place multiple
|
1456 |
+
enum values into the list. The 'default' may be a single string
|
1457 |
+
(which will be converted into a single-element list) or a list of
|
1458 |
+
strings.
|
1459 |
+
|
1460 |
+
Args:
|
1461 |
+
name: str, the flag name.
|
1462 |
+
default: Union[Iterable[Text], Text, None], the default value of the flag;
|
1463 |
+
see `DEFINE_multi`.
|
1464 |
+
enum_values: [str], a non-empty list of strings with the possible values for
|
1465 |
+
the flag.
|
1466 |
+
help: str, the help message.
|
1467 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1468 |
+
flag will be registered. This should almost never need to be overridden.
|
1469 |
+
case_sensitive: Whether or not the enum is to be case-sensitive.
|
1470 |
+
required: bool, is this a required flag. This must be used as a keyword
|
1471 |
+
argument.
|
1472 |
+
**args: Dictionary with extra keyword args that are passed to the
|
1473 |
+
``Flag.__init__``.
|
1474 |
+
|
1475 |
+
Returns:
|
1476 |
+
a handle to defined flag.
|
1477 |
+
"""
|
1478 |
+
parser = _argument_parser.EnumParser(enum_values, case_sensitive)
|
1479 |
+
serializer = _argument_parser.ArgumentSerializer()
|
1480 |
+
return DEFINE_multi(
|
1481 |
+
parser,
|
1482 |
+
serializer,
|
1483 |
+
name,
|
1484 |
+
default,
|
1485 |
+
'<%s>: %s' % ('|'.join(enum_values), help),
|
1486 |
+
flag_values,
|
1487 |
+
required=True if required else False,
|
1488 |
+
**args,
|
1489 |
+
)
|
1490 |
+
|
1491 |
+
|
1492 |
+
@overload
|
1493 |
+
def DEFINE_multi_enum_class( # pylint: disable=invalid-name
|
1494 |
+
name: Text,
|
1495 |
+
# This is separate from `Union[None, _ET, Iterable[Text], Text]` to avoid a
|
1496 |
+
# Pytype issue inferring the return value to
|
1497 |
+
# FlagHolder[List[Union[_ET, enum.Enum]]] when an iterable of concrete enum
|
1498 |
+
# subclasses are used.
|
1499 |
+
default: Iterable[_ET],
|
1500 |
+
enum_class: Type[_ET],
|
1501 |
+
help: Text, # pylint: disable=redefined-builtin
|
1502 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1503 |
+
module_name: Optional[Text] = ...,
|
1504 |
+
*,
|
1505 |
+
required: 'typing.Literal[True]',
|
1506 |
+
**args: Any
|
1507 |
+
) -> _flagvalues.FlagHolder[List[_ET]]:
|
1508 |
+
...
|
1509 |
+
|
1510 |
+
|
1511 |
+
@overload
|
1512 |
+
def DEFINE_multi_enum_class( # pylint: disable=invalid-name
|
1513 |
+
name: Text,
|
1514 |
+
default: Union[None, _ET, Iterable[Text], Text],
|
1515 |
+
enum_class: Type[_ET],
|
1516 |
+
help: Text, # pylint: disable=redefined-builtin
|
1517 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1518 |
+
module_name: Optional[Text] = ...,
|
1519 |
+
*,
|
1520 |
+
required: 'typing.Literal[True]',
|
1521 |
+
**args: Any
|
1522 |
+
) -> _flagvalues.FlagHolder[List[_ET]]:
|
1523 |
+
...
|
1524 |
+
|
1525 |
+
|
1526 |
+
@overload
|
1527 |
+
def DEFINE_multi_enum_class( # pylint: disable=invalid-name
|
1528 |
+
name: Text,
|
1529 |
+
default: None,
|
1530 |
+
enum_class: Type[_ET],
|
1531 |
+
help: Text, # pylint: disable=redefined-builtin
|
1532 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1533 |
+
module_name: Optional[Text] = ...,
|
1534 |
+
required: bool = ...,
|
1535 |
+
**args: Any
|
1536 |
+
) -> _flagvalues.FlagHolder[Optional[List[_ET]]]:
|
1537 |
+
...
|
1538 |
+
|
1539 |
+
|
1540 |
+
@overload
|
1541 |
+
def DEFINE_multi_enum_class( # pylint: disable=invalid-name
|
1542 |
+
name: Text,
|
1543 |
+
# This is separate from `Union[None, _ET, Iterable[Text], Text]` to avoid a
|
1544 |
+
# Pytype issue inferring the return value to
|
1545 |
+
# FlagHolder[List[Union[_ET, enum.Enum]]] when an iterable of concrete enum
|
1546 |
+
# subclasses are used.
|
1547 |
+
default: Iterable[_ET],
|
1548 |
+
enum_class: Type[_ET],
|
1549 |
+
help: Text, # pylint: disable=redefined-builtin
|
1550 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1551 |
+
module_name: Optional[Text] = ...,
|
1552 |
+
required: bool = ...,
|
1553 |
+
**args: Any
|
1554 |
+
) -> _flagvalues.FlagHolder[List[_ET]]:
|
1555 |
+
...
|
1556 |
+
|
1557 |
+
|
1558 |
+
@overload
|
1559 |
+
def DEFINE_multi_enum_class( # pylint: disable=invalid-name
|
1560 |
+
name: Text,
|
1561 |
+
default: Union[_ET, Iterable[Text], Text],
|
1562 |
+
enum_class: Type[_ET],
|
1563 |
+
help: Text, # pylint: disable=redefined-builtin
|
1564 |
+
flag_values: _flagvalues.FlagValues = ...,
|
1565 |
+
module_name: Optional[Text] = ...,
|
1566 |
+
required: bool = ...,
|
1567 |
+
**args: Any
|
1568 |
+
) -> _flagvalues.FlagHolder[List[_ET]]:
|
1569 |
+
...
|
1570 |
+
|
1571 |
+
|
1572 |
+
def DEFINE_multi_enum_class( # pylint: disable=invalid-name,redefined-builtin
|
1573 |
+
name,
|
1574 |
+
default,
|
1575 |
+
enum_class,
|
1576 |
+
help,
|
1577 |
+
flag_values=_flagvalues.FLAGS,
|
1578 |
+
module_name=None,
|
1579 |
+
case_sensitive=False,
|
1580 |
+
required=False,
|
1581 |
+
**args):
|
1582 |
+
"""Registers a flag whose value can be a list of enum members.
|
1583 |
+
|
1584 |
+
Use the flag on the command line multiple times to place multiple
|
1585 |
+
enum values into the list.
|
1586 |
+
|
1587 |
+
Args:
|
1588 |
+
name: str, the flag name.
|
1589 |
+
default: Union[Iterable[Enum], Iterable[Text], Enum, Text, None], the
|
1590 |
+
default value of the flag; see `DEFINE_multi`; only differences are
|
1591 |
+
documented here. If the value is a single Enum, it is treated as a
|
1592 |
+
single-item list of that Enum value. If it is an iterable, text values
|
1593 |
+
within the iterable will be converted to the equivalent Enum objects.
|
1594 |
+
enum_class: class, the Enum class with all the possible values for the flag.
|
1595 |
+
help: str, the help message.
|
1596 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1597 |
+
flag will be registered. This should almost never need to be overridden.
|
1598 |
+
module_name: A string, the name of the Python module declaring this flag. If
|
1599 |
+
not provided, it will be computed using the stack trace of this call.
|
1600 |
+
case_sensitive: bool, whether to map strings to members of the enum_class
|
1601 |
+
without considering case.
|
1602 |
+
required: bool, is this a required flag. This must be used as a keyword
|
1603 |
+
argument.
|
1604 |
+
**args: Dictionary with extra keyword args that are passed to the
|
1605 |
+
``Flag.__init__``.
|
1606 |
+
|
1607 |
+
Returns:
|
1608 |
+
a handle to defined flag.
|
1609 |
+
"""
|
1610 |
+
# NOTE: pytype fails if this is a direct return.
|
1611 |
+
result = DEFINE_flag(
|
1612 |
+
_flag.MultiEnumClassFlag(
|
1613 |
+
name,
|
1614 |
+
default,
|
1615 |
+
help,
|
1616 |
+
enum_class,
|
1617 |
+
case_sensitive=case_sensitive,
|
1618 |
+
**args,
|
1619 |
+
),
|
1620 |
+
flag_values,
|
1621 |
+
module_name,
|
1622 |
+
required=True if required else False,
|
1623 |
+
)
|
1624 |
+
return result
|
1625 |
+
|
1626 |
+
|
1627 |
+
def DEFINE_alias( # pylint: disable=invalid-name
|
1628 |
+
name: Text,
|
1629 |
+
original_name: Text,
|
1630 |
+
flag_values: _flagvalues.FlagValues = _flagvalues.FLAGS,
|
1631 |
+
module_name: Optional[Text] = None,
|
1632 |
+
) -> _flagvalues.FlagHolder[Any]:
|
1633 |
+
"""Defines an alias flag for an existing one.
|
1634 |
+
|
1635 |
+
Args:
|
1636 |
+
name: str, the flag name.
|
1637 |
+
original_name: str, the original flag name.
|
1638 |
+
flag_values: :class:`FlagValues`, the FlagValues instance with which the
|
1639 |
+
flag will be registered. This should almost never need to be overridden.
|
1640 |
+
module_name: A string, the name of the module that defines this flag.
|
1641 |
+
|
1642 |
+
Returns:
|
1643 |
+
a handle to defined flag.
|
1644 |
+
|
1645 |
+
Raises:
|
1646 |
+
flags.FlagError:
|
1647 |
+
UnrecognizedFlagError: if the referenced flag doesn't exist.
|
1648 |
+
DuplicateFlagError: if the alias name has been used by some existing flag.
|
1649 |
+
"""
|
1650 |
+
if original_name not in flag_values:
|
1651 |
+
raise _exceptions.UnrecognizedFlagError(original_name)
|
1652 |
+
flag = flag_values[original_name]
|
1653 |
+
|
1654 |
+
class _FlagAlias(_flag.Flag):
|
1655 |
+
"""Overrides Flag class so alias value is copy of original flag value."""
|
1656 |
+
|
1657 |
+
def parse(self, argument):
|
1658 |
+
flag.parse(argument)
|
1659 |
+
self.present += 1
|
1660 |
+
|
1661 |
+
def _parse_from_default(self, value):
|
1662 |
+
# The value was already parsed by the aliased flag, so there is no
|
1663 |
+
# need to call the parser on it a second time.
|
1664 |
+
# Additionally, because of how MultiFlag parses and merges values,
|
1665 |
+
# it isn't possible to delegate to the aliased flag and still get
|
1666 |
+
# the correct values.
|
1667 |
+
return value
|
1668 |
+
|
1669 |
+
@property
|
1670 |
+
def value(self):
|
1671 |
+
return flag.value
|
1672 |
+
|
1673 |
+
@value.setter
|
1674 |
+
def value(self, value):
|
1675 |
+
flag.value = value
|
1676 |
+
|
1677 |
+
help_msg = 'Alias for --%s.' % flag.name
|
1678 |
+
# If alias_name has been used, flags.DuplicatedFlag will be raised.
|
1679 |
+
return DEFINE_flag(
|
1680 |
+
_FlagAlias(
|
1681 |
+
flag.parser,
|
1682 |
+
flag.serializer,
|
1683 |
+
name,
|
1684 |
+
flag.default,
|
1685 |
+
help_msg,
|
1686 |
+
boolean=flag.boolean), flag_values, module_name)
|
venv/lib/python3.11/site-packages/absl/flags/_exceptions.py
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
|
15 |
+
"""Exception classes in ABSL flags library.
|
16 |
+
|
17 |
+
Do NOT import this module directly. Import the flags package and use the
|
18 |
+
aliases defined at the package level instead.
|
19 |
+
"""
|
20 |
+
|
21 |
+
import sys
|
22 |
+
|
23 |
+
from absl.flags import _helpers
|
24 |
+
|
25 |
+
|
26 |
+
_helpers.disclaim_module_ids.add(id(sys.modules[__name__]))
|
27 |
+
|
28 |
+
|
29 |
+
class Error(Exception):
|
30 |
+
"""The base class for all flags errors."""
|
31 |
+
|
32 |
+
|
33 |
+
class CantOpenFlagFileError(Error):
|
34 |
+
"""Raised when flagfile fails to open.
|
35 |
+
|
36 |
+
E.g. the file doesn't exist, or has wrong permissions.
|
37 |
+
"""
|
38 |
+
|
39 |
+
|
40 |
+
class DuplicateFlagError(Error):
|
41 |
+
"""Raised if there is a flag naming conflict."""
|
42 |
+
|
43 |
+
@classmethod
|
44 |
+
def from_flag(cls, flagname, flag_values, other_flag_values=None):
|
45 |
+
"""Creates a DuplicateFlagError by providing flag name and values.
|
46 |
+
|
47 |
+
Args:
|
48 |
+
flagname: str, the name of the flag being redefined.
|
49 |
+
flag_values: :class:`FlagValues`, the FlagValues instance containing the
|
50 |
+
first definition of flagname.
|
51 |
+
other_flag_values: :class:`FlagValues`, if it is not None, it should be
|
52 |
+
the FlagValues object where the second definition of flagname occurs.
|
53 |
+
If it is None, we assume that we're being called when attempting to
|
54 |
+
create the flag a second time, and we use the module calling this one
|
55 |
+
as the source of the second definition.
|
56 |
+
|
57 |
+
Returns:
|
58 |
+
An instance of DuplicateFlagError.
|
59 |
+
"""
|
60 |
+
first_module = flag_values.find_module_defining_flag(
|
61 |
+
flagname, default='<unknown>')
|
62 |
+
if other_flag_values is None:
|
63 |
+
second_module = _helpers.get_calling_module()
|
64 |
+
else:
|
65 |
+
second_module = other_flag_values.find_module_defining_flag(
|
66 |
+
flagname, default='<unknown>')
|
67 |
+
flag_summary = flag_values[flagname].help
|
68 |
+
msg = ("The flag '%s' is defined twice. First from %s, Second from %s. "
|
69 |
+
"Description from first occurrence: %s") % (
|
70 |
+
flagname, first_module, second_module, flag_summary)
|
71 |
+
return cls(msg)
|
72 |
+
|
73 |
+
|
74 |
+
class IllegalFlagValueError(Error):
|
75 |
+
"""Raised when the flag command line argument is illegal."""
|
76 |
+
|
77 |
+
|
78 |
+
class UnrecognizedFlagError(Error):
|
79 |
+
"""Raised when a flag is unrecognized.
|
80 |
+
|
81 |
+
Attributes:
|
82 |
+
flagname: str, the name of the unrecognized flag.
|
83 |
+
flagvalue: The value of the flag, empty if the flag is not defined.
|
84 |
+
"""
|
85 |
+
|
86 |
+
def __init__(self, flagname, flagvalue='', suggestions=None):
|
87 |
+
self.flagname = flagname
|
88 |
+
self.flagvalue = flagvalue
|
89 |
+
if suggestions:
|
90 |
+
# Space before the question mark is intentional to not include it in the
|
91 |
+
# selection when copy-pasting the suggestion from (some) terminals.
|
92 |
+
tip = '. Did you mean: %s ?' % ', '.join(suggestions)
|
93 |
+
else:
|
94 |
+
tip = ''
|
95 |
+
super(UnrecognizedFlagError, self).__init__(
|
96 |
+
'Unknown command line flag \'%s\'%s' % (flagname, tip))
|
97 |
+
|
98 |
+
|
99 |
+
class UnparsedFlagAccessError(Error):
|
100 |
+
"""Raised when accessing the flag value from unparsed :class:`FlagValues`."""
|
101 |
+
|
102 |
+
|
103 |
+
class ValidationError(Error):
|
104 |
+
"""Raised when flag validator constraint is not satisfied."""
|
105 |
+
|
106 |
+
|
107 |
+
class FlagNameConflictsWithMethodError(Error):
|
108 |
+
"""Raised when a flag name conflicts with :class:`FlagValues` methods."""
|
venv/lib/python3.11/site-packages/absl/flags/_flag.py
ADDED
@@ -0,0 +1,556 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
|
15 |
+
"""Contains Flag class - information about single command-line flag.
|
16 |
+
|
17 |
+
Do NOT import this module directly. Import the flags package and use the
|
18 |
+
aliases defined at the package level instead.
|
19 |
+
"""
|
20 |
+
|
21 |
+
from collections import abc
|
22 |
+
import copy
|
23 |
+
import enum
|
24 |
+
import functools
|
25 |
+
from typing import Any, Dict, Generic, Iterable, List, Optional, Text, Type, TypeVar, Union
|
26 |
+
from xml.dom import minidom
|
27 |
+
|
28 |
+
from absl.flags import _argument_parser
|
29 |
+
from absl.flags import _exceptions
|
30 |
+
from absl.flags import _helpers
|
31 |
+
|
32 |
+
_T = TypeVar('_T')
|
33 |
+
_ET = TypeVar('_ET', bound=enum.Enum)
|
34 |
+
|
35 |
+
|
36 |
+
@functools.total_ordering
|
37 |
+
class Flag(Generic[_T]):
|
38 |
+
"""Information about a command-line flag.
|
39 |
+
|
40 |
+
Attributes:
|
41 |
+
name: the name for this flag
|
42 |
+
default: the default value for this flag
|
43 |
+
default_unparsed: the unparsed default value for this flag.
|
44 |
+
default_as_str: default value as repr'd string, e.g., "'true'"
|
45 |
+
(or None)
|
46 |
+
value: the most recent parsed value of this flag set by :meth:`parse`
|
47 |
+
help: a help string or None if no help is available
|
48 |
+
short_name: the single letter alias for this flag (or None)
|
49 |
+
boolean: if 'true', this flag does not accept arguments
|
50 |
+
present: true if this flag was parsed from command line flags
|
51 |
+
parser: an :class:`~absl.flags.ArgumentParser` object
|
52 |
+
serializer: an ArgumentSerializer object
|
53 |
+
allow_override: the flag may be redefined without raising an error,
|
54 |
+
and newly defined flag overrides the old one.
|
55 |
+
allow_override_cpp: use the flag from C++ if available the flag
|
56 |
+
definition is replaced by the C++ flag after init
|
57 |
+
allow_hide_cpp: use the Python flag despite having a C++ flag with
|
58 |
+
the same name (ignore the C++ flag)
|
59 |
+
using_default_value: the flag value has not been set by user
|
60 |
+
allow_overwrite: the flag may be parsed more than once without
|
61 |
+
raising an error, the last set value will be used
|
62 |
+
allow_using_method_names: whether this flag can be defined even if
|
63 |
+
it has a name that conflicts with a FlagValues method.
|
64 |
+
validators: list of the flag validators.
|
65 |
+
|
66 |
+
The only public method of a ``Flag`` object is :meth:`parse`, but it is
|
67 |
+
typically only called by a :class:`~absl.flags.FlagValues` object. The
|
68 |
+
:meth:`parse` method is a thin wrapper around the
|
69 |
+
:meth:`ArgumentParser.parse()<absl.flags.ArgumentParser.parse>` method. The
|
70 |
+
parsed value is saved in ``.value``, and the ``.present`` attribute is
|
71 |
+
updated. If this flag was already present, an Error is raised.
|
72 |
+
|
73 |
+
:meth:`parse` is also called during ``__init__`` to parse the default value
|
74 |
+
and initialize the ``.value`` attribute. This enables other python modules to
|
75 |
+
safely use flags even if the ``__main__`` module neglects to parse the
|
76 |
+
command line arguments. The ``.present`` attribute is cleared after
|
77 |
+
``__init__`` parsing. If the default value is set to ``None``, then the
|
78 |
+
``__init__`` parsing step is skipped and the ``.value`` attribute is
|
79 |
+
initialized to None.
|
80 |
+
|
81 |
+
Note: The default value is also presented to the user in the help
|
82 |
+
string, so it is important that it be a legal value for this flag.
|
83 |
+
"""
|
84 |
+
|
85 |
+
# NOTE: pytype doesn't find defaults without this.
|
86 |
+
default: Optional[_T]
|
87 |
+
default_as_str: Optional[Text]
|
88 |
+
default_unparsed: Union[Optional[_T], Text]
|
89 |
+
|
90 |
+
def __init__(
|
91 |
+
self,
|
92 |
+
parser: _argument_parser.ArgumentParser[_T],
|
93 |
+
serializer: Optional[_argument_parser.ArgumentSerializer[_T]],
|
94 |
+
name: Text,
|
95 |
+
default: Union[Optional[_T], Text],
|
96 |
+
help_string: Optional[Text],
|
97 |
+
short_name: Optional[Text] = None,
|
98 |
+
boolean: bool = False,
|
99 |
+
allow_override: bool = False,
|
100 |
+
allow_override_cpp: bool = False,
|
101 |
+
allow_hide_cpp: bool = False,
|
102 |
+
allow_overwrite: bool = True,
|
103 |
+
allow_using_method_names: bool = False,
|
104 |
+
) -> None:
|
105 |
+
self.name = name
|
106 |
+
|
107 |
+
if not help_string:
|
108 |
+
help_string = '(no help available)'
|
109 |
+
|
110 |
+
self.help = help_string
|
111 |
+
self.short_name = short_name
|
112 |
+
self.boolean = boolean
|
113 |
+
self.present = 0
|
114 |
+
self.parser = parser
|
115 |
+
self.serializer = serializer
|
116 |
+
self.allow_override = allow_override
|
117 |
+
self.allow_override_cpp = allow_override_cpp
|
118 |
+
self.allow_hide_cpp = allow_hide_cpp
|
119 |
+
self.allow_overwrite = allow_overwrite
|
120 |
+
self.allow_using_method_names = allow_using_method_names
|
121 |
+
|
122 |
+
self.using_default_value = True
|
123 |
+
self._value = None
|
124 |
+
self.validators = []
|
125 |
+
if self.allow_hide_cpp and self.allow_override_cpp:
|
126 |
+
raise _exceptions.Error(
|
127 |
+
"Can't have both allow_hide_cpp (means use Python flag) and "
|
128 |
+
'allow_override_cpp (means use C++ flag after InitGoogle)')
|
129 |
+
|
130 |
+
self._set_default(default)
|
131 |
+
|
132 |
+
@property
|
133 |
+
def value(self) -> Optional[_T]:
|
134 |
+
return self._value
|
135 |
+
|
136 |
+
@value.setter
|
137 |
+
def value(self, value: Optional[_T]):
|
138 |
+
self._value = value
|
139 |
+
|
140 |
+
def __hash__(self):
|
141 |
+
return hash(id(self))
|
142 |
+
|
143 |
+
def __eq__(self, other):
|
144 |
+
return self is other
|
145 |
+
|
146 |
+
def __lt__(self, other):
|
147 |
+
if isinstance(other, Flag):
|
148 |
+
return id(self) < id(other)
|
149 |
+
return NotImplemented
|
150 |
+
|
151 |
+
def __bool__(self):
|
152 |
+
raise TypeError('A Flag instance would always be True. '
|
153 |
+
'Did you mean to test the `.value` attribute?')
|
154 |
+
|
155 |
+
def __getstate__(self):
|
156 |
+
raise TypeError("can't pickle Flag objects")
|
157 |
+
|
158 |
+
def __copy__(self):
|
159 |
+
raise TypeError('%s does not support shallow copies. '
|
160 |
+
'Use copy.deepcopy instead.' % type(self).__name__)
|
161 |
+
|
162 |
+
def __deepcopy__(self, memo: Dict[int, Any]) -> 'Flag[_T]':
|
163 |
+
result = object.__new__(type(self))
|
164 |
+
result.__dict__ = copy.deepcopy(self.__dict__, memo)
|
165 |
+
return result
|
166 |
+
|
167 |
+
def _get_parsed_value_as_string(self, value: Optional[_T]) -> Optional[Text]:
|
168 |
+
"""Returns parsed flag value as string."""
|
169 |
+
if value is None:
|
170 |
+
return None
|
171 |
+
if self.serializer:
|
172 |
+
return repr(self.serializer.serialize(value))
|
173 |
+
if self.boolean:
|
174 |
+
if value:
|
175 |
+
return repr('true')
|
176 |
+
else:
|
177 |
+
return repr('false')
|
178 |
+
return repr(str(value))
|
179 |
+
|
180 |
+
def parse(self, argument: Union[Text, Optional[_T]]) -> None:
|
181 |
+
"""Parses string and sets flag value.
|
182 |
+
|
183 |
+
Args:
|
184 |
+
argument: str or the correct flag value type, argument to be parsed.
|
185 |
+
"""
|
186 |
+
if self.present and not self.allow_overwrite:
|
187 |
+
raise _exceptions.IllegalFlagValueError(
|
188 |
+
'flag --%s=%s: already defined as %s' % (
|
189 |
+
self.name, argument, self.value))
|
190 |
+
self.value = self._parse(argument)
|
191 |
+
self.present += 1
|
192 |
+
|
193 |
+
def _parse(self, argument: Union[Text, _T]) -> Optional[_T]:
|
194 |
+
"""Internal parse function.
|
195 |
+
|
196 |
+
It returns the parsed value, and does not modify class states.
|
197 |
+
|
198 |
+
Args:
|
199 |
+
argument: str or the correct flag value type, argument to be parsed.
|
200 |
+
|
201 |
+
Returns:
|
202 |
+
The parsed value.
|
203 |
+
"""
|
204 |
+
try:
|
205 |
+
return self.parser.parse(argument)
|
206 |
+
except (TypeError, ValueError) as e: # Recast as IllegalFlagValueError.
|
207 |
+
raise _exceptions.IllegalFlagValueError(
|
208 |
+
'flag --%s=%s: %s' % (self.name, argument, e))
|
209 |
+
|
210 |
+
def unparse(self) -> None:
|
211 |
+
self.value = self.default
|
212 |
+
self.using_default_value = True
|
213 |
+
self.present = 0
|
214 |
+
|
215 |
+
def serialize(self) -> Text:
|
216 |
+
"""Serializes the flag."""
|
217 |
+
return self._serialize(self.value)
|
218 |
+
|
219 |
+
def _serialize(self, value: Optional[_T]) -> Text:
|
220 |
+
"""Internal serialize function."""
|
221 |
+
if value is None:
|
222 |
+
return ''
|
223 |
+
if self.boolean:
|
224 |
+
if value:
|
225 |
+
return '--%s' % self.name
|
226 |
+
else:
|
227 |
+
return '--no%s' % self.name
|
228 |
+
else:
|
229 |
+
if not self.serializer:
|
230 |
+
raise _exceptions.Error(
|
231 |
+
'Serializer not present for flag %s' % self.name)
|
232 |
+
return '--%s=%s' % (self.name, self.serializer.serialize(value))
|
233 |
+
|
234 |
+
def _set_default(self, value: Union[Optional[_T], Text]) -> None:
|
235 |
+
"""Changes the default value (and current value too) for this Flag."""
|
236 |
+
self.default_unparsed = value
|
237 |
+
if value is None:
|
238 |
+
self.default = None
|
239 |
+
else:
|
240 |
+
self.default = self._parse_from_default(value)
|
241 |
+
self.default_as_str = self._get_parsed_value_as_string(self.default)
|
242 |
+
if self.using_default_value:
|
243 |
+
self.value = self.default
|
244 |
+
|
245 |
+
# This is split out so that aliases can skip regular parsing of the default
|
246 |
+
# value.
|
247 |
+
def _parse_from_default(self, value: Union[Text, _T]) -> Optional[_T]:
|
248 |
+
return self._parse(value)
|
249 |
+
|
250 |
+
def flag_type(self) -> Text:
|
251 |
+
"""Returns a str that describes the type of the flag.
|
252 |
+
|
253 |
+
NOTE: we use strings, and not the types.*Type constants because
|
254 |
+
our flags can have more exotic types, e.g., 'comma separated list
|
255 |
+
of strings', 'whitespace separated list of strings', etc.
|
256 |
+
"""
|
257 |
+
return self.parser.flag_type()
|
258 |
+
|
259 |
+
def _create_xml_dom_element(
|
260 |
+
self, doc: minidom.Document, module_name: str, is_key: bool = False
|
261 |
+
) -> minidom.Element:
|
262 |
+
"""Returns an XML element that contains this flag's information.
|
263 |
+
|
264 |
+
This is information that is relevant to all flags (e.g., name,
|
265 |
+
meaning, etc.). If you defined a flag that has some other pieces of
|
266 |
+
info, then please override _ExtraXMLInfo.
|
267 |
+
|
268 |
+
Please do NOT override this method.
|
269 |
+
|
270 |
+
Args:
|
271 |
+
doc: minidom.Document, the DOM document it should create nodes from.
|
272 |
+
module_name: str,, the name of the module that defines this flag.
|
273 |
+
is_key: boolean, True iff this flag is key for main module.
|
274 |
+
|
275 |
+
Returns:
|
276 |
+
A minidom.Element instance.
|
277 |
+
"""
|
278 |
+
element = doc.createElement('flag')
|
279 |
+
if is_key:
|
280 |
+
element.appendChild(_helpers.create_xml_dom_element(doc, 'key', 'yes'))
|
281 |
+
element.appendChild(_helpers.create_xml_dom_element(
|
282 |
+
doc, 'file', module_name))
|
283 |
+
# Adds flag features that are relevant for all flags.
|
284 |
+
element.appendChild(_helpers.create_xml_dom_element(doc, 'name', self.name))
|
285 |
+
if self.short_name:
|
286 |
+
element.appendChild(_helpers.create_xml_dom_element(
|
287 |
+
doc, 'short_name', self.short_name))
|
288 |
+
if self.help:
|
289 |
+
element.appendChild(_helpers.create_xml_dom_element(
|
290 |
+
doc, 'meaning', self.help))
|
291 |
+
# The default flag value can either be represented as a string like on the
|
292 |
+
# command line, or as a Python object. We serialize this value in the
|
293 |
+
# latter case in order to remain consistent.
|
294 |
+
if self.serializer and not isinstance(self.default, str):
|
295 |
+
if self.default is not None:
|
296 |
+
default_serialized = self.serializer.serialize(self.default)
|
297 |
+
else:
|
298 |
+
default_serialized = ''
|
299 |
+
else:
|
300 |
+
default_serialized = self.default
|
301 |
+
element.appendChild(_helpers.create_xml_dom_element(
|
302 |
+
doc, 'default', default_serialized))
|
303 |
+
value_serialized = self._serialize_value_for_xml(self.value)
|
304 |
+
element.appendChild(_helpers.create_xml_dom_element(
|
305 |
+
doc, 'current', value_serialized))
|
306 |
+
element.appendChild(_helpers.create_xml_dom_element(
|
307 |
+
doc, 'type', self.flag_type()))
|
308 |
+
# Adds extra flag features this flag may have.
|
309 |
+
for e in self._extra_xml_dom_elements(doc):
|
310 |
+
element.appendChild(e)
|
311 |
+
return element
|
312 |
+
|
313 |
+
def _serialize_value_for_xml(self, value: Optional[_T]) -> Any:
|
314 |
+
"""Returns the serialized value, for use in an XML help text."""
|
315 |
+
return value
|
316 |
+
|
317 |
+
def _extra_xml_dom_elements(
|
318 |
+
self, doc: minidom.Document
|
319 |
+
) -> List[minidom.Element]:
|
320 |
+
"""Returns extra info about this flag in XML.
|
321 |
+
|
322 |
+
"Extra" means "not already included by _create_xml_dom_element above."
|
323 |
+
|
324 |
+
Args:
|
325 |
+
doc: minidom.Document, the DOM document it should create nodes from.
|
326 |
+
|
327 |
+
Returns:
|
328 |
+
A list of minidom.Element.
|
329 |
+
"""
|
330 |
+
# Usually, the parser knows the extra details about the flag, so
|
331 |
+
# we just forward the call to it.
|
332 |
+
return self.parser._custom_xml_dom_elements(doc) # pylint: disable=protected-access
|
333 |
+
|
334 |
+
|
335 |
+
class BooleanFlag(Flag[bool]):
|
336 |
+
"""Basic boolean flag.
|
337 |
+
|
338 |
+
Boolean flags do not take any arguments, and their value is either
|
339 |
+
``True`` (1) or ``False`` (0). The false value is specified on the command
|
340 |
+
line by prepending the word ``'no'`` to either the long or the short flag
|
341 |
+
name.
|
342 |
+
|
343 |
+
For example, if a Boolean flag was created whose long name was
|
344 |
+
``'update'`` and whose short name was ``'x'``, then this flag could be
|
345 |
+
explicitly unset through either ``--noupdate`` or ``--nox``.
|
346 |
+
"""
|
347 |
+
|
348 |
+
def __init__(
|
349 |
+
self,
|
350 |
+
name: Text,
|
351 |
+
default: Union[Optional[bool], Text],
|
352 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
353 |
+
short_name: Optional[Text] = None,
|
354 |
+
**args
|
355 |
+
) -> None:
|
356 |
+
p = _argument_parser.BooleanParser()
|
357 |
+
super(BooleanFlag, self).__init__(
|
358 |
+
p, None, name, default, help, short_name, True, **args
|
359 |
+
)
|
360 |
+
|
361 |
+
|
362 |
+
class EnumFlag(Flag[Text]):
|
363 |
+
"""Basic enum flag; its value can be any string from list of enum_values."""
|
364 |
+
|
365 |
+
def __init__(
|
366 |
+
self,
|
367 |
+
name: Text,
|
368 |
+
default: Optional[Text],
|
369 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
370 |
+
enum_values: Iterable[Text],
|
371 |
+
short_name: Optional[Text] = None,
|
372 |
+
case_sensitive: bool = True,
|
373 |
+
**args
|
374 |
+
):
|
375 |
+
p = _argument_parser.EnumParser(enum_values, case_sensitive)
|
376 |
+
g = _argument_parser.ArgumentSerializer()
|
377 |
+
super(EnumFlag, self).__init__(
|
378 |
+
p, g, name, default, help, short_name, **args)
|
379 |
+
# NOTE: parser should be typed EnumParser but the constructor
|
380 |
+
# restricts the available interface to ArgumentParser[str].
|
381 |
+
self.parser = p
|
382 |
+
self.help = '<%s>: %s' % ('|'.join(p.enum_values), self.help)
|
383 |
+
|
384 |
+
def _extra_xml_dom_elements(
|
385 |
+
self, doc: minidom.Document
|
386 |
+
) -> List[minidom.Element]:
|
387 |
+
elements = []
|
388 |
+
for enum_value in self.parser.enum_values:
|
389 |
+
elements.append(_helpers.create_xml_dom_element(
|
390 |
+
doc, 'enum_value', enum_value))
|
391 |
+
return elements
|
392 |
+
|
393 |
+
|
394 |
+
class EnumClassFlag(Flag[_ET]):
|
395 |
+
"""Basic enum flag; its value is an enum class's member."""
|
396 |
+
|
397 |
+
def __init__(
|
398 |
+
self,
|
399 |
+
name: Text,
|
400 |
+
default: Union[Optional[_ET], Text],
|
401 |
+
help: Optional[Text], # pylint: disable=redefined-builtin
|
402 |
+
enum_class: Type[_ET],
|
403 |
+
short_name: Optional[Text] = None,
|
404 |
+
case_sensitive: bool = False,
|
405 |
+
**args
|
406 |
+
):
|
407 |
+
p = _argument_parser.EnumClassParser(
|
408 |
+
enum_class, case_sensitive=case_sensitive)
|
409 |
+
g = _argument_parser.EnumClassSerializer(lowercase=not case_sensitive)
|
410 |
+
super(EnumClassFlag, self).__init__(
|
411 |
+
p, g, name, default, help, short_name, **args)
|
412 |
+
# NOTE: parser should be typed EnumClassParser[_ET] but the constructor
|
413 |
+
# restricts the available interface to ArgumentParser[_ET].
|
414 |
+
self.parser = p
|
415 |
+
self.help = '<%s>: %s' % ('|'.join(p.member_names), self.help)
|
416 |
+
|
417 |
+
def _extra_xml_dom_elements(
|
418 |
+
self, doc: minidom.Document
|
419 |
+
) -> List[minidom.Element]:
|
420 |
+
elements = []
|
421 |
+
for enum_value in self.parser.enum_class.__members__.keys():
|
422 |
+
elements.append(_helpers.create_xml_dom_element(
|
423 |
+
doc, 'enum_value', enum_value))
|
424 |
+
return elements
|
425 |
+
|
426 |
+
|
427 |
+
class MultiFlag(Generic[_T], Flag[List[_T]]):
|
428 |
+
"""A flag that can appear multiple time on the command-line.
|
429 |
+
|
430 |
+
The value of such a flag is a list that contains the individual values
|
431 |
+
from all the appearances of that flag on the command-line.
|
432 |
+
|
433 |
+
See the __doc__ for Flag for most behavior of this class. Only
|
434 |
+
differences in behavior are described here:
|
435 |
+
|
436 |
+
* The default value may be either a single value or an iterable of values.
|
437 |
+
A single value is transformed into a single-item list of that value.
|
438 |
+
|
439 |
+
* The value of the flag is always a list, even if the option was
|
440 |
+
only supplied once, and even if the default value is a single
|
441 |
+
value
|
442 |
+
"""
|
443 |
+
|
444 |
+
def __init__(self, *args, **kwargs):
|
445 |
+
super(MultiFlag, self).__init__(*args, **kwargs)
|
446 |
+
self.help += ';\n repeat this option to specify a list of values'
|
447 |
+
|
448 |
+
def parse(self, arguments: Union[Text, _T, Iterable[_T]]): # pylint: disable=arguments-renamed
|
449 |
+
"""Parses one or more arguments with the installed parser.
|
450 |
+
|
451 |
+
Args:
|
452 |
+
arguments: a single argument or a list of arguments (typically a
|
453 |
+
list of default values); a single argument is converted
|
454 |
+
internally into a list containing one item.
|
455 |
+
"""
|
456 |
+
new_values = self._parse(arguments)
|
457 |
+
if self.present:
|
458 |
+
self.value.extend(new_values)
|
459 |
+
else:
|
460 |
+
self.value = new_values
|
461 |
+
self.present += len(new_values)
|
462 |
+
|
463 |
+
def _parse(self, arguments: Union[Text, Optional[Iterable[_T]]]) -> List[_T]: # pylint: disable=arguments-renamed
|
464 |
+
if (isinstance(arguments, abc.Iterable) and
|
465 |
+
not isinstance(arguments, str)):
|
466 |
+
arguments = list(arguments)
|
467 |
+
|
468 |
+
if not isinstance(arguments, list):
|
469 |
+
# Default value may be a list of values. Most other arguments
|
470 |
+
# will not be, so convert them into a single-item list to make
|
471 |
+
# processing simpler below.
|
472 |
+
arguments = [arguments]
|
473 |
+
|
474 |
+
return [super(MultiFlag, self)._parse(item) for item in arguments]
|
475 |
+
|
476 |
+
def _serialize(self, value: Optional[List[_T]]) -> Text:
|
477 |
+
"""See base class."""
|
478 |
+
if not self.serializer:
|
479 |
+
raise _exceptions.Error(
|
480 |
+
'Serializer not present for flag %s' % self.name)
|
481 |
+
if value is None:
|
482 |
+
return ''
|
483 |
+
|
484 |
+
serialized_items = [
|
485 |
+
super(MultiFlag, self)._serialize(value_item) for value_item in value
|
486 |
+
]
|
487 |
+
|
488 |
+
return '\n'.join(serialized_items)
|
489 |
+
|
490 |
+
def flag_type(self):
|
491 |
+
"""See base class."""
|
492 |
+
return 'multi ' + self.parser.flag_type()
|
493 |
+
|
494 |
+
def _extra_xml_dom_elements(
|
495 |
+
self, doc: minidom.Document
|
496 |
+
) -> List[minidom.Element]:
|
497 |
+
elements = []
|
498 |
+
if hasattr(self.parser, 'enum_values'):
|
499 |
+
for enum_value in self.parser.enum_values: # pytype: disable=attribute-error
|
500 |
+
elements.append(_helpers.create_xml_dom_element(
|
501 |
+
doc, 'enum_value', enum_value))
|
502 |
+
return elements
|
503 |
+
|
504 |
+
|
505 |
+
class MultiEnumClassFlag(MultiFlag[_ET]): # pytype: disable=not-indexable
|
506 |
+
"""A multi_enum_class flag.
|
507 |
+
|
508 |
+
See the __doc__ for MultiFlag for most behaviors of this class. In addition,
|
509 |
+
this class knows how to handle enum.Enum instances as values for this flag
|
510 |
+
type.
|
511 |
+
"""
|
512 |
+
|
513 |
+
def __init__(
|
514 |
+
self,
|
515 |
+
name: str,
|
516 |
+
default: Union[None, Iterable[_ET], _ET, Iterable[Text], Text],
|
517 |
+
help_string: str,
|
518 |
+
enum_class: Type[_ET],
|
519 |
+
case_sensitive: bool = False,
|
520 |
+
**args
|
521 |
+
):
|
522 |
+
p = _argument_parser.EnumClassParser(
|
523 |
+
enum_class, case_sensitive=case_sensitive)
|
524 |
+
g = _argument_parser.EnumClassListSerializer(
|
525 |
+
list_sep=',', lowercase=not case_sensitive)
|
526 |
+
super(MultiEnumClassFlag, self).__init__(
|
527 |
+
p, g, name, default, help_string, **args)
|
528 |
+
# NOTE: parser should be typed EnumClassParser[_ET] but the constructor
|
529 |
+
# restricts the available interface to ArgumentParser[str].
|
530 |
+
self.parser = p
|
531 |
+
# NOTE: serializer should be non-Optional but this isn't inferred.
|
532 |
+
self.serializer = g
|
533 |
+
self.help = (
|
534 |
+
'<%s>: %s;\n repeat this option to specify a list of values' %
|
535 |
+
('|'.join(p.member_names), help_string or '(no help available)'))
|
536 |
+
|
537 |
+
def _extra_xml_dom_elements(
|
538 |
+
self, doc: minidom.Document
|
539 |
+
) -> List[minidom.Element]:
|
540 |
+
elements = []
|
541 |
+
for enum_value in self.parser.enum_class.__members__.keys(): # pytype: disable=attribute-error
|
542 |
+
elements.append(_helpers.create_xml_dom_element(
|
543 |
+
doc, 'enum_value', enum_value))
|
544 |
+
return elements
|
545 |
+
|
546 |
+
def _serialize_value_for_xml(self, value):
|
547 |
+
"""See base class."""
|
548 |
+
if value is not None:
|
549 |
+
if not self.serializer:
|
550 |
+
raise _exceptions.Error(
|
551 |
+
'Serializer not present for flag %s' % self.name
|
552 |
+
)
|
553 |
+
value_serialized = self.serializer.serialize(value)
|
554 |
+
else:
|
555 |
+
value_serialized = ''
|
556 |
+
return value_serialized
|
venv/lib/python3.11/site-packages/absl/flags/_flagvalues.py
ADDED
@@ -0,0 +1,1480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The Abseil Authors.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
"""Defines the FlagValues class - registry of 'Flag' objects.
|
15 |
+
|
16 |
+
Do NOT import this module directly. Import the flags package and use the
|
17 |
+
aliases defined at the package level instead.
|
18 |
+
"""
|
19 |
+
|
20 |
+
import copy
|
21 |
+
import itertools
|
22 |
+
import logging
|
23 |
+
import os
|
24 |
+
import sys
|
25 |
+
from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Sequence, Text, TextIO, Generic, TypeVar, Union, Tuple
|
26 |
+
from xml.dom import minidom
|
27 |
+
|
28 |
+
from absl.flags import _exceptions
|
29 |
+
from absl.flags import _flag
|
30 |
+
from absl.flags import _helpers
|
31 |
+
from absl.flags import _validators_classes
|
32 |
+
from absl.flags._flag import Flag
|
33 |
+
|
34 |
+
# Add flagvalues module to disclaimed module ids.
|
35 |
+
_helpers.disclaim_module_ids.add(id(sys.modules[__name__]))
|
36 |
+
|
37 |
+
_T = TypeVar('_T')
|
38 |
+
|
39 |
+
|
40 |
+
class FlagValues:
|
41 |
+
"""Registry of :class:`~absl.flags.Flag` objects.
|
42 |
+
|
43 |
+
A :class:`FlagValues` can then scan command line arguments, passing flag
|
44 |
+
arguments through to the 'Flag' objects that it owns. It also
|
45 |
+
provides easy access to the flag values. Typically only one
|
46 |
+
:class:`FlagValues` object is needed by an application:
|
47 |
+
:const:`FLAGS`.
|
48 |
+
|
49 |
+
This class is heavily overloaded:
|
50 |
+
|
51 |
+
:class:`Flag` objects are registered via ``__setitem__``::
|
52 |
+
|
53 |
+
FLAGS['longname'] = x # register a new flag
|
54 |
+
|
55 |
+
The ``.value`` attribute of the registered :class:`~absl.flags.Flag` objects
|
56 |
+
can be accessed as attributes of this :class:`FlagValues` object, through
|
57 |
+
``__getattr__``. Both the long and short name of the original
|
58 |
+
:class:`~absl.flags.Flag` objects can be used to access its value::
|
59 |
+
|
60 |
+
FLAGS.longname # parsed flag value
|
61 |
+
FLAGS.x # parsed flag value (short name)
|
62 |
+
|
63 |
+
Command line arguments are scanned and passed to the registered
|
64 |
+
:class:`~absl.flags.Flag` objects through the ``__call__`` method. Unparsed
|
65 |
+
arguments, including ``argv[0]`` (e.g. the program name) are returned::
|
66 |
+
|
67 |
+
argv = FLAGS(sys.argv) # scan command line arguments
|
68 |
+
|
69 |
+
The original registered :class:`~absl.flags.Flag` objects can be retrieved
|
70 |
+
through the use of the dictionary-like operator, ``__getitem__``::
|
71 |
+
|
72 |
+
x = FLAGS['longname'] # access the registered Flag object
|
73 |
+
|
74 |
+
The ``str()`` operator of a :class:`absl.flags.FlagValues` object provides
|
75 |
+
help for all of the registered :class:`~absl.flags.Flag` objects.
|
76 |
+
"""
|
77 |
+
|
78 |
+
_HAS_DYNAMIC_ATTRIBUTES = True
|
79 |
+
|
80 |
+
# A note on collections.abc.Mapping:
|
81 |
+
# FlagValues defines __getitem__, __iter__, and __len__. It makes perfect
|
82 |
+
# sense to let it be a collections.abc.Mapping class. However, we are not
|
83 |
+
# able to do so. The mixin methods, e.g. keys, values, are not uncommon flag
|
84 |
+
# names. Those flag values would not be accessible via the FLAGS.xxx form.
|
85 |
+
|
86 |
+
__dict__: Dict[str, Any]
|
87 |
+
|
88 |
+
def __init__(self):
|
89 |
+
# Since everything in this class is so heavily overloaded, the only
|
90 |
+
# way of defining and using fields is to access __dict__ directly.
|
91 |
+
|
92 |
+
# Dictionary: flag name (string) -> Flag object.
|
93 |
+
self.__dict__['__flags'] = {}
|
94 |
+
|
95 |
+
# Set: name of hidden flag (string).
|
96 |
+
# Holds flags that should not be directly accessible from Python.
|
97 |
+
self.__dict__['__hiddenflags'] = set()
|
98 |
+
|
99 |
+
# Dictionary: module name (string) -> list of Flag objects that are defined
|
100 |
+
# by that module.
|
101 |
+
self.__dict__['__flags_by_module'] = {}
|
102 |
+
# Dictionary: module id (int) -> list of Flag objects that are defined by
|
103 |
+
# that module.
|
104 |
+
self.__dict__['__flags_by_module_id'] = {}
|
105 |
+
# Dictionary: module name (string) -> list of Flag objects that are
|
106 |
+
# key for that module.
|
107 |
+
self.__dict__['__key_flags_by_module'] = {}
|
108 |
+
|
109 |
+
# Bool: True if flags were parsed.
|
110 |
+
self.__dict__['__flags_parsed'] = False
|
111 |
+
|
112 |
+
# Bool: True if unparse_flags() was called.
|
113 |
+
self.__dict__['__unparse_flags_called'] = False
|
114 |
+
|
115 |
+
# None or Method(name, value) to call from __setattr__ for an unknown flag.
|
116 |
+
self.__dict__['__set_unknown'] = None
|
117 |
+
|
118 |
+
# A set of banned flag names. This is to prevent users from accidentally
|
119 |
+
# defining a flag that has the same name as a method on this class.
|
120 |
+
# Users can still allow defining the flag by passing
|
121 |
+
# allow_using_method_names=True in DEFINE_xxx functions.
|
122 |
+
self.__dict__['__banned_flag_names'] = frozenset(dir(FlagValues))
|
123 |
+
|
124 |
+
# Bool: Whether to use GNU style scanning.
|
125 |
+
self.__dict__['__use_gnu_getopt'] = True
|
126 |
+
|
127 |
+
# Bool: Whether use_gnu_getopt has been explicitly set by the user.
|
128 |
+
self.__dict__['__use_gnu_getopt_explicitly_set'] = False
|
129 |
+
|
130 |
+
# Function: Takes a flag name as parameter, returns a tuple
|
131 |
+
# (is_retired, type_is_bool).
|
132 |
+
self.__dict__['__is_retired_flag_func'] = None
|
133 |
+
|
134 |
+
def set_gnu_getopt(self, gnu_getopt: bool = True) -> None:
|
135 |
+
"""Sets whether or not to use GNU style scanning.
|
136 |
+
|
137 |
+
GNU style allows mixing of flag and non-flag arguments. See
|
138 |
+
http://docs.python.org/library/getopt.html#getopt.gnu_getopt
|
139 |
+
|
140 |
+
Args:
|
141 |
+
gnu_getopt: bool, whether or not to use GNU style scanning.
|
142 |
+
"""
|
143 |
+
self.__dict__['__use_gnu_getopt'] = gnu_getopt
|
144 |
+
self.__dict__['__use_gnu_getopt_explicitly_set'] = True
|
145 |
+
|
146 |
+
def is_gnu_getopt(self) -> bool:
|
147 |
+
return self.__dict__['__use_gnu_getopt']
|
148 |
+
|
149 |
+
def _flags(self) -> Dict[Text, Flag]:
|
150 |
+
return self.__dict__['__flags']
|
151 |
+
|
152 |
+
def flags_by_module_dict(self) -> Dict[Text, List[Flag]]:
|
153 |
+
"""Returns the dictionary of module_name -> list of defined flags.
|
154 |
+
|
155 |
+
Returns:
|
156 |
+
A dictionary. Its keys are module names (strings). Its values
|
157 |
+
are lists of Flag objects.
|
158 |
+
"""
|
159 |
+
return self.__dict__['__flags_by_module']
|
160 |
+
|
161 |
+
def flags_by_module_id_dict(self) -> Dict[int, List[Flag]]:
|
162 |
+
"""Returns the dictionary of module_id -> list of defined flags.
|
163 |
+
|
164 |
+
Returns:
|
165 |
+
A dictionary. Its keys are module IDs (ints). Its values
|
166 |
+
are lists of Flag objects.
|
167 |
+
"""
|
168 |
+
return self.__dict__['__flags_by_module_id']
|
169 |
+
|
170 |
+
def key_flags_by_module_dict(self) -> Dict[Text, List[Flag]]:
|
171 |
+
"""Returns the dictionary of module_name -> list of key flags.
|
172 |
+
|
173 |
+
Returns:
|
174 |
+
A dictionary. Its keys are module names (strings). Its values
|
175 |
+
are lists of Flag objects.
|
176 |
+
"""
|
177 |
+
return self.__dict__['__key_flags_by_module']
|
178 |
+
|
179 |
+
def register_flag_by_module(self, module_name: Text, flag: Flag) -> None:
|
180 |
+
"""Records the module that defines a specific flag.
|
181 |
+
|
182 |
+
We keep track of which flag is defined by which module so that we
|
183 |
+
can later sort the flags by module.
|
184 |
+
|
185 |
+
Args:
|
186 |
+
module_name: str, the name of a Python module.
|
187 |
+
flag: Flag, the Flag instance that is key to the module.
|
188 |
+
"""
|
189 |
+
flags_by_module = self.flags_by_module_dict()
|
190 |
+
flags_by_module.setdefault(module_name, []).append(flag)
|
191 |
+
|
192 |
+
def register_flag_by_module_id(self, module_id: int, flag: Flag) -> None:
|
193 |
+
"""Records the module that defines a specific flag.
|
194 |
+
|
195 |
+
Args:
|
196 |
+
module_id: int, the ID of the Python module.
|
197 |
+
flag: Flag, the Flag instance that is key to the module.
|
198 |
+
"""
|
199 |
+
flags_by_module_id = self.flags_by_module_id_dict()
|
200 |
+
flags_by_module_id.setdefault(module_id, []).append(flag)
|
201 |
+
|
202 |
+
def register_key_flag_for_module(self, module_name: Text, flag: Flag) -> None:
|
203 |
+
"""Specifies that a flag is a key flag for a module.
|
204 |
+
|
205 |
+
Args:
|
206 |
+
module_name: str, the name of a Python module.
|
207 |
+
flag: Flag, the Flag instance that is key to the module.
|
208 |
+
"""
|
209 |
+
key_flags_by_module = self.key_flags_by_module_dict()
|
210 |
+
# The list of key flags for the module named module_name.
|
211 |
+
key_flags = key_flags_by_module.setdefault(module_name, [])
|
212 |
+
# Add flag, but avoid duplicates.
|
213 |
+
if flag not in key_flags:
|
214 |
+
key_flags.append(flag)
|
215 |
+
|
216 |
+
def _flag_is_registered(self, flag_obj: Flag) -> bool:
|
217 |
+
"""Checks whether a Flag object is registered under long name or short name.
|
218 |
+
|
219 |
+
Args:
|
220 |
+
flag_obj: Flag, the Flag instance to check for.
|
221 |
+
|
222 |
+
Returns:
|
223 |
+
bool, True iff flag_obj is registered under long name or short name.
|
224 |
+
"""
|
225 |
+
flag_dict = self._flags()
|
226 |
+
# Check whether flag_obj is registered under its long name.
|
227 |
+
name = flag_obj.name
|
228 |
+
if flag_dict.get(name, None) == flag_obj:
|
229 |
+
return True
|
230 |
+
# Check whether flag_obj is registered under its short name.
|
231 |
+
short_name = flag_obj.short_name
|
232 |
+
if (short_name is not None and flag_dict.get(short_name, None) == flag_obj):
|
233 |
+
return True
|
234 |
+
return False
|
235 |
+
|
236 |
+
def _cleanup_unregistered_flag_from_module_dicts(
|
237 |
+
self, flag_obj: Flag
|
238 |
+
) -> None:
|
239 |
+
"""Cleans up unregistered flags from all module -> [flags] dictionaries.
|
240 |
+
|
241 |
+
If flag_obj is registered under either its long name or short name, it
|
242 |
+
won't be removed from the dictionaries.
|
243 |
+
|
244 |
+
Args:
|
245 |
+
flag_obj: Flag, the Flag instance to clean up for.
|
246 |
+
"""
|
247 |
+
if self._flag_is_registered(flag_obj):
|
248 |
+
return
|
249 |
+
for flags_by_module_dict in (self.flags_by_module_dict(),
|
250 |
+
self.flags_by_module_id_dict(),
|
251 |
+
self.key_flags_by_module_dict()):
|
252 |
+
for flags_in_module in flags_by_module_dict.values():
|
253 |
+
# While (as opposed to if) takes care of multiple occurrences of a
|
254 |
+
# flag in the list for the same module.
|
255 |
+
while flag_obj in flags_in_module:
|
256 |
+
flags_in_module.remove(flag_obj)
|
257 |
+
|
258 |
+
def get_flags_for_module(self, module: Union[Text, Any]) -> List[Flag]:
|
259 |
+
"""Returns the list of flags defined by a module.
|
260 |
+
|
261 |
+
Args:
|
262 |
+
module: module|str, the module to get flags from.
|
263 |
+
|
264 |
+
Returns:
|
265 |
+
[Flag], a new list of Flag instances. Caller may update this list as
|
266 |
+
desired: none of those changes will affect the internals of this
|
267 |
+
FlagValue instance.
|
268 |
+
"""
|
269 |
+
if not isinstance(module, str):
|
270 |
+
module = module.__name__
|
271 |
+
if module == '__main__':
|
272 |
+
module = sys.argv[0]
|
273 |
+
|
274 |
+
return list(self.flags_by_module_dict().get(module, []))
|
275 |
+
|
276 |
+
def get_key_flags_for_module(self, module: Union[Text, Any]) -> List[Flag]:
|
277 |
+
"""Returns the list of key flags for a module.
|
278 |
+
|
279 |
+
Args:
|
280 |
+
module: module|str, the module to get key flags from.
|
281 |
+
|
282 |
+
Returns:
|
283 |
+
[Flag], a new list of Flag instances. Caller may update this list as
|
284 |
+
desired: none of those changes will affect the internals of this
|
285 |
+
FlagValue instance.
|
286 |
+
"""
|
287 |
+
if not isinstance(module, str):
|
288 |
+
module = module.__name__
|
289 |
+
if module == '__main__':
|
290 |
+
module = sys.argv[0]
|
291 |
+
|
292 |
+
# Any flag is a key flag for the module that defined it. NOTE:
|
293 |
+
# key_flags is a fresh list: we can update it without affecting the
|
294 |
+
# internals of this FlagValues object.
|
295 |
+
key_flags = self.get_flags_for_module(module)
|
296 |
+
|
297 |
+
# Take into account flags explicitly declared as key for a module.
|
298 |
+
for flag in self.key_flags_by_module_dict().get(module, []):
|
299 |
+
if flag not in key_flags:
|
300 |
+
key_flags.append(flag)
|
301 |
+
return key_flags
|
302 |
+
|
303 |
+
# TODO(yileiyang): Restrict default to Optional[Text].
|
304 |
+
def find_module_defining_flag(
|
305 |
+
self, flagname: Text, default: Optional[_T] = None
|
306 |
+
) -> Union[str, Optional[_T]]:
|
307 |
+
"""Return the name of the module defining this flag, or default.
|
308 |
+
|
309 |
+
Args:
|
310 |
+
flagname: str, name of the flag to lookup.
|
311 |
+
default: Value to return if flagname is not defined. Defaults to None.
|
312 |
+
|
313 |
+
Returns:
|
314 |
+
The name of the module which registered the flag with this name.
|
315 |
+
If no such module exists (i.e. no flag with this name exists),
|
316 |
+
we return default.
|
317 |
+
"""
|
318 |
+
registered_flag = self._flags().get(flagname)
|
319 |
+
if registered_flag is None:
|
320 |
+
return default
|
321 |
+
for module, flags in self.flags_by_module_dict().items():
|
322 |
+
for flag in flags:
|
323 |
+
# It must compare the flag with the one in _flags. This is because a
|
324 |
+
# flag might be overridden only for its long name (or short name),
|
325 |
+
# and only its short name (or long name) is considered registered.
|
326 |
+
if (flag.name == registered_flag.name and
|
327 |
+
flag.short_name == registered_flag.short_name):
|
328 |
+
return module
|
329 |
+
return default
|
330 |
+
|
331 |
+
# TODO(yileiyang): Restrict default to Optional[Text].
|
332 |
+
def find_module_id_defining_flag(
|
333 |
+
self, flagname: Text, default: Optional[_T] = None
|
334 |
+
) -> Union[int, Optional[_T]]:
|
335 |
+
"""Return the ID of the module defining this flag, or default.
|
336 |
+
|
337 |
+
Args:
|
338 |
+
flagname: str, name of the flag to lookup.
|
339 |
+
default: Value to return if flagname is not defined. Defaults to None.
|
340 |
+
|
341 |
+
Returns:
|
342 |
+
The ID of the module which registered the flag with this name.
|
343 |
+
If no such module exists (i.e. no flag with this name exists),
|
344 |
+
we return default.
|
345 |
+
"""
|
346 |
+
registered_flag = self._flags().get(flagname)
|
347 |
+
if registered_flag is None:
|
348 |
+
return default
|
349 |
+
for module_id, flags in self.flags_by_module_id_dict().items():
|
350 |
+
for flag in flags:
|
351 |
+
# It must compare the flag with the one in _flags. This is because a
|
352 |
+
# flag might be overridden only for its long name (or short name),
|
353 |
+
# and only its short name (or long name) is considered registered.
|
354 |
+
if (flag.name == registered_flag.name and
|
355 |
+
flag.short_name == registered_flag.short_name):
|
356 |
+
return module_id
|
357 |
+
return default
|
358 |
+
|
359 |
+
def _register_unknown_flag_setter(
|
360 |
+
self, setter: Callable[[str, Any], None]
|
361 |
+
) -> None:
|
362 |
+
"""Allow set default values for undefined flags.
|
363 |
+
|
364 |
+
Args:
|
365 |
+
setter: Method(name, value) to call to __setattr__ an unknown flag. Must
|
366 |
+
raise NameError or ValueError for invalid name/value.
|
367 |
+
"""
|
368 |
+
self.__dict__['__set_unknown'] = setter
|
369 |
+
|
370 |
+
def _set_unknown_flag(self, name: str, value: _T) -> _T:
|
371 |
+
"""Returns value if setting flag |name| to |value| returned True.
|
372 |
+
|
373 |
+
Args:
|
374 |
+
name: str, name of the flag to set.
|
375 |
+
value: Value to set.
|
376 |
+
|
377 |
+
Returns:
|
378 |
+
Flag value on successful call.
|
379 |
+
|
380 |
+
Raises:
|
381 |
+
UnrecognizedFlagError
|
382 |
+
IllegalFlagValueError
|
383 |
+
"""
|
384 |
+
setter = self.__dict__['__set_unknown']
|
385 |
+
if setter:
|
386 |
+
try:
|
387 |
+
setter(name, value)
|
388 |
+
return value
|
389 |
+
except (TypeError, ValueError): # Flag value is not valid.
|
390 |
+
raise _exceptions.IllegalFlagValueError(
|
391 |
+
'"{1}" is not valid for --{0}'.format(name, value))
|
392 |
+
except NameError: # Flag name is not valid.
|
393 |
+
pass
|
394 |
+
raise _exceptions.UnrecognizedFlagError(name, value)
|
395 |
+
|
396 |
+
def append_flag_values(self, flag_values: 'FlagValues') -> None:
|
397 |
+
"""Appends flags registered in another FlagValues instance.
|
398 |
+
|
399 |
+
Args:
|
400 |
+
flag_values: FlagValues, the FlagValues instance from which to copy flags.
|
401 |
+
"""
|
402 |
+
for flag_name, flag in flag_values._flags().items(): # pylint: disable=protected-access
|
403 |
+
# Each flags with short_name appears here twice (once under its
|
404 |
+
# normal name, and again with its short name). To prevent
|
405 |
+
# problems (DuplicateFlagError) with double flag registration, we
|
406 |
+
# perform a check to make sure that the entry we're looking at is
|
407 |
+
# for its normal name.
|
408 |
+
if flag_name == flag.name:
|
409 |
+
try:
|
410 |
+
self[flag_name] = flag
|
411 |
+
except _exceptions.DuplicateFlagError:
|
412 |
+
raise _exceptions.DuplicateFlagError.from_flag(
|
413 |
+
flag_name, self, other_flag_values=flag_values)
|
414 |
+
|
415 |
+
def remove_flag_values(
|
416 |
+
self, flag_values: 'Union[FlagValues, Iterable[Text]]'
|
417 |
+
) -> None:
|
418 |
+
"""Remove flags that were previously appended from another FlagValues.
|
419 |
+
|
420 |
+
Args:
|
421 |
+
flag_values: FlagValues, the FlagValues instance containing flags to
|
422 |
+
remove.
|
423 |
+
"""
|
424 |
+
for flag_name in flag_values:
|
425 |
+
self.__delattr__(flag_name)
|
426 |
+
|
427 |
+
def __setitem__(self, name: Text, flag: Flag) -> None:
|
428 |
+
"""Registers a new flag variable."""
|
429 |
+
fl = self._flags()
|
430 |
+
if not isinstance(flag, _flag.Flag):
|
431 |
+
raise _exceptions.IllegalFlagValueError(
|
432 |
+
f'Expect Flag instances, found type {type(flag)}. '
|
433 |
+
"Maybe you didn't mean to use FlagValue.__setitem__?")
|
434 |
+
if not isinstance(name, str):
|
435 |
+
raise _exceptions.Error('Flag name must be a string')
|
436 |
+
if not name:
|
437 |
+
raise _exceptions.Error('Flag name cannot be empty')
|
438 |
+
if ' ' in name:
|
439 |
+
raise _exceptions.Error('Flag name cannot contain a space')
|
440 |
+
self._check_method_name_conflicts(name, flag)
|
441 |
+
if name in fl and not flag.allow_override and not fl[name].allow_override:
|
442 |
+
module, module_name = _helpers.get_calling_module_object_and_name()
|
443 |
+
if (self.find_module_defining_flag(name) == module_name and
|
444 |
+
id(module) != self.find_module_id_defining_flag(name)):
|
445 |
+
# If the flag has already been defined by a module with the same name,
|
446 |
+
# but a different ID, we can stop here because it indicates that the
|
447 |
+
# module is simply being imported a subsequent time.
|
448 |
+
return
|
449 |
+
raise _exceptions.DuplicateFlagError.from_flag(name, self)
|
450 |
+
# If a new flag overrides an old one, we need to cleanup the old flag's
|
451 |
+
# modules if it's not registered.
|
452 |
+
flags_to_cleanup = set()
|
453 |
+
short_name: str = flag.short_name # pytype: disable=annotation-type-mismatch
|
454 |
+
if short_name is not None:
|
455 |
+
if (short_name in fl and not flag.allow_override and
|
456 |
+
not fl[short_name].allow_override):
|
457 |
+
raise _exceptions.DuplicateFlagError.from_flag(short_name, self)
|
458 |
+
if short_name in fl and fl[short_name] != flag:
|
459 |
+
flags_to_cleanup.add(fl[short_name])
|
460 |
+
fl[short_name] = flag
|
461 |
+
if (name not in fl # new flag
|
462 |
+
or fl[name].using_default_value or not flag.using_default_value):
|
463 |
+
if name in fl and fl[name] != flag:
|
464 |
+
flags_to_cleanup.add(fl[name])
|
465 |
+
fl[name] = flag
|
466 |
+
for f in flags_to_cleanup:
|
467 |
+
self._cleanup_unregistered_flag_from_module_dicts(f)
|
468 |
+
|
469 |
+
def __dir__(self) -> List[Text]:
|
470 |
+
"""Returns list of names of all defined flags.
|
471 |
+
|
472 |
+
Useful for TAB-completion in ipython.
|
473 |
+
|
474 |
+
Returns:
|
475 |
+
[str], a list of names of all defined flags.
|
476 |
+
"""
|
477 |
+
return sorted(self.__dict__['__flags'])
|
478 |
+
|
479 |
+
def __getitem__(self, name: Text) -> Flag:
|
480 |
+
"""Returns the Flag object for the flag --name."""
|
481 |
+
return self._flags()[name]
|
482 |
+
|
483 |
+
def _hide_flag(self, name):
|
484 |
+
"""Marks the flag --name as hidden."""
|
485 |
+
self.__dict__['__hiddenflags'].add(name)
|
486 |
+
|
487 |
+
def __getattr__(self, name: Text) -> Any:
|
488 |
+
"""Retrieves the 'value' attribute of the flag --name."""
|
489 |
+
fl = self._flags()
|
490 |
+
if name not in fl:
|
491 |
+
raise AttributeError(name)
|
492 |
+
if name in self.__dict__['__hiddenflags']:
|
493 |
+
raise AttributeError(name)
|
494 |
+
|
495 |
+
if self.__dict__['__flags_parsed'] or fl[name].present:
|
496 |
+
return fl[name].value
|
497 |
+
else:
|
498 |
+
raise _exceptions.UnparsedFlagAccessError(
|
499 |
+
'Trying to access flag --%s before flags were parsed.' % name)
|
500 |
+
|
501 |
+
def __setattr__(self, name: Text, value: _T) -> _T:
|
502 |
+
"""Sets the 'value' attribute of the flag --name."""
|
503 |
+
self._set_attributes(**{name: value})
|
504 |
+
return value
|
505 |
+
|
506 |
+
def _set_attributes(self, **attributes: Any) -> None:
|
507 |
+
"""Sets multiple flag values together, triggers validators afterwards."""
|
508 |
+
fl = self._flags()
|
509 |
+
known_flag_vals = {}
|
510 |
+
known_flag_used_defaults = {}
|
511 |
+
try:
|
512 |
+
for name, value in attributes.items():
|
513 |
+
if name in self.__dict__['__hiddenflags']:
|
514 |
+
raise AttributeError(name)
|
515 |
+
if name in fl:
|
516 |
+
orig = fl[name].value
|
517 |
+
fl[name].value = value
|
518 |
+
known_flag_vals[name] = orig
|
519 |
+
else:
|
520 |
+
self._set_unknown_flag(name, value)
|
521 |
+
for name in known_flag_vals:
|
522 |
+
self._assert_validators(fl[name].validators)
|
523 |
+
known_flag_used_defaults[name] = fl[name].using_default_value
|
524 |
+
fl[name].using_default_value = False
|
525 |
+
except:
|
526 |
+
for name, orig in known_flag_vals.items():
|
527 |
+
fl[name].value = orig
|
528 |
+
for name, orig in known_flag_used_defaults.items():
|
529 |
+
fl[name].using_default_value = orig
|
530 |
+
# NOTE: We do not attempt to undo unknown flag side effects because we
|
531 |
+
# cannot reliably undo the user-configured behavior.
|
532 |
+
raise
|
533 |
+
|
534 |
+
def validate_all_flags(self) -> None:
|
535 |
+
"""Verifies whether all flags pass validation.
|
536 |
+
|
537 |
+
Raises:
|
538 |
+
AttributeError: Raised if validators work with a non-existing flag.
|
539 |
+
IllegalFlagValueError: Raised if validation fails for at least one
|
540 |
+
validator.
|
541 |
+
"""
|
542 |
+
all_validators = set()
|
543 |
+
for flag in self._flags().values():
|
544 |
+
all_validators.update(flag.validators)
|
545 |
+
self._assert_validators(all_validators)
|
546 |
+
|
547 |
+
def _assert_validators(
|
548 |
+
self, validators: Iterable[_validators_classes.Validator]
|
549 |
+
) -> None:
|
550 |
+
"""Asserts if all validators in the list are satisfied.
|
551 |
+
|
552 |
+
It asserts validators in the order they were created.
|
553 |
+
|
554 |
+
Args:
|
555 |
+
validators: Iterable(validators.Validator), validators to be verified.
|
556 |
+
|
557 |
+
Raises:
|
558 |
+
AttributeError: Raised if validators work with a non-existing flag.
|
559 |
+
IllegalFlagValueError: Raised if validation fails for at least one
|
560 |
+
validator.
|
561 |
+
"""
|
562 |
+
messages = []
|
563 |
+
bad_flags = set()
|
564 |
+
for validator in sorted(
|
565 |
+
validators, key=lambda validator: validator.insertion_index):
|
566 |
+
try:
|
567 |
+
if isinstance(validator, _validators_classes.SingleFlagValidator):
|
568 |
+
if validator.flag_name in bad_flags:
|
569 |
+
continue
|
570 |
+
elif isinstance(validator, _validators_classes.MultiFlagsValidator):
|
571 |
+
if bad_flags & set(validator.flag_names):
|
572 |
+
continue
|
573 |
+
validator.verify(self)
|
574 |
+
except _exceptions.ValidationError as e:
|
575 |
+
if isinstance(validator, _validators_classes.SingleFlagValidator):
|
576 |
+
bad_flags.add(validator.flag_name)
|
577 |
+
elif isinstance(validator, _validators_classes.MultiFlagsValidator):
|
578 |
+
bad_flags.update(set(validator.flag_names))
|
579 |
+
message = validator.print_flags_with_values(self)
|
580 |
+
messages.append('%s: %s' % (message, str(e)))
|
581 |
+
if messages:
|
582 |
+
raise _exceptions.IllegalFlagValueError('\n'.join(messages))
|
583 |
+
|
584 |
+
def __delattr__(self, flag_name: Text) -> None:
|
585 |
+
"""Deletes a previously-defined flag from a flag object.
|
586 |
+
|
587 |
+
This method makes sure we can delete a flag by using
|
588 |
+
|
589 |
+
del FLAGS.<flag_name>
|
590 |
+
|
591 |
+
E.g.,
|
592 |
+
|
593 |
+
flags.DEFINE_integer('foo', 1, 'Integer flag.')
|
594 |
+
del flags.FLAGS.foo
|
595 |
+
|
596 |
+
If a flag is also registered by its the other name (long name or short
|
597 |
+
name), the other name won't be deleted.
|
598 |
+
|
599 |
+
Args:
|
600 |
+
flag_name: str, the name of the flag to be deleted.
|
601 |
+
|
602 |
+
Raises:
|
603 |
+
AttributeError: Raised when there is no registered flag named flag_name.
|
604 |
+
"""
|
605 |
+
fl = self._flags()
|
606 |
+
if flag_name not in fl:
|
607 |
+
raise AttributeError(flag_name)
|
608 |
+
|
609 |
+
flag_obj = fl[flag_name]
|
610 |
+
del fl[flag_name]
|
611 |
+
|
612 |
+
self._cleanup_unregistered_flag_from_module_dicts(flag_obj)
|
613 |
+
|
614 |
+
def set_default(self, name: Text, value: Any) -> None:
|
615 |
+
"""Changes the default value of the named flag object.
|
616 |
+
|
617 |
+
The flag's current value is also updated if the flag is currently using
|
618 |
+
the default value, i.e. not specified in the command line, and not set
|
619 |
+
by FLAGS.name = value.
|
620 |
+
|
621 |
+
Args:
|
622 |
+
name: str, the name of the flag to modify.
|
623 |
+
value: The new default value.
|
624 |
+
|
625 |
+
Raises:
|
626 |
+
UnrecognizedFlagError: Raised when there is no registered flag named name.
|
627 |
+
IllegalFlagValueError: Raised when value is not valid.
|
628 |
+
"""
|
629 |
+
fl = self._flags()
|
630 |
+
if name not in fl:
|
631 |
+
self._set_unknown_flag(name, value)
|
632 |
+
return
|
633 |
+
fl[name]._set_default(value) # pylint: disable=protected-access
|
634 |
+
self._assert_validators(fl[name].validators)
|
635 |
+
|
636 |
+
def __contains__(self, name: Text) -> bool:
|
637 |
+
"""Returns True if name is a value (flag) in the dict."""
|
638 |
+
return name in self._flags()
|
639 |
+
|
640 |
+
def __len__(self) -> int:
|
641 |
+
return len(self.__dict__['__flags'])
|
642 |
+
|
643 |
+
def __iter__(self) -> Iterator[Text]:
|
644 |
+
return iter(self._flags())
|
645 |
+
|
646 |
+
def __call__(
|
647 |
+
self, argv: Sequence[Text], known_only: bool = False
|
648 |
+
) -> List[Text]:
|
649 |
+
"""Parses flags from argv; stores parsed flags into this FlagValues object.
|
650 |
+
|
651 |
+
All unparsed arguments are returned.
|
652 |
+
|
653 |
+
Args:
|
654 |
+
argv: a tuple/list of strings.
|
655 |
+
known_only: bool, if True, parse and remove known flags; return the rest
|
656 |
+
untouched. Unknown flags specified by --undefok are not returned.
|
657 |
+
|
658 |
+
Returns:
|
659 |
+
The list of arguments not parsed as options, including argv[0].
|
660 |
+
|
661 |
+
Raises:
|
662 |
+
Error: Raised on any parsing error.
|
663 |
+
TypeError: Raised on passing wrong type of arguments.
|
664 |
+
ValueError: Raised on flag value parsing error.
|
665 |
+
"""
|
666 |
+
if isinstance(argv, (str, bytes)):
|
667 |
+
raise TypeError(
|
668 |
+
'argv should be a tuple/list of strings, not bytes or string.')
|
669 |
+
if not argv:
|
670 |
+
raise ValueError(
|
671 |
+
'argv cannot be an empty list, and must contain the program name as '
|
672 |
+
'the first element.')
|
673 |
+
|
674 |
+
# This pre parses the argv list for --flagfile=<> options.
|
675 |
+
program_name = argv[0]
|
676 |
+
args = self.read_flags_from_files(argv[1:], force_gnu=False)
|
677 |
+
|
678 |
+
# Parse the arguments.
|
679 |
+
unknown_flags, unparsed_args = self._parse_args(args, known_only)
|
680 |
+
|
681 |
+
# Handle unknown flags by raising UnrecognizedFlagError.
|
682 |
+
# Note some users depend on us raising this particular error.
|
683 |
+
for name, value in unknown_flags:
|
684 |
+
suggestions = _helpers.get_flag_suggestions(name, list(self))
|
685 |
+
raise _exceptions.UnrecognizedFlagError(
|
686 |
+
name, value, suggestions=suggestions)
|
687 |
+
|
688 |
+
self.mark_as_parsed()
|
689 |
+
self.validate_all_flags()
|
690 |
+
return [program_name] + unparsed_args
|
691 |
+
|
692 |
+
def __getstate__(self) -> Any:
|
693 |
+
raise TypeError("can't pickle FlagValues")
|
694 |
+
|
695 |
+
def __copy__(self) -> Any:
|
696 |
+
raise TypeError('FlagValues does not support shallow copies. '
|
697 |
+
'Use absl.testing.flagsaver or copy.deepcopy instead.')
|
698 |
+
|
699 |
+
def __deepcopy__(self, memo) -> Any:
|
700 |
+
result = object.__new__(type(self))
|
701 |
+
result.__dict__.update(copy.deepcopy(self.__dict__, memo))
|
702 |
+
return result
|
703 |
+
|
704 |
+
def _set_is_retired_flag_func(self, is_retired_flag_func):
|
705 |
+
"""Sets a function for checking retired flags.
|
706 |
+
|
707 |
+
Do not use it. This is a private absl API used to check retired flags
|
708 |
+
registered by the absl C++ flags library.
|
709 |
+
|
710 |
+
Args:
|
711 |
+
is_retired_flag_func: Callable(str) -> (bool, bool), a function takes flag
|
712 |
+
name as parameter, returns a tuple (is_retired, type_is_bool).
|
713 |
+
"""
|
714 |
+
self.__dict__['__is_retired_flag_func'] = is_retired_flag_func
|
715 |
+
|
716 |
+
def _parse_args(
|
717 |
+
self, args: List[str], known_only: bool
|
718 |
+
) -> Tuple[List[Tuple[Optional[str], Any]], List[str]]:
|
719 |
+
"""Helper function to do the main argument parsing.
|
720 |
+
|
721 |
+
This function goes through args and does the bulk of the flag parsing.
|
722 |
+
It will find the corresponding flag in our flag dictionary, and call its
|
723 |
+
.parse() method on the flag value.
|
724 |
+
|
725 |
+
Args:
|
726 |
+
args: [str], a list of strings with the arguments to parse.
|
727 |
+
known_only: bool, if True, parse and remove known flags; return the rest
|
728 |
+
untouched. Unknown flags specified by --undefok are not returned.
|
729 |
+
|
730 |
+
Returns:
|
731 |
+
A tuple with the following:
|
732 |
+
unknown_flags: List of (flag name, arg) for flags we don't know about.
|
733 |
+
unparsed_args: List of arguments we did not parse.
|
734 |
+
|
735 |
+
Raises:
|
736 |
+
Error: Raised on any parsing error.
|
737 |
+
ValueError: Raised on flag value parsing error.
|
738 |
+
"""
|
739 |
+
unparsed_names_and_args = [] # A list of (flag name or None, arg).
|
740 |
+
undefok = set()
|
741 |
+
retired_flag_func = self.__dict__['__is_retired_flag_func']
|
742 |
+
|
743 |
+
flag_dict = self._flags()
|
744 |
+
args = iter(args)
|
745 |
+
for arg in args:
|
746 |
+
value = None
|
747 |
+
|
748 |
+
def get_value():
|
749 |
+
# pylint: disable=cell-var-from-loop
|
750 |
+
try:
|
751 |
+
return next(args) if value is None else value
|
752 |
+
except StopIteration:
|
753 |
+
raise _exceptions.Error('Missing value for flag ' + arg) # pylint: disable=undefined-loop-variable
|
754 |
+
|
755 |
+
if not arg.startswith('-'):
|
756 |
+
# A non-argument: default is break, GNU is skip.
|
757 |
+
unparsed_names_and_args.append((None, arg))
|
758 |
+
if self.is_gnu_getopt():
|
759 |
+
continue
|
760 |
+
else:
|
761 |
+
break
|
762 |
+
|
763 |
+
if arg == '--':
|
764 |
+
if known_only:
|
765 |
+
unparsed_names_and_args.append((None, arg))
|
766 |
+
break
|
767 |
+
|
768 |
+
# At this point, arg must start with '-'.
|
769 |
+
if arg.startswith('--'):
|
770 |
+
arg_without_dashes = arg[2:]
|
771 |
+
else:
|
772 |
+
arg_without_dashes = arg[1:]
|
773 |
+
|
774 |
+
if '=' in arg_without_dashes:
|
775 |
+
name, value = arg_without_dashes.split('=', 1)
|
776 |
+
else:
|
777 |
+
name, value = arg_without_dashes, None
|
778 |
+
|
779 |
+
if not name:
|
780 |
+
# The argument is all dashes (including one dash).
|
781 |
+
unparsed_names_and_args.append((None, arg))
|
782 |
+
if self.is_gnu_getopt():
|
783 |
+
continue
|
784 |
+
else:
|
785 |
+
break
|
786 |
+
|
787 |
+
# --undefok is a special case.
|
788 |
+
if name == 'undefok':
|
789 |
+
value = get_value()
|
790 |
+
undefok.update(v.strip() for v in value.split(','))
|
791 |
+
undefok.update('no' + v.strip() for v in value.split(','))
|
792 |
+
continue
|
793 |
+
|
794 |
+
flag = flag_dict.get(name)
|
795 |
+
if flag is not None:
|
796 |
+
if flag.boolean and value is None:
|
797 |
+
value = 'true'
|
798 |
+
else:
|
799 |
+
value = get_value()
|
800 |
+
elif name.startswith('no') and len(name) > 2:
|
801 |
+
# Boolean flags can take the form of --noflag, with no value.
|
802 |
+
noflag = flag_dict.get(name[2:])
|
803 |
+
if noflag is not None and noflag.boolean:
|
804 |
+
if value is not None:
|
805 |
+
raise ValueError(arg + ' does not take an argument')
|
806 |
+
flag = noflag
|
807 |
+
value = 'false'
|
808 |
+
|
809 |
+
if retired_flag_func and flag is None:
|
810 |
+
is_retired, is_bool = retired_flag_func(name)
|
811 |
+
|
812 |
+
# If we didn't recognize that flag, but it starts with
|
813 |
+
# "no" then maybe it was a boolean flag specified in the
|
814 |
+
# --nofoo form.
|
815 |
+
if not is_retired and name.startswith('no'):
|
816 |
+
is_retired, is_bool = retired_flag_func(name[2:])
|
817 |
+
is_retired = is_retired and is_bool
|
818 |
+
|
819 |
+
if is_retired:
|
820 |
+
if not is_bool and value is None:
|
821 |
+
# This happens when a non-bool retired flag is specified
|
822 |
+
# in format of "--flag value".
|
823 |
+
get_value()
|
824 |
+
logging.error(
|
825 |
+
'Flag "%s" is retired and should no longer be specified. See '
|
826 |
+
'https://abseil.io/tips/90.',
|
827 |
+
name,
|
828 |
+
)
|
829 |
+
continue
|
830 |
+
|
831 |
+
if flag is not None:
|
832 |
+
# LINT.IfChange
|
833 |
+
flag.parse(value)
|
834 |
+
flag.using_default_value = False
|
835 |
+
# LINT.ThenChange(../testing/flagsaver.py:flag_override_parsing)
|
836 |
+
else:
|
837 |
+
unparsed_names_and_args.append((name, arg))
|
838 |
+
|
839 |
+
unknown_flags = []
|
840 |
+
unparsed_args = []
|
841 |
+
for name, arg in unparsed_names_and_args:
|
842 |
+
if name is None:
|
843 |
+
# Positional arguments.
|
844 |
+
unparsed_args.append(arg)
|
845 |
+
elif name in undefok:
|
846 |
+
# Remove undefok flags.
|
847 |
+
continue
|
848 |
+
else:
|
849 |
+
# This is an unknown flag.
|
850 |
+
if known_only:
|
851 |
+
unparsed_args.append(arg)
|
852 |
+
else:
|
853 |
+
unknown_flags.append((name, arg))
|
854 |
+
|
855 |
+
unparsed_args.extend(list(args))
|
856 |
+
return unknown_flags, unparsed_args
|
857 |
+
|
858 |
+
def is_parsed(self) -> bool:
|
859 |
+
"""Returns whether flags were parsed."""
|
860 |
+
return self.__dict__['__flags_parsed']
|
861 |
+
|
862 |
+
def mark_as_parsed(self) -> None:
|
863 |
+
"""Explicitly marks flags as parsed.
|
864 |
+
|
865 |
+
Use this when the caller knows that this FlagValues has been parsed as if
|
866 |
+
a ``__call__()`` invocation has happened. This is only a public method for
|
867 |
+
use by things like appcommands which do additional command like parsing.
|
868 |
+
"""
|
869 |
+
self.__dict__['__flags_parsed'] = True
|
870 |
+
|
871 |
+
def unparse_flags(self) -> None:
|
872 |
+
"""Unparses all flags to the point before any FLAGS(argv) was called."""
|
873 |
+
for f in self._flags().values():
|
874 |
+
f.unparse()
|
875 |
+
# We log this message before marking flags as unparsed to avoid a
|
876 |
+
# problem when the logging library causes flags access.
|
877 |
+
logging.info('unparse_flags() called; flags access will now raise errors.')
|
878 |
+
self.__dict__['__flags_parsed'] = False
|
879 |
+
self.__dict__['__unparse_flags_called'] = True
|
880 |
+
|
881 |
+
def flag_values_dict(self) -> Dict[Text, Any]:
|
882 |
+
"""Returns a dictionary that maps flag names to flag values."""
|
883 |
+
return {name: flag.value for name, flag in self._flags().items()}
|
884 |
+
|
885 |
+
def __str__(self):
|
886 |
+
"""Returns a help string for all known flags."""
|
887 |
+
return self.get_help()
|
888 |
+
|
889 |
+
def get_help(
|
890 |
+
self, prefix: Text = '', include_special_flags: bool = True
|
891 |
+
) -> Text:
|
892 |
+
"""Returns a help string for all known flags.
|
893 |
+
|
894 |
+
Args:
|
895 |
+
prefix: str, per-line output prefix.
|
896 |
+
include_special_flags: bool, whether to include description of
|
897 |
+
SPECIAL_FLAGS, i.e. --flagfile and --undefok.
|
898 |
+
|
899 |
+
Returns:
|
900 |
+
str, formatted help message.
|
901 |
+
"""
|
902 |
+
flags_by_module = self.flags_by_module_dict()
|
903 |
+
if flags_by_module:
|
904 |
+
modules = sorted(flags_by_module)
|
905 |
+
# Print the help for the main module first, if possible.
|
906 |
+
main_module = sys.argv[0]
|
907 |
+
if main_module in modules:
|
908 |
+
modules.remove(main_module)
|
909 |
+
modules = [main_module] + modules
|
910 |
+
return self._get_help_for_modules(modules, prefix, include_special_flags)
|
911 |
+
else:
|
912 |
+
output_lines = []
|
913 |
+
# Just print one long list of flags.
|
914 |
+
values = self._flags().values()
|
915 |
+
if include_special_flags:
|
916 |
+
values = itertools.chain(
|
917 |
+
values, _helpers.SPECIAL_FLAGS._flags().values() # pylint: disable=protected-access # pytype: disable=attribute-error
|
918 |
+
)
|
919 |
+
self._render_flag_list(values, output_lines, prefix)
|
920 |
+
return '\n'.join(output_lines)
|
921 |
+
|
922 |
+
def _get_help_for_modules(self, modules, prefix, include_special_flags):
|
923 |
+
"""Returns the help string for a list of modules.
|
924 |
+
|
925 |
+
Private to absl.flags package.
|
926 |
+
|
927 |
+
Args:
|
928 |
+
modules: List[str], a list of modules to get the help string for.
|
929 |
+
prefix: str, a string that is prepended to each generated help line.
|
930 |
+
include_special_flags: bool, whether to include description of
|
931 |
+
SPECIAL_FLAGS, i.e. --flagfile and --undefok.
|
932 |
+
"""
|
933 |
+
output_lines = []
|
934 |
+
for module in modules:
|
935 |
+
self._render_our_module_flags(module, output_lines, prefix)
|
936 |
+
if include_special_flags:
|
937 |
+
self._render_module_flags(
|
938 |
+
'absl.flags',
|
939 |
+
_helpers.SPECIAL_FLAGS._flags().values(), # pylint: disable=protected-access # pytype: disable=attribute-error
|
940 |
+
output_lines,
|
941 |
+
prefix,
|
942 |
+
)
|
943 |
+
return '\n'.join(output_lines)
|
944 |
+
|
945 |
+
def _render_module_flags(self, module, flags, output_lines, prefix=''):
|
946 |
+
"""Returns a help string for a given module."""
|
947 |
+
if not isinstance(module, str):
|
948 |
+
module = module.__name__
|
949 |
+
output_lines.append('\n%s%s:' % (prefix, module))
|
950 |
+
self._render_flag_list(flags, output_lines, prefix + ' ')
|
951 |
+
|
952 |
+
def _render_our_module_flags(self, module, output_lines, prefix=''):
|
953 |
+
"""Returns a help string for a given module."""
|
954 |
+
flags = self.get_flags_for_module(module)
|
955 |
+
if flags:
|
956 |
+
self._render_module_flags(module, flags, output_lines, prefix)
|
957 |
+
|
958 |
+
def _render_our_module_key_flags(self, module, output_lines, prefix=''):
|
959 |
+
"""Returns a help string for the key flags of a given module.
|
960 |
+
|
961 |
+
Args:
|
962 |
+
module: module|str, the module to render key flags for.
|
963 |
+
output_lines: [str], a list of strings. The generated help message lines
|
964 |
+
will be appended to this list.
|
965 |
+
prefix: str, a string that is prepended to each generated help line.
|
966 |
+
"""
|
967 |
+
key_flags = self.get_key_flags_for_module(module)
|
968 |
+
if key_flags:
|
969 |
+
self._render_module_flags(module, key_flags, output_lines, prefix)
|
970 |
+
|
971 |
+
def module_help(self, module: Any) -> Text:
|
972 |
+
"""Describes the key flags of a module.
|
973 |
+
|
974 |
+
Args:
|
975 |
+
module: module|str, the module to describe the key flags for.
|
976 |
+
|
977 |
+
Returns:
|
978 |
+
str, describing the key flags of a module.
|
979 |
+
"""
|
980 |
+
helplist = []
|
981 |
+
self._render_our_module_key_flags(module, helplist)
|
982 |
+
return '\n'.join(helplist)
|
983 |
+
|
984 |
+
def main_module_help(self) -> Text:
|
985 |
+
"""Describes the key flags of the main module.
|
986 |
+
|
987 |
+
Returns:
|
988 |
+
str, describing the key flags of the main module.
|
989 |
+
"""
|
990 |
+
return self.module_help(sys.argv[0])
|
991 |
+
|
992 |
+
def _render_flag_list(self, flaglist, output_lines, prefix=' '):
|
993 |
+
fl = self._flags()
|
994 |
+
special_fl = _helpers.SPECIAL_FLAGS._flags() # pylint: disable=protected-access # pytype: disable=attribute-error
|
995 |
+
flaglist = [(flag.name, flag) for flag in flaglist]
|
996 |
+
flaglist.sort()
|
997 |
+
flagset = {}
|
998 |
+
for (name, flag) in flaglist:
|
999 |
+
# It's possible this flag got deleted or overridden since being
|
1000 |
+
# registered in the per-module flaglist. Check now against the
|
1001 |
+
# canonical source of current flag information, the _flags.
|
1002 |
+
if fl.get(name, None) != flag and special_fl.get(name, None) != flag:
|
1003 |
+
# a different flag is using this name now
|
1004 |
+
continue
|
1005 |
+
# only print help once
|
1006 |
+
if flag in flagset:
|
1007 |
+
continue
|
1008 |
+
flagset[flag] = 1
|
1009 |
+
flaghelp = ''
|
1010 |
+
if flag.short_name:
|
1011 |
+
flaghelp += '-%s,' % flag.short_name
|
1012 |
+
if flag.boolean:
|
1013 |
+
flaghelp += '--[no]%s:' % flag.name
|
1014 |
+
else:
|
1015 |
+
flaghelp += '--%s:' % flag.name
|
1016 |
+
flaghelp += ' '
|
1017 |
+
if flag.help:
|
1018 |
+
flaghelp += flag.help
|
1019 |
+
flaghelp = _helpers.text_wrap(
|
1020 |
+
flaghelp, indent=prefix + ' ', firstline_indent=prefix)
|
1021 |
+
if flag.default_as_str:
|
1022 |
+
flaghelp += '\n'
|
1023 |
+
flaghelp += _helpers.text_wrap(
|
1024 |
+
'(default: %s)' % flag.default_as_str, indent=prefix + ' ')
|
1025 |
+
if flag.parser.syntactic_help:
|
1026 |
+
flaghelp += '\n'
|
1027 |
+
flaghelp += _helpers.text_wrap(
|
1028 |
+
'(%s)' % flag.parser.syntactic_help, indent=prefix + ' ')
|
1029 |
+
output_lines.append(flaghelp)
|
1030 |
+
|
1031 |
+
def get_flag_value(self, name: Text, default: Any) -> Any: # pylint: disable=invalid-name
|
1032 |
+
"""Returns the value of a flag (if not None) or a default value.
|
1033 |
+
|
1034 |
+
Args:
|
1035 |
+
name: str, the name of a flag.
|
1036 |
+
default: Default value to use if the flag value is None.
|
1037 |
+
|
1038 |
+
Returns:
|
1039 |
+
Requested flag value or default.
|
1040 |
+
"""
|
1041 |
+
|
1042 |
+
value = self.__getattr__(name)
|
1043 |
+
if value is not None: # Can't do if not value, b/c value might be '0' or ""
|
1044 |
+
return value
|
1045 |
+
else:
|
1046 |
+
return default
|
1047 |
+
|
1048 |
+
def _is_flag_file_directive(self, flag_string):
|
1049 |
+
"""Checks whether flag_string contain a --flagfile=<foo> directive."""
|
1050 |
+
if isinstance(flag_string, str):
|
1051 |
+
if flag_string.startswith('--flagfile='):
|
1052 |
+
return 1
|
1053 |
+
elif flag_string == '--flagfile':
|
1054 |
+
return 1
|
1055 |
+
elif flag_string.startswith('-flagfile='):
|
1056 |
+
return 1
|
1057 |
+
elif flag_string == '-flagfile':
|
1058 |
+
return 1
|
1059 |
+
else:
|
1060 |
+
return 0
|
1061 |
+
return 0
|
1062 |
+
|
1063 |
+
def _extract_filename(self, flagfile_str):
|
1064 |
+
"""Returns filename from a flagfile_str of form -[-]flagfile=filename.
|
1065 |
+
|
1066 |
+
The cases of --flagfile foo and -flagfile foo shouldn't be hitting
|
1067 |
+
this function, as they are dealt with in the level above this
|
1068 |
+
function.
|
1069 |
+
|
1070 |
+
Args:
|
1071 |
+
flagfile_str: str, the flagfile string.
|
1072 |
+
|
1073 |
+
Returns:
|
1074 |
+
str, the filename from a flagfile_str of form -[-]flagfile=filename.
|
1075 |
+
|
1076 |
+
Raises:
|
1077 |
+
Error: Raised when illegal --flagfile is provided.
|
1078 |
+
"""
|
1079 |
+
if flagfile_str.startswith('--flagfile='):
|
1080 |
+
return os.path.expanduser((flagfile_str[(len('--flagfile=')):]).strip())
|
1081 |
+
elif flagfile_str.startswith('-flagfile='):
|
1082 |
+
return os.path.expanduser((flagfile_str[(len('-flagfile=')):]).strip())
|
1083 |
+
else:
|
1084 |
+
raise _exceptions.Error('Hit illegal --flagfile type: %s' % flagfile_str)
|
1085 |
+
|
1086 |
+
def _get_flag_file_lines(self, filename, parsed_file_stack=None):
|
1087 |
+
"""Returns the useful (!=comments, etc) lines from a file with flags.
|
1088 |
+
|
1089 |
+
Args:
|
1090 |
+
filename: str, the name of the flag file.
|
1091 |
+
parsed_file_stack: [str], a list of the names of the files that we have
|
1092 |
+
recursively encountered at the current depth. MUTATED BY THIS FUNCTION
|
1093 |
+
(but the original value is preserved upon successfully returning from
|
1094 |
+
function call).
|
1095 |
+
|
1096 |
+
Returns:
|
1097 |
+
List of strings. See the note below.
|
1098 |
+
|
1099 |
+
NOTE(springer): This function checks for a nested --flagfile=<foo>
|
1100 |
+
tag and handles the lower file recursively. It returns a list of
|
1101 |
+
all the lines that _could_ contain command flags. This is
|
1102 |
+
EVERYTHING except whitespace lines and comments (lines starting
|
1103 |
+
with '#' or '//').
|
1104 |
+
"""
|
1105 |
+
# For consistency with the cpp version, ignore empty values.
|
1106 |
+
if not filename:
|
1107 |
+
return []
|
1108 |
+
if parsed_file_stack is None:
|
1109 |
+
parsed_file_stack = []
|
1110 |
+
# We do a little safety check for reparsing a file we've already encountered
|
1111 |
+
# at a previous depth.
|
1112 |
+
if filename in parsed_file_stack:
|
1113 |
+
sys.stderr.write('Warning: Hit circular flagfile dependency. Ignoring'
|
1114 |
+
' flagfile: %s\n' % (filename,))
|
1115 |
+
return []
|
1116 |
+
else:
|
1117 |
+
parsed_file_stack.append(filename)
|
1118 |
+
|
1119 |
+
line_list = [] # All line from flagfile.
|
1120 |
+
flag_line_list = [] # Subset of lines w/o comments, blanks, flagfile= tags.
|
1121 |
+
try:
|
1122 |
+
file_obj = open(filename, 'r')
|
1123 |
+
except IOError as e_msg:
|
1124 |
+
raise _exceptions.CantOpenFlagFileError(
|
1125 |
+
'ERROR:: Unable to open flagfile: %s' % e_msg)
|
1126 |
+
|
1127 |
+
with file_obj:
|
1128 |
+
line_list = file_obj.readlines()
|
1129 |
+
|
1130 |
+
# This is where we check each line in the file we just read.
|
1131 |
+
for line in line_list:
|
1132 |
+
if line.isspace():
|
1133 |
+
pass
|
1134 |
+
# Checks for comment (a line that starts with '#').
|
1135 |
+
elif line.startswith('#') or line.startswith('//'):
|
1136 |
+
pass
|
1137 |
+
# Checks for a nested "--flagfile=<bar>" flag in the current file.
|
1138 |
+
# If we find one, recursively parse down into that file.
|
1139 |
+
elif self._is_flag_file_directive(line):
|
1140 |
+
sub_filename = self._extract_filename(line)
|
1141 |
+
included_flags = self._get_flag_file_lines(
|
1142 |
+
sub_filename, parsed_file_stack=parsed_file_stack)
|
1143 |
+
flag_line_list.extend(included_flags)
|
1144 |
+
else:
|
1145 |
+
# Any line that's not a comment or a nested flagfile should get
|
1146 |
+
# copied into 2nd position. This leaves earlier arguments
|
1147 |
+
# further back in the list, thus giving them higher priority.
|
1148 |
+
flag_line_list.append(line.strip())
|
1149 |
+
|
1150 |
+
parsed_file_stack.pop()
|
1151 |
+
return flag_line_list
|
1152 |
+
|
1153 |
+
def read_flags_from_files(
|
1154 |
+
self, argv: Sequence[Text], force_gnu: bool = True
|
1155 |
+
) -> List[Text]:
|
1156 |
+
"""Processes command line args, but also allow args to be read from file.
|
1157 |
+
|
1158 |
+
Args:
|
1159 |
+
argv: [str], a list of strings, usually sys.argv[1:], which may contain
|
1160 |
+
one or more flagfile directives of the form --flagfile="./filename".
|
1161 |
+
Note that the name of the program (sys.argv[0]) should be omitted.
|
1162 |
+
force_gnu: bool, if False, --flagfile parsing obeys the
|
1163 |
+
FLAGS.is_gnu_getopt() value. If True, ignore the value and always follow
|
1164 |
+
gnu_getopt semantics.
|
1165 |
+
|
1166 |
+
Returns:
|
1167 |
+
A new list which has the original list combined with what we read
|
1168 |
+
from any flagfile(s).
|
1169 |
+
|
1170 |
+
Raises:
|
1171 |
+
IllegalFlagValueError: Raised when --flagfile is provided with no
|
1172 |
+
argument.
|
1173 |
+
|
1174 |
+
This function is called by FLAGS(argv).
|
1175 |
+
It scans the input list for a flag that looks like:
|
1176 |
+
--flagfile=<somefile>. Then it opens <somefile>, reads all valid key
|
1177 |
+
and value pairs and inserts them into the input list in exactly the
|
1178 |
+
place where the --flagfile arg is found.
|
1179 |
+
|
1180 |
+
Note that your application's flags are still defined the usual way
|
1181 |
+
using absl.flags DEFINE_flag() type functions.
|
1182 |
+
|
1183 |
+
Notes (assuming we're getting a commandline of some sort as our input):
|
1184 |
+
|
1185 |
+
* For duplicate flags, the last one we hit should "win".
|
1186 |
+
* Since flags that appear later win, a flagfile's settings can be "weak"
|
1187 |
+
if the --flagfile comes at the beginning of the argument sequence,
|
1188 |
+
and it can be "strong" if the --flagfile comes at the end.
|
1189 |
+
* A further "--flagfile=<otherfile.cfg>" CAN be nested in a flagfile.
|
1190 |
+
It will be expanded in exactly the spot where it is found.
|
1191 |
+
* In a flagfile, a line beginning with # or // is a comment.
|
1192 |
+
* Entirely blank lines _should_ be ignored.
|
1193 |
+
"""
|
1194 |
+
rest_of_args = argv
|
1195 |
+
new_argv = []
|
1196 |
+
while rest_of_args:
|
1197 |
+
current_arg = rest_of_args[0]
|
1198 |
+
rest_of_args = rest_of_args[1:]
|
1199 |
+
if self._is_flag_file_directive(current_arg):
|
1200 |
+
# This handles the case of -(-)flagfile foo. In this case the
|
1201 |
+
# next arg really is part of this one.
|
1202 |
+
if current_arg == '--flagfile' or current_arg == '-flagfile':
|
1203 |
+
if not rest_of_args:
|
1204 |
+
raise _exceptions.IllegalFlagValueError(
|
1205 |
+
'--flagfile with no argument')
|
1206 |
+
flag_filename = os.path.expanduser(rest_of_args[0])
|
1207 |
+
rest_of_args = rest_of_args[1:]
|
1208 |
+
else:
|
1209 |
+
# This handles the case of (-)-flagfile=foo.
|
1210 |
+
flag_filename = self._extract_filename(current_arg)
|
1211 |
+
new_argv.extend(self._get_flag_file_lines(flag_filename))
|
1212 |
+
else:
|
1213 |
+
new_argv.append(current_arg)
|
1214 |
+
# Stop parsing after '--', like getopt and gnu_getopt.
|
1215 |
+
if current_arg == '--':
|
1216 |
+
break
|
1217 |
+
# Stop parsing after a non-flag, like getopt.
|
1218 |
+
if not current_arg.startswith('-'):
|
1219 |
+
if not force_gnu and not self.__dict__['__use_gnu_getopt']:
|
1220 |
+
break
|
1221 |
+
else:
|
1222 |
+
if ('=' not in current_arg and rest_of_args and
|
1223 |
+
not rest_of_args[0].startswith('-')):
|
1224 |
+
# If this is an occurrence of a legitimate --x y, skip the value
|
1225 |
+
# so that it won't be mistaken for a standalone arg.
|
1226 |
+
fl = self._flags()
|
1227 |
+
name = current_arg.lstrip('-')
|
1228 |
+
if name in fl and not fl[name].boolean:
|
1229 |
+
current_arg = rest_of_args[0]
|
1230 |
+
rest_of_args = rest_of_args[1:]
|
1231 |
+
new_argv.append(current_arg)
|
1232 |
+
|
1233 |
+
if rest_of_args:
|
1234 |
+
new_argv.extend(rest_of_args)
|
1235 |
+
|
1236 |
+
return new_argv
|
1237 |
+
|
1238 |
+
def flags_into_string(self) -> Text:
|
1239 |
+
"""Returns a string with the flags assignments from this FlagValues object.
|
1240 |
+
|
1241 |
+
This function ignores flags whose value is None. Each flag
|
1242 |
+
assignment is separated by a newline.
|
1243 |
+
|
1244 |
+
NOTE: MUST mirror the behavior of the C++ CommandlineFlagsIntoString
|
1245 |
+
from https://github.com/gflags/gflags.
|
1246 |
+
|
1247 |
+
Returns:
|
1248 |
+
str, the string with the flags assignments from this FlagValues object.
|
1249 |
+
The flags are ordered by (module_name, flag_name).
|
1250 |
+
"""
|
1251 |
+
module_flags = sorted(self.flags_by_module_dict().items())
|
1252 |
+
s = ''
|
1253 |
+
for unused_module_name, flags in module_flags:
|
1254 |
+
flags = sorted(flags, key=lambda f: f.name)
|
1255 |
+
for flag in flags:
|
1256 |
+
if flag.value is not None:
|
1257 |
+
s += flag.serialize() + '\n'
|
1258 |
+
return s
|
1259 |
+
|
1260 |
+
def append_flags_into_file(self, filename: Text) -> None:
|
1261 |
+
"""Appends all flags assignments from this FlagInfo object to a file.
|
1262 |
+
|
1263 |
+
Output will be in the format of a flagfile.
|
1264 |
+
|
1265 |
+
NOTE: MUST mirror the behavior of the C++ AppendFlagsIntoFile
|
1266 |
+
from https://github.com/gflags/gflags.
|
1267 |
+
|
1268 |
+
Args:
|
1269 |
+
filename: str, name of the file.
|
1270 |
+
"""
|
1271 |
+
with open(filename, 'a') as out_file:
|
1272 |
+
out_file.write(self.flags_into_string())
|
1273 |
+
|
1274 |
+
def write_help_in_xml_format(self, outfile: Optional[TextIO] = None) -> None:
|
1275 |
+
"""Outputs flag documentation in XML format.
|
1276 |
+
|
1277 |
+
NOTE: We use element names that are consistent with those used by
|
1278 |
+
the C++ command-line flag library, from
|
1279 |
+
https://github.com/gflags/gflags.
|
1280 |
+
We also use a few new elements (e.g., <key>), but we do not
|
1281 |
+
interfere / overlap with existing XML elements used by the C++
|
1282 |
+
library. Please maintain this consistency.
|
1283 |
+
|
1284 |
+
Args:
|
1285 |
+
outfile: File object we write to. Default None means sys.stdout.
|
1286 |
+
"""
|
1287 |
+
doc = minidom.Document()
|
1288 |
+
all_flag = doc.createElement('AllFlags')
|
1289 |
+
doc.appendChild(all_flag)
|
1290 |
+
|
1291 |
+
all_flag.appendChild(
|
1292 |
+
_helpers.create_xml_dom_element(doc, 'program',
|
1293 |
+
os.path.basename(sys.argv[0])))
|
1294 |
+
|
1295 |
+
usage_doc = sys.modules['__main__'].__doc__
|
1296 |
+
if not usage_doc:
|
1297 |
+
usage_doc = '\nUSAGE: %s [flags]\n' % sys.argv[0]
|
1298 |
+
else:
|
1299 |
+
usage_doc = usage_doc.replace('%s', sys.argv[0])
|
1300 |
+
all_flag.appendChild(
|
1301 |
+
_helpers.create_xml_dom_element(doc, 'usage', usage_doc))
|
1302 |
+
|
1303 |
+
# Get list of key flags for the main module.
|
1304 |
+
key_flags = self.get_key_flags_for_module(sys.argv[0])
|
1305 |
+
|
1306 |
+
# Sort flags by declaring module name and next by flag name.
|
1307 |
+
flags_by_module = self.flags_by_module_dict()
|
1308 |
+
all_module_names = list(flags_by_module.keys())
|
1309 |
+
all_module_names.sort()
|
1310 |
+
for module_name in all_module_names:
|
1311 |
+
flag_list = [(f.name, f) for f in flags_by_module[module_name]]
|
1312 |
+
flag_list.sort()
|
1313 |
+
for unused_flag_name, flag in flag_list:
|
1314 |
+
is_key = flag in key_flags
|
1315 |
+
all_flag.appendChild(
|
1316 |
+
flag._create_xml_dom_element( # pylint: disable=protected-access
|
1317 |
+
doc,
|
1318 |
+
module_name,
|
1319 |
+
is_key=is_key))
|
1320 |
+
|
1321 |
+
outfile = outfile or sys.stdout
|
1322 |
+
outfile.write(
|
1323 |
+
doc.toprettyxml(indent=' ', encoding='utf-8').decode('utf-8'))
|
1324 |
+
outfile.flush()
|
1325 |
+
|
1326 |
+
def _check_method_name_conflicts(self, name: str, flag: Flag):
|
1327 |
+
if flag.allow_using_method_names:
|
1328 |
+
return
|
1329 |
+
short_name = flag.short_name
|
1330 |
+
flag_names = {name} if short_name is None else {name, short_name}
|
1331 |
+
for flag_name in flag_names:
|
1332 |
+
if flag_name in self.__dict__['__banned_flag_names']:
|
1333 |
+
raise _exceptions.FlagNameConflictsWithMethodError(
|
1334 |
+
'Cannot define a flag named "{name}". It conflicts with a method '
|
1335 |
+
'on class "{class_name}". To allow defining it, use '
|
1336 |
+
'allow_using_method_names and access the flag value with '
|
1337 |
+
"FLAGS['{name}'].value. FLAGS.{name} returns the method, "
|
1338 |
+
'not the flag value.'.format(
|
1339 |
+
name=flag_name, class_name=type(self).__name__))
|
1340 |
+
|
1341 |
+
|
1342 |
+
FLAGS = FlagValues()
|
1343 |
+
|
1344 |
+
|
1345 |
+
class FlagHolder(Generic[_T]):
|
1346 |
+
"""Holds a defined flag.
|
1347 |
+
|
1348 |
+
This facilitates a cleaner api around global state. Instead of::
|
1349 |
+
|
1350 |
+
flags.DEFINE_integer('foo', ...)
|
1351 |
+
flags.DEFINE_integer('bar', ...)
|
1352 |
+
|
1353 |
+
def method():
|
1354 |
+
# prints parsed value of 'bar' flag
|
1355 |
+
print(flags.FLAGS.foo)
|
1356 |
+
# runtime error due to typo or possibly bad coding style.
|
1357 |
+
print(flags.FLAGS.baz)
|
1358 |
+
|
1359 |
+
it encourages code like::
|
1360 |
+
|
1361 |
+
_FOO_FLAG = flags.DEFINE_integer('foo', ...)
|
1362 |
+
_BAR_FLAG = flags.DEFINE_integer('bar', ...)
|
1363 |
+
|
1364 |
+
def method():
|
1365 |
+
print(_FOO_FLAG.value)
|
1366 |
+
print(_BAR_FLAG.value)
|
1367 |
+
|
1368 |
+
since the name of the flag appears only once in the source code.
|
1369 |
+
"""
|
1370 |
+
|
1371 |
+
value: _T
|
1372 |
+
|
1373 |
+
def __init__(
|
1374 |
+
self,
|
1375 |
+
flag_values: FlagValues,
|
1376 |
+
flag: Flag[_T],
|
1377 |
+
ensure_non_none_value: bool = False,
|
1378 |
+
):
|
1379 |
+
"""Constructs a FlagHolder instance providing typesafe access to flag.
|
1380 |
+
|
1381 |
+
Args:
|
1382 |
+
flag_values: The container the flag is registered to.
|
1383 |
+
flag: The flag object for this flag.
|
1384 |
+
ensure_non_none_value: Is the value of the flag allowed to be None.
|
1385 |
+
"""
|
1386 |
+
self._flagvalues = flag_values
|
1387 |
+
# We take the entire flag object, but only keep the name. Why?
|
1388 |
+
# - We want FlagHolder[T] to be generic container
|
1389 |
+
# - flag_values contains all flags, so has no reference to T.
|
1390 |
+
# - typecheckers don't like to see a generic class where none of the ctor
|
1391 |
+
# arguments refer to the generic type.
|
1392 |
+
self._name = flag.name
|
1393 |
+
# We intentionally do NOT check if the default value is None.
|
1394 |
+
# This allows future use of this for "required flags with None default"
|
1395 |
+
self._ensure_non_none_value = ensure_non_none_value
|
1396 |
+
|
1397 |
+
def __eq__(self, other):
|
1398 |
+
raise TypeError(
|
1399 |
+
"unsupported operand type(s) for ==: '{0}' and '{1}' "
|
1400 |
+
"(did you mean to use '{0}.value' instead?)".format(
|
1401 |
+
type(self).__name__, type(other).__name__))
|
1402 |
+
|
1403 |
+
def __bool__(self):
|
1404 |
+
raise TypeError(
|
1405 |
+
"bool() not supported for instances of type '{0}' "
|
1406 |
+
"(did you mean to use '{0}.value' instead?)".format(
|
1407 |
+
type(self).__name__))
|
1408 |
+
|
1409 |
+
__nonzero__ = __bool__
|
1410 |
+
|
1411 |
+
@property
|
1412 |
+
def name(self) -> Text:
|
1413 |
+
return self._name
|
1414 |
+
|
1415 |
+
@property
|
1416 |
+
def value(self) -> _T:
|
1417 |
+
"""Returns the value of the flag.
|
1418 |
+
|
1419 |
+
If ``_ensure_non_none_value`` is ``True``, then return value is not
|
1420 |
+
``None``.
|
1421 |
+
|
1422 |
+
Raises:
|
1423 |
+
UnparsedFlagAccessError: if flag parsing has not finished.
|
1424 |
+
IllegalFlagValueError: if value is None unexpectedly.
|
1425 |
+
"""
|
1426 |
+
val = getattr(self._flagvalues, self._name)
|
1427 |
+
if self._ensure_non_none_value and val is None:
|
1428 |
+
raise _exceptions.IllegalFlagValueError(
|
1429 |
+
'Unexpected None value for flag %s' % self._name)
|
1430 |
+
return val
|
1431 |
+
|
1432 |
+
@property
|
1433 |
+
def default(self) -> _T:
|
1434 |
+
"""Returns the default value of the flag."""
|
1435 |
+
return self._flagvalues[self._name].default
|
1436 |
+
|
1437 |
+
@property
|
1438 |
+
def present(self) -> bool:
|
1439 |
+
"""Returns True if the flag was parsed from command-line flags."""
|
1440 |
+
return bool(self._flagvalues[self._name].present)
|
1441 |
+
|
1442 |
+
def serialize(self) -> Text:
|
1443 |
+
"""Returns a serialized representation of the flag."""
|
1444 |
+
return self._flagvalues[self._name].serialize()
|
1445 |
+
|
1446 |
+
|
1447 |
+
def resolve_flag_ref(
|
1448 |
+
flag_ref: Union[str, FlagHolder], flag_values: FlagValues
|
1449 |
+
) -> Tuple[str, FlagValues]:
|
1450 |
+
"""Helper to validate and resolve a flag reference argument."""
|
1451 |
+
if isinstance(flag_ref, FlagHolder):
|
1452 |
+
new_flag_values = flag_ref._flagvalues # pylint: disable=protected-access
|
1453 |
+
if flag_values != FLAGS and flag_values != new_flag_values:
|
1454 |
+
raise ValueError(
|
1455 |
+
'flag_values must not be customized when operating on a FlagHolder')
|
1456 |
+
return flag_ref.name, new_flag_values
|
1457 |
+
return flag_ref, flag_values
|
1458 |
+
|
1459 |
+
|
1460 |
+
def resolve_flag_refs(
|
1461 |
+
flag_refs: Sequence[Union[str, FlagHolder]], flag_values: FlagValues
|
1462 |
+
) -> Tuple[List[str], FlagValues]:
|
1463 |
+
"""Helper to validate and resolve flag reference list arguments."""
|
1464 |
+
fv = None
|
1465 |
+
names = []
|
1466 |
+
for ref in flag_refs:
|
1467 |
+
if isinstance(ref, FlagHolder):
|
1468 |
+
newfv = ref._flagvalues # pylint: disable=protected-access
|
1469 |
+
name = ref.name
|
1470 |
+
else:
|
1471 |
+
newfv = flag_values
|
1472 |
+
name = ref
|
1473 |
+
if fv and fv != newfv:
|
1474 |
+
raise ValueError(
|
1475 |
+
'multiple FlagValues instances used in invocation. '
|
1476 |
+
'FlagHolders must be registered to the same FlagValues instance as '
|
1477 |
+
'do flag names, if provided.')
|
1478 |
+
fv = newfv
|
1479 |
+
names.append(name)
|
1480 |
+
return names, fv
|