omegaconf 2.4.0.dev3__tar.gz → 2.4.0.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omegaconf-2.4.0.dev8/PKG-INFO +63 -0
- omegaconf-2.4.0.dev8/README.md +32 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/build_helpers/build_helpers.py +9 -10
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/_utils.py +127 -16
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/base.py +36 -7
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/basecontainer.py +26 -6
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarLexer.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarParser.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarParserListener.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarParserVisitor.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar_parser.py +4 -2
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar_visitor.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/omegaconf.py +4 -6
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/typing.py +1 -6
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/version.py +4 -4
- omegaconf-2.4.0.dev8/omegaconf.egg-info/PKG-INFO +63 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf.egg-info/SOURCES.txt +0 -4
- omegaconf-2.4.0.dev8/omegaconf.egg-info/requires.txt +1 -0
- omegaconf-2.4.0.dev8/omegaconf.egg-info/top_level.txt +1 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/pyproject.toml +8 -1
- omegaconf-2.4.0.dev8/requirements/base.txt +1 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/setup.cfg +7 -2
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/setup.py +8 -8
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/__init__.py +2 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/test_oc_decode.py +2 -2
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/test_oc_deprecated.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/test_custom_resolvers.py +2 -2
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/test_interpolation.py +4 -8
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/data/attr_classes.py +3 -3
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/data/dataclasses.py +3 -3
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/data/dataclasses_pre_311.py +10 -8
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/test_structured_config.py +10 -10
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_basic_ops_dict.py +1 -1
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_basic_ops_list.py +15 -12
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_compare_dictconfig_vs_dict.py +2 -2
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_create.py +71 -24
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_errors.py +4 -6
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_grammar.py +3 -3
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_merge.py +9 -21
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_nodes.py +49 -2
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_select.py +4 -4
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_to_container.py +65 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_to_yaml.py +2 -4
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_utils.py +7 -7
- omegaconf-2.4.0.dev3/PKG-INFO +0 -72
- omegaconf-2.4.0.dev3/README.md +0 -51
- omegaconf-2.4.0.dev3/omegaconf.egg-info/PKG-INFO +0 -72
- omegaconf-2.4.0.dev3/omegaconf.egg-info/requires.txt +0 -7
- omegaconf-2.4.0.dev3/omegaconf.egg-info/top_level.txt +0 -2
- omegaconf-2.4.0.dev3/pydevd_plugins/__init__.py +0 -6
- omegaconf-2.4.0.dev3/pydevd_plugins/extensions/__init__.py +0 -6
- omegaconf-2.4.0.dev3/pydevd_plugins/extensions/pydevd_plugin_omegaconf.py +0 -126
- omegaconf-2.4.0.dev3/requirements/base.txt +0 -5
- omegaconf-2.4.0.dev3/tests/test_pydev_resolver_plugin.py +0 -278
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/LICENSE +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/MANIFEST.in +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/build_helpers/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/build_helpers/bin/antlr-4.11.1-complete.jar +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/build_helpers/get_vendored.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/build_helpers/test_helpers.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/_impl.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/dictconfig.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/errors.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/OmegaConfGrammarLexer.g4 +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/OmegaConfGrammarParser.g4 +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/listconfig.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/nodes.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/py.typed +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/resolvers/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/resolvers/oc/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/resolvers/oc/dict.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/BufferedTokenStream.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/CommonTokenFactory.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/CommonTokenStream.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/FileStream.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/InputStream.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/IntervalSet.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/LL1Analyzer.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/Lexer.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/ListTokenSource.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/Parser.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/ParserInterpreter.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/ParserRuleContext.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/PredictionContext.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/Recognizer.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/RuleContext.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/StdinStream.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/Token.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/TokenStreamRewriter.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/Utils.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/_pygrun.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATN.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNConfig.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNConfigSet.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNDeserializationOptions.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNDeserializer.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNState.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ATNType.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/LexerATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/LexerAction.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/LexerActionExecutor.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/ParserATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/PredictionMode.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/SemanticContext.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/Transition.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/atn/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/dfa/DFA.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/dfa/DFASerializer.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/dfa/DFAState.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/dfa/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/error/DiagnosticErrorListener.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/error/ErrorListener.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/error/ErrorStrategy.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/error/Errors.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/error/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/Chunk.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/ParseTreeMatch.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/ParseTreePattern.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/ParseTreePatternMatcher.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/RuleTagToken.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/TokenTagToken.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/Tree.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/Trees.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/tree/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/xpath/XPath.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/xpath/XPathLexer.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/vendor/antlr4/xpath/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf.egg-info/dependency_links.txt +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/conftest.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/data/2.0.6.pickle +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/data/2.1.0.rc1.pickle +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/data/load.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/data/save.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/examples/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/examples/dataclass_postponed_annotations.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/examples/test_dataclass_example.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/examples/test_postponed_annotations.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/test_oc_create.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/test_oc_dict.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/test_oc_env.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/interpolation/built_in_resolvers/test_oc_select.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/data/__init__.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/structured_conf/test_structured_basic.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_base_config.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_config_eq.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_get_full_key.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_matrix.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_nested_containers.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_omegaconf.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_readonly.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_serialization.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_struct.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_unions.py +0 -0
- {omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/tests/test_update.py +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: omegaconf
|
|
3
|
+
Version: 2.4.0.dev8
|
|
4
|
+
Summary: A flexible configuration library
|
|
5
|
+
Home-page: https://github.com/omry/omegaconf
|
|
6
|
+
Author: Omry Yadan
|
|
7
|
+
Author-email: omry@yadan.net
|
|
8
|
+
Keywords: yaml configuration config
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: PyYAML>=5.1.0
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: description-content-type
|
|
25
|
+
Dynamic: home-page
|
|
26
|
+
Dynamic: keywords
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
|
30
|
+
Dynamic: summary
|
|
31
|
+
|
|
32
|
+
# OmegaConf
|
|
33
|
+
| | Description |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Project | [](https://badge.fury.io/py/omegaconf)[](https://pepy.tech/project/omegaconf) |
|
|
36
|
+
| Code quality| [](https://circleci.com/gh/omry/omegaconf)[](https://coveralls.io/github/omry/omegaconf)|
|
|
37
|
+
| Docs and support |[](https://omegaconf.readthedocs.io/en/2.1_branch/)[](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)|
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
OmegaConf is a hierarchical configuration system, with support for merging configurations from multiple sources (YAML config files, dataclasses/objects and CLI arguments)
|
|
41
|
+
providing a consistent API regardless of how the configuration was created.
|
|
42
|
+
|
|
43
|
+
## Optional subprojects
|
|
44
|
+
|
|
45
|
+
- [`omegaconf-pydevd`](./subprojects/omegaconf-pydevd/README.md): optional `pydevd` debugger plugin for inspecting OmegaConf objects in supported debuggers.
|
|
46
|
+
|
|
47
|
+
## Releases
|
|
48
|
+
|
|
49
|
+
### Upcoming (2.4.0.dev)
|
|
50
|
+
OmegaConf 2.4.0.dev is the upcoming development version.
|
|
51
|
+
* [Documentation](https://omegaconf.readthedocs.io/en/latest/)
|
|
52
|
+
* [Source code](https://github.com/omry/omegaconf/tree/master)
|
|
53
|
+
|
|
54
|
+
### Stable (2.3)
|
|
55
|
+
OmegaConf 2.3 is the current stable version.
|
|
56
|
+
* [What's new](https://github.com/omry/omegaconf/releases/tag/v2.3.0)
|
|
57
|
+
* [Documentation](https://omegaconf.readthedocs.io/en/2.3_branch/)
|
|
58
|
+
* [Source code](https://github.com/omry/omegaconf/tree/2.3_branch)
|
|
59
|
+
|
|
60
|
+
Install with `pip install --upgrade omegaconf`
|
|
61
|
+
|
|
62
|
+
## Live tutorial
|
|
63
|
+
Run the live tutorial: [](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# OmegaConf
|
|
2
|
+
| | Description |
|
|
3
|
+
| --- | --- |
|
|
4
|
+
| Project | [](https://badge.fury.io/py/omegaconf)[](https://pepy.tech/project/omegaconf) |
|
|
5
|
+
| Code quality| [](https://circleci.com/gh/omry/omegaconf)[](https://coveralls.io/github/omry/omegaconf)|
|
|
6
|
+
| Docs and support |[](https://omegaconf.readthedocs.io/en/2.1_branch/)[](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)|
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
OmegaConf is a hierarchical configuration system, with support for merging configurations from multiple sources (YAML config files, dataclasses/objects and CLI arguments)
|
|
10
|
+
providing a consistent API regardless of how the configuration was created.
|
|
11
|
+
|
|
12
|
+
## Optional subprojects
|
|
13
|
+
|
|
14
|
+
- [`omegaconf-pydevd`](./subprojects/omegaconf-pydevd/README.md): optional `pydevd` debugger plugin for inspecting OmegaConf objects in supported debuggers.
|
|
15
|
+
|
|
16
|
+
## Releases
|
|
17
|
+
|
|
18
|
+
### Upcoming (2.4.0.dev)
|
|
19
|
+
OmegaConf 2.4.0.dev is the upcoming development version.
|
|
20
|
+
* [Documentation](https://omegaconf.readthedocs.io/en/latest/)
|
|
21
|
+
* [Source code](https://github.com/omry/omegaconf/tree/master)
|
|
22
|
+
|
|
23
|
+
### Stable (2.3)
|
|
24
|
+
OmegaConf 2.3 is the current stable version.
|
|
25
|
+
* [What's new](https://github.com/omry/omegaconf/releases/tag/v2.3.0)
|
|
26
|
+
* [Documentation](https://omegaconf.readthedocs.io/en/2.3_branch/)
|
|
27
|
+
* [Source code](https://github.com/omry/omegaconf/tree/2.3_branch)
|
|
28
|
+
|
|
29
|
+
Install with `pip install --upgrade omegaconf`
|
|
30
|
+
|
|
31
|
+
## Live tutorial
|
|
32
|
+
Run the live tutorial: [](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import codecs
|
|
2
1
|
import distutils.log
|
|
3
2
|
import errno
|
|
4
3
|
import os
|
|
@@ -64,26 +63,26 @@ class ANTLRCommand(Command): # type: ignore # pragma: no cover
|
|
|
64
63
|
build_dir = Path(__file__).parent.absolute()
|
|
65
64
|
project_root = build_dir.parent
|
|
66
65
|
lib = "antlr4"
|
|
67
|
-
pkgname =
|
|
66
|
+
pkgname = "omegaconf.vendor"
|
|
68
67
|
|
|
69
68
|
replacements = [
|
|
70
69
|
partial( # import antlr4 -> import omegaconf.vendor.antlr4
|
|
71
|
-
re.compile(r
|
|
72
|
-
r
|
|
70
|
+
re.compile(r"(^\s*)import {}\n".format(lib), flags=re.M).sub,
|
|
71
|
+
r"\1from {} import {}\n".format(pkgname, lib),
|
|
73
72
|
),
|
|
74
73
|
partial( # from antlr4 -> from fomegaconf.vendor.antlr4
|
|
75
|
-
re.compile(r
|
|
76
|
-
r
|
|
74
|
+
re.compile(r"(^\s*)from {}(\.|\s+)".format(lib), flags=re.M).sub,
|
|
75
|
+
r"\1from {}.{}\2".format(pkgname, lib),
|
|
77
76
|
),
|
|
78
77
|
]
|
|
79
78
|
|
|
80
79
|
path = project_root / "omegaconf" / "grammar" / "gen"
|
|
81
80
|
for item in path.iterdir():
|
|
82
81
|
if item.is_file() and item.name.endswith(".py"):
|
|
83
|
-
text = item.read_text(
|
|
82
|
+
text = item.read_text("utf8")
|
|
84
83
|
for replacement in replacements:
|
|
85
84
|
text = replacement(text)
|
|
86
|
-
item.write_text(text,
|
|
85
|
+
item.write_text(text, "utf8")
|
|
87
86
|
|
|
88
87
|
|
|
89
88
|
class BuildPyCommand(build_py.build_py): # pragma: no cover
|
|
@@ -148,7 +147,7 @@ class DevelopCommand(develop.develop): # pragma: no cover
|
|
|
148
147
|
|
|
149
148
|
class SDistCommand(sdist.sdist): # pragma: no cover
|
|
150
149
|
def run(self) -> None:
|
|
151
|
-
if not self.dry_run: # type: ignore
|
|
150
|
+
if not self.dry_run: # type: ignore[attr-defined]
|
|
152
151
|
self.run_command("clean")
|
|
153
152
|
run_antlr(self)
|
|
154
153
|
sdist.sdist.run(self)
|
|
@@ -196,7 +195,7 @@ def find(
|
|
|
196
195
|
|
|
197
196
|
def find_version(*file_paths: str) -> str:
|
|
198
197
|
root = Path(__file__).parent.parent.absolute()
|
|
199
|
-
with
|
|
198
|
+
with open(root / Path(*file_paths), "r", encoding="utf-8") as fp:
|
|
200
199
|
version_file = fp.read()
|
|
201
200
|
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
|
|
202
201
|
if version_match:
|
|
@@ -114,6 +114,7 @@ _DEFAULT_MARKER_: Any = Marker("_DEFAULT_MARKER_")
|
|
|
114
114
|
|
|
115
115
|
class OmegaConfDumper(BaseDumper): # type: ignore
|
|
116
116
|
str_representer_added = False
|
|
117
|
+
pathlib_representers_added = False
|
|
117
118
|
|
|
118
119
|
@staticmethod
|
|
119
120
|
def str_representer(dumper: yaml.Dumper, data: str) -> yaml.ScalarNode:
|
|
@@ -124,11 +125,51 @@ class OmegaConfDumper(BaseDumper): # type: ignore
|
|
|
124
125
|
style=("'" if with_quotes else None),
|
|
125
126
|
)
|
|
126
127
|
|
|
128
|
+
@staticmethod
|
|
129
|
+
def pathlib_path_representer(dumper: yaml.Dumper, data: Any) -> yaml.Node:
|
|
130
|
+
# Use old pathlib.Path tag for cross-version compatibility
|
|
131
|
+
# Extract constructor args from __reduce__ and use sequence representation
|
|
132
|
+
return dumper.represent_sequence( # pragma: no cover
|
|
133
|
+
"tag:yaml.org,2002:python/object/apply:pathlib.Path",
|
|
134
|
+
[str(data)],
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
@staticmethod
|
|
138
|
+
def pathlib_posix_path_representer(dumper: yaml.Dumper, data: Any) -> yaml.Node:
|
|
139
|
+
# Use old pathlib.PosixPath tag for cross-version compatibility
|
|
140
|
+
return dumper.represent_sequence(
|
|
141
|
+
"tag:yaml.org,2002:python/object/apply:pathlib.PosixPath",
|
|
142
|
+
[str(data)],
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
@staticmethod
|
|
146
|
+
def pathlib_windows_path_representer(dumper: yaml.Dumper, data: Any) -> yaml.Node:
|
|
147
|
+
# Use old pathlib.WindowsPath tag for cross-version compatibility
|
|
148
|
+
return dumper.represent_sequence( # pragma: no cover
|
|
149
|
+
"tag:yaml.org,2002:python/object/apply:pathlib.WindowsPath",
|
|
150
|
+
[str(data)],
|
|
151
|
+
)
|
|
152
|
+
|
|
127
153
|
|
|
128
154
|
def get_omega_conf_dumper() -> Type[OmegaConfDumper]:
|
|
129
155
|
if not OmegaConfDumper.str_representer_added:
|
|
130
156
|
OmegaConfDumper.add_representer(str, OmegaConfDumper.str_representer)
|
|
131
157
|
OmegaConfDumper.str_representer_added = True
|
|
158
|
+
|
|
159
|
+
# Add representers for pathlib types to ensure cross-version compatibility.
|
|
160
|
+
# Python 3.13+ uses pathlib._local.* internally, so we normalize to old pathlib.* tags
|
|
161
|
+
if not OmegaConfDumper.pathlib_representers_added:
|
|
162
|
+
from pathlib import Path, PosixPath, WindowsPath
|
|
163
|
+
|
|
164
|
+
OmegaConfDumper.add_representer(Path, OmegaConfDumper.pathlib_path_representer)
|
|
165
|
+
OmegaConfDumper.add_representer(
|
|
166
|
+
PosixPath, OmegaConfDumper.pathlib_posix_path_representer
|
|
167
|
+
)
|
|
168
|
+
OmegaConfDumper.add_representer(
|
|
169
|
+
WindowsPath, OmegaConfDumper.pathlib_windows_path_representer
|
|
170
|
+
)
|
|
171
|
+
OmegaConfDumper.pathlib_representers_added = True
|
|
172
|
+
|
|
132
173
|
return OmegaConfDumper
|
|
133
174
|
|
|
134
175
|
|
|
@@ -138,19 +179,72 @@ def yaml_is_bool(b: str) -> bool:
|
|
|
138
179
|
|
|
139
180
|
def get_yaml_loader() -> Any:
|
|
140
181
|
class OmegaConfLoader(BaseLoader): # type: ignore
|
|
141
|
-
def
|
|
142
|
-
|
|
143
|
-
|
|
182
|
+
def flatten_mapping(self, node: yaml.Node) -> Any:
|
|
183
|
+
merge_tag = "tag:yaml.org,2002:merge"
|
|
184
|
+
explicit_keys = set()
|
|
185
|
+
for key_node, _ in node.value:
|
|
186
|
+
if key_node.tag == merge_tag:
|
|
187
|
+
continue
|
|
144
188
|
if key_node.tag != yaml.resolver.BaseResolver.DEFAULT_SCALAR_TAG:
|
|
145
189
|
continue
|
|
146
|
-
if key_node.value in
|
|
190
|
+
if key_node.value in explicit_keys:
|
|
147
191
|
raise yaml.constructor.ConstructorError(
|
|
148
192
|
"while constructing a mapping",
|
|
149
193
|
node.start_mark,
|
|
150
194
|
f"found duplicate key {key_node.value}",
|
|
151
195
|
key_node.start_mark,
|
|
152
196
|
)
|
|
153
|
-
|
|
197
|
+
explicit_keys.add(key_node.value)
|
|
198
|
+
|
|
199
|
+
merge = []
|
|
200
|
+
index = 0
|
|
201
|
+
while index < len(node.value):
|
|
202
|
+
key_node, value_node = node.value[index]
|
|
203
|
+
if key_node.tag == merge_tag:
|
|
204
|
+
del node.value[index]
|
|
205
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
206
|
+
self.flatten_mapping(value_node)
|
|
207
|
+
merge.extend(value_node.value)
|
|
208
|
+
elif isinstance(value_node, yaml.SequenceNode):
|
|
209
|
+
submerge = []
|
|
210
|
+
for subnode in value_node.value:
|
|
211
|
+
if not isinstance(subnode, yaml.MappingNode):
|
|
212
|
+
raise yaml.constructor.ConstructorError(
|
|
213
|
+
"while constructing a mapping",
|
|
214
|
+
node.start_mark,
|
|
215
|
+
"expected a mapping for merging, but found "
|
|
216
|
+
f"{subnode.id}",
|
|
217
|
+
subnode.start_mark,
|
|
218
|
+
)
|
|
219
|
+
self.flatten_mapping(subnode)
|
|
220
|
+
submerge.append(subnode.value)
|
|
221
|
+
submerge.reverse()
|
|
222
|
+
for value in submerge:
|
|
223
|
+
merge.extend(value)
|
|
224
|
+
else:
|
|
225
|
+
raise yaml.constructor.ConstructorError(
|
|
226
|
+
"while constructing a mapping",
|
|
227
|
+
node.start_mark,
|
|
228
|
+
"expected a mapping or list of mappings for merging, "
|
|
229
|
+
f"but found {value_node.id}",
|
|
230
|
+
value_node.start_mark,
|
|
231
|
+
)
|
|
232
|
+
elif key_node.tag == "tag:yaml.org,2002:value":
|
|
233
|
+
key_node.tag = yaml.resolver.BaseResolver.DEFAULT_SCALAR_TAG
|
|
234
|
+
index += 1
|
|
235
|
+
else:
|
|
236
|
+
index += 1
|
|
237
|
+
|
|
238
|
+
if merge:
|
|
239
|
+
merge = [
|
|
240
|
+
(key_node, value_node)
|
|
241
|
+
for key_node, value_node in merge
|
|
242
|
+
if key_node.tag != yaml.resolver.BaseResolver.DEFAULT_SCALAR_TAG
|
|
243
|
+
or key_node.value not in explicit_keys
|
|
244
|
+
]
|
|
245
|
+
node.value = merge + node.value
|
|
246
|
+
|
|
247
|
+
def construct_mapping(self, node: yaml.Node, deep: bool = False) -> Any:
|
|
154
248
|
return super().construct_mapping(node, deep=deep)
|
|
155
249
|
|
|
156
250
|
loader = OmegaConfLoader
|
|
@@ -190,6 +284,20 @@ def get_yaml_loader() -> Any:
|
|
|
190
284
|
lambda loader, node: pathlib.WindowsPath(*loader.construct_sequence(node)),
|
|
191
285
|
)
|
|
192
286
|
|
|
287
|
+
# Python 3.13+ uses internal pathlib._local module
|
|
288
|
+
loader.add_constructor(
|
|
289
|
+
"tag:yaml.org,2002:python/object/apply:pathlib._local.Path",
|
|
290
|
+
lambda loader, node: pathlib.Path(*loader.construct_sequence(node)),
|
|
291
|
+
)
|
|
292
|
+
loader.add_constructor(
|
|
293
|
+
"tag:yaml.org,2002:python/object/apply:pathlib._local.PosixPath",
|
|
294
|
+
lambda loader, node: pathlib.PosixPath(*loader.construct_sequence(node)),
|
|
295
|
+
)
|
|
296
|
+
loader.add_constructor(
|
|
297
|
+
"tag:yaml.org,2002:python/object/apply:pathlib._local.WindowsPath",
|
|
298
|
+
lambda loader, node: pathlib.WindowsPath(*loader.construct_sequence(node)),
|
|
299
|
+
)
|
|
300
|
+
|
|
193
301
|
return loader
|
|
194
302
|
|
|
195
303
|
|
|
@@ -350,7 +458,7 @@ def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, A
|
|
|
350
458
|
value = MISSING
|
|
351
459
|
if is_union_annotation(type_) and not is_supported_union_annotation(type_):
|
|
352
460
|
e = ConfigValueError(
|
|
353
|
-
f"Unions of containers are not supported:\n{name}: {type_str(type_)}"
|
|
461
|
+
f"Unions of containers are not supported:\n{name}: {type_str(type_)}" # noqa: E231
|
|
354
462
|
)
|
|
355
463
|
format_and_raise(node=None, key=None, value=value, cause=e, msg=str(e))
|
|
356
464
|
|
|
@@ -409,7 +517,7 @@ def get_dataclass_data(
|
|
|
409
517
|
|
|
410
518
|
if is_union_annotation(type_) and not is_supported_union_annotation(type_):
|
|
411
519
|
e = ConfigValueError(
|
|
412
|
-
f"Unions of containers are not supported:\n{name}: {type_str(type_)}"
|
|
520
|
+
f"Unions of containers are not supported:\n{name}: {type_str(type_)}" # noqa: E231
|
|
413
521
|
)
|
|
414
522
|
format_and_raise(node=None, key=None, value=value, cause=e, msg=str(e))
|
|
415
523
|
try:
|
|
@@ -864,20 +972,16 @@ def format_and_raise(
|
|
|
864
972
|
)
|
|
865
973
|
|
|
866
974
|
if ref_type not in (None, Any):
|
|
867
|
-
template = dedent(
|
|
868
|
-
"""\
|
|
975
|
+
template = dedent("""\
|
|
869
976
|
$MSG
|
|
870
977
|
full_key: $FULL_KEY
|
|
871
978
|
reference_type=$REF_TYPE
|
|
872
|
-
object_type=$OBJECT_TYPE"""
|
|
873
|
-
)
|
|
979
|
+
object_type=$OBJECT_TYPE""")
|
|
874
980
|
else:
|
|
875
|
-
template = dedent(
|
|
876
|
-
"""\
|
|
981
|
+
template = dedent("""\
|
|
877
982
|
$MSG
|
|
878
983
|
full_key: $FULL_KEY
|
|
879
|
-
object_type=$OBJECT_TYPE"""
|
|
880
|
-
)
|
|
984
|
+
object_type=$OBJECT_TYPE""")
|
|
881
985
|
s = string.Template(template=template)
|
|
882
986
|
|
|
883
987
|
message = s.substitute(
|
|
@@ -941,7 +1045,14 @@ def type_str(t: Any, include_module_name: bool = False) -> str:
|
|
|
941
1045
|
and t.__module__ != "typing"
|
|
942
1046
|
and not t.__module__.startswith("omegaconf.")
|
|
943
1047
|
):
|
|
944
|
-
|
|
1048
|
+
module_name = str(t.__module__)
|
|
1049
|
+
if isinstance(t, type) and issubclass(t, pathlib.PurePath):
|
|
1050
|
+
# Python 3.13+ uses pathlib._local internally, normalize to pathlib for # Path types
|
|
1051
|
+
# Normalize pathlib._local to pathlib for cross-version compatibility
|
|
1052
|
+
if module_name == "pathlib._local": # pragma: no cover
|
|
1053
|
+
module_name = "pathlib"
|
|
1054
|
+
|
|
1055
|
+
module_prefix = module_name + "."
|
|
945
1056
|
else:
|
|
946
1057
|
module_prefix = ""
|
|
947
1058
|
ret = module_prefix + ret
|
|
@@ -248,16 +248,19 @@ class Node(ABC):
|
|
|
248
248
|
self,
|
|
249
249
|
throw_on_resolution_failure: bool = False,
|
|
250
250
|
memo: Optional[Set[int]] = None,
|
|
251
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
251
252
|
) -> Optional["Node"]:
|
|
252
253
|
return self._dereference_node_impl(
|
|
253
254
|
throw_on_resolution_failure=throw_on_resolution_failure,
|
|
254
255
|
memo=memo,
|
|
256
|
+
resolved_node_cache=resolved_node_cache,
|
|
255
257
|
)
|
|
256
258
|
|
|
257
259
|
def _dereference_node_impl(
|
|
258
260
|
self,
|
|
259
261
|
throw_on_resolution_failure: bool,
|
|
260
262
|
memo: Optional[Set[int]] = None,
|
|
263
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
261
264
|
) -> Optional["Node"]:
|
|
262
265
|
if not self._is_interpolation():
|
|
263
266
|
return self
|
|
@@ -278,6 +281,7 @@ class Node(ABC):
|
|
|
278
281
|
parse_tree=parse(_get_value(self)),
|
|
279
282
|
throw_on_resolution_failure=throw_on_resolution_failure,
|
|
280
283
|
memo=memo,
|
|
284
|
+
resolved_node_cache=resolved_node_cache,
|
|
281
285
|
)
|
|
282
286
|
|
|
283
287
|
def _get_root(self) -> "Container":
|
|
@@ -456,6 +460,7 @@ class Container(Box):
|
|
|
456
460
|
throw_on_missing: bool,
|
|
457
461
|
throw_on_resolution_failure: bool,
|
|
458
462
|
memo: Optional[Set[int]] = None,
|
|
463
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
459
464
|
) -> Tuple[Optional["Container"], Optional[str], Optional[Node]]:
|
|
460
465
|
"""
|
|
461
466
|
Select a value using dot separated key sequence
|
|
@@ -482,6 +487,7 @@ class Container(Box):
|
|
|
482
487
|
ret = ret._maybe_dereference_node(
|
|
483
488
|
throw_on_resolution_failure=throw_on_resolution_failure,
|
|
484
489
|
memo=memo,
|
|
490
|
+
resolved_node_cache=resolved_node_cache,
|
|
485
491
|
)
|
|
486
492
|
|
|
487
493
|
if ret is not None and not isinstance(ret, Container):
|
|
@@ -506,12 +512,15 @@ class Container(Box):
|
|
|
506
512
|
if value is None:
|
|
507
513
|
return root, last_key, None
|
|
508
514
|
|
|
515
|
+
value_id = id(value)
|
|
516
|
+
if resolved_node_cache is not None and value_id in resolved_node_cache:
|
|
517
|
+
return root, last_key, resolved_node_cache[value_id]
|
|
518
|
+
|
|
509
519
|
if memo is not None:
|
|
510
|
-
|
|
511
|
-
if vid in memo:
|
|
520
|
+
if value_id in memo:
|
|
512
521
|
raise InterpolationResolutionError("Recursive interpolation detected")
|
|
513
522
|
# push to memo "stack"
|
|
514
|
-
memo.add(
|
|
523
|
+
memo.add(value_id)
|
|
515
524
|
|
|
516
525
|
try:
|
|
517
526
|
value = root._maybe_resolve_interpolation(
|
|
@@ -520,11 +529,15 @@ class Container(Box):
|
|
|
520
529
|
value=value,
|
|
521
530
|
throw_on_resolution_failure=throw_on_resolution_failure,
|
|
522
531
|
memo=memo,
|
|
532
|
+
resolved_node_cache=resolved_node_cache,
|
|
523
533
|
)
|
|
524
534
|
finally:
|
|
525
535
|
if memo is not None:
|
|
526
536
|
# pop from memo "stack"
|
|
527
|
-
memo.remove(
|
|
537
|
+
memo.remove(value_id)
|
|
538
|
+
|
|
539
|
+
if resolved_node_cache is not None and value is not None:
|
|
540
|
+
resolved_node_cache[value_id] = value
|
|
528
541
|
|
|
529
542
|
return root, last_key, value
|
|
530
543
|
|
|
@@ -536,6 +549,7 @@ class Container(Box):
|
|
|
536
549
|
parse_tree: OmegaConfGrammarParser.ConfigValueContext,
|
|
537
550
|
throw_on_resolution_failure: bool,
|
|
538
551
|
memo: Optional[Set[int]],
|
|
552
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
539
553
|
) -> Optional["Node"]:
|
|
540
554
|
"""
|
|
541
555
|
Resolve an interpolation.
|
|
@@ -568,7 +582,11 @@ class Container(Box):
|
|
|
568
582
|
|
|
569
583
|
try:
|
|
570
584
|
resolved = self.resolve_parse_tree(
|
|
571
|
-
parse_tree=parse_tree,
|
|
585
|
+
parse_tree=parse_tree,
|
|
586
|
+
node=value,
|
|
587
|
+
key=key,
|
|
588
|
+
memo=memo,
|
|
589
|
+
resolved_node_cache=resolved_node_cache,
|
|
572
590
|
)
|
|
573
591
|
except InterpolationResolutionError:
|
|
574
592
|
if throw_on_resolution_failure:
|
|
@@ -636,7 +654,10 @@ class Container(Box):
|
|
|
636
654
|
parent = parent._get_parent()
|
|
637
655
|
|
|
638
656
|
def _resolve_node_interpolation(
|
|
639
|
-
self,
|
|
657
|
+
self,
|
|
658
|
+
inter_key: str,
|
|
659
|
+
memo: Optional[Set[int]],
|
|
660
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
640
661
|
) -> "Node":
|
|
641
662
|
"""A node interpolation is of the form `${foo.bar}`"""
|
|
642
663
|
try:
|
|
@@ -652,6 +673,7 @@ class Container(Box):
|
|
|
652
673
|
throw_on_missing=True,
|
|
653
674
|
throw_on_resolution_failure=True,
|
|
654
675
|
memo=memo,
|
|
676
|
+
resolved_node_cache=resolved_node_cache,
|
|
655
677
|
)
|
|
656
678
|
except MissingMandatoryValue as exc:
|
|
657
679
|
raise InterpolationToMissingValueError(
|
|
@@ -696,6 +718,7 @@ class Container(Box):
|
|
|
696
718
|
value: Node,
|
|
697
719
|
throw_on_resolution_failure: bool,
|
|
698
720
|
memo: Optional[Set[int]] = None,
|
|
721
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
699
722
|
) -> Optional[Node]:
|
|
700
723
|
value_kind = get_value_kind(value)
|
|
701
724
|
if value_kind != ValueKind.INTERPOLATION:
|
|
@@ -709,6 +732,7 @@ class Container(Box):
|
|
|
709
732
|
parse_tree=parse_tree,
|
|
710
733
|
throw_on_resolution_failure=throw_on_resolution_failure,
|
|
711
734
|
memo=memo if memo is not None else set(),
|
|
735
|
+
resolved_node_cache=resolved_node_cache,
|
|
712
736
|
)
|
|
713
737
|
|
|
714
738
|
def resolve_parse_tree(
|
|
@@ -717,6 +741,7 @@ class Container(Box):
|
|
|
717
741
|
node: Node,
|
|
718
742
|
memo: Optional[Set[int]] = None,
|
|
719
743
|
key: Optional[Any] = None,
|
|
744
|
+
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
720
745
|
) -> Any:
|
|
721
746
|
"""
|
|
722
747
|
Resolve a given parse tree into its value.
|
|
@@ -728,7 +753,11 @@ class Container(Box):
|
|
|
728
753
|
def node_interpolation_callback(
|
|
729
754
|
inter_key: str, memo: Optional[Set[int]]
|
|
730
755
|
) -> Optional["Node"]:
|
|
731
|
-
return self._resolve_node_interpolation(
|
|
756
|
+
return self._resolve_node_interpolation(
|
|
757
|
+
inter_key=inter_key,
|
|
758
|
+
memo=memo,
|
|
759
|
+
resolved_node_cache=resolved_node_cache,
|
|
760
|
+
)
|
|
732
761
|
|
|
733
762
|
def resolver_interpolation_callback(
|
|
734
763
|
name: str, args: Tuple[Any, ...], args_str: Tuple[str, ...]
|
|
@@ -214,9 +214,13 @@ class BaseContainer(Container, ABC):
|
|
|
214
214
|
throw_on_missing: bool,
|
|
215
215
|
enum_to_str: bool = False,
|
|
216
216
|
structured_config_mode: SCMode = SCMode.DICT,
|
|
217
|
+
resolved_node_cache: Optional[Dict[int, Node]] = None,
|
|
217
218
|
) -> Union[None, Any, str, Dict[DictKeyType, Any], List[Any]]:
|
|
218
219
|
from omegaconf import MISSING, DictConfig, ListConfig
|
|
219
220
|
|
|
221
|
+
if resolve and resolved_node_cache is None:
|
|
222
|
+
resolved_node_cache = {}
|
|
223
|
+
|
|
220
224
|
def convert(val: Node) -> Any:
|
|
221
225
|
value = val._value()
|
|
222
226
|
if enum_to_str and isinstance(value, Enum):
|
|
@@ -230,11 +234,26 @@ class BaseContainer(Container, ABC):
|
|
|
230
234
|
except MissingMandatoryValue as e:
|
|
231
235
|
conf._format_and_raise(key=key, value=None, cause=e)
|
|
232
236
|
assert isinstance(node, Node)
|
|
237
|
+
node_id = id(node)
|
|
233
238
|
if resolve:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
cached = (
|
|
240
|
+
resolved_node_cache.get(node_id)
|
|
241
|
+
if resolved_node_cache is not None
|
|
242
|
+
else None
|
|
243
|
+
)
|
|
244
|
+
if cached is not None:
|
|
245
|
+
node = cached
|
|
246
|
+
else:
|
|
247
|
+
try:
|
|
248
|
+
node = node._maybe_dereference_node(
|
|
249
|
+
throw_on_resolution_failure=True,
|
|
250
|
+
resolved_node_cache=resolved_node_cache,
|
|
251
|
+
)
|
|
252
|
+
except InterpolationResolutionError as e:
|
|
253
|
+
conf._format_and_raise(key=key, value=None, cause=e)
|
|
254
|
+
assert node is not None
|
|
255
|
+
if resolved_node_cache is not None:
|
|
256
|
+
resolved_node_cache[node_id] = node
|
|
238
257
|
|
|
239
258
|
if isinstance(node, Container):
|
|
240
259
|
value = BaseContainer._to_content(
|
|
@@ -243,6 +262,7 @@ class BaseContainer(Container, ABC):
|
|
|
243
262
|
throw_on_missing=throw_on_missing,
|
|
244
263
|
enum_to_str=enum_to_str,
|
|
245
264
|
structured_config_mode=structured_config_mode,
|
|
265
|
+
resolved_node_cache=resolved_node_cache,
|
|
246
266
|
)
|
|
247
267
|
else:
|
|
248
268
|
value = convert(node)
|
|
@@ -738,9 +758,9 @@ class BaseContainer(Container, ABC):
|
|
|
738
758
|
|
|
739
759
|
def _slice_to_str(x: slice) -> str:
|
|
740
760
|
if x.step is not None:
|
|
741
|
-
return f"{x.start}:{x.stop}:{x.step}"
|
|
761
|
+
return f"{x.start}:{x.stop}:{x.step}" # noqa: E231
|
|
742
762
|
else:
|
|
743
|
-
return f"{x.start}:{x.stop}"
|
|
763
|
+
return f"{x.start}:{x.stop}" # noqa: E231
|
|
744
764
|
|
|
745
765
|
def prepand(
|
|
746
766
|
full_key: str,
|
{omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarLexer.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated from /home/
|
|
1
|
+
# Generated from /home/runner/work/omegaconf/omegaconf/omegaconf/grammar/OmegaConfGrammarLexer.g4 by ANTLR 4.11.1
|
|
2
2
|
from omegaconf.vendor.antlr4 import *
|
|
3
3
|
from io import StringIO
|
|
4
4
|
import sys
|
{omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarParser.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated from /home/
|
|
1
|
+
# Generated from /home/runner/work/omegaconf/omegaconf/omegaconf/grammar/OmegaConfGrammarParser.g4 by ANTLR 4.11.1
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
from omegaconf.vendor.antlr4 import *
|
|
4
4
|
from io import StringIO
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated from /home/
|
|
1
|
+
# Generated from /home/runner/work/omegaconf/omegaconf/omegaconf/grammar/OmegaConfGrammarParser.g4 by ANTLR 4.11.1
|
|
2
2
|
from omegaconf.vendor.antlr4 import *
|
|
3
3
|
if __name__ is not None and "." in __name__:
|
|
4
4
|
from .OmegaConfGrammarParser import OmegaConfGrammarParser
|
{omegaconf-2.4.0.dev3 → omegaconf-2.4.0.dev8}/omegaconf/grammar/gen/OmegaConfGrammarParserVisitor.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated from /home/
|
|
1
|
+
# Generated from /home/runner/work/omegaconf/omegaconf/omegaconf/grammar/OmegaConfGrammarParser.g4 by ANTLR 4.11.1
|
|
2
2
|
from omegaconf.vendor.antlr4 import *
|
|
3
3
|
if __name__ is not None and "." in __name__:
|
|
4
4
|
from .OmegaConfGrammarParser import OmegaConfGrammarParser
|
|
@@ -28,8 +28,10 @@ _node_inter = f"\\${{\\s*{_node_path}\\s*}}" # node interpolation ${foo.bar}
|
|
|
28
28
|
_id = "[a-zA-Z_][\\w\\-]*" # foo, foo_bar, foo-bar, abc123
|
|
29
29
|
_resolver_name = f"({_id}(\\.{_id})*)?" # foo, ns.bar3, ns_1.ns_2.b0z
|
|
30
30
|
_arg = r"[a-zA-Z_0-9/\-\+.$%*@?|]+" # string representing a resolver argument
|
|
31
|
-
_args = f"{_arg}(\\s*,\\s*{_arg})*" # list of resolver arguments
|
|
32
|
-
_resolver_inter =
|
|
31
|
+
_args = f"{_arg}(\\s*,\\s*{_arg})*" # list of resolver arguments # noqa: E231
|
|
32
|
+
_resolver_inter = (
|
|
33
|
+
f"\\${{\\s*{_resolver_name}\\s*:\\s*{_args}?\\s*}}" # ${foo:bar} # noqa: E231
|
|
34
|
+
)
|
|
33
35
|
_inter = f"({_node_inter}|{_resolver_inter})" # any kind of interpolation
|
|
34
36
|
_outer = "([^$]|\\$(?!{))+" # any character except $ (unless not followed by {)
|
|
35
37
|
SIMPLE_INTERPOLATION_PATTERN = re.compile(
|
|
@@ -251,7 +251,7 @@ class GrammarVisitor(OmegaConfGrammarParserVisitor):
|
|
|
251
251
|
warnings.warn(
|
|
252
252
|
f"In the sequence `{txt}` some elements are missing: please replace "
|
|
253
253
|
f"them with empty quoted strings. "
|
|
254
|
-
f"See https://github.com/omry/omegaconf/issues/572 for details.",
|
|
254
|
+
f"See https://github.com/omry/omegaconf/issues/572 for details.", # noqa: E231
|
|
255
255
|
category=UserWarning,
|
|
256
256
|
)
|
|
257
257
|
|