omegaconf 2.4.0.dev11__tar.gz → 2.4.0.dev12__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.dev11/omegaconf.egg-info → omegaconf-2.4.0.dev12}/PKG-INFO +2 -2
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/README.md +1 -1
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/_utils.py +23 -7
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/base.py +27 -1
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/basecontainer.py +58 -21
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/dictconfig.py +0 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/listconfig.py +8 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/omegaconf.py +107 -72
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/version.py +1 -1
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12/omegaconf.egg-info}/PKG-INFO +2 -2
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/pyproject.toml +11 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/setup.cfg +1 -1
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/conftest.py +2 -2
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/test_oc_create.py +2 -2
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/test_oc_dict.py +3 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/test_custom_resolvers.py +51 -48
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/test_interpolation.py +3 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/test_structured_config.py +34 -1
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_basic_ops_list.py +20 -0
- omegaconf-2.4.0.dev12/tests/test_config_eq.py +429 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_create.py +36 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_errors.py +126 -4
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_grammar.py +6 -6
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_matrix.py +11 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_merge.py +109 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_omegaconf.py +6 -6
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_select.py +11 -3
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_to_container.py +1 -1
- omegaconf-2.4.0.dev11/tests/test_config_eq.py +0 -171
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/LICENSE +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/MANIFEST.in +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/build_helpers/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/build_helpers/bin/antlr-4.11.1-complete.jar +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/build_helpers/build_helpers.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/build_helpers/get_vendored.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/build_helpers/test_helpers.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/_impl.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/_yaml.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/errors.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/OmegaConfGrammarLexer.g4 +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/OmegaConfGrammarParser.g4 +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/gen/OmegaConfGrammarLexer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/gen/OmegaConfGrammarParser.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/gen/OmegaConfGrammarParserListener.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/gen/OmegaConfGrammarParserVisitor.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar/gen/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar_parser.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/grammar_visitor.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/nodes.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/py.typed +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/resolvers/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/resolvers/oc/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/resolvers/oc/dict.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/typing.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/BufferedTokenStream.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/CommonTokenFactory.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/CommonTokenStream.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/FileStream.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/InputStream.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/IntervalSet.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/LL1Analyzer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/Lexer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/ListTokenSource.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/Parser.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/ParserInterpreter.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/ParserRuleContext.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/PredictionContext.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/Recognizer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/RuleContext.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/StdinStream.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/Token.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/TokenStreamRewriter.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/Utils.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/_pygrun.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATN.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNConfig.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNConfigSet.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNDeserializationOptions.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNDeserializer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNState.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ATNType.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/LexerATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/LexerAction.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/LexerActionExecutor.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/ParserATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/PredictionMode.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/SemanticContext.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/Transition.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/atn/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/dfa/DFA.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/dfa/DFASerializer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/dfa/DFAState.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/dfa/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/error/DiagnosticErrorListener.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/error/ErrorListener.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/error/ErrorStrategy.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/error/Errors.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/error/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/Chunk.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/ParseTreeMatch.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/ParseTreePattern.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/ParseTreePatternMatcher.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/RuleTagToken.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/TokenTagToken.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/Tree.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/Trees.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/tree/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/xpath/XPath.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/xpath/XPathLexer.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf/vendor/antlr4/xpath/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf.egg-info/SOURCES.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf.egg-info/dependency_links.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf.egg-info/requires.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/omegaconf.egg-info/top_level.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/requirements/base.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/requirements/dev.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/requirements/docs.txt +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/setup.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/data/2.0.6.pickle +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/data/2.1.0.rc1.pickle +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/data/load.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/data/save.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/examples/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/examples/dataclass_postponed_annotations.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/examples/test_dataclass_example.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/examples/test_postponed_annotations.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/test_oc_decode.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/test_oc_deprecated.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/test_oc_env.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/interpolation/built_in_resolvers/test_oc_select.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/data/__init__.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/data/attr_classes.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/data/dataclasses.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/data/dataclasses_pre_311.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/structured_conf/test_structured_basic.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_base_config.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_basic_ops_dict.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_compare_dictconfig_vs_dict.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_container_unions.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_get_full_key.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_nested_containers.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_nodes.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_readonly.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_serialization.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_struct.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_to_yaml.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_unions.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_update.py +0 -0
- {omegaconf-2.4.0.dev11 → omegaconf-2.4.0.dev12}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: omegaconf
|
|
3
|
-
Version: 2.4.0.
|
|
3
|
+
Version: 2.4.0.dev12
|
|
4
4
|
Summary: A flexible configuration library
|
|
5
5
|
Home-page: https://github.com/omry/omegaconf
|
|
6
6
|
Author: Omry Yadan
|
|
@@ -57,7 +57,7 @@ Dynamic: summary
|
|
|
57
57
|
| Project | [](https://badge.fury.io/py/omegaconf)[](https://pepy.tech/project/omegaconf) |
|
|
58
58
|
| Code quality| [](https://dl.circleci.com/status-badge/redirect/gh/omry/omegaconf/tree/main)[](https://coveralls.io/github/omry/omegaconf)|
|
|
59
59
|
| Docs and support |[](https://omegaconf.readthedocs.io/en/2.3_branch/)[](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)[](https://hydra-framework.zulipchat.com/)|
|
|
60
|
-
| Backlog | [
|
|
60
|
+
| Backlog | [](https://omry.github.io/backlog-atlas/) |
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
OmegaConf is a hierarchical configuration system, with support for merging configurations from multiple sources (YAML config files, dataclasses/objects and CLI arguments)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
| Project | [](https://badge.fury.io/py/omegaconf)[](https://pepy.tech/project/omegaconf) |
|
|
5
5
|
| Code quality| [](https://dl.circleci.com/status-badge/redirect/gh/omry/omegaconf/tree/main)[](https://coveralls.io/github/omry/omegaconf)|
|
|
6
6
|
| Docs and support |[](https://omegaconf.readthedocs.io/en/2.3_branch/)[](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)[](https://hydra-framework.zulipchat.com/)|
|
|
7
|
-
| Backlog | [
|
|
7
|
+
| Backlog | [](https://omry.github.io/backlog-atlas/) |
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
OmegaConf is a hierarchical configuration system, with support for merging configurations from multiple sources (YAML config files, dataclasses/objects and CLI arguments)
|
|
@@ -340,6 +340,7 @@ def get_attr_class_fields(obj: Any) -> List["AttrAttribute[Any]"]:
|
|
|
340
340
|
|
|
341
341
|
|
|
342
342
|
def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, Any]:
|
|
343
|
+
from omegaconf.base import Node
|
|
343
344
|
from omegaconf.omegaconf import OmegaConf, _maybe_wrap
|
|
344
345
|
|
|
345
346
|
flags = {"allow_objects": allow_objects} if allow_objects is not None else {}
|
|
@@ -377,6 +378,8 @@ def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, A
|
|
|
377
378
|
value = default.factory()
|
|
378
379
|
else:
|
|
379
380
|
value = default
|
|
381
|
+
if isinstance(value, Node):
|
|
382
|
+
value = copy.deepcopy(value)
|
|
380
383
|
if is_union_annotation(type_) and not is_supported_union_annotation(type_):
|
|
381
384
|
e = ConfigValueError(
|
|
382
385
|
f"Unions of containers are not supported:\n{name}: {type_str(type_)}" # noqa: E231
|
|
@@ -410,6 +413,7 @@ def get_dataclass_fields(obj: Any) -> List["dataclasses.Field[Any]"]:
|
|
|
410
413
|
def get_dataclass_data(
|
|
411
414
|
obj: Any, allow_objects: Optional[bool] = None
|
|
412
415
|
) -> Dict[str, Any]:
|
|
416
|
+
from omegaconf.base import Node
|
|
413
417
|
from omegaconf.omegaconf import MISSING, OmegaConf, _maybe_wrap
|
|
414
418
|
|
|
415
419
|
flags = {"allow_objects": allow_objects} if allow_objects is not None else {}
|
|
@@ -435,6 +439,8 @@ def get_dataclass_data(
|
|
|
435
439
|
value = field.default_factory() # type: ignore
|
|
436
440
|
else:
|
|
437
441
|
value = MISSING
|
|
442
|
+
if isinstance(value, Node):
|
|
443
|
+
value = copy.deepcopy(value)
|
|
438
444
|
|
|
439
445
|
if is_union_annotation(type_) and not is_supported_union_annotation(type_):
|
|
440
446
|
e = ConfigValueError(
|
|
@@ -747,7 +753,10 @@ def get_dict_key_value_types(ref_type: Any) -> Tuple[Any, Any]:
|
|
|
747
753
|
if args is None:
|
|
748
754
|
bases = getattr(ref_type, "__orig_bases__", None)
|
|
749
755
|
if bases is not None and len(bases) > 0:
|
|
750
|
-
|
|
756
|
+
for base in bases:
|
|
757
|
+
if is_dict_annotation(base):
|
|
758
|
+
args = getattr(base, "__args__", None)
|
|
759
|
+
break
|
|
751
760
|
|
|
752
761
|
key_type: Any
|
|
753
762
|
element_type: Any
|
|
@@ -755,7 +764,7 @@ def get_dict_key_value_types(ref_type: Any) -> Tuple[Any, Any]:
|
|
|
755
764
|
key_type = Any
|
|
756
765
|
element_type = Any
|
|
757
766
|
else:
|
|
758
|
-
if args is not None:
|
|
767
|
+
if args is not None and len(args) == 2:
|
|
759
768
|
key_type = args[0]
|
|
760
769
|
element_type = args[1]
|
|
761
770
|
else:
|
|
@@ -829,12 +838,16 @@ def get_type_hint(obj: Any, key: Any = None) -> Optional[Type[Any]]:
|
|
|
829
838
|
return Any # type: ignore
|
|
830
839
|
|
|
831
840
|
|
|
832
|
-
def
|
|
841
|
+
def _is_full_backtrace_enabled() -> bool:
|
|
833
842
|
# Set the environment variable OC_CAUSE=1 to get a stacktrace that includes the
|
|
834
843
|
# causing exception.
|
|
835
844
|
env_var = os.environ["OC_CAUSE"] if "OC_CAUSE" in os.environ else None
|
|
836
845
|
debugging = sys.gettrace() is not None
|
|
837
|
-
|
|
846
|
+
return (debugging and not env_var == "0") or (env_var == "1")
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
def _raise(ex: Exception, cause: Exception) -> None:
|
|
850
|
+
full_backtrace = _is_full_backtrace_enabled()
|
|
838
851
|
if full_backtrace:
|
|
839
852
|
# In the alias case (`cause is ex`), assigning `ex.__cause__ = cause`
|
|
840
853
|
# would create a self-reference cycle that pins `ex` (and transitively
|
|
@@ -845,9 +858,12 @@ def _raise(ex: Exception, cause: Exception) -> None:
|
|
|
845
858
|
else:
|
|
846
859
|
ex.__cause__ = None
|
|
847
860
|
try:
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
861
|
+
# Set env var OC_CAUSE=1 for full trace. In normal mode, avoid
|
|
862
|
+
# preserving the active traceback because it can retain caller frame
|
|
863
|
+
# locals until cyclic GC runs.
|
|
864
|
+
if full_backtrace:
|
|
865
|
+
raise ex.with_traceback(sys.exc_info()[2])
|
|
866
|
+
raise ex.with_traceback(None) from None
|
|
851
867
|
finally:
|
|
852
868
|
# Follow https://peps.python.org/pep-3110/ to break
|
|
853
869
|
# the exception reference cycle.
|
|
@@ -22,6 +22,7 @@ from ._utils import (
|
|
|
22
22
|
NoneType,
|
|
23
23
|
ValueKind,
|
|
24
24
|
_get_value,
|
|
25
|
+
_is_full_backtrace_enabled,
|
|
25
26
|
_is_interpolation,
|
|
26
27
|
_is_missing_value,
|
|
27
28
|
_is_special,
|
|
@@ -42,6 +43,7 @@ from .errors import (
|
|
|
42
43
|
InterpolationToMissingValueError,
|
|
43
44
|
InterpolationValidationError,
|
|
44
45
|
MissingMandatoryValue,
|
|
46
|
+
OmegaConfBaseException,
|
|
45
47
|
UnsupportedInterpolationType,
|
|
46
48
|
ValidationError,
|
|
47
49
|
)
|
|
@@ -238,6 +240,17 @@ class Node(ABC):
|
|
|
238
240
|
msg: Optional[str] = None,
|
|
239
241
|
type_override: Any = None,
|
|
240
242
|
) -> NoReturn:
|
|
243
|
+
if (
|
|
244
|
+
type_override is None
|
|
245
|
+
and isinstance(cause, OmegaConfBaseException)
|
|
246
|
+
and cause._initialized
|
|
247
|
+
):
|
|
248
|
+
if not _is_full_backtrace_enabled():
|
|
249
|
+
cause.__traceback__ = None
|
|
250
|
+
cause.__context__ = None
|
|
251
|
+
# Keep the re-raise in this common wrapper so callers do not need
|
|
252
|
+
# to remember traceback cleanup before forwarding OmegaConf errors.
|
|
253
|
+
raise
|
|
241
254
|
format_and_raise(
|
|
242
255
|
node=self,
|
|
243
256
|
key=key,
|
|
@@ -690,6 +703,7 @@ class Container(Box):
|
|
|
690
703
|
resolved_node_cache: Optional[Dict[int, "Node"]] = None,
|
|
691
704
|
) -> "Node":
|
|
692
705
|
"""A node interpolation is of the form `${foo.bar}`"""
|
|
706
|
+
original_inter_key = inter_key
|
|
693
707
|
try:
|
|
694
708
|
root_node, inter_key = self._resolve_key_and_root(inter_key)
|
|
695
709
|
except ConfigKeyError as exc:
|
|
@@ -711,7 +725,19 @@ class Container(Box):
|
|
|
711
725
|
).with_traceback(sys.exc_info()[2])
|
|
712
726
|
|
|
713
727
|
if parent is None or value is None:
|
|
714
|
-
|
|
728
|
+
msg = f"Interpolation key '{inter_key}' not found"
|
|
729
|
+
if original_inter_key != inter_key:
|
|
730
|
+
try:
|
|
731
|
+
resolved_inter_key = root_node._get_full_key(inter_key)
|
|
732
|
+
except Exception as exc:
|
|
733
|
+
resolved_inter_key = (
|
|
734
|
+
f"<unresolvable due to {type(exc).__name__}: {exc}>"
|
|
735
|
+
)
|
|
736
|
+
msg = (
|
|
737
|
+
f"Interpolation key '{original_inter_key}' not found"
|
|
738
|
+
f" (resolved to '{resolved_inter_key}')"
|
|
739
|
+
)
|
|
740
|
+
raise InterpolationKeyError(msg)
|
|
715
741
|
else:
|
|
716
742
|
self._validate_not_dereferencing_to_parent(node=self, target=value)
|
|
717
743
|
return value
|
|
@@ -359,6 +359,7 @@ class BaseContainer(Container, ABC):
|
|
|
359
359
|
dest: "BaseContainer",
|
|
360
360
|
src: "BaseContainer",
|
|
361
361
|
list_merge_mode: ListMergeMode = ListMergeMode.REPLACE,
|
|
362
|
+
_allow_readonly_target: bool = False,
|
|
362
363
|
) -> None:
|
|
363
364
|
"""merge src into dest and return a new copy, does not modified input"""
|
|
364
365
|
from omegaconf import AnyNode, DictConfig, ValueNode
|
|
@@ -465,6 +466,7 @@ class BaseContainer(Container, ABC):
|
|
|
465
466
|
dest_node._merge_with(
|
|
466
467
|
src_node,
|
|
467
468
|
list_merge_mode=list_merge_mode,
|
|
469
|
+
_allow_readonly_target=_allow_readonly_target,
|
|
468
470
|
)
|
|
469
471
|
elif not src_node_missing:
|
|
470
472
|
dest.__setitem__(key, src_node)
|
|
@@ -581,6 +583,7 @@ class BaseContainer(Container, ABC):
|
|
|
581
583
|
"BaseContainer", Dict[str, Any], List[Any], Tuple[Any, ...], Any
|
|
582
584
|
],
|
|
583
585
|
list_merge_mode: ListMergeMode = ListMergeMode.REPLACE,
|
|
586
|
+
_allow_readonly_target: bool = False,
|
|
584
587
|
) -> None:
|
|
585
588
|
from .dictconfig import DictConfig
|
|
586
589
|
from .listconfig import ListConfig
|
|
@@ -594,21 +597,35 @@ class BaseContainer(Container, ABC):
|
|
|
594
597
|
if self._get_flag("allow_objects") is True:
|
|
595
598
|
my_flags = {"allow_objects": True}
|
|
596
599
|
other = _ensure_container(other, flags=my_flags)
|
|
600
|
+
prev_readonly = self._get_node_flag("readonly")
|
|
597
601
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
)
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
602
|
+
readonly_overridden = (
|
|
603
|
+
_allow_readonly_target and self._get_flag("readonly") is True
|
|
604
|
+
)
|
|
605
|
+
if readonly_overridden:
|
|
606
|
+
# Non-public merge construction may target readonly containers.
|
|
607
|
+
# Temporarily relax them without changing merge_with() semantics.
|
|
608
|
+
self._set_flag("readonly", False)
|
|
609
|
+
|
|
610
|
+
try:
|
|
611
|
+
if isinstance(self, DictConfig) and isinstance(other, DictConfig):
|
|
612
|
+
BaseContainer._map_merge(
|
|
613
|
+
self,
|
|
614
|
+
other,
|
|
615
|
+
list_merge_mode=list_merge_mode,
|
|
616
|
+
_allow_readonly_target=_allow_readonly_target,
|
|
617
|
+
)
|
|
618
|
+
elif isinstance(self, ListConfig) and isinstance(other, ListConfig):
|
|
619
|
+
BaseContainer._list_merge(
|
|
620
|
+
self,
|
|
621
|
+
other,
|
|
622
|
+
list_merge_mode=list_merge_mode,
|
|
623
|
+
)
|
|
624
|
+
else:
|
|
625
|
+
raise TypeError("Cannot merge DictConfig with ListConfig")
|
|
626
|
+
finally:
|
|
627
|
+
if readonly_overridden:
|
|
628
|
+
self._set_flag("readonly", prev_readonly)
|
|
612
629
|
|
|
613
630
|
# recursively correct the parent hierarchy after the merge
|
|
614
631
|
self._re_parent()
|
|
@@ -917,6 +934,19 @@ def _update_types(node: Node, ref_type: Any, object_type: Optional[type]) -> Non
|
|
|
917
934
|
node._metadata.object_type = object_type
|
|
918
935
|
|
|
919
936
|
if node._metadata.ref_type is Any:
|
|
937
|
+
new_is_optional, new_ref_type = _resolve_optional(ref_type)
|
|
938
|
+
if is_dict_annotation(new_ref_type) and is_structured_config(
|
|
939
|
+
node._metadata.object_type
|
|
940
|
+
):
|
|
941
|
+
from ._utils import get_dict_key_value_types
|
|
942
|
+
|
|
943
|
+
assert isinstance(node._metadata, ContainerMetadata)
|
|
944
|
+
node._metadata.optional = new_is_optional
|
|
945
|
+
node._metadata.ref_type = new_ref_type
|
|
946
|
+
node._metadata.key_type, node._metadata.element_type = (
|
|
947
|
+
get_dict_key_value_types(new_ref_type)
|
|
948
|
+
)
|
|
949
|
+
return
|
|
920
950
|
_deep_update_type_hint(node, ref_type)
|
|
921
951
|
|
|
922
952
|
|
|
@@ -972,17 +1002,24 @@ def _deep_update_type_hint(node: Node, type_hint: Any) -> None:
|
|
|
972
1002
|
|
|
973
1003
|
def _deep_update_subnode(node: BaseContainer, key: Any, value_type_hint: Any) -> None:
|
|
974
1004
|
"""Get node[key] and ensure it is compatible with value_type_hint, mutating if necessary."""
|
|
1005
|
+
from .nodes import AnyNode
|
|
1006
|
+
|
|
975
1007
|
subnode = node._get_node(key)
|
|
976
1008
|
assert isinstance(subnode, Node)
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1009
|
+
_, ref_type = _resolve_optional(value_type_hint)
|
|
1010
|
+
if (
|
|
1011
|
+
_is_special(subnode)
|
|
1012
|
+
or (isinstance(subnode, AnyNode) and ref_type is not Any)
|
|
1013
|
+
or (
|
|
1014
|
+
is_union_annotation(value_type_hint)
|
|
1015
|
+
and (
|
|
1016
|
+
not isinstance(subnode, UnionNode)
|
|
1017
|
+
or get_type_hint(subnode) != value_type_hint
|
|
1018
|
+
)
|
|
982
1019
|
)
|
|
983
1020
|
):
|
|
984
|
-
# Ensure special values are wrapped in a Node
|
|
985
|
-
# is compatible with the type hint.
|
|
1021
|
+
# Ensure dynamically typed or special values are wrapped in a Node
|
|
1022
|
+
# subclass that is compatible with the type hint.
|
|
986
1023
|
node._wrap_value_and_set(key, subnode._value(), value_type_hint)
|
|
987
1024
|
subnode = node._get_node(key)
|
|
988
1025
|
assert isinstance(subnode, Node)
|
|
@@ -48,7 +48,6 @@ from .errors import (
|
|
|
48
48
|
InterpolationResolutionError,
|
|
49
49
|
KeyValidationError,
|
|
50
50
|
MissingMandatoryValue,
|
|
51
|
-
OmegaConfBaseException,
|
|
52
51
|
ReadonlyConfigError,
|
|
53
52
|
ValidationError,
|
|
54
53
|
)
|
|
@@ -344,8 +343,6 @@ class DictConfig(BaseContainer, MutableMapping[Any, Any]):
|
|
|
344
343
|
try:
|
|
345
344
|
self.__set_impl(key, value)
|
|
346
345
|
except Exception as e:
|
|
347
|
-
if isinstance(e, OmegaConfBaseException) and e._initialized:
|
|
348
|
-
raise e
|
|
349
346
|
self._format_and_raise(key=key, value=value, cause=e)
|
|
350
347
|
assert False
|
|
351
348
|
|
|
@@ -15,6 +15,7 @@ from typing import (
|
|
|
15
15
|
|
|
16
16
|
from ._utils import (
|
|
17
17
|
ValueKind,
|
|
18
|
+
_get_value,
|
|
18
19
|
_is_missing_literal,
|
|
19
20
|
_is_none,
|
|
20
21
|
_resolve_optional,
|
|
@@ -512,9 +513,11 @@ class ListConfig(BaseContainer, MutableSequence[Any]):
|
|
|
512
513
|
self.resolve = resolve
|
|
513
514
|
self.iterator = iter(lst.__dict__["_content"])
|
|
514
515
|
self.index = 0
|
|
516
|
+
from .base import UnionNode
|
|
515
517
|
from .nodes import ValueNode
|
|
516
518
|
|
|
517
519
|
self.ValueNode = ValueNode
|
|
520
|
+
self.UnionNode = UnionNode
|
|
518
521
|
|
|
519
522
|
def __next__(self) -> Any:
|
|
520
523
|
x = next(self.iterator)
|
|
@@ -526,6 +529,11 @@ class ListConfig(BaseContainer, MutableSequence[Any]):
|
|
|
526
529
|
self.index = self.index + 1
|
|
527
530
|
if isinstance(x, self.ValueNode):
|
|
528
531
|
return x._value()
|
|
532
|
+
elif self.resolve and isinstance(x, self.UnionNode):
|
|
533
|
+
# Resolved iteration mirrors indexing and yields the selected
|
|
534
|
+
# concrete value instead of leaking the UnionNode wrapper. The
|
|
535
|
+
# unresolved path keeps the node so copies preserve its type.
|
|
536
|
+
return _get_value(x)
|
|
529
537
|
else:
|
|
530
538
|
# Must be omegaconf.Container. not checking for perf reasons.
|
|
531
539
|
if x._is_none():
|
|
@@ -109,13 +109,13 @@ def SI(interpolation: str) -> Any:
|
|
|
109
109
|
def register_default_resolvers() -> None:
|
|
110
110
|
from omegaconf.resolvers import oc
|
|
111
111
|
|
|
112
|
-
OmegaConf.
|
|
113
|
-
OmegaConf.
|
|
114
|
-
OmegaConf.
|
|
115
|
-
OmegaConf.
|
|
116
|
-
OmegaConf.
|
|
117
|
-
OmegaConf.
|
|
118
|
-
OmegaConf.
|
|
112
|
+
OmegaConf.register_resolver("oc.create", oc.create)
|
|
113
|
+
OmegaConf.register_resolver("oc.decode", oc.decode)
|
|
114
|
+
OmegaConf.register_resolver("oc.deprecated", oc.deprecated)
|
|
115
|
+
OmegaConf.register_resolver("oc.env", oc.env)
|
|
116
|
+
OmegaConf.register_resolver("oc.select", oc.select)
|
|
117
|
+
OmegaConf.register_resolver("oc.dict.keys", oc.dict.keys)
|
|
118
|
+
OmegaConf.register_resolver("oc.dict.values", oc.dict.values)
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
class OmegaConf:
|
|
@@ -417,6 +417,9 @@ class OmegaConf:
|
|
|
417
417
|
"""
|
|
418
418
|
Merge a list of previously created configs into a single one
|
|
419
419
|
|
|
420
|
+
Note for maintainers: changes to merge behavior should also consider
|
|
421
|
+
whether OmegaConf.unsafe_merge() needs the same coverage.
|
|
422
|
+
|
|
420
423
|
:param configs: Input configs
|
|
421
424
|
:param list_merge_mode: Behavior for merging lists
|
|
422
425
|
REPLACE: Replaces the target list with the new one (default)
|
|
@@ -430,15 +433,11 @@ class OmegaConf:
|
|
|
430
433
|
target = _ensure_container(target)
|
|
431
434
|
assert isinstance(target, (DictConfig, ListConfig))
|
|
432
435
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
turned_readonly = target._get_flag("readonly") is True
|
|
439
|
-
|
|
440
|
-
if turned_readonly:
|
|
441
|
-
OmegaConf.set_readonly(target, True)
|
|
436
|
+
target._merge_with(
|
|
437
|
+
*configs[1:],
|
|
438
|
+
list_merge_mode=list_merge_mode,
|
|
439
|
+
_allow_readonly_target=True,
|
|
440
|
+
)
|
|
442
441
|
|
|
443
442
|
return target
|
|
444
443
|
|
|
@@ -475,9 +474,10 @@ class OmegaConf:
|
|
|
475
474
|
with flag_override(
|
|
476
475
|
target, ["readonly", "no_deepcopy_set_nodes"], [False, True]
|
|
477
476
|
):
|
|
478
|
-
target.
|
|
477
|
+
target._merge_with(
|
|
479
478
|
*configs[1:],
|
|
480
479
|
list_merge_mode=list_merge_mode,
|
|
480
|
+
_allow_readonly_target=True,
|
|
481
481
|
)
|
|
482
482
|
turned_readonly = target._get_flag("readonly") is True
|
|
483
483
|
|
|
@@ -487,61 +487,7 @@ class OmegaConf:
|
|
|
487
487
|
return target
|
|
488
488
|
|
|
489
489
|
@staticmethod
|
|
490
|
-
def register_resolver(
|
|
491
|
-
warnings.warn(
|
|
492
|
-
dedent("""\
|
|
493
|
-
register_resolver() is deprecated.
|
|
494
|
-
See https://github.com/omry/omegaconf/issues/426 for migration instructions.
|
|
495
|
-
"""),
|
|
496
|
-
stacklevel=2,
|
|
497
|
-
)
|
|
498
|
-
return OmegaConf.legacy_register_resolver(name, resolver)
|
|
499
|
-
|
|
500
|
-
# This function will eventually be deprecated and removed.
|
|
501
|
-
@staticmethod
|
|
502
|
-
def legacy_register_resolver(name: str, resolver: Resolver) -> None:
|
|
503
|
-
assert callable(resolver), "resolver must be callable"
|
|
504
|
-
# noinspection PyProtectedMember
|
|
505
|
-
assert (
|
|
506
|
-
name not in BaseContainer._resolvers
|
|
507
|
-
), f"resolver '{name}' is already registered"
|
|
508
|
-
|
|
509
|
-
def resolver_wrapper(
|
|
510
|
-
config: BaseContainer,
|
|
511
|
-
parent: BaseContainer,
|
|
512
|
-
node: Node,
|
|
513
|
-
args: Tuple[Any, ...],
|
|
514
|
-
args_str: Tuple[str, ...],
|
|
515
|
-
) -> Any:
|
|
516
|
-
cache = OmegaConf.get_cache(config)[name]
|
|
517
|
-
# "Un-escape " spaces and commas.
|
|
518
|
-
args_unesc = [x.replace(r"\ ", " ").replace(r"\,", ",") for x in args_str]
|
|
519
|
-
|
|
520
|
-
# Nested interpolations behave in a potentially surprising way with
|
|
521
|
-
# legacy resolvers (they remain as strings, e.g., "${foo}"). If any
|
|
522
|
-
# input looks like an interpolation we thus raise an exception.
|
|
523
|
-
try:
|
|
524
|
-
bad_arg = next(i for i in args_unesc if "${" in i)
|
|
525
|
-
except StopIteration:
|
|
526
|
-
pass
|
|
527
|
-
else:
|
|
528
|
-
raise ValueError(
|
|
529
|
-
f"Resolver '{name}' was called with argument '{bad_arg}' that appears "
|
|
530
|
-
f"to be an interpolation. Nested interpolations are not supported for "
|
|
531
|
-
f"resolvers registered with `[legacy_]register_resolver()`, please use "
|
|
532
|
-
f"`register_new_resolver()` instead (see "
|
|
533
|
-
f"https://github.com/omry/omegaconf/issues/426 for migration instructions)." # noqa: E231
|
|
534
|
-
)
|
|
535
|
-
key = args_str
|
|
536
|
-
val = cache[key] if key in cache else resolver(*args_unesc)
|
|
537
|
-
cache[key] = val
|
|
538
|
-
return val
|
|
539
|
-
|
|
540
|
-
# noinspection PyProtectedMember
|
|
541
|
-
BaseContainer._resolvers[name] = resolver_wrapper
|
|
542
|
-
|
|
543
|
-
@staticmethod
|
|
544
|
-
def register_new_resolver(
|
|
490
|
+
def register_resolver(
|
|
545
491
|
name: str,
|
|
546
492
|
resolver: Resolver,
|
|
547
493
|
*,
|
|
@@ -621,6 +567,76 @@ class OmegaConf:
|
|
|
621
567
|
# noinspection PyProtectedMember
|
|
622
568
|
BaseContainer._resolvers[name] = resolver_wrapper
|
|
623
569
|
|
|
570
|
+
@staticmethod
|
|
571
|
+
def register_new_resolver(
|
|
572
|
+
name: str,
|
|
573
|
+
resolver: Resolver,
|
|
574
|
+
*,
|
|
575
|
+
replace: bool = False,
|
|
576
|
+
use_cache: bool = False,
|
|
577
|
+
) -> None:
|
|
578
|
+
warnings.warn(
|
|
579
|
+
dedent("""\
|
|
580
|
+
register_new_resolver() is deprecated and will be removed in a future release.
|
|
581
|
+
Use register_resolver() instead.
|
|
582
|
+
See https://github.com/omry/omegaconf/issues/426 for migration instructions.
|
|
583
|
+
"""),
|
|
584
|
+
stacklevel=2,
|
|
585
|
+
)
|
|
586
|
+
return OmegaConf.register_resolver(
|
|
587
|
+
name, resolver, replace=replace, use_cache=use_cache
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
@staticmethod
|
|
591
|
+
def legacy_register_resolver(name: str, resolver: Resolver) -> None:
|
|
592
|
+
warnings.warn(
|
|
593
|
+
dedent("""\
|
|
594
|
+
legacy_register_resolver() is deprecated and will be removed in a future release.
|
|
595
|
+
Use register_resolver() instead.
|
|
596
|
+
See https://github.com/omry/omegaconf/issues/426 for migration instructions.
|
|
597
|
+
"""),
|
|
598
|
+
stacklevel=2,
|
|
599
|
+
)
|
|
600
|
+
assert callable(resolver), "resolver must be callable"
|
|
601
|
+
# noinspection PyProtectedMember
|
|
602
|
+
assert (
|
|
603
|
+
name not in BaseContainer._resolvers
|
|
604
|
+
), f"resolver '{name}' is already registered"
|
|
605
|
+
|
|
606
|
+
def resolver_wrapper(
|
|
607
|
+
config: BaseContainer,
|
|
608
|
+
parent: BaseContainer,
|
|
609
|
+
node: Node,
|
|
610
|
+
args: Tuple[Any, ...],
|
|
611
|
+
args_str: Tuple[str, ...],
|
|
612
|
+
) -> Any:
|
|
613
|
+
cache = OmegaConf.get_cache(config)[name]
|
|
614
|
+
# "Un-escape " spaces and commas.
|
|
615
|
+
args_unesc = [x.replace(r"\ ", " ").replace(r"\,", ",") for x in args_str]
|
|
616
|
+
|
|
617
|
+
# Nested interpolations behave in a potentially surprising way with
|
|
618
|
+
# legacy resolvers (they remain as strings, e.g., "${foo}"). If any
|
|
619
|
+
# input looks like an interpolation we thus raise an exception.
|
|
620
|
+
try:
|
|
621
|
+
bad_arg = next(i for i in args_unesc if "${" in i)
|
|
622
|
+
except StopIteration:
|
|
623
|
+
pass
|
|
624
|
+
else:
|
|
625
|
+
raise ValueError(
|
|
626
|
+
f"Resolver '{name}' was called with argument '{bad_arg}' that appears "
|
|
627
|
+
f"to be an interpolation. Nested interpolations are not supported for "
|
|
628
|
+
f"resolvers registered with `legacy_register_resolver()`, please use "
|
|
629
|
+
f"`register_resolver()` instead (see "
|
|
630
|
+
f"https://github.com/omry/omegaconf/issues/426 for migration instructions)." # noqa: E231
|
|
631
|
+
)
|
|
632
|
+
key = args_str
|
|
633
|
+
val = cache[key] if key in cache else resolver(*args_unesc)
|
|
634
|
+
cache[key] = val
|
|
635
|
+
return val
|
|
636
|
+
|
|
637
|
+
# noinspection PyProtectedMember
|
|
638
|
+
BaseContainer._resolvers[name] = resolver_wrapper
|
|
639
|
+
|
|
624
640
|
@classmethod
|
|
625
641
|
def has_resolver(cls, name: str) -> bool:
|
|
626
642
|
"""
|
|
@@ -808,6 +824,25 @@ class OmegaConf:
|
|
|
808
824
|
structured_config_mode=structured_config_mode,
|
|
809
825
|
)
|
|
810
826
|
|
|
827
|
+
@staticmethod
|
|
828
|
+
def structural_equality(cfg1: Any, cfg2: Any) -> bool:
|
|
829
|
+
"""
|
|
830
|
+
Compare two configs by their unresolved container structure.
|
|
831
|
+
|
|
832
|
+
This is equivalent to converting both configs with
|
|
833
|
+
``OmegaConf.to_container(resolve=False, throw_on_missing=False)`` and
|
|
834
|
+
comparing the resulting containers. Interpolations and custom resolver
|
|
835
|
+
expressions are compared as their raw strings and are not resolved.
|
|
836
|
+
Missing values do not raise.
|
|
837
|
+
|
|
838
|
+
:param cfg1: First OmegaConf config to compare.
|
|
839
|
+
:param cfg2: Second OmegaConf config to compare.
|
|
840
|
+
:return: ``True`` if both configs have the same unresolved structure.
|
|
841
|
+
"""
|
|
842
|
+
return OmegaConf.to_container(
|
|
843
|
+
cfg1, resolve=False, throw_on_missing=False
|
|
844
|
+
) == OmegaConf.to_container(cfg2, resolve=False, throw_on_missing=False)
|
|
845
|
+
|
|
811
846
|
@staticmethod
|
|
812
847
|
def to_object(cfg: Any) -> Union[Dict[DictKeyType, Any], List[Any], None, str, Any]:
|
|
813
848
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: omegaconf
|
|
3
|
-
Version: 2.4.0.
|
|
3
|
+
Version: 2.4.0.dev12
|
|
4
4
|
Summary: A flexible configuration library
|
|
5
5
|
Home-page: https://github.com/omry/omegaconf
|
|
6
6
|
Author: Omry Yadan
|
|
@@ -57,7 +57,7 @@ Dynamic: summary
|
|
|
57
57
|
| Project | [](https://badge.fury.io/py/omegaconf)[](https://pepy.tech/project/omegaconf) |
|
|
58
58
|
| Code quality| [](https://dl.circleci.com/status-badge/redirect/gh/omry/omegaconf/tree/main)[](https://coveralls.io/github/omry/omegaconf)|
|
|
59
59
|
| Docs and support |[](https://omegaconf.readthedocs.io/en/2.3_branch/)[](https://mybinder.org/v2/gh/omry/omegaconf/master?filepath=docs%2Fnotebook%2FTutorial.ipynb)[](https://hydra-framework.zulipchat.com/)|
|
|
60
|
-
| Backlog | [
|
|
60
|
+
| Backlog | [](https://omry.github.io/backlog-atlas/) |
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
OmegaConf is a hierarchical configuration system, with support for merging configurations from multiple sources (YAML config files, dataclasses/objects and CLI arguments)
|
|
@@ -7,6 +7,7 @@ exclude = '''
|
|
|
7
7
|
| omegaconf/grammar/gen
|
|
8
8
|
| omegaconf/vendor
|
|
9
9
|
| \.nox
|
|
10
|
+
| \.venv
|
|
10
11
|
| build
|
|
11
12
|
| subprojects
|
|
12
13
|
| temp
|
|
@@ -17,15 +18,21 @@ exclude = '''
|
|
|
17
18
|
'''
|
|
18
19
|
|
|
19
20
|
[tool.isort]
|
|
20
|
-
skip_glob = [
|
|
21
|
+
skip_glob = [
|
|
22
|
+
".venv/*",
|
|
23
|
+
"temp/*",
|
|
24
|
+
"omegaconf/vendor/*",
|
|
25
|
+
"subprojects/*",
|
|
26
|
+
".claude/*",
|
|
27
|
+
]
|
|
21
28
|
|
|
22
29
|
[tool.pytest.ini_options]
|
|
23
30
|
addopts = "--import-mode=append -Werror"
|
|
24
31
|
pythonpath = ["."]
|
|
25
|
-
norecursedirs = ["subprojects", ".git", ".sl"]
|
|
32
|
+
norecursedirs = ["subprojects", ".git", ".sl", ".venv"]
|
|
26
33
|
|
|
27
34
|
[tool.bumpversion]
|
|
28
|
-
current_version = "2.4.0.
|
|
35
|
+
current_version = "2.4.0.dev12"
|
|
29
36
|
parse = '''(?x)
|
|
30
37
|
(?P<major>\d+)
|
|
31
38
|
\.(?P<minor>\d+)
|
|
@@ -102,6 +109,7 @@ project-excludes = [
|
|
|
102
109
|
"build/**",
|
|
103
110
|
"temp/**",
|
|
104
111
|
".nox/**",
|
|
112
|
+
".venv/**",
|
|
105
113
|
"omegaconf/vendor/**",
|
|
106
114
|
"subprojects/**",
|
|
107
115
|
]
|
|
@@ -4,7 +4,7 @@ test = pytest
|
|
|
4
4
|
[flake8]
|
|
5
5
|
max-line-length = 88
|
|
6
6
|
extend-ignore = E203, E501
|
|
7
|
-
exclude = .git,.eggs,.nox,build,temp,vendor,subprojects,omegaconf/grammar/gen,omegaconf/vendor
|
|
7
|
+
exclude = .git,.eggs,.nox,.venv,build,temp,vendor,subprojects,omegaconf/grammar/gen,omegaconf/vendor
|
|
8
8
|
|
|
9
9
|
[egg_info]
|
|
10
10
|
tag_build =
|